diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/builtins.cup | 30 | ||||
| -rw-r--r-- | compiler/codegen.cup | 15 | ||||
| -rw-r--r-- | compiler/lexer.cup | 4 | ||||
| -rw-r--r-- | compiler/parser.cup | 2 |
4 files changed, 50 insertions, 1 deletions
diff --git a/compiler/builtins.cup b/compiler/builtins.cup index 8aae3d9..bee24e0 100644 --- a/compiler/builtins.cup +++ b/compiler/builtins.cup @@ -18,7 +18,16 @@ fn builtin_create_syscall(name: char*, num_args: int) { // Defined in `parser.cup` fn constant_push(name: char*, val: int); +const MACOS_SYSCALL_OFFSET = 33554432; // 0x2000000; fn builtins_push_posix_constants() { + + // TODO: make this permanent? + if (OS_IS_MACOS) { + constant_push("SYS_execve", 59 + MACOS_SYSCALL_OFFSET); + } else { + constant_push("SYS_execve", 59); + } + constant_push("SYS_read", SYS_read); constant_push("SYS_write", SYS_write); constant_push("SYS_exit", SYS_exit); @@ -72,6 +81,14 @@ fn initialize_builtins() { vector_push(node.d.func.args, variable_new("val", type_new(TYPE_ANY), 0)); vector_push(all_builtins, node); + // The return value of fork() is weird on macOS, parent/child is returned in rdx + // and the child pid is returned in rax, so we'll make our own wrapper. + node = node_new(AST_BUILTIN); + node.etyp = type_new(TYPE_INT); + node.d.func.name = "fork"; + node.d.func.args = vector_new_sized(0); + vector_push(all_builtins, node); + builtin_create_syscall("syscall0", 0); builtin_create_syscall("syscall1", 1); builtin_create_syscall("syscall2", 2); @@ -155,4 +172,17 @@ fn generate_builtins() { emit_asm(" syscall\n"); emit_asm(" ret\n"); } + + emit_asm("func_fork:\n"); + emit_asm(" mov rdi, [rsp+8]\n"); + emit_asm(" mov rax, "); emit_num(SYS_fork); emit_asm("\n"); + emit_asm(" syscall\n"); + if (OS_IS_MACOS) { + // If rdx is 0, we are in the child, so set rax to 0 to match Linux + emit_asm(" cmp rdx, 0\n"); + emit_asm(" je .L1\n"); + emit_asm(" mov rax, 0\n"); + emit_asm(".L1:\n"); + } + emit_asm(" ret\n"); }
\ No newline at end of file diff --git a/compiler/codegen.cup b/compiler/codegen.cup index 67a401c..bf20a8b 100644 --- a/compiler/codegen.cup +++ b/compiler/codegen.cup @@ -142,6 +142,21 @@ fn generate_expr_into_rax(node: Node*) { emit_asm(" pop rbx\n"); emit_asm(" sub rax, rbx\n"); + } else if (node.typ == AST_LSHIFT) { + generate_expr_into_rax(node.d.binary.rhs); + emit_asm(" push rax\n"); + generate_expr_into_rax(node.d.binary.lhs); + emit_asm(" pop rcx\n"); + emit_asm(" shl rax, cl\n"); + + + } else if (node.typ == AST_RSHIFT) { + generate_expr_into_rax(node.d.binary.rhs); + emit_asm(" push rax\n"); + generate_expr_into_rax(node.d.binary.lhs); + emit_asm(" pop rcx\n"); + emit_asm(" shr rax, cl\n"); + } else if (node.typ == AST_DIV) { generate_expr_into_rax(node.d.binary.rhs); emit_asm(" push rax\n"); diff --git a/compiler/lexer.cup b/compiler/lexer.cup index 9e967f8..e6d0c0b 100644 --- a/compiler/lexer.cup +++ b/compiler/lexer.cup @@ -138,12 +138,16 @@ fn lexer_next(lexer: Lexer*, token: Token*) { } else if (c == '<') { + if (lexer_peek_char(lexer, 1) == '<') + return lexer_make_token(lexer, token, TOKEN_LSHIFT, 2); if (lexer_peek_char(lexer, 1) == '=') return lexer_make_token(lexer, token, TOKEN_LEQ, 2); return lexer_make_token(lexer, token, TOKEN_LT, 1); } else if (c == '>') { + if (lexer_peek_char(lexer, 1) == '>') + return lexer_make_token(lexer, token, TOKEN_RSHIFT, 2); if (lexer_peek_char(lexer, 1) == '=') return lexer_make_token(lexer, token, TOKEN_GEQ, 2); return lexer_make_token(lexer, token, TOKEN_GT, 1); diff --git a/compiler/parser.cup b/compiler/parser.cup index d57885e..d3fa64f 100644 --- a/compiler/parser.cup +++ b/compiler/parser.cup @@ -482,7 +482,7 @@ fn parse_additive(lexer: Lexer*): Node* { let lhs = parse_term(lexer); lexer_peek(lexer, &token); - while (token.typ == TOKEN_PLUS || token.typ == TOKEN_MINUS) { + while (token.typ == TOKEN_PLUS || token.typ == TOKEN_MINUS || token.typ == TOKEN_LSHIFT || token.typ == TOKEN_RSHIFT) { lexer_next(lexer, &token); let op = node_new(binary_token_to_op(token.typ)); let rhs = parse_term(lexer); |