From 7cbef14e8393475b1e569fdbfff2c46db859d43f Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Thu, 4 Nov 2021 11:58:53 +0100 Subject: Add `cons`, `car` and `cdr` primitives --- src/compiler.h | 72 ++++++++++++++++++++++++++++++++++++++++++++----- src/parser.c | 1 + src/x86_64/postlude.asm | 4 +++ src/x86_64/prelude.asm | 7 ++++- 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/src/compiler.h b/src/compiler.h index 7323f4d..070f24a 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -5,15 +5,24 @@ #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 HEAP_SIZE MB(32) + +// Immediate constants. +#define NIL_VAL 47 +#define BOOL_MASK 127 +#define BOOL_TAG 31 +#define BOOL_SHIFT 7 #define TRUE_VAL ((1 << BOOL_SHIFT) | BOOL_TAG) #define FALSE_VAL ((0 << BOOL_SHIFT) | BOOL_TAG) -#define FIXNUM_MASK 1 +#define FIXNUM_MASK 3 #define FIXNUM_TAG 0 -#define FIXNUM_SHIFT 1 +#define FIXNUM_SHIFT 2 + +// Heap allocated objects. +#define STRING_MASK 7 +#define STRING_TAG 3 +#define PAIR_MASK 7 +#define PAIR_TAG 1 void compile_object(Object *obj); void compile_fixnum(Object *obj); @@ -268,6 +277,49 @@ compile_arithmetic_list(OpType op, Object* args) { printf(" ;; <-- compile_arithmetic\n"); } +void +compile_cons(Object *obj) { + printf(" ;; --> compile_cons\n"); + // Store objects into the car and cdr. + compile_object(obj->head); + compile_object(obj->tail->head); + printf(" pop rdx\n"); + printf(" pop rax\n"); + printf(" mov [rsi], rax\n"); + printf(" mov [rsi + 8], rdx\n"); + + // Push memory address of cons cell. + printf(" mov rax, rsi\n"); + printf(" or rax, %ld\n", PAIR_TAG); + printf(" push rax\n"); + + // Bump allocation register. + printf(" add rsi, 16\n"); + printf(" ;; <-- compile_cons\n"); +} + +void +compile_car(Object *obj) { + printf(" ;; <-- compile_car\n"); + compile_object(obj->head); + printf(" pop rax\n"); + printf(" and eax, %ld\n", ~PAIR_MASK); + printf(" mov rdx, [rax]\n"); + printf(" push rdx\n"); + printf(" ;; <-- compile_car\n"); +} + +void +compile_cdr(Object *obj) { + printf(" ;; <-- compile_cdr\n"); + compile_object(obj->head); + printf(" pop rax\n"); + printf(" and eax, %ld\n", ~PAIR_MASK); + printf(" mov rdx, [rax + 8]\n"); + printf(" push rdx\n"); + printf(" ;; <-- compile_cdr\n"); +} + void compile_proc_call(Object *obj) { // TODO: Probably we want to use a hash table for these lookups that is @@ -310,6 +362,12 @@ compile_proc_call(Object *obj) { compile_cmp_list(OP_GREATER_EQ, obj->tail); } else if (sv_equal(&obj->head->text, &STRING("<="))) { compile_cmp_list(OP_LESS_EQ, obj->tail); + } else if (sv_equal(&obj->head->text, &STRING("cons"))) { + compile_cons(obj->tail); + } else if (sv_equal(&obj->head->text, &STRING("car"))) { + compile_car(obj->tail); + } else if (sv_equal(&obj->head->text, &STRING("cdr"))) { + compile_cdr(obj->tail); } else { fprintf(stderr, "error: not implemented\n"); exit(EXIT_FAILURE); @@ -359,12 +417,12 @@ compile(Root *roots) { printf("%%define FIXNUM_MASK %d\n", FIXNUM_MASK); printf("%%define FIXNUM_TAG %d\n", FIXNUM_TAG); printf("%%define FIXNUM_SHIFT %d\n", FIXNUM_SHIFT); + printf("%%define HEAP_SIZE %ld\n", HEAP_SIZE); printf("\n"); emit_file(PRELUDE_FILE); for (size_t i = 0; i < array_size(roots); i++) { Object *root = roots[i]; compile_object(root); - // OBJ_PRINT(root); } emit_file(POSTLUDE_FILE); } diff --git a/src/parser.c b/src/parser.c index 9191aa2..5632e13 100644 --- a/src/parser.c +++ b/src/parser.c @@ -11,6 +11,7 @@ static char *builtins [] = { "not", "and", "or", "nil?", "zero?", "fixnum?", "bool?", "display", + "cons", "car", "cdr", }; uint64_t diff --git a/src/x86_64/postlude.asm b/src/x86_64/postlude.asm index 3355286..37f9df1 100644 --- a/src/x86_64/postlude.asm +++ b/src/x86_64/postlude.asm @@ -9,3 +9,7 @@ exit: mov rax, 60 xor rdi, rdi syscall + +section .bss +bdl_heap: + resb HEAP_SIZE diff --git a/src/x86_64/prelude.asm b/src/x86_64/prelude.asm index 6bb6627..e57e820 100644 --- a/src/x86_64/prelude.asm +++ b/src/x86_64/prelude.asm @@ -1,3 +1,4 @@ +section .text printdln: sar rdi, FIXNUM_SHIFT sub rsp, 40 @@ -98,4 +99,8 @@ display_end: global _start _start: - push NIL_VAL + ;; point `rdi` to the start of the heap. + mov rsi, bdl_heap + + ;; make sure the last element in the stack is the nil value. + push NIL_VAL -- cgit v1.2.1