diff options
| author | Mustafa Quraish <[email protected]> | 2022-02-04 06:16:18 -0500 |
|---|---|---|
| committer | Mustafa Quraish <[email protected]> | 2022-02-05 08:56:15 -0500 |
| commit | 8fd0a145947011f113abaab245e35f1adfb6eb48 (patch) | |
| tree | 957bcf38c33d697c2fe5dd997bc294ae28adcaec /src/builtins.c | |
| parent | Update README.md (diff) | |
| download | cup-8fd0a145947011f113abaab245e35f1adfb6eb48.tar.xz cup-8fd0a145947011f113abaab245e35f1adfb6eb48.zip | |
Allow `builtins.c` to inject constants into program, use for syscalls
We can now directly expose the `syscallN()` APIs to the program and
define the `open()`, `write()` etc syscalls in the stdlib. This
simplifies the implementation a decent bunch :^)
Diffstat (limited to 'src/builtins.c')
| -rw-r--r-- | src/builtins.c | 105 |
1 files changed, 57 insertions, 48 deletions
diff --git a/src/builtins.c b/src/builtins.c index 45f203d..97ac9ee 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -2,8 +2,10 @@ #include "ast.h" #include "utils.h" #include "generator.h" +#include "parser.h" #include <string.h> #include <stdlib.h> +#include <fcntl.h> #include <assert.h> #include <stdarg.h> #include <sys/syscall.h> @@ -12,47 +14,32 @@ static Node *custom_builtins[MAX_CUSTOM_BUILTIN_COUNT]; static i64 custom_builtins_count = 0; -#define MAX_SYSCALL_BUILTIN_COUNT 256 -static Node *syscall_builtins[MAX_SYSCALL_BUILTIN_COUNT]; -static i64 syscall_builtins_count = 0; - static void push_builtin(Node *node) { assert(custom_builtins_count < MAX_CUSTOM_BUILTIN_COUNT); custom_builtins[custom_builtins_count++] = node; } -static void make_syscall(int num_args, i64 syscall_num, char *name, Type *return_type, ...) -{ - Node *node = Node_new(AST_BUILTIN); +static void push_syscall_builtin(char *name, int num_args) { + Node *node; + node = Node_new(AST_BUILTIN); node->func.name = name; - node->func.return_type = return_type; - node->func.num_args = num_args; - node->func.args = calloc(sizeof(Variable), num_args); - - // This is a hack to get around the fact that we can't pass a variable - // Luckily, we don't actually use this field for the builtins anyway. - node->func.max_locals_size = syscall_num; - - va_list ap; - va_start(ap, return_type); - for (i64 i = 0; i < num_args; i++) - { - Type *typ = va_arg(ap, Type *); - if (!typ) { - fprintf(stderr, "Error: Builtin %s has no type for argument %lld\n", name, i); - exit(1); - } - node->func.args[i] = (Variable){"arg", typ, 0}; + node->func.return_type = type_new(TYPE_INT); + node->func.num_args = num_args+1; + node->func.args = (Variable *)calloc(sizeof(Variable), num_args+1); + node->func.args[0] = (Variable){"syscall_num", type_new(TYPE_INT), 0}; + for (int i = 0; i < num_args; i++) { + node->func.args[i+1].type = type_new(TYPE_ANY); } - va_end(ap); - - assert(syscall_builtins_count < MAX_SYSCALL_BUILTIN_COUNT); - syscall_builtins[syscall_builtins_count++] = node; + push_builtin(node); } +void push_posix_constants(); + void initialize_builtins() { + push_posix_constants(); + Node *node; // FIXME: The `TYPE_ANY` is a hack node = Node_new(AST_BUILTIN); @@ -63,15 +50,14 @@ void initialize_builtins() node->func.args[0] = (Variable){"val", type_new(TYPE_ANY), 0}; push_builtin(node); - make_syscall(3, SYS_write, "write", type_new(TYPE_INT), - type_new(TYPE_INT), type_new_ptr(TYPE_CHAR), type_new(TYPE_INT) // Args - ); - make_syscall(3, SYS_read, "read", type_new(TYPE_INT), - type_new(TYPE_INT), type_new_ptr(TYPE_CHAR), type_new(TYPE_INT) // Args - ); - make_syscall(1, SYS_exit, "exit", type_new(TYPE_NONE), - type_new(TYPE_INT) // Args - ); + push_syscall_builtin("syscall0", 0); + push_syscall_builtin("syscall1", 1); + push_syscall_builtin("syscall2", 2); + push_syscall_builtin("syscall3", 3); + push_syscall_builtin("syscall4", 4); + push_syscall_builtin("syscall5", 5); + push_syscall_builtin("syscall6", 6); + push_syscall_builtin("syscall7", 7); } Node *find_builtin_function(Token *token) @@ -80,25 +66,20 @@ Node *find_builtin_function(Token *token) if (strcmp(custom_builtins[i]->func.name, token->value.as_string) == 0) return custom_builtins[i]; } - for (i64 i = 0; i < syscall_builtins_count; i++) { - if (strcmp(syscall_builtins[i]->func.name, token->value.as_string) == 0) - return syscall_builtins[i]; - } return NULL; } char *x86_64_syscall_regs[10] = { - "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13" + "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11", "r12" }; static void generate_syscall_builtins(FILE *out) { - for (i64 i = 0; i < syscall_builtins_count; i++) { - Node *node = syscall_builtins[i]; - fprintf(out, "func_%s:\n", node->func.name); - for (i64 i = 0; i < node->func.num_args; i++) + for (i64 sysc_args = 0; sysc_args < 7; sysc_args++) { + fprintf(out, "func_syscall%lld:\n", sysc_args); + for (i64 i = 0; i < sysc_args+1; i++) fprintf(out, " mov %s, [rsp+%lld]\n", x86_64_syscall_regs[i], (i+1) * 8); - generate_syscall(node->func.max_locals_size, out); + fprintf(out, " syscall\n"); fprintf(out, " ret\n"); } } @@ -149,4 +130,32 @@ void generate_builtins(FILE *out) { generate_custom_builtins(out); generate_syscall_builtins(out); +} + + +#define PUSH_SYS_(name) push_constant("SYS_" #name, get_syscall_num(SYS_##name)) +#define PUSH(name) push_constant(#name, name) + +void push_posix_constants() +{ + PUSH_SYS_(read); + PUSH_SYS_(write); + PUSH_SYS_(exit); + PUSH_SYS_(open); + PUSH_SYS_(openat); + PUSH_SYS_(close); + PUSH_SYS_(fork); + PUSH_SYS_(wait4); + + PUSH(SEEK_SET); + PUSH(SEEK_CUR); + PUSH(SEEK_END); + + PUSH(O_RDONLY); + PUSH(O_WRONLY); + PUSH(O_RDWR); + PUSH(O_CREAT); + PUSH(O_EXCL); + PUSH(O_TRUNC); + PUSH(AT_FDCWD); }
\ No newline at end of file |