aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Moon Flower <moon@coffin.ir> 2025-02-26 12:16:34 +0330
committerGravatar Moon Flower <moon@coffin.ir> 2025-02-26 12:16:34 +0330
commit93d17188c89a9197a2cb0bdad4d5ca9ac3be4461 (patch)
treebdbd50206f87ea00a124c94b29398f9037f3014a
parentAdded foreach (diff)
a few fixes and changes
-rw-r--r--Makefile2
-rw-r--r--main.c16
-rw-r--r--moonshine.h777
3 files changed, 469 insertions, 326 deletions
diff --git a/Makefile b/Makefile
index e785055..323ab9e 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/main.c b/main.c
index 3952bd7..b01452e 100644
--- a/main.c
+++ b/main.c
@@ -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;