diff options
-rw-r--r-- | src/compiler.h | 46 | ||||
-rw-r--r-- | src/x86_64/postlude.asm | 25 | ||||
-rw-r--r-- | 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 @@ | |||
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 | |||
8 | void compile_object(Object *obj); | 16 | void compile_object(Object *obj); |
9 | void compile_fixnum(Object *obj); | 17 | void compile_fixnum(Object *obj); |
10 | void compile_proc_call(Object *obj); | 18 | void compile_proc_call(Object *obj); |
@@ -26,10 +34,27 @@ emit_file(char *file_name) { | |||
26 | 34 | ||
27 | void | 35 | void |
28 | compile_fixnum(Object *obj) { | 36 | compile_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 | |||
43 | void | ||
44 | compile_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 | |||
52 | void | ||
53 | compile_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 | ||
35 | typedef enum OpType { | 60 | typedef enum OpType { |
@@ -42,9 +67,11 @@ typedef enum OpType { | |||
42 | 67 | ||
43 | void | 68 | void |
44 | arithmetic_op(OpType type) { | 69 | arithmetic_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 | ||
72 | void | 101 | void |
73 | compile_proc_call(Object *obj) { | 102 | compile_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 | ||
95 | void | 124 | void |
96 | compile_object(Object *obj) { | 125 | compile_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 | ||
18 | not_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 | ||
27 | not_fixnum: | ||
4 | 28 | ||
29 | exit: | ||
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 | |||
1 | printdln: | 10 | printdln: |
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 | |||
65 | printbool: | ||
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 | ||
72 | print_false: | ||
73 | mov rsi, false_str ; addr | ||
74 | mov rdx, 6 ; number of bytes | ||
75 | |||
76 | bool_write: | ||
77 | mov rax, 1 | ||
78 | mov rdi, 1 | ||
79 | syscall | ||
80 | ret | ||
81 | |||
82 | true_str: | ||
83 | db "true", 10 | ||
84 | false_str: | ||
85 | db "false", 10 | ||
54 | 86 | ||
55 | global _start | 87 | global _start |
56 | _start: | 88 | _start: |
89 | push NIL_VAL | ||