diff options
| author | Mustafa Quraish <[email protected]> | 2022-02-07 03:07:52 -0500 |
|---|---|---|
| committer | Mustafa Quraish <[email protected]> | 2022-02-07 03:18:08 -0500 |
| commit | fad2a035cbd3194faf7b03ff7fd6e47720827ff1 (patch) | |
| tree | 2143b2e63ab6f49b169f12dc2f481b97a633b261 | |
| parent | [cup] Add support for `here` keyword + fix `putu_buffer` bug (diff) | |
| download | cup-fad2a035cbd3194faf7b03ff7fd6e47720827ff1.tar.xz cup-fad2a035cbd3194faf7b03ff7fd6e47720827ff1.zip | |
Add missing files to self-hosted directory
... Someone forgot to add them into the repo for a while.
| -rw-r--r-- | compiler/builtins.cup | 158 | ||||
| -rw-r--r-- | compiler/parser.cup | 13 | ||||
| -rw-r--r-- | compiler/types.cup | 1 | ||||
| -rw-r--r-- | std/file.cup | 99 |
4 files changed, 271 insertions, 0 deletions
diff --git a/compiler/builtins.cup b/compiler/builtins.cup new file mode 100644 index 0000000..8aae3d9 --- /dev/null +++ b/compiler/builtins.cup @@ -0,0 +1,158 @@ +import "compiler/ast.cup" +import "std/vector.cup" + +let all_builtins = vector_new(); + +fn builtin_create_syscall(name: char*, num_args: int) { + let node = node_new(AST_BUILTIN); + node.etyp = type_new(TYPE_ANY); + node.d.func.name = name; + node.d.func.args = vector_new_sized(num_args+1); // +1 for syscall number + vector_push(node.d.func.args, variable_new("val", type_new(TYPE_INT), 0)); + for (let i = 0; i < num_args; i = i + 1) { + vector_push(node.d.func.args, variable_new("arg", type_new(TYPE_ANY), 0)); + } + vector_push(all_builtins, node); +} + +// Defined in `parser.cup` +fn constant_push(name: char*, val: int); + +fn builtins_push_posix_constants() { + constant_push("SYS_read", SYS_read); + constant_push("SYS_write", SYS_write); + constant_push("SYS_exit", SYS_exit); + constant_push("SYS_open", SYS_open); + constant_push("SYS_lseek", SYS_lseek); + constant_push("SYS_openat", SYS_openat); + constant_push("SYS_close", SYS_close); + constant_push("SYS_fork", SYS_fork); + constant_push("SYS_wait4", SYS_wait4); + constant_push("SYS_mmap", SYS_mmap); + + constant_push("SEEK_SET", SEEK_SET); + constant_push("SEEK_CUR", SEEK_CUR); + constant_push("SEEK_END", SEEK_END); + + constant_push("O_RDONLY", O_RDONLY); + constant_push("O_WRONLY", O_WRONLY); + constant_push("O_RDWR", O_RDWR); + constant_push("O_CREAT", O_CREAT); + constant_push("O_EXCL", O_EXCL); + constant_push("O_TRUNC", O_TRUNC); + constant_push("AT_FDCWD", AT_FDCWD); + + constant_push("PROT_READ", PROT_READ); + constant_push("PROT_WRITE", PROT_WRITE); + constant_push("PROT_EXEC", PROT_EXEC); + constant_push("PROT_NONE", PROT_NONE); + + constant_push("MAP_SHARED", MAP_SHARED); + constant_push("MAP_PRIVATE", MAP_PRIVATE); + constant_push("MAP_ANONYMOUS", MAP_ANONYMOUS); + constant_push("MAP_FIXED", MAP_FIXED); + + constant_push("MAP_FAILED", MAP_FAILED); +} + +fn initialize_builtins() { + let node: Node*; + let var: Variable*; + + builtins_push_posix_constants(); + + constant_push("OS_IS_MACOS", OS_IS_MACOS); + constant_push("OS_IS_LINUX", OS_IS_LINUX); + + // This is very annoying to do by hand. + node = node_new(AST_BUILTIN); + node.etyp = type_new(TYPE_VOID); + node.d.func.name = "print"; + node.d.func.args = vector_new_sized(1); + vector_push(node.d.func.args, variable_new("val", type_new(TYPE_ANY), 0)); + vector_push(all_builtins, node); + + builtin_create_syscall("syscall0", 0); + builtin_create_syscall("syscall1", 1); + builtin_create_syscall("syscall2", 2); + builtin_create_syscall("syscall3", 3); + builtin_create_syscall("syscall4", 4); + builtin_create_syscall("syscall5", 5); + builtin_create_syscall("syscall6", 6); + builtin_create_syscall("syscall7", 7); +} + +fn find_builtin_function(token: Token*): Node* { + for (let i = 0; i < all_builtins.size; i = i + 1) { + let node: Node* = all_builtins.data[i]; + if (streq(node.d.func.name, token.value.as_string)) { + return node; + } + } + return null; +} + +// Defined in "compiler/codegen.c" +fn emit_asm(msg: char*); +fn emit_num(val: int); +fn generate_syscall(num: int); + +fn generate_builtins() { + emit_asm("func_print:\n"); + emit_asm(" mov rdi, [rsp+8]\n"); + emit_asm(" mov r9, -3689348814741910323\n"); + emit_asm(" sub rsp, 40\n"); + emit_asm(" mov byte [rsp+31], 10\n"); + emit_asm(" lea rcx, [rsp+30]\n"); + emit_asm(" mov qword rbx, 0\n"); + emit_asm(".L2:\n"); + emit_asm(" mov rax, rdi\n"); + emit_asm(" lea r8, [rsp+32]\n"); + emit_asm(" mul r9\n"); + emit_asm(" mov rax, rdi\n"); + emit_asm(" sub r8, rcx\n"); + emit_asm(" shr rdx, 3\n"); + emit_asm(" lea rsi, [rdx+rdx*4]\n"); + emit_asm(" add rsi, rsi\n"); + emit_asm(" sub rax, rsi\n"); + emit_asm(" add eax, 48\n"); + emit_asm(" mov byte [rcx], al\n"); + emit_asm(" mov rax, rdi\n"); + emit_asm(" mov rdi, rdx\n"); + emit_asm(" mov rdx, rcx\n"); + emit_asm(" sub rcx, 1\n"); + emit_asm(" cmp rax, 9\n"); + emit_asm(" ja .L2\n"); + emit_asm(" lea rax, [rsp+32]\n"); + emit_asm(" mov edi, 1\n"); + emit_asm(" sub rdx, rax\n"); + emit_asm(" xor eax, eax\n"); + emit_asm(" lea rsi, [rsp+32+rdx]\n"); + emit_asm(" mov rdx, r8\n"); + generate_syscall(SYS_write); + emit_asm(" add rsp, 40\n"); + emit_asm(" ret\n"); + + // Syscalls + let x86_64_sysc_regs: char*[10]; + x86_64_sysc_regs[0] = "rax"; + x86_64_sysc_regs[1] = "rdi"; + x86_64_sysc_regs[2] = "rsi"; + x86_64_sysc_regs[3] = "rdx"; + x86_64_sysc_regs[4] = "rcx"; + x86_64_sysc_regs[5] = "r8"; + x86_64_sysc_regs[6] = "r9"; + x86_64_sysc_regs[7] = "r10"; + x86_64_sysc_regs[8] = "r11"; + x86_64_sysc_regs[9] = "r12"; + + for (let sysc_args = 0; sysc_args < 7; ++sysc_args) { + emit_asm("func_syscall"); emit_num(sysc_args); emit_asm(":\n"); + for (let i = 0; i < sysc_args+1; ++i) { + emit_asm(" mov "); emit_asm(x86_64_sysc_regs[i]); + emit_asm(", [rsp+"); emit_num((i+1)*8); emit_asm("]\n"); + } + emit_asm(" syscall\n"); + emit_asm(" ret\n"); + } +}
\ No newline at end of file diff --git a/compiler/parser.cup b/compiler/parser.cup index d13a309..8f02c57 100644 --- a/compiler/parser.cup +++ b/compiler/parser.cup @@ -697,6 +697,19 @@ fn parse_var_declaration(lexer: Lexer*): Node* { add_variable_to_current_block(&decl.var); } + if (0) { + putsln("------------------"); + location_print(&token.loc); + putsln(" : Variable declared"); + puts("Name: "); + putsln(decl.var.name); + puts("Type: "); + putsln(create_type_string(decl.var.typ)); + puts("Offset: "); + putu(abs(decl.var.offset)); + putsln("\n------------------"); + } + return node; } diff --git a/compiler/types.cup b/compiler/types.cup index 2addd95..10a2d6f 100644 --- a/compiler/types.cup +++ b/compiler/types.cup @@ -132,3 +132,4 @@ fn is_struct_or_structptr(typ: Type*): int { return true; return false; } + diff --git a/std/file.cup b/std/file.cup new file mode 100644 index 0000000..91b02e7 --- /dev/null +++ b/std/file.cup @@ -0,0 +1,99 @@ +import "std/common.cup" + +const __FILE_BUFFER_CAP = 1024; + +struct File { + fd: int; + name: char*; + // Buffer + buffer: char[__FILE_BUFFER_CAP]; + buffer_size: int; +}; + +fn fopen(name: char*, mode: char): File* { + let open_mode: int; + if (mode == 'w') open_mode = O_WRONLY | O_CREAT | O_TRUNC; + else if (mode == 'r') open_mode = O_RDONLY; + else die("Unknown file open mode"); + + let f: File* = malloc(sizeof(File)); + f.name = name; + f.fd = open(name, open_mode, 438); // 438 = 0o666 + if (f.fd < 0) + die("Could not open file"); + f.buffer_size = 0; + return f; +} + +fn fflush(f: File*) { + if (f.buffer_size > 0) { + let n = write(f.fd, f.buffer, f.buffer_size); + if (n < 0) + die("Could not write to file"); + f.buffer_size = 0; + } +} + +fn fwrite(f: File*, buf: char*, size: int) { + if (f.buffer_size + size > __FILE_BUFFER_CAP) + fflush(f); + if (size > __FILE_BUFFER_CAP) { + write(f.fd, buf, size); + } else { + memcpy(f.buffer + f.buffer_size, buf, size); + f.buffer_size = f.buffer_size + size; + } +} + +fn fread(f: File*, buf: char*, size: int): int { + let n = read(f.fd, buf, size); + if (n < 0) + die("Could not read from file"); + return n; +} + +fn fclose(f: File*) { + fflush(f); + close(f.fd); +} + +fn fputs(f: File*, s: char*) { + fwrite(f, s, strlen(s)); +} + +fn fputc(f: File*, c: char) { + fwrite(f, &c, 1); +} + +fn fputu(f: File*, n: int) { + let buf: char[32]; + let len = putu_buffer(n, buf); + fwrite(f, buf, len); +} + +// Resets file position to the beginning of the file +fn fsize(f: File*): int { + let pos = lseek(f.fd, 0, SEEK_CUR); + let size = lseek(f.fd, 0, SEEK_END); + lseek(f.fd, pos, SEEK_SET); + return size; +} + +// Map file to memory and return pointer +fn fmap(f: File*, sizeptr: int*): char* { + let size = fsize(f); + let ptr = mmap(null, size, PROT_READ, MAP_PRIVATE, f.fd, 0); + if (ptr == MAP_FAILED) + die("Could not map file"); + if (sizeptr) *sizeptr = size; + return ptr; +} + +fn fread_to_string(f: File*, sizeptr: int*): char* { + let size = fsize(f); + let text: char* = malloc(size + 1); + fread(f, text, size); + text[size] = 0; + if (sizeptr) *sizeptr = size; + return text; +}
\ No newline at end of file |