From 64f4b9192c231236ddeb10548e577ca1e3f40e9b Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 1 Nov 2021 16:59:01 +0100 Subject: Add support for immediate constants - Fixnums are tagged with a zero on the LSB. - The nil value is equal to exactly 1. - Boolean values have a 11 tag. A value of 111 is true and 011 false. --- src/compiler.h | 46 +++++++++++++++--- src/x86_64/postlude.asm | 25 ++++++++++ src/x86_64/prelude.asm | 125 ++++++++++++++++++++++++++++++------------------ 3 files changed, 143 insertions(+), 53 deletions(-) diff --git a/src/compiler.h b/src/compiler.h index 3fed075..7d6fa6b 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -5,6 +5,14 @@ #define PRELUDE_FILE "src/x86_64/prelude.asm" #define POSTLUDE_FILE "src/x86_64/postlude.asm" +#define NIL_VAL 1 +#define BOOL_MASK 3 +#define BOOL_TAG 3 +#define BOOL_SHIFT 2 +#define FIXNUM_MASK 1 +#define FIXNUM_TAG 0 +#define FIXNUM_SHIFT 1 + void compile_object(Object *obj); void compile_fixnum(Object *obj); void compile_proc_call(Object *obj); @@ -26,10 +34,27 @@ emit_file(char *file_name) { void compile_fixnum(Object *obj) { - printf(" ;; -- compile_fixnum --\n"); - printf(" mov rax, %ld\n", obj->fixnum); + printf(" ;; --> compile_fixnum\n"); + printf(" mov rax, %ld\n", (obj->fixnum << FIXNUM_SHIFT) | FIXNUM_TAG); + printf(" push rax\n"); + printf(" ;; <-- compile_fixnum\n"); +} + +void +compile_boolean(Object *obj) { + printf(" ;; --> compile_boolean\n"); + int is_true = obj->type == OBJ_TYPE_TRUE; + printf(" mov rax, %d\n", (is_true << BOOL_SHIFT) | BOOL_TAG); + printf(" push rax\n"); + printf(" ;; <-- compile_boolean\n"); +} + +void +compile_nil(void) { + printf(" ;; --> compile_nil\n"); + printf(" mov rax, %d\n", NIL_VAL); printf(" push rax\n"); - printf(" ;; --------------------\n"); + printf(" ;; <-- compile_nil\n"); } typedef enum OpType { @@ -42,9 +67,11 @@ typedef enum OpType { void arithmetic_op(OpType type) { - printf(" ;; -- arithmetic_op --\n"); + printf(" ;; --> arithmetic_op\n"); printf(" pop rcx\n"); printf(" pop rax\n"); + printf(" sar rax, %d\n", FIXNUM_SHIFT); + printf(" sar rcx, %d\n", FIXNUM_SHIFT); switch (type) { case OP_ADD: { printf(" add rax, rcx\n"); @@ -65,13 +92,15 @@ arithmetic_op(OpType type) { printf(" mov rax, rdx\n"); } break; } + // No need to add the FIXNUM_TAG here, since it's zero. + printf(" sal rax, %d\n", FIXNUM_SHIFT); printf(" push rax\n"); - printf(" ;; -------------------\n"); + printf(" ;; <-- arithmetic_op\n"); } void compile_proc_call(Object *obj) { - printf(" ;; -- compile_proc_call --\n"); + printf(" ;; --> compile_proc_call\n"); OpType op; if (sv_equal(&obj->head->text, &STRING("+"))) { op = OP_ADD;} if (sv_equal(&obj->head->text, &STRING("-"))) { op = OP_SUB;} @@ -89,12 +118,15 @@ compile_proc_call(Object *obj) { args = args->tail; arithmetic_op(op); } - printf(" ;; -----------------------\n"); + printf(" ;; <-- compile_proc_call\n"); } void compile_object(Object *obj) { switch (obj->type) { + case OBJ_TYPE_NIL: { compile_nil(); } break; + case OBJ_TYPE_TRUE: + case OBJ_TYPE_FALSE: { compile_boolean(obj); } break; case OBJ_TYPE_FIXNUM: { compile_fixnum(obj); } break; case OBJ_TYPE_PAIR: { compile_proc_call(obj); } break; default: break; diff --git a/src/x86_64/postlude.asm b/src/x86_64/postlude.asm index 139c4e1..5c8e56f 100644 --- a/src/x86_64/postlude.asm +++ b/src/x86_64/postlude.asm @@ -1,7 +1,32 @@ + +_start_return: ;; return the last value in the stack pop rdi + + ;; is nil? + mov rax, rdi + cmp rax, NIL_VAL + je exit + + ;; is boolean? + mov rax, rdi + and rax, BOOL_MASK + cmp rax, BOOL_TAG + jne not_bool + call printbool + jmp exit +not_bool: + + ;; is fixnum? + mov rax, rdi + and rax, FIXNUM_MASK + cmp rax, FIXNUM_TAG + jne not_fixnum call printdln + jmp exit +not_fixnum: +exit: ; exit syscall mov rax, 60 xor rdi, rdi diff --git a/src/x86_64/prelude.asm b/src/x86_64/prelude.asm index 788b8e9..c314ba4 100644 --- a/src/x86_64/prelude.asm +++ b/src/x86_64/prelude.asm @@ -1,56 +1,89 @@ +;; Value types. +%define NIL_VAL 1 +%define BOOL_MASK 3 +%define BOOL_TAG 3 +%define BOOL_SHIFT 2 +%define FIXNUM_MASK 1 +%define FIXNUM_TAG 0 +%define FIXNUM_SHIFT 1 + printdln: - sub rsp, 40 - mov BYTE [rsp+31], 10 - test rdi, rdi - jne .L2 - mov BYTE [rsp+30], 48 - mov eax, 30 - mov r8d, 2 + sar rdi, FIXNUM_SHIFT + sub rsp, 40 + mov BYTE [rsp+31], 10 + test rdi, rdi + jne .L2 + mov BYTE [rsp+30], 48 + mov eax, 30 + mov r8d, 2 .L3: - lea rsi, [rsp+rax] - mov rdx, r8 - ;; write syscall (Linux) - mov rdi, 1 - mov rax, 1 - syscall - add rsp, 40 - ret + lea rsi, [rsp+rax] + mov rdx, r8 + mov rdi, 1 + mov rax, 1 + syscall + add rsp, 40 + ret .L2: - mov r10d, 1 - js .L12 + mov r10d, 1 + js .L12 .L4: - mov r8d, 1 - lea r9, [rsp+31] - mov rsi, -3689348814741910323 + mov r8d, 1 + lea r9, [rsp+31] + mov rsi, -3689348814741910323 .L5: - mov rax, rdi - mov rcx, r9 - mul rsi - sub rcx, r8 - shr rdx, 3 - lea rax, [rdx+rdx*4] - add rax, rax - sub rdi, rax - mov rax, r8 - add r8, 1 - add edi, 48 - mov BYTE [rcx], dil - mov rdi, rdx - test rdx, rdx - jne .L5 - cmp r10d, -1 - jne .L10 - not r8 - mov BYTE [rsp+32+r8], 45 - lea r8, [rax+2] + mov rax, rdi + mov rcx, r9 + mul rsi + sub rcx, r8 + shr rdx, 3 + lea rax, [rdx+rdx*4] + add rax, rax + sub rdi, rax + mov rax, r8 + add r8, 1 + add edi, 48 + mov BYTE [rcx], dil + mov rdi, rdx + test rdx, rdx + jne .L5 + cmp r10d, -1 + jne .L10 + not r8 + mov BYTE [rsp+32+r8], 45 + lea r8, [rax+2] .L10: - mov eax, 32 - sub rax, r8 - jmp .L3 + mov eax, 32 + sub rax, r8 + jmp .L3 .L12: - neg rdi - mov r10d, -1 - jmp .L4 + neg rdi + mov r10d, -1 + jmp .L4 + ret + +printbool: + shr rdi, BOOL_SHIFT + cmp rdi, 0 + je print_false + mov rsi, true_str ; addr + mov rdx, 5 ; number of bytes + jmp bool_write +print_false: + mov rsi, false_str ; addr + mov rdx, 6 ; number of bytes + +bool_write: + mov rax, 1 + mov rdi, 1 + syscall + ret + +true_str: + db "true", 10 +false_str: + db "false", 10 global _start _start: + push NIL_VAL -- cgit v1.2.1