aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-11-01 14:30:30 +0100
committerBad Diode <bd@badd10de.dev>2021-11-01 14:30:30 +0100
commit7418a5042471a3a7f05283d36e45b6b422d9785b (patch)
tree1a041c75f8c30c0ef9adf0d14bf046344b06dc60
parente64cb7e315961d3f7772b42c2170acc2bd500a69 (diff)
downloadbdl-7418a5042471a3a7f05283d36e45b6b422d9785b.tar.gz
bdl-7418a5042471a3a7f05283d36e45b6b422d9785b.zip
Add x86_64 compilation for arithmetic expressionsv0.10
-rw-r--r--Makefile6
-rw-r--r--README.md2
-rw-r--r--src/compiler.h115
-rw-r--r--src/main.c6
-rw-r--r--src/x86_64/postlude.asm8
-rw-r--r--src/x86_64/prelude.asm56
6 files changed, 191 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index b1d8597..581dc1a 100644
--- a/Makefile
+++ b/Makefile
@@ -52,6 +52,12 @@ tests: $(BIN)
52 # ./$(BIN) examples/types.bdl | diff tests/types_expected.txt - 52 # ./$(BIN) examples/types.bdl | diff tests/types_expected.txt -
53 # ./$(BIN) examples/variables.bdl | diff tests/variables_expected.txt - 53 # ./$(BIN) examples/variables.bdl | diff tests/variables_expected.txt -
54 54
55run: $(BIN)
56 $(BIN) example.bdl > build/example.asm
57 nasm -felf64 build/example.asm -o build/example.o
58 ld build/example.o -o build/example
59 @./build/example
60
55# Remove build directory. 61# Remove build directory.
56clean: 62clean:
57 rm -rf $(BUILD_DIR) 63 rm -rf $(BUILD_DIR)
diff --git a/README.md b/README.md
index cdb30a8..b5681c8 100644
--- a/README.md
+++ b/README.md
@@ -75,6 +75,7 @@ program : <statement>* EOF
75- [An Incremental Approach to Compiler Construction][ghuloum11] 75- [An Incremental Approach to Compiler Construction][ghuloum11]
76- [Make-A-Lisp Guide][mal] 76- [Make-A-Lisp Guide][mal]
77- [An Introduction to Scheme and its Implementation][intro-to-scheme-and-imp] 77- [An Introduction to Scheme and its Implementation][intro-to-scheme-and-imp]
78- [Scheme to C][scheme-to-c]
78 79
79[sicp]: https://mitpress.mit.edu/sites/default/files/sicp/index.html 80[sicp]: https://mitpress.mit.edu/sites/default/files/sicp/index.html
80[crafting-interpreters]: https://craftinginterpreters.com/ 81[crafting-interpreters]: https://craftinginterpreters.com/
@@ -83,3 +84,4 @@ program : <statement>* EOF
83[ghuloum11]: http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf 84[ghuloum11]: http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf
84[mal]: https://github.com/kanaka/mal/blob/master/process/guide.md 85[mal]: https://github.com/kanaka/mal/blob/master/process/guide.md
85[intro-to-scheme-and-imp]: https://www.cs.utexas.edu/ftp/garbage/cs345/schintro-v14/schintro_toc.html#SEC271 86[intro-to-scheme-and-imp]: https://www.cs.utexas.edu/ftp/garbage/cs345/schintro-v14/schintro_toc.html#SEC271
87[scheme-to-c]: https://github.com/akeep/scheme-to-c
diff --git a/src/compiler.h b/src/compiler.h
new file mode 100644
index 0000000..3fed075
--- /dev/null
+++ b/src/compiler.h
@@ -0,0 +1,115 @@
1#ifndef BDL_COMPILER_H
2#define BDL_COMPILER_H
3
4
5#define PRELUDE_FILE "src/x86_64/prelude.asm"
6#define POSTLUDE_FILE "src/x86_64/postlude.asm"
7
8void compile_object(Object *obj);
9void compile_fixnum(Object *obj);
10void compile_proc_call(Object *obj);
11void compile(Root *roots);
12
13void
14emit_file(char *file_name) {
15 FILE *file = fopen(file_name, "r");
16 if (!file) {
17 fprintf(stderr, "error: couldn't open input file: %s\n", file_name);
18 exit(EXIT_FAILURE);
19 }
20 char buf[1024];
21 size_t n = 0;
22 while ((n = fread(&buf, 1, 1024, file)) > 0) {
23 fwrite(buf, 1, n, stdout);
24 }
25}
26
27void
28compile_fixnum(Object *obj) {
29 printf(" ;; -- compile_fixnum --\n");
30 printf(" mov rax, %ld\n", obj->fixnum);
31 printf(" push rax\n");
32 printf(" ;; --------------------\n");
33}
34
35typedef enum OpType {
36 OP_ADD,
37 OP_SUB,
38 OP_MUL,
39 OP_DIV,
40 OP_MOD,
41} OpType;
42
43void
44arithmetic_op(OpType type) {
45 printf(" ;; -- arithmetic_op --\n");
46 printf(" pop rcx\n");
47 printf(" pop rax\n");
48 switch (type) {
49 case OP_ADD: {
50 printf(" add rax, rcx\n");
51 } break;
52 case OP_SUB: {
53 printf(" sub rax, rcx\n");
54 } break;
55 case OP_MUL: {
56 printf(" mul rcx\n");
57 } break;
58 case OP_DIV: {
59 printf(" mov rdx, 0\n");
60 printf(" div rcx\n");
61 } break;
62 case OP_MOD: {
63 printf(" mov rdx, 0\n");
64 printf(" div rcx\n");
65 printf(" mov rax, rdx\n");
66 } break;
67 }
68 printf(" push rax\n");
69 printf(" ;; -------------------\n");
70}
71
72void
73compile_proc_call(Object *obj) {
74 printf(" ;; -- compile_proc_call --\n");
75 OpType op;
76 if (sv_equal(&obj->head->text, &STRING("+"))) { op = OP_ADD;}
77 if (sv_equal(&obj->head->text, &STRING("-"))) { op = OP_SUB;}
78 if (sv_equal(&obj->head->text, &STRING("*"))) { op = OP_MUL;}
79 if (sv_equal(&obj->head->text, &STRING("/"))) { op = OP_DIV;}
80 if (sv_equal(&obj->head->text, &STRING("%"))) { op = OP_MOD;}
81 // TODO: Resolve function call.
82 Object *args = obj->tail;
83 // TODO: capture first operand in the accumulator. Number of arguments
84 // checking should have been handled in the parser.
85 compile_object(args->head);
86 args = args->tail;
87 while (args != NULL) {
88 compile_object(args->head);
89 args = args->tail;
90 arithmetic_op(op);
91 }
92 printf(" ;; -----------------------\n");
93}
94
95void
96compile_object(Object *obj) {
97 switch (obj->type) {
98 case OBJ_TYPE_FIXNUM: { compile_fixnum(obj); } break;
99 case OBJ_TYPE_PAIR: { compile_proc_call(obj); } break;
100 default: break;
101 }
102}
103
104void
105compile(Root *roots) {
106 emit_file(PRELUDE_FILE);
107 for (size_t i = 0; i < array_size(roots); i++) {
108 Object *root = roots[i];
109 compile_object(root);
110 // OBJ_PRINT(root);
111 }
112 emit_file(POSTLUDE_FILE);
113}
114
115#endif // BDL_COMPILER_H
diff --git a/src/main.c b/src/main.c
index 6a683a7..cf4bfa4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,6 +8,7 @@
8#include "errors.c" 8#include "errors.c"
9#include "lexer.c" 9#include "lexer.c"
10#include "parser.c" 10#include "parser.c"
11#include "compiler.h"
11 12
12void 13void
13init(void) { 14init(void) {
@@ -41,9 +42,10 @@ process_source(const StringView *source, const char *file_name) {
41 } 42 }
42 array_free(tokens); 43 array_free(tokens);
43 44
44 // TODO: Semantic analysis.
45 // TODO: Optimization. 45 // TODO: Optimization.
46 // TODO: Compilation. 46
47 // Compilation.
48 compile(roots);
47 49
48 // Free resources. 50 // Free resources.
49 free_objects(); 51 free_objects();
diff --git a/src/x86_64/postlude.asm b/src/x86_64/postlude.asm
new file mode 100644
index 0000000..139c4e1
--- /dev/null
+++ b/src/x86_64/postlude.asm
@@ -0,0 +1,8 @@
1 ;; return the last value in the stack
2 pop rdi
3 call printdln
4
5 ; exit syscall
6 mov rax, 60
7 xor rdi, rdi
8 syscall
diff --git a/src/x86_64/prelude.asm b/src/x86_64/prelude.asm
new file mode 100644
index 0000000..788b8e9
--- /dev/null
+++ b/src/x86_64/prelude.asm
@@ -0,0 +1,56 @@
1printdln:
2 sub rsp, 40
3 mov BYTE [rsp+31], 10
4 test rdi, rdi
5 jne .L2
6 mov BYTE [rsp+30], 48
7 mov eax, 30
8 mov r8d, 2
9.L3:
10 lea rsi, [rsp+rax]
11 mov rdx, r8
12 ;; write syscall (Linux)
13 mov rdi, 1
14 mov rax, 1
15 syscall
16 add rsp, 40
17 ret
18.L2:
19 mov r10d, 1
20 js .L12
21.L4:
22 mov r8d, 1
23 lea r9, [rsp+31]
24 mov rsi, -3689348814741910323
25.L5:
26 mov rax, rdi
27 mov rcx, r9
28 mul rsi
29 sub rcx, r8
30 shr rdx, 3
31 lea rax, [rdx+rdx*4]
32 add rax, rax
33 sub rdi, rax
34 mov rax, r8
35 add r8, 1
36 add edi, 48
37 mov BYTE [rcx], dil
38 mov rdi, rdx
39 test rdx, rdx
40 jne .L5
41 cmp r10d, -1
42 jne .L10
43 not r8
44 mov BYTE [rsp+32+r8], 45
45 lea r8, [rax+2]
46.L10:
47 mov eax, 32
48 sub rax, r8
49 jmp .L3
50.L12:
51 neg rdi
52 mov r10d, -1
53 jmp .L4
54
55global _start
56_start: