diff options
| author | 2025-02-26 12:16:34 +0330 | |
|---|---|---|
| committer | 2025-02-26 12:16:34 +0330 | |
| commit | 93d17188c89a9197a2cb0bdad4d5ca9ac3be4461 (patch) | |
| tree | bdbd50206f87ea00a124c94b29398f9037f3014a | |
| parent | Added foreach (diff) | |
a few fixes and changes
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | main.c | 16 | ||||
| -rw-r--r-- | moonshine.h | 777 |
3 files changed, 469 insertions, 326 deletions
@@ -1,5 +1,5 @@ FLAGS = -Wno-incompatible-library-redeclaration -nostartfiles -SIZE_FLAGS = -flto -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -s -fno-unwind-tables -fomit-frame-pointer -fno-asynchronous-unwind-tables -fno-ident -fvisibility=hidden -march=native -Wl,--build-id=none +SIZE_FLAGS = -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -s -fno-unwind-tables -fomit-frame-pointer -fno-asynchronous-unwind-tables -fno-ident -fvisibility=hidden -march=native -Wl,--build-id=none all: m4 c test @@ -1,16 +1,18 @@ // This is the test unit, not the actual code. +#define __MOONSHINE_LIBC_WARNINGS #include "moonshine.h" -int main() { - array(int) test = new (int); +void cleanup_free(var* input) { print("Free that thang ", input); } + +#define auto_free __attribute__((cleanup(cleanup_free))) - int j = 1; - for(int i = 100; i >= 0; i--) push(test, i % (j++)); +#define create(name, ...) \ + auto_free var cat(name, _parent) = __VA_ARGS__; \ + auto name = cat(name, _parent); - foreach(numba in test) { - print("Item: ", numba, " index ", numba_index); - } +int main() { + print("Wow ", strdup("Gay smex")[ 0 ]); return 0; } diff --git a/moonshine.h b/moonshine.h index d842fae..ab0ba1a 100644 --- a/moonshine.h +++ b/moonshine.h @@ -1,28 +1,53 @@ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wincompatible-library-redeclaration" + #ifndef moonshine_header -#define moonshine_header + #define moonshine_header // -#include "moonshine.m4.h" + #include "moonshine.m4.h" + + #define new(a, ...) ((a **) new_x(a __VA_OPT__(, ) __VA_ARGS__, new2, new1)(a __VA_OPT__(, ) __VA_ARGS__)) + #define new_x(a, b, c, ...) c + #define new1(type) (__new_array(#type, sizeof(type), 0)) + #define new2(type, count) (__new_array(#type, sizeof(type), count)) + + #define fill(type, ...) \ + ({ \ + type __fill_values[] = { __VA_ARGS__ }; \ + u4 __fill_count = sizeof(__fill_values) / sizeof(type); \ + auto __fill_arr = new (type, __fill_count); \ + for (u4 __i = 0; __i < __fill_count; __i++) { de(__fill_arr)[ __i ] = __fill_values[ __i ]; } \ + __fill_arr; \ + }) + + #define single(...) \ + ({ \ + auto value = __VA_ARGS__; \ + fill(typeof(value), value); \ + }) int errno = 0; -#define NULL ((void *) 0) -#define null ((void *) 0) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) -#if defined __x86_64__ && !defined __ILP32__ - #define __WORDSIZE 64 -#else - #define __WORDSIZE 32 - #define __WORDSIZE32_SIZE_ULONG 0 - #define __WORDSIZE32_PTediFF_LONG 0 -#endif + #define NULL ((void *) 0) -#define __WORDSIZE_TIME64_COMPAT32 1 + #if defined __x86_64__ && !defined __ILP32__ + #define __WORDSIZE 64 + #else + #define __WORDSIZE 32 + #define __WORDSIZE32_SIZE_ULONG 0 + #define __WORDSIZE32_PTediFF_LONG 0 + #endif -#ifdef __x86_64__ - #define __syscall_WORDSIZE 64 -#endif + #define __WORDSIZE_TIME64_COMPAT32 1 + + #ifdef __x86_64__ + #define __syscall_WORDSIZE 64 + #endif typedef signed char int8_t; typedef unsigned char uint8_t; @@ -30,28 +55,30 @@ typedef signed short int int16_t; typedef unsigned short int uint16_t; typedef signed int int32_t; typedef unsigned int uint32_t; -#if __WORDSIZE == 64 + #if __WORDSIZE == 64 typedef signed long int int64_t; typedef unsigned long int uint64_t; -#else + #else __extension__ typedef signed long long int int64_t; __extension__ typedef unsigned long long int uint64_t; -#endif + #endif typedef unsigned char byte; -#define string char * -typedef void *ptr; -typedef void *var; -typedef uint64_t u8; -typedef int64_t i8; -typedef int32_t i4; -typedef uint32_t u4; +typedef char *string; +typedef const char *ctring; +typedef void *ptr; +typedef void *var; +typedef const void *car; +typedef uint64_t u8; +typedef int64_t i8; +typedef int32_t i4; +typedef uint32_t u4; typedef uint8_t bool; const bool true = 1; const bool false = 0; -#define auto __auto_type + #define auto __auto_type enum glob_type { type_char, @@ -75,142 +102,145 @@ enum glob_type { void globprint(const enum glob_type type, const char *value_text, const char *text, const void *value); -#define print_local(value) \ - ({ \ - __auto_type obj = value; \ - _Generic( \ - obj, \ - char: globprint(type_char, "", "char", &obj), \ - int: globprint(type_int, #value, "int", &obj), \ - string: globprint(type_string, "", "string", &obj), \ - bool: globprint(type_bool, "", "bool", &obj), \ - u4: globprint(type_u32, "", "u32", &obj), \ - float: globprint(type_float, "", "float", &obj), \ - double: globprint(type_double, "", "double", &obj), \ - u8: globprint(type_u64, "", "u64", &obj), \ - i8: globprint(type_i64, "", "i64", &obj), \ - var: globprint(type_pointer, "", "pointer", &obj), \ - default: globprint(type_unknown, #value, "unknown", &obj)); \ - }) - -#define print(...) \ - ({ \ - EXPAND_print_local(__VA_ARGS__); \ - putchar('\n'); \ - }) - -#define item(value, code) \ - case value: { \ - code; \ - }; break -#define none(code) \ - default: { \ - code; \ - } break - -#define decast(type) (*((type *) value)) - -#define puts(value) write(value, strlen(value), stdout) -#define puts_static(value) write(value, sizeof(value), stdout) - -#define expand(x) x -#define __demon(code, ID) \ - ({ \ - flush(stdout); \ - auto cat(fork_, ID) = fork(); \ - if (cat(fork_, ID) < 0) { \ - puts_static("Failed to fork!\n"); \ - exit(1); \ - } else if (cat(fork_, ID) == 0) { \ + #define print_local(value) \ + ({ \ + __auto_type obj = value; \ + _Generic( \ + obj, \ + char: globprint(type_char, "", "char", &obj), \ + int: globprint(type_int, #value, "int", &obj), \ + string: globprint(type_string, "", "string", &obj), \ + bool: globprint(type_bool, "", "bool", &obj), \ + u4: globprint(type_u32, "", "u32", &obj), \ + float: globprint(type_float, "", "float", &obj), \ + double: globprint(type_double, "", "double", &obj), \ + u8: globprint(type_u64, "", "u64", &obj), \ + i8: globprint(type_i64, "", "i64", &obj), \ + var: globprint(type_pointer, "", "pointer", &obj), \ + default: globprint(type_unknown, #value, "unknown", &obj)); \ + }) + + #define print(...) \ + ({ \ + EXPAND_print_local(__VA_ARGS__); \ + putchar('\n'); \ + }) + + #define item(value, code) \ + case value: { \ code; \ - exit(0); \ - byte *osjdoijsoij = (byte *) (0 + 129387 - 129387); \ - (void) *osjdoijsoij; \ - }; \ - cat(fork_, ID); \ - }) -#define demon(code) /* Fork the current process and creates an async process that runs \ - in parallel, it also returns the PID of the child process to the \ - parent, in case you need to wait until the child dies. */ \ - __demon(code, expand(__COUNTER__)) - -#define syscall1(num) \ - ({ \ - long result; \ - __asm__ volatile("syscall" : "=a"(result) : "a"(num) : "rcx", "r11", "memory", "cc"); \ - result; \ - }) - -#define syscall2(num, arg1) \ - ({ \ - long result; \ - __asm__ volatile("syscall" : "=a"(result) : "a"(num), "D"(arg1) : "rcx", "r11", "memory", "cc"); \ - result; \ - }) - -#define syscall3(num, arg1, arg2) \ - ({ \ - long result; \ - __asm__ volatile("syscall" : "=a"(result) : "a"(num), "D"(arg1), "S"(arg2) : "rcx", "r11", "memory", "cc"); \ - result; \ - }) - -#define syscall4(num, arg1, arg2, arg3) \ - ({ \ - long result; \ - __asm__ volatile("syscall" : "=a"(result) : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3) : "rcx", "r11", "memory", "cc"); \ - result; \ - }) - -#define syscall5(num, arg1, arg2, arg3, arg4) \ - ({ \ - long result; \ - register long __arg4 __asm__("r10") = (long) (arg4); \ - __asm__ volatile("syscall" \ - : "=a"(result) \ - : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(__arg4) \ - : "rcx", "r11", "memory", "cc"); \ - result; \ - }) - -#define syscall6(num, arg1, arg2, arg3, arg4, arg5) \ - ({ \ - long result; \ - register long __arg4 __asm__("r10") = (long) (arg4); \ - register long __arg5 __asm__("r8") = (long) (arg5); \ - __asm__ volatile("syscall" \ - : "=a"(result) \ - : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(__arg4), "r"(__arg5) \ - : "rcx", "r11", "memory", "cc"); \ - result; \ - }) - -#define syscall7(num, arg1, arg2, arg3, arg4, arg5, arg6) \ - ({ \ - long result; \ - register long __arg4 __asm__("r10") = (long) (arg4); \ - register long __arg5 __asm__("r8") = (long) (arg5); \ - register long __arg6 __asm__("r9") = (long) (arg6); \ - __asm__ volatile("syscall" \ - : "=a"(result) \ - : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(__arg4), "r"(__arg5), "r"(__arg6) \ - : "rcx", "r11", "memory", "cc"); \ - result; \ - }) + }; break + #define none(code) \ + default: { \ + code; \ + } break + + #define decast(type) (*((type *) value)) + + #define puts(value) write(value, strlen(value), stdout) + #define puts_static(value) write(value, sizeof(value), stdout) + + #define expand(x) x + #define __demon(code, ID) \ + ({ \ + flush(stdout); \ + auto cat(fork_, ID) = fork(); \ + if (cat(fork_, ID) < 0) { \ + puts_static("Failed to fork!\n"); \ + exit(1); \ + } else if (cat(fork_, ID) == 0) { \ + code; \ + exit(0); \ + byte *osjdoijsoij = (byte *) (0 + 129387 - 129387); \ + (void) *osjdoijsoij; \ + }; \ + cat(fork_, ID); \ + }) + #define demon(code) /* Fork the current process and creates an async process that runs \ + in parallel, it also returns the PID of the child process to the \ + parent, in case you need to wait until the child dies. */ \ + __demon(code, expand(__COUNTER__)) + + #define syscall1(num) \ + ({ \ + long result; \ + __asm__ volatile("syscall" : "=a"(result) : "a"(num) : "rcx", "r11", "memory", "cc"); \ + result; \ + }) + + #define syscall2(num, arg1) \ + ({ \ + long result; \ + __asm__ volatile("syscall" : "=a"(result) : "a"(num), "D"(arg1) : "rcx", "r11", "memory", "cc"); \ + result; \ + }) + + #define syscall3(num, arg1, arg2) \ + ({ \ + long result; \ + __asm__ volatile("syscall" : "=a"(result) : "a"(num), "D"(arg1), "S"(arg2) : "rcx", "r11", "memory", "cc"); \ + result; \ + }) + + #define syscall4(num, arg1, arg2, arg3) \ + ({ \ + long result; \ + __asm__ volatile("syscall" \ + : "=a"(result) \ + : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3) \ + : "rcx", "r11", "memory", "cc"); \ + result; \ + }) + + #define syscall5(num, arg1, arg2, arg3, arg4) \ + ({ \ + long result; \ + register long __arg4 __asm__("r10") = (long) (arg4); \ + __asm__ volatile("syscall" \ + : "=a"(result) \ + : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(__arg4) \ + : "rcx", "r11", "memory", "cc"); \ + result; \ + }) + + #define syscall6(num, arg1, arg2, arg3, arg4, arg5) \ + ({ \ + long result; \ + register long __arg4 __asm__("r10") = (long) (arg4); \ + register long __arg5 __asm__("r8") = (long) (arg5); \ + __asm__ volatile("syscall" \ + : "=a"(result) \ + : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(__arg4), "r"(__arg5) \ + : "rcx", "r11", "memory", "cc"); \ + result; \ + }) + + #define syscall7(num, arg1, arg2, arg3, arg4, arg5, arg6) \ + ({ \ + long result; \ + register long __arg4 __asm__("r10") = (long) (arg4); \ + register long __arg5 __asm__("r8") = (long) (arg5); \ + register long __arg6 __asm__("r9") = (long) (arg6); \ + __asm__ volatile("syscall" \ + : "=a"(result) \ + : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(__arg4), "r"(__arg5), "r"(__arg6) \ + : "rcx", "r11", "memory", "cc"); \ + result; \ + }) void exit(const int exit_code) { const uint64_t syscall_number = 60; - syscall2(syscall_number, exit_code); + (void) syscall2(syscall_number, exit_code); __builtin_unreachable(); } -#define stdin 0 /* Standard input. */ -#define stdout 1 /* Standard output. */ -#define stderr 2 /* Standard error output. */ + #define stdin 0 /* Standard input. */ + #define stdout 1 /* Standard output. */ + #define stderr 2 /* Standard error output. */ -#define BUFFER_SIZE 4096 + #define BUFFER_SIZE 4096 static char buffer[ BUFFER_SIZE ]; static int buffer_index = 0; @@ -220,6 +250,8 @@ int flush(int fd); int write(const char *ptr, const int size, const int fd) { int total_written = 0; for (int i = 0; i < size; i++) { + if (ptr[ i ] == 0) continue; + if (buffer_index >= BUFFER_SIZE || ptr[ i ] == '\n') { int result = flush(fd); if (result < 0) { return -1; } @@ -245,49 +277,89 @@ int write(const char *ptr, const int size, const int fd) { } int flush(int fd) { - if (buffer_index == 0) { - return 0; // Nothing to flush - } + if (buffer_index == 0) { return 0; } int result = syscall4(1, fd, buffer, buffer_index); - buffer_index = 0; // Reset buffer index + buffer_index = 0; return result; } -#define putchar(x) \ - ({ \ - byte y = x; \ - write((char *) &y, 1, stdout); \ - }) + #define putchar(x) \ + ({ \ + byte y = x; \ + write((char *) &y, 1, stdout); \ + }) -#ifdef __MOONSHINE_MALLOC_WARNINGS -void malloc() { throw("Don't use base malloc!"); } + #define SYS_read 0 -void realloc() { throw("Don't use base realloc!"); } +char getchar() { + char c; + u8 result = syscall4(SYS_read, stdin, &c, 1); -void free() { throw("Don't use base free!"); } -#endif + // print("Wow ", (u8)c); + if (c == 0) return -1; + if (result <= 0) return -1; -#define MAP_SHARED 0x01 /* Share changes */ -#define MAP_PRIVATE 0x02 /* Changes are private */ -#define PROT_READ 0x1 /* page can be read */ -#define PROT_WRITE 0x2 /* page can be written */ -#define PROT_EXEC 0x4 /* page can be executed */ -#define MAP_FIXED 0x10 /* Interpret addr exactly */ -#define MAP_ANONYMOUS 0x20 /* don't use a file */ + return c; +} -byte strcmp(const string left, const string right) { + #define __MOONSHINE_MALLOC_WARNINGS + #ifdef __MOONSHINE_MALLOC_WARNINGS + #define MOONSHINE_LEGACY_LIBC_WARNING \ + "You are using moonshine, this library does not allow the use of legacy libc functions. Please use the " \ + "moonshine-provided alternative instead." +void malloc() __attribute__((deprecated(MOONSHINE_LEGACY_LIBC_WARNING, "alloc"))); +void realloc() __attribute__((deprecated(MOONSHINE_LEGACY_LIBC_WARNING, "remap"))); +void free() __attribute__((deprecated(MOONSHINE_LEGACY_LIBC_WARNING, "release"))); + #endif + + #define MAP_SHARED 0x01 /* Share changes */ + #define MAP_PRIVATE 0x02 /* Changes are private */ + #define PROT_READ 0x1 /* page can be read */ + #define PROT_WRITE 0x2 /* page can be written */ + #define PROT_EXEC 0x4 /* page can be executed */ + #define MAP_FIXED 0x10 /* Interpret addr exactly */ + #define MAP_ANONYMOUS 0x20 /* don't use a file */ + +__attribute__((diagnose_as_builtin(__builtin_strcmp, 1, 2))) byte strcmp(ctring left, ctring right) { while (*left && (*left == *right) && left++ && right++); return (byte) (*left) - (byte) (*right); } -#define eq(a, b) (strcmp(a, b) == 0) + #define eq(a, b) (strcmp(a, b) == 0) + +u8 strnlen(ctring txt, u8 len) { + u8 s = 0; + while (s < len && txt[ s ] != '\0') s++; + return s; +} + +__attribute__((diagnose_as_builtin(__builtin_memset, 1, 2, 3))) void memset(var _ptr, int n, u8 size) { + string ptr = _ptr; + for (u8 i = 0; i < size; i++) ptr[ i ] = n; +} + +__attribute__((diagnose_as_builtin(__builtin_memmove, 1, 2, 3))) void *memmove(void *dest, const void *src, unsigned long n) { + unsigned char *d = (unsigned char *) dest; + const unsigned char *s = (const unsigned char *) src; + if (d == s || n == 0) return dest; + if (d < s || d >= s + n) + for (unsigned long i = 0; i < n; i++) d[ i ] = s[ i ]; + else + for (unsigned long i = n; i > 0; i--) d[ i - 1 ] = s[ i - 1 ]; + + return dest; +} + +__attribute__((diagnose_as_builtin(__builtin_memcpy, 1, 2, 3))) void memcpy(var _dest, car _src, const unsigned long n) { + string dest = _dest; + ctring src = _src; -void memcpy(string dest, const string src, const unsigned long n) { for (u8 i = 0; i < n; i++) dest[ i ] = src[ i ]; } -var __bare_mmap(const var addr, const u8 len, const int prot, const int flags, const int fd, const int64_t offset) { +var __bare_mmap(const var addr, const u8 len, const int prot, const int flags, const int fd, const int64_t offset) + [[clang::allocating]] { const u8 syscall_number = 9; const var result = (var) syscall7(syscall_number, addr, len, prot, flags, fd, offset); @@ -307,46 +379,50 @@ int __bare_munmap(const var addr, const uint64_t len) { return result; } -var __bare_alloc(const uint64_t size) { +var __bare_alloc(const uint64_t size) [[clang::allocating]] { return __bare_mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_ANONYMOUS, -1, 0); } -#define SYS_getpid 39 -#define SYS_kill 62 - -#define SIGTRAP 5 -#define SIGILL 4 - -#define getpid() syscall1(SYS_getpid) -#define kill(pid, sig) syscall3(SYS_kill, pid, sig) -#define raise(sig) kill(getpid(), sig) - -// TODO: Setting a breakpoint multiple times can fuck with the stdout buffer, somehow -#define breakpoint(str) \ - ({ \ - const string wowie = "" str; \ - (void) wowie; \ - (void) raise(SIGTRAP); \ - }) - -#define throw(...) \ - ({ \ - print("Error: ", __VA_ARGS__); \ - puts_static("The following is an exception-related crash:"); \ - (void) raise(SIGILL); \ - __builtin_unreachable(); \ - 0; \ - }) - -var __bare_mremap(const var ptr, const uint64_t old, const uint64_t new) { + #define SYS_getpid 39 + #define SYS_kill 62 + + #define SIGTRAP 5 + #define SIGILL 4 + + #define getpid() syscall1(SYS_getpid) + #define kill(pid, sig) syscall3(SYS_kill, pid, sig) + #define raise(sig) kill(getpid(), sig) + + // TODO: Setting a breakpoint multiple times can fuck with the stdout buffer, somehow + #define breakpoint(str) \ + ({ \ + const string wowie = "" str; \ + (void) wowie; \ + (void) raise(SIGTRAP); \ + }) + + #define fg_ansi(r, g, b) "\e[38;2;" #r ";" #g ";" #b "m" + #define bg_ansi(r, g, b) "\e[48;2;" #r ";" #g ";" #b "m" + #define no_ansi() "\e[0m" + + #define throw(...) \ + ({ \ + print(fg_ansi(255, 90, 90) "Error: ", __VA_ARGS__, no_ansi()); \ + puts_static(fg_ansi(235, 235, 50) "The following is an exception-related crash: " no_ansi()); \ + (void) raise(SIGILL); \ + __builtin_unreachable(); \ + 0; \ + }) + +var __bare_mremap(const var ptr, const uint64_t old, const uint64_t new) [[clang::allocating]] { const var new_ptr = __bare_alloc(new); memcpy(new_ptr, ptr, old); __bare_munmap(ptr, old); return new_ptr; } -#define BASE_ARRAY_CAPACITY 32 -#define BASE_PAGE_TABLE_CAPACITY 16 + #define BASE_ARRAY_CAPACITY 32 + #define BASE_PAGE_TABLE_CAPACITY 16 struct AllocatedPointer { u8 size; @@ -377,20 +453,20 @@ struct PageTable { struct Page *pages; }; -#define AllocatedPointer(size, location) \ - ((struct AllocatedPointer) { .size = (size), .location = (location), .allocated = true }) -#define PageArray() \ - ((struct PageArray) { .capacity = BASE_ARRAY_CAPACITY, \ - .data = __bare_alloc(sizeof(struct AllocatedPointer) * BASE_ARRAY_CAPACITY) }) -#define Page(page_size) \ - ((struct Page) { .dirty = true, \ - .last_result = {}, \ - .size = page_size, \ - .start = __bare_alloc(sizeof(byte) * page_size), \ - .pointers = PageArray() }) - -#define PageTable() \ - ((struct PageTable) { 0, BASE_PAGE_TABLE_CAPACITY, __bare_alloc(sizeof(struct Page) * BASE_PAGE_TABLE_CAPACITY) }) + #define AllocatedPointer(size, location) \ + ((struct AllocatedPointer) { .size = (size), .location = (location), .allocated = true }) + #define PageArray() \ + ((struct PageArray) { .capacity = BASE_ARRAY_CAPACITY, \ + .data = __bare_alloc(sizeof(struct AllocatedPointer) * BASE_ARRAY_CAPACITY) }) + #define Page(page_size) \ + ((struct Page) { .dirty = true, \ + .last_result = {}, \ + .size = page_size, \ + .start = __bare_alloc(sizeof(byte) * page_size), \ + .pointers = PageArray() }) + + #define PageTable() \ + ((struct PageTable) { 0, BASE_PAGE_TABLE_CAPACITY, __bare_alloc(sizeof(struct Page) * BASE_PAGE_TABLE_CAPACITY) }) struct PageTable global_page_table; @@ -433,9 +509,9 @@ static int compare_locations(const void *a, const void *b) { return 0; } -#define align_value(value) ((u8) ((((value) + 15) & ~15ULL))) + #define align_value(value) ((u8) ((((value) + 15) & ~15ULL))) -struct FreeBlock find_free_space(struct Page *page) { +struct FreeBlock find_free_space(struct Page *page) [[clang::nonallocating]] { if (!page->dirty) return page->last_result; struct FreeBlock max_free = { 0, 0 }; @@ -503,14 +579,14 @@ struct FreeBlock find_free_space(struct Page *page) { return max_free; } -#define max(a, b) ((a) > (b) ? (a) : (b)) + #define max(a, b) ((a) > (b) ? (a) : (b)) // remove empty pages void clean_pages() { for (u8 i = 0; i < global_page_table.size; i++) { auto page = &global_page_table.pages[ i ]; - if (page->start == null) continue; + if (page->start == NULL) continue; for (u8 ptr = 0; ptr < page->pointers.size; ptr++) { if (page->pointers.data[ ptr ].allocated) goto LEAVE_PAGE; @@ -525,8 +601,13 @@ void clean_pages() { } } -var alloc(const u8 _len) { - clean_pages(); +__attribute__((diagnose_as_builtin(__builtin_malloc, 1))) __attribute__((malloc)) var alloc(const u8 _len) + [[clang::allocating]] { + static int alloc_count = 0; + if (alloc_count++ == 10) { + alloc_count = 0; + clean_pages(); + } const u8 len = align_value(_len); @@ -535,7 +616,7 @@ var alloc(const u8 _len) { struct FreeBlock max_biggest_free = { 0, 0 }; for (u8 i = 0; i < global_page_table.size; i++) { - if (global_page_table.pages[ i ].start == null) continue; + if (global_page_table.pages[ i ].start == NULL) continue; struct FreeBlock biggest_free = find_free_space(&global_page_table.pages[ i ]); if (biggest_free.size <= max_biggest_free.size) continue; @@ -543,11 +624,11 @@ var alloc(const u8 _len) { biggest_free_page = i; } - auto page = &global_page_table.pages[ biggest_free_page ]; + u8 place = biggest_free_page; + auto page = &global_page_table.pages[ place ]; if (max_biggest_free.size < len) { // add a page - u8 place = 0; // re-use page space for (u8 i = 0; i < global_page_table.size; i++) { @@ -560,8 +641,10 @@ var alloc(const u8 _len) { place = global_page_table.size; global_page_table.size++; if (global_page_table.size == global_page_table.capacity) { - global_page_table.pages - = __bare_mremap(global_page_table.pages, global_page_table.size, global_page_table.capacity *= 2); + global_page_table.pages = __bare_mremap( + global_page_table.pages, + global_page_table.size * sizeof(struct Page), + (global_page_table.capacity *= 2) * sizeof(struct Page)); } END: @@ -587,7 +670,10 @@ var alloc(const u8 _len) { pointer_place = page->pointers.size++; if (page->pointers.size == page->pointers.capacity) { - page->pointers.data = __bare_mremap(page->pointers.data, page->pointers.size, page->pointers.capacity *= 2); + page->pointers.data = __bare_mremap( + page->pointers.data, + page->pointers.size * sizeof(struct AllocatedPointer), + (page->pointers.capacity *= 2) * sizeof(struct AllocatedPointer)); } ABYSS:; @@ -615,19 +701,19 @@ struct FoundPointer find_pointer(const var addr) { if (addr >= (var) page->start && location < page->size) { // Address is in this page - struct AllocatedPointer *best_ptr = null; + struct AllocatedPointer *best_ptr = NULL; for (u8 j = 0; j < page->pointers.size; j++) { struct AllocatedPointer *ptr = &page->pointers.data[ j ]; if (ptr->location == location) { - if (!ptr->allocated && best_ptr != null) continue; + if (!ptr->allocated && best_ptr != NULL) continue; best_ptr = ptr; } } if (!best_ptr->allocated) throw("Unallocated pointer? "); - if (best_ptr == null) throw("Pointer for location does not exist in page"); + if (best_ptr == NULL) throw("Pointer for location does not exist in page"); return (struct FoundPointer) { .allocation_size = best_ptr->size, .pointer_ref = best_ptr, .page_ref = page, .page_index = i @@ -645,22 +731,29 @@ void unmap(const struct FoundPointer ptr, const var addr) { ptr.page_ref->dirty = true; } -void release(const var addr) { unmap(find_pointer(addr), addr); } +__attribute__((diagnose_as_builtin(__builtin_free, 1))) void release(const var addr) { + if (addr == 0) return; + unmap(find_pointer(addr), addr); +} -var remap(const var ptr, const u8 new) { - const var new_ptr = alloc(new); - const auto found = find_pointer(ptr); +__attribute__((diagnose_as_builtin(__builtin_realloc, 1, 2))) var remap(const var ptr, const u8 new_size) { + const var new_ptr = alloc(new_size); + if (ptr == 0) return new_ptr; + const auto found = find_pointer(ptr); memcpy(new_ptr, ptr, found.allocation_size); unmap(found, ptr); return new_ptr; } -unsigned long strlen(const char *str) { +__attribute__((diagnose_as_builtin(__builtin_strlen, 1))) unsigned long strlen(ctring str) { unsigned long len = 0; while (str[ len ] != '\0') len++; return len; } + #define t(type) type ** + #define de(obj) (*(obj)) + int fork() { const uint64_t syscall_number = 57; const int pid = syscall1(syscall_number); @@ -680,7 +773,7 @@ int wait(const int *status) { bool mine(const ptr pointer) { bool *glob_var = __bare_alloc(sizeof(bool)); - demon({ + (void) demon({ *glob_var = 0; byte *x = pointer; byte y = *x; @@ -697,8 +790,8 @@ bool mine(const ptr pointer) { return output; } -#define cast_index(arr, type, index) ((type *) arr)[ index ] -#define cast_ptr(arr, type, index) (&cast_index(arr, type, index)) + #define cast_index(arr, type, index) ((type *) arr)[ index ] + #define cast_ptr(arr, type, index) (&cast_index(arr, type, index)) const int magic_number = 0xB00E; typedef int magic_type; @@ -706,7 +799,7 @@ const int __addon_size = 2 * sizeof(u4) + sizeof(string) + sizeof(magic_type); const int addon_size = align_value(__addon_size); const int spacer_size = addon_size - __addon_size; -const var *__new_array(const string type_name, const u4 type_size, const u4 count) { +const var *__new_array(const string type_name, const u4 type_size, const u4 count) [[clang::allocating]] { // string name, and one place for the special code const u8 size = type_size * count + addon_size; @@ -716,8 +809,8 @@ const var *__new_array(const string type_name, const u4 type_size, const u4 coun cast_index(ptr, magic_type, 0) = magic_number; // magic number for arrays ptr = cast_ptr(ptr, magic_type, 1); - cast_index(ptr, const string, 0) = type_name; - ptr = cast_ptr(ptr, string, 1); + cast_index(ptr, ctring, 0) = type_name; + ptr = cast_ptr(ptr, string, 1); cast_index(ptr, u4, 0) = type_size; cast_index(ptr, u4, 1) = count; @@ -734,20 +827,20 @@ const var *__new_array(const string type_name, const u4 type_size, const u4 coun // 2. Based on the capacity, detect whether we should or shouldn't reallocate the memory // 3. eg. if an item is popped, we may keep that memory intact so that further allocations and memory copies will be unnecessary -void unsafe_extend( +__attribute__((flatten)) void unsafe_extend( var *array_ref, const var array_from_u4, const var array_base, const u4 element_count, const u4 element_size, - const u4 offset) { + const u4 offset) [[clang::allocating]] { cast_index(array_from_u4, u4, 1) += offset; const var new_base = remap(array_base, addon_size + element_size * (element_count + offset)); const string array_place = &((string) new_base)[ addon_size ]; *array_ref = (var) array_place; } -void unsafe_push(var *array, const var ptr, const u4 ptr_size) { +void unsafe_push(var *array, const var ptr, const u4 ptr_size) [[clang::allocating]] { const var main_wrap = cast_ptr(*array, byte, -addon_size); var array_wrap = main_wrap; @@ -762,7 +855,7 @@ void unsafe_push(var *array, const var ptr, const u4 ptr_size) { const u4 element_count = cast_index(array_wrap, u4, 1); const u4 element_size = cast_index(array_wrap, u4, 0); - if (element_size != ptr_size && ptr_size != 0) { + if (unlikely(element_size != ptr_size && ptr_size != 0)) { throw( "Mismatching array size: Item of size ", ptr_size, @@ -774,46 +867,102 @@ void unsafe_push(var *array, const var ptr, const u4 ptr_size) { } unsafe_extend(array, array_wrap, main_wrap, element_count, element_size, 1); - memcpy(array[ 0 ] + element_count * element_size, ptr, ptr_size); + memcpy(&(((char *) array[ 0 ])[ element_count * element_size ]), ptr, ptr_size); +} + + // IMPROVE + #define safe_push(type, array, ptr, ...) \ + ({ \ + type **_array = array; \ + type _ptr = ptr __VA_OPT__(, ) __VA_ARGS__; \ + unsafe_push((var *) _array, (var) & (_ptr), sizeof(type)); \ + }) + #define push(array, ptr, ...) safe_push(typeof((array)[ 0 ][ 0 ]), array, ptr __VA_OPT__(, ) __VA_ARGS__) + #define address_item(__array, __index) \ + ({ \ + const auto arr = __array; \ + const u8 index = __index; \ + if (unlikely(index >= count(arr))) throw("Requested index address in array exceeds the size of the array!"); \ + if (unlikely(index < 0)) throw("Cannot address negative offset in array!"); \ + &(arr[ 0 ][ index ]); \ + }) + #define get(__array, __index) \ + ({ \ + const auto main = __array; \ + const auto arr = main[ 0 ]; \ + const u8 __get_index = __index; \ + if (unlikely(__get_index > count(main))) \ + throw("Requested index in array (", __get_index, ") exceeds the size of the array! (", count(main), ")"); \ + if (unlikely(__get_index < 0)) throw("Cannot access negative offset in array!"); \ + arr[ __get_index ]; \ + }) + #define count(array) \ + ((u4) cast_index(cast_ptr(cast_ptr(cast_ptr(*array, byte, -addon_size), magic_type, 1), string, 1), u4, 1)) + #define element_size(array) \ + (u4) cast_index(cast_ptr(cast_ptr(cast_ptr(*array, byte, -addon_size), magic_type, 1), string, 1), u4, 0) + #define last(array) get(array, count(array) - 1) + + #define in , + #define foreach(...) foreach_xp(foreach_inner, (__VA_ARGS__)) + #define foreach_xp(a, b) a b + #define foreach_inner(item, array) \ + u4 cat(item, _index) = 0; \ + for (auto item = get(array, cat(item, _index)++); cat(item, _index) <= count(array); \ + item = get(array, cat(item, _index)++)) + + #define LIBC_WARNINGS_TEXT(name) \ + "[[>>> The " name \ + " function is part of the moonshine revamp, which means it behaves a bit differently than the libc " name \ + ". If you acknowledge this fact and you've read on how this function behaves, you may disable the revamp warnings by " \ + "defining the __MOONSHINE_LIBC_WARNINGS flag before including the moonshine library: #define " \ + "__MOONSHINE_LIBC_WARNINGS " \ + "<<<]]" + + #ifndef __MOONSHINE_LIBC_WARNINGS +__attribute__((deprecated(LIBC_WARNINGS_TEXT("strdup")))) + #endif + +__attribute__((diagnose_as_builtin(__builtin_strdup, 1))) +t(char) strdup(ctring str) { + const u8 len = strlen(str); + const auto obj = new (char, len + 1); + + for (u8 i = 0; i < len; i++) obj[ 0 ][ i ] = str[ i ]; + + obj[ 0 ][ len ] = 0; + + return obj; } -// IMPROVE -#define safe_push(type, array, ptr) \ - ({ \ - type **_array = array; \ - type _ptr = ptr; \ - unsafe_push((var *) _array, (var) & _ptr, sizeof(type)); \ - }) -#define push(array, ptr) safe_push(typeof((array)[ 0 ][ 0 ]), array, ptr) -#define address_item(__array, __index) \ - ({ \ - const auto arr = __array; \ - const u8 index = __index; \ - if (index >= count(arr)) throw("Requested index address in array exceeds the size of the array!"); \ - if (index < 0) throw("Cannot address negative offset in array!"); \ - &(arr[ 0 ][ index ]); \ - }) -#define get(__array, __index) \ - ({ \ - const auto main = __array; \ - const auto arr = main[ 0 ]; \ - const u8 __get_index = __index; \ - if (__get_index > count(main)) \ - throw("Requested index in array (", __get_index, ") exceeds the size of the array! (", count(main), ")"); \ - if (__get_index < 0) throw("Cannot access negative offset in array!"); \ - arr[ __get_index ]; \ - }) -#define count(array) ((u4) cast_index(cast_ptr(cast_ptr(cast_ptr(*array, byte, -addon_size), magic_type, 1), string, 1), u4, 1)) -#define element_size(array) \ - (u4) cast_index(cast_ptr(cast_ptr(cast_ptr(*array, byte, -addon_size), magic_type, 1), string, 1), u4, 0) -#define last(array) get(array, count(array) - 1) - -#define in , -#define foreach(...) foreach_xp(foreach_inner, (__VA_ARGS__)) -#define foreach_xp(a, b) a b -#define foreach_inner(item, array) \ - u4 cat(item, _index) = 0; \ - for (auto item = get(array, cat(item, _index)++); cat(item, _index) <= count(array); item = get(array, cat(item, _index)++)) +var *__reverse_array(var *array) { + const u4 element_size = element_size(array); + const u4 count_val = count(array); + if (count_val <= 1) return array; + byte temp[ element_size ]; + + for (u4 i = 0; i < count_val / 2; i++) { + u4 left_idx = i; + u4 right_idx = count_val - 1 - i; + + memcpy(temp, address_item(array, left_idx), element_size); + memcpy(address_item(array, left_idx), address_item(array, right_idx), element_size); + memcpy(address_item(array, right_idx), temp, element_size); + } + + return array; +} + + #define reverse_array(...) (typeof(__VA_ARGS__)) __reverse_array((var *) __VA_ARGS__) + +t(char) strndup(ctring str, u8 len) { + const auto obj = new (char, len + 1); + + for (u8 i = 0; i < len; i++) obj[ 0 ][ i ] = str[ i ]; + + obj[ 0 ][ len ] = 0; + + return obj; +} void puts_number(const int64_t number, const bool is_signed) { uint64_t n; @@ -863,13 +1012,13 @@ void puts_float(const float number) { } } -void puts_hex(const unsigned char hex) { +__attribute__((flatten)) void puts_hex(const unsigned char hex) { const char hex_chars[] = "0123456789abcdef"; putchar(hex_chars[ hex >> 4 ]); putchar(hex_chars[ hex & 0x0F ]); } -void puts_pointer(const void *ptr) { +__attribute__((flatten)) void puts_pointer(const void *ptr) { puts_static("0x"); unsigned long address = (unsigned long) ptr; @@ -963,17 +1112,9 @@ void globprint(const enum glob_type type, const char *value_text, const char *te const auto data = 243; const auto array = 247; -#define array(type) type ** -#define de(obj) (*(obj)) - -#define new(a, ...) ((a **) new_x(a __VA_OPT__(, ) __VA_ARGS__, new2, new1)(a __VA_OPT__(, ) __VA_ARGS__)) -#define new_x(a, b, c, ...) c -#define new1(type) (__new_array(#type, sizeof(type), 0)) -#define new2(type, count) (__new_array(#type, sizeof(type), count)) - string *environ; -__attribute__((noreturn)) void __moonshine_start(int argc, string *argv, string *envp) { +[[noreturn]] void __moonshine_start(int argc, string *argv, string *envp) { global_page_table = PageTable(); environ = envp; @@ -1025,26 +1166,26 @@ __attribute__((force_align_arg_pointer)) __attribute__((naked)) void _start(void typedef long ssize_t; typedef long off_t; -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 + #define SEEK_SET 0 + #define SEEK_CUR 1 + #define SEEK_END 2 -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 64 /* (0100 octal) */ -#define O_TRUNC 512 /* (01000 octal) */ -#define O_APPEND 1024 /* (02000 octal) */ + #define O_RDONLY 0 + #define O_WRONLY 1 + #define O_RDWR 2 + #define O_CREAT 64 /* (0100 octal) */ + #define O_TRUNC 512 /* (01000 octal) */ + #define O_APPEND 1024 /* (02000 octal) */ -#define DEFAULT_PERMISSIONS 0666 + #define DEFAULT_PERMISSIONS 0666 -#define AT_FDCWD (-100) + #define AT_FDCWD (-100) -#define SYS_read 0 -#define SYS_write 1 -#define SYS_close 3 -#define SYS_lseek 8 -#define SYS_openat 257 + #define SYS_read 0 + #define SYS_write 1 + #define SYS_close 3 + #define SYS_lseek 8 + #define SYS_openat 257 typedef struct FILE { int fd; @@ -1085,7 +1226,7 @@ FILE *fopen(const char *pathname, const char *mode) { FILE *file = (FILE *) alloc(sizeof(FILE)); if (!file) { - syscall2(SYS_close, fd); + (void) syscall2(SYS_close, fd); return 0; } file->fd = fd; |
