aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-11-01 16:59:01 +0100
committerBad Diode <bd@badd10de.dev>2021-11-01 16:59:01 +0100
commit64f4b9192c231236ddeb10548e577ca1e3f40e9b (patch)
treea02912deccb28307b000e9a6e2a98413395979ef
parent7418a5042471a3a7f05283d36e45b6b422d9785b (diff)
downloadbdl-64f4b9192c231236ddeb10548e577ca1e3f40e9b.tar.gz
bdl-64f4b9192c231236ddeb10548e577ca1e3f40e9b.zip
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.
-rw-r--r--src/compiler.h46
-rw-r--r--src/x86_64/postlude.asm25
-rw-r--r--src/x86_64/prelude.asm125
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 @@
5#define PRELUDE_FILE "src/x86_64/prelude.asm" 5#define PRELUDE_FILE "src/x86_64/prelude.asm"
6#define POSTLUDE_FILE "src/x86_64/postlude.asm" 6#define POSTLUDE_FILE "src/x86_64/postlude.asm"
7 7
8#define NIL_VAL 1
9#define BOOL_MASK 3
10#define BOOL_TAG 3
11#define BOOL_SHIFT 2
12#define FIXNUM_MASK 1
13#define FIXNUM_TAG 0
14#define FIXNUM_SHIFT 1
15
8void compile_object(Object *obj); 16void compile_object(Object *obj);
9void compile_fixnum(Object *obj); 17void compile_fixnum(Object *obj);
10void compile_proc_call(Object *obj); 18void compile_proc_call(Object *obj);
@@ -26,10 +34,27 @@ emit_file(char *file_name) {
26 34
27void 35void
28compile_fixnum(Object *obj) { 36compile_fixnum(Object *obj) {
29 printf(" ;; -- compile_fixnum --\n"); 37 printf(" ;; --> compile_fixnum\n");
30 printf(" mov rax, %ld\n", obj->fixnum); 38 printf(" mov rax, %ld\n", (obj->fixnum << FIXNUM_SHIFT) | FIXNUM_TAG);
39 printf(" push rax\n");
40 printf(" ;; <-- compile_fixnum\n");
41}
42
43void
44compile_boolean(Object *obj) {
45 printf(" ;; --> compile_boolean\n");
46 int is_true = obj->type == OBJ_TYPE_TRUE;
47 printf(" mov rax, %d\n", (is_true << BOOL_SHIFT) | BOOL_TAG);
48 printf(" push rax\n");
49 printf(" ;; <-- compile_boolean\n");
50}
51
52void
53compile_nil(void) {
54 printf(" ;; --> compile_nil\n");
55 printf(" mov rax, %d\n", NIL_VAL);
31 printf(" push rax\n"); 56 printf(" push rax\n");
32 printf(" ;; --------------------\n"); 57 printf(" ;; <-- compile_nil\n");
33} 58}
34 59
35typedef enum OpType { 60typedef enum OpType {
@@ -42,9 +67,11 @@ typedef enum OpType {
42 67
43void 68void
44arithmetic_op(OpType type) { 69arithmetic_op(OpType type) {
45 printf(" ;; -- arithmetic_op --\n"); 70 printf(" ;; --> arithmetic_op\n");
46 printf(" pop rcx\n"); 71 printf(" pop rcx\n");
47 printf(" pop rax\n"); 72 printf(" pop rax\n");
73 printf(" sar rax, %d\n", FIXNUM_SHIFT);
74 printf(" sar rcx, %d\n", FIXNUM_SHIFT);
48 switch (type) { 75 switch (type) {
49 case OP_ADD: { 76 case OP_ADD: {
50 printf(" add rax, rcx\n"); 77 printf(" add rax, rcx\n");
@@ -65,13 +92,15 @@ arithmetic_op(OpType type) {
65 printf(" mov rax, rdx\n"); 92 printf(" mov rax, rdx\n");
66 } break; 93 } break;
67 } 94 }
95 // No need to add the FIXNUM_TAG here, since it's zero.
96 printf(" sal rax, %d\n", FIXNUM_SHIFT);
68 printf(" push rax\n"); 97 printf(" push rax\n");
69 printf(" ;; -------------------\n"); 98 printf(" ;; <-- arithmetic_op\n");
70} 99}
71 100
72void 101void
73compile_proc_call(Object *obj) { 102compile_proc_call(Object *obj) {
74 printf(" ;; -- compile_proc_call --\n"); 103 printf(" ;; --> compile_proc_call\n");
75 OpType op; 104 OpType op;
76 if (sv_equal(&obj->head->text, &STRING("+"))) { op = OP_ADD;} 105 if (sv_equal(&obj->head->text, &STRING("+"))) { op = OP_ADD;}
77 if (sv_equal(&obj->head->text, &STRING("-"))) { op = OP_SUB;} 106 if (sv_equal(&obj->head->text, &STRING("-"))) { op = OP_SUB;}
@@ -89,12 +118,15 @@ compile_proc_call(Object *obj) {
89 args = args->tail; 118 args = args->tail;
90 arithmetic_op(op); 119 arithmetic_op(op);
91 } 120 }
92 printf(" ;; -----------------------\n"); 121 printf(" ;; <-- compile_proc_call\n");
93} 122}
94 123
95void 124void
96compile_object(Object *obj) { 125compile_object(Object *obj) {
97 switch (obj->type) { 126 switch (obj->type) {
127 case OBJ_TYPE_NIL: { compile_nil(); } break;
128 case OBJ_TYPE_TRUE:
129 case OBJ_TYPE_FALSE: { compile_boolean(obj); } break;
98 case OBJ_TYPE_FIXNUM: { compile_fixnum(obj); } break; 130 case OBJ_TYPE_FIXNUM: { compile_fixnum(obj); } break;
99 case OBJ_TYPE_PAIR: { compile_proc_call(obj); } break; 131 case OBJ_TYPE_PAIR: { compile_proc_call(obj); } break;
100 default: break; 132 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 @@
1
2_start_return:
1 ;; return the last value in the stack 3 ;; return the last value in the stack
2 pop rdi 4 pop rdi
5
6 ;; is nil?
7 mov rax, rdi
8 cmp rax, NIL_VAL
9 je exit
10
11 ;; is boolean?
12 mov rax, rdi
13 and rax, BOOL_MASK
14 cmp rax, BOOL_TAG
15 jne not_bool
16 call printbool
17 jmp exit
18not_bool:
19
20 ;; is fixnum?
21 mov rax, rdi
22 and rax, FIXNUM_MASK
23 cmp rax, FIXNUM_TAG
24 jne not_fixnum
3 call printdln 25 call printdln
26 jmp exit
27not_fixnum:
4 28
29exit:
5 ; exit syscall 30 ; exit syscall
6 mov rax, 60 31 mov rax, 60
7 xor rdi, rdi 32 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 @@
1;; Value types.
2%define NIL_VAL 1
3%define BOOL_MASK 3
4%define BOOL_TAG 3
5%define BOOL_SHIFT 2
6%define FIXNUM_MASK 1
7%define FIXNUM_TAG 0
8%define FIXNUM_SHIFT 1
9
1printdln: 10printdln:
2 sub rsp, 40 11 sar rdi, FIXNUM_SHIFT
3 mov BYTE [rsp+31], 10 12 sub rsp, 40
4 test rdi, rdi 13 mov BYTE [rsp+31], 10
5 jne .L2 14 test rdi, rdi
6 mov BYTE [rsp+30], 48 15 jne .L2
7 mov eax, 30 16 mov BYTE [rsp+30], 48
8 mov r8d, 2 17 mov eax, 30
18 mov r8d, 2
9.L3: 19.L3:
10 lea rsi, [rsp+rax] 20 lea rsi, [rsp+rax]
11 mov rdx, r8 21 mov rdx, r8
12 ;; write syscall (Linux) 22 mov rdi, 1
13 mov rdi, 1 23 mov rax, 1
14 mov rax, 1 24 syscall
15 syscall 25 add rsp, 40
16 add rsp, 40 26 ret
17 ret
18.L2: 27.L2:
19 mov r10d, 1 28 mov r10d, 1
20 js .L12 29 js .L12
21.L4: 30.L4:
22 mov r8d, 1 31 mov r8d, 1
23 lea r9, [rsp+31] 32 lea r9, [rsp+31]
24 mov rsi, -3689348814741910323 33 mov rsi, -3689348814741910323
25.L5: 34.L5:
26 mov rax, rdi 35 mov rax, rdi
27 mov rcx, r9 36 mov rcx, r9
28 mul rsi 37 mul rsi
29 sub rcx, r8 38 sub rcx, r8
30 shr rdx, 3 39 shr rdx, 3
31 lea rax, [rdx+rdx*4] 40 lea rax, [rdx+rdx*4]
32 add rax, rax 41 add rax, rax
33 sub rdi, rax 42 sub rdi, rax
34 mov rax, r8 43 mov rax, r8
35 add r8, 1 44 add r8, 1
36 add edi, 48 45 add edi, 48
37 mov BYTE [rcx], dil 46 mov BYTE [rcx], dil
38 mov rdi, rdx 47 mov rdi, rdx
39 test rdx, rdx 48 test rdx, rdx
40 jne .L5 49 jne .L5
41 cmp r10d, -1 50 cmp r10d, -1
42 jne .L10 51 jne .L10
43 not r8 52 not r8
44 mov BYTE [rsp+32+r8], 45 53 mov BYTE [rsp+32+r8], 45
45 lea r8, [rax+2] 54 lea r8, [rax+2]
46.L10: 55.L10:
47 mov eax, 32 56 mov eax, 32
48 sub rax, r8 57 sub rax, r8
49 jmp .L3 58 jmp .L3
50.L12: 59.L12:
51 neg rdi 60 neg rdi
52 mov r10d, -1 61 mov r10d, -1
53 jmp .L4 62 jmp .L4
63 ret
64
65printbool:
66 shr rdi, BOOL_SHIFT
67 cmp rdi, 0
68 je print_false
69 mov rsi, true_str ; addr
70 mov rdx, 5 ; number of bytes
71 jmp bool_write
72print_false:
73 mov rsi, false_str ; addr
74 mov rdx, 6 ; number of bytes
75
76bool_write:
77 mov rax, 1
78 mov rdi, 1
79 syscall
80 ret
81
82true_str:
83 db "true", 10
84false_str:
85 db "false", 10
54 86
55global _start 87global _start
56_start: 88_start:
89 push NIL_VAL