aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-11-09 16:32:57 +0100
committerBad Diode <bd@badd10de.dev>2021-11-09 16:32:57 +0100
commit795707881285fd171c552516b11e5f7aca65f064 (patch)
treeb01b6a27b5e72abba140708c1f88bd99629846d6
parent701369bfb490596a7336415d01142fdee52d5415 (diff)
downloadbdl-795707881285fd171c552516b11e5f7aca65f064.tar.gz
bdl-795707881285fd171c552516b11e5f7aca65f064.zip
Add compilation context
This prepares the compiler for the compilation of lambdas/procedures.
-rw-r--r--src/compiler.h342
-rw-r--r--src/x86_64/prelude.asm11
2 files changed, 204 insertions, 149 deletions
diff --git a/src/compiler.h b/src/compiler.h
index 3227eba..64e6df9 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -13,6 +13,16 @@ typedef struct Constant {
13 13
14static Constant *constants = NULL; 14static Constant *constants = NULL;
15static char **labels = NULL; 15static char **labels = NULL;
16static char **procedures = NULL;
17
18static char* current_context = NULL;
19#define context_printf(fmt, ...) \
20do { \
21 char buf[KB(4)]; \
22 int n_chars = sprintf(buf, fmt, ##__VA_ARGS__); \
23 array_insert(current_context, buf, n_chars); \
24} while(false);
25
16 26
17// TODO: Separate c/h files 27// TODO: Separate c/h files
18// TODO: Create a "driver.c" file with the (display) function for external 28// TODO: Create a "driver.c" file with the (display) function for external
@@ -70,27 +80,27 @@ emit_file(char *file_name) {
70 80
71void 81void
72compile_fixnum(Object *obj) { 82compile_fixnum(Object *obj) {
73 printf(" ;; --> compile_fixnum\n"); 83 context_printf(" ;; --> compile_fixnum\n");
74 printf(" mov rax, %zu\n", (obj->fixnum << FIXNUM_SHIFT) | FIXNUM_TAG); 84 context_printf(" mov rax, %zu\n", (obj->fixnum << FIXNUM_SHIFT) | FIXNUM_TAG);
75 printf(" push rax\n"); 85 context_printf(" push rax\n");
76 printf(" ;; <-- compile_fixnum\n"); 86 context_printf(" ;; <-- compile_fixnum\n");
77} 87}
78 88
79void 89void
80compile_boolean(Object *obj) { 90compile_boolean(Object *obj) {
81 printf(" ;; --> compile_boolean\n"); 91 context_printf(" ;; --> compile_boolean\n");
82 int is_true = obj->type == OBJ_TYPE_TRUE; 92 int is_true = obj->type == OBJ_TYPE_TRUE;
83 printf(" mov rax, %zu\n", (is_true << BOOL_SHIFT) | BOOL_TAG); 93 context_printf(" mov rax, %zu\n", (is_true << BOOL_SHIFT) | BOOL_TAG);
84 printf(" push rax\n"); 94 context_printf(" push rax\n");
85 printf(" ;; <-- compile_boolean\n"); 95 context_printf(" ;; <-- compile_boolean\n");
86} 96}
87 97
88void 98void
89compile_nil(void) { 99compile_nil(void) {
90 printf(" ;; --> compile_nil\n"); 100 context_printf(" ;; --> compile_nil\n");
91 printf(" mov rax, NIL_VAL\n"); 101 context_printf(" mov rax, NIL_VAL\n");
92 printf(" push rax\n"); 102 context_printf(" push rax\n");
93 printf(" ;; <-- compile_nil\n"); 103 context_printf(" ;; <-- compile_nil\n");
94} 104}
95 105
96typedef enum OpType { 106typedef enum OpType {
@@ -115,95 +125,95 @@ typedef enum OpType {
115 125
116void 126void
117compile_type_predicate(OpType op, Object* args) { 127compile_type_predicate(OpType op, Object* args) {
118 printf(" ;; --> compile_type_predicate\n"); 128 context_printf(" ;; --> compile_type_predicate\n");
119 compile_object(args->head); 129 compile_object(args->head);
120 printf(" pop rax\n"); 130 context_printf(" pop rax\n");
121 switch (op) { 131 switch (op) {
122 case OP_IS_NIL: { 132 case OP_IS_NIL: {
123 printf(" cmp rax, NIL_VAL\n"); 133 context_printf(" cmp rax, NIL_VAL\n");
124 } break; 134 } break;
125 case OP_IS_ZERO: { 135 case OP_IS_ZERO: {
126 printf(" cmp rax, 0\n"); 136 context_printf(" cmp rax, 0\n");
127 } break; 137 } break;
128 case OP_IS_BOOL: { 138 case OP_IS_BOOL: {
129 printf(" and rax, BOOL_MASK\n"); 139 context_printf(" and rax, BOOL_MASK\n");
130 printf(" cmp rax, BOOL_TAG\n"); 140 context_printf(" cmp rax, BOOL_TAG\n");
131 } break; 141 } break;
132 case OP_IS_FIXNUM: { 142 case OP_IS_FIXNUM: {
133 printf(" and rax, FIXNUM_MASK\n"); 143 context_printf(" and rax, FIXNUM_MASK\n");
134 printf(" cmp rax, FIXNUM_TAG\n"); 144 context_printf(" cmp rax, FIXNUM_TAG\n");
135 } break; 145 } break;
136 default: break; 146 default: break;
137 } 147 }
138 printf(" mov rax, 0\n"); 148 context_printf(" mov rax, 0\n");
139 printf(" sete al\n"); 149 context_printf(" sete al\n");
140 printf(" shl rax, BOOL_SHIFT\n"); 150 context_printf(" shl rax, BOOL_SHIFT\n");
141 printf(" or rax, BOOL_TAG\n"); 151 context_printf(" or rax, BOOL_TAG\n");
142 printf(" push rax\n"); 152 context_printf(" push rax\n");
143 printf(" ;; <-- compile_type_predicate\n"); 153 context_printf(" ;; <-- compile_type_predicate\n");
144} 154}
145 155
146void 156void
147compile_not(Object* args) { 157compile_not(Object* args) {
148 printf(" ;; --> compile_not\n"); 158 context_printf(" ;; --> compile_not\n");
149 compile_object(args->head); 159 compile_object(args->head);
150 printf(" pop rax\n"); 160 context_printf(" pop rax\n");
151 printf(" cmp rax, FALSE_VAL\n"); 161 context_printf(" cmp rax, FALSE_VAL\n");
152 printf(" mov rax, 0\n"); 162 context_printf(" mov rax, 0\n");
153 printf(" sete al\n"); 163 context_printf(" sete al\n");
154 printf(" shl rax, BOOL_SHIFT\n"); 164 context_printf(" shl rax, BOOL_SHIFT\n");
155 printf(" or rax, BOOL_TAG\n"); 165 context_printf(" or rax, BOOL_TAG\n");
156 printf(" push rax\n"); 166 context_printf(" push rax\n");
157 printf(" ;; <-- compile_not\n"); 167 context_printf(" ;; <-- compile_not\n");
158} 168}
159 169
160void 170void
161compile_and(Object *args) { 171compile_and(Object *args) {
162 printf(" ;; --> compile_and\n"); 172 context_printf(" ;; --> compile_and\n");
163 char *lab_false = generate_label("BDLL"); 173 char *lab_false = generate_label("BDLL");
164 char *lab_exit = generate_label("BDLL"); 174 char *lab_exit = generate_label("BDLL");
165 while (args != NULL) { 175 while (args != NULL) {
166 compile_object(args->head); 176 compile_object(args->head);
167 args = args->tail; 177 args = args->tail;
168 printf(" pop rax\n"); 178 context_printf(" pop rax\n");
169 printf(" cmp rax, FALSE_VAL\n"); 179 context_printf(" cmp rax, FALSE_VAL\n");
170 printf(" je %s\n", lab_false); 180 context_printf(" je %s\n", lab_false);
171 } 181 }
172 printf(" mov rax, TRUE_VAL\n"); 182 context_printf(" mov rax, TRUE_VAL\n");
173 printf(" push rax\n"); 183 context_printf(" push rax\n");
174 printf(" jmp %s\n", lab_exit); 184 context_printf(" jmp %s\n", lab_exit);
175 printf("%s:\n", lab_false); 185 context_printf("%s:\n", lab_false);
176 printf(" mov rax, FALSE_VAL\n"); 186 context_printf(" mov rax, FALSE_VAL\n");
177 printf(" push rax\n"); 187 context_printf(" push rax\n");
178 printf("%s:\n", lab_exit); 188 context_printf("%s:\n", lab_exit);
179 printf(" ;; <-- compile_and\n"); 189 context_printf(" ;; <-- compile_and\n");
180} 190}
181 191
182void 192void
183compile_or(Object *args) { 193compile_or(Object *args) {
184 printf(" ;; --> compile_or\n"); 194 context_printf(" ;; --> compile_or\n");
185 char *lab_true = generate_label("BDLL"); 195 char *lab_true = generate_label("BDLL");
186 char *lab_exit = generate_label("BDLL"); 196 char *lab_exit = generate_label("BDLL");
187 while (args != NULL) { 197 while (args != NULL) {
188 compile_object(args->head); 198 compile_object(args->head);
189 args = args->tail; 199 args = args->tail;
190 printf(" pop rax\n"); 200 context_printf(" pop rax\n");
191 printf(" cmp rax, FALSE_VAL\n"); 201 context_printf(" cmp rax, FALSE_VAL\n");
192 printf(" jne %s\n", lab_true); 202 context_printf(" jne %s\n", lab_true);
193 } 203 }
194 printf(" mov rax, FALSE_VAL\n"); 204 context_printf(" mov rax, FALSE_VAL\n");
195 printf(" push rax\n"); 205 context_printf(" push rax\n");
196 printf(" jmp %s\n", lab_exit); 206 context_printf(" jmp %s\n", lab_exit);
197 printf("%s:\n", lab_true); 207 context_printf("%s:\n", lab_true);
198 printf(" mov rax, TRUE_VAL\n"); 208 context_printf(" mov rax, TRUE_VAL\n");
199 printf(" push rax\n"); 209 context_printf(" push rax\n");
200 printf("%s:\n", lab_exit); 210 context_printf("%s:\n", lab_exit);
201 printf(" ;; <-- compile_or\n"); 211 context_printf(" ;; <-- compile_or\n");
202} 212}
203 213
204void 214void
205compile_cmp_list(OpType op, Object* args) { 215compile_cmp_list(OpType op, Object* args) {
206 printf(" ;; --> compile_cmp_list\n"); 216 context_printf(" ;; --> compile_cmp_list\n");
207 compile_object(args->head); 217 compile_object(args->head);
208 char *lab_false = generate_label("BDLL"); 218 char *lab_false = generate_label("BDLL");
209 char *lab_exit = generate_label("BDLL"); 219 char *lab_exit = generate_label("BDLL");
@@ -213,116 +223,116 @@ compile_cmp_list(OpType op, Object* args) {
213 args = args->tail; 223 args = args->tail;
214 224
215 // Current value. 225 // Current value.
216 printf(" pop rcx\n"); 226 context_printf(" pop rcx\n");
217 227
218 // Previous value. 228 // Previous value.
219 printf(" pop rax\n"); 229 context_printf(" pop rax\n");
220 230
221 // Comparison. 231 // Comparison.
222 printf(" cmp rax, rcx\n"); 232 context_printf(" cmp rax, rcx\n");
223 switch (op) { 233 switch (op) {
224 case OP_EQUAL: { printf(" jne %s\n", lab_false); } break; 234 case OP_EQUAL: { context_printf(" jne %s\n", lab_false); } break;
225 case OP_GREATER: { printf(" jle %s\n", lab_false); } break; 235 case OP_GREATER: { context_printf(" jle %s\n", lab_false); } break;
226 case OP_LESS: { printf(" jge %s\n", lab_false); } break; 236 case OP_LESS: { context_printf(" jge %s\n", lab_false); } break;
227 case OP_GREATER_EQ: { printf(" jl %s\n", lab_false); } break; 237 case OP_GREATER_EQ: { context_printf(" jl %s\n", lab_false); } break;
228 case OP_LESS_EQ: { printf(" jg %s\n", lab_false); } break; 238 case OP_LESS_EQ: { context_printf(" jg %s\n", lab_false); } break;
229 default: break; 239 default: break;
230 } 240 }
231 printf(" push rcx\n"); 241 context_printf(" push rcx\n");
232 } 242 }
233 printf(" pop rcx\n"); 243 context_printf(" pop rcx\n");
234 printf(" mov rax, TRUE_VAL\n"); 244 context_printf(" mov rax, TRUE_VAL\n");
235 printf(" push rax\n"); 245 context_printf(" push rax\n");
236 printf(" jmp %s\n", lab_exit); 246 context_printf(" jmp %s\n", lab_exit);
237 printf("%s:\n", lab_false); 247 context_printf("%s:\n", lab_false);
238 printf(" mov rax, FALSE_VAL\n"); 248 context_printf(" mov rax, FALSE_VAL\n");
239 printf(" push rax\n"); 249 context_printf(" push rax\n");
240 printf("%s:\n", lab_exit); 250 context_printf("%s:\n", lab_exit);
241 printf(" ;; <-- compile_cmp_list\n"); 251 context_printf(" ;; <-- compile_cmp_list\n");
242} 252}
243 253
244void 254void
245compile_arithmetic_list(OpType op, Object* args) { 255compile_arithmetic_list(OpType op, Object* args) {
246 printf(" ;; --> compile_arithmetic\n"); 256 context_printf(" ;; --> compile_arithmetic\n");
247 compile_object(args->head); 257 compile_object(args->head);
248 args = args->tail; 258 args = args->tail;
249 while (args != NULL) { 259 while (args != NULL) {
250 compile_object(args->head); 260 compile_object(args->head);
251 args = args->tail; 261 args = args->tail;
252 printf(" pop rcx\n"); 262 context_printf(" pop rcx\n");
253 printf(" pop rax\n"); 263 context_printf(" pop rax\n");
254 switch (op) { 264 switch (op) {
255 case OP_ADD: { printf(" add rax, rcx\n"); } break; 265 case OP_ADD: { context_printf(" add rax, rcx\n"); } break;
256 case OP_SUB: { printf(" sub rax, rcx\n"); } break; 266 case OP_SUB: { context_printf(" sub rax, rcx\n"); } break;
257 case OP_MUL: { 267 case OP_MUL: {
258 printf(" sar rax, FIXNUM_SHIFT\n"); 268 context_printf(" sar rax, FIXNUM_SHIFT\n");
259 printf(" sar rcx, FIXNUM_SHIFT\n"); 269 context_printf(" sar rcx, FIXNUM_SHIFT\n");
260 printf(" mul rcx\n"); 270 context_printf(" mul rcx\n");
261 printf(" shl rax, FIXNUM_SHIFT\n"); 271 context_printf(" shl rax, FIXNUM_SHIFT\n");
262 } break; 272 } break;
263 case OP_DIV: { 273 case OP_DIV: {
264 printf(" sar rax, FIXNUM_SHIFT\n"); 274 context_printf(" sar rax, FIXNUM_SHIFT\n");
265 printf(" sar rcx, FIXNUM_SHIFT\n"); 275 context_printf(" sar rcx, FIXNUM_SHIFT\n");
266 printf(" mov rdx, 0\n"); 276 context_printf(" mov rdx, 0\n");
267 printf(" div rcx\n"); 277 context_printf(" div rcx\n");
268 printf(" shl rax, FIXNUM_SHIFT\n"); 278 context_printf(" shl rax, FIXNUM_SHIFT\n");
269 } break; 279 } break;
270 case OP_MOD: { 280 case OP_MOD: {
271 printf(" sar rax, FIXNUM_SHIFT\n"); 281 context_printf(" sar rax, FIXNUM_SHIFT\n");
272 printf(" sar rcx, FIXNUM_SHIFT\n"); 282 context_printf(" sar rcx, FIXNUM_SHIFT\n");
273 printf(" mov rdx, 0\n"); 283 context_printf(" mov rdx, 0\n");
274 printf(" div rcx\n"); 284 context_printf(" div rcx\n");
275 printf(" mov rax, rdx\n"); 285 context_printf(" mov rax, rdx\n");
276 printf(" shl rax, FIXNUM_SHIFT\n"); 286 context_printf(" shl rax, FIXNUM_SHIFT\n");
277 } break; 287 } break;
278 default: break; 288 default: break;
279 } 289 }
280 printf(" push rax\n"); 290 context_printf(" push rax\n");
281 } 291 }
282 printf(" ;; <-- compile_arithmetic\n"); 292 context_printf(" ;; <-- compile_arithmetic\n");
283} 293}
284 294
285void 295void
286compile_cons(Object *obj) { 296compile_cons(Object *obj) {
287 printf(" ;; --> compile_cons\n"); 297 context_printf(" ;; --> compile_cons\n");
288 // Store objects into the car and cdr. 298 // Store objects into the car and cdr.
289 compile_object(obj->head); 299 compile_object(obj->head);
290 compile_object(obj->tail->head); 300 compile_object(obj->tail->head);
291 printf(" pop rdx\n"); 301 context_printf(" pop rdx\n");
292 printf(" pop rax\n"); 302 context_printf(" pop rax\n");
293 printf(" mov [r15], rax\n"); 303 context_printf(" mov [r15], rax\n");
294 printf(" mov [r15 + 8], rdx\n"); 304 context_printf(" mov [r15 + 8], rdx\n");
295 305
296 // Push memory address of cons cell. 306 // Push memory address of cons cell.
297 printf(" mov rax, r15\n"); 307 context_printf(" mov rax, r15\n");
298 printf(" or rax, %zu\n", PAIR_TAG); 308 context_printf(" or rax, %zu\n", PAIR_TAG);
299 printf(" push rax\n"); 309 context_printf(" push rax\n");
300 310
301 // Bump allocation register. 311 // Bump allocation register.
302 printf(" add r15, 16\n"); 312 context_printf(" add r15, 16\n");
303 printf(" ;; <-- compile_cons\n"); 313 context_printf(" ;; <-- compile_cons\n");
304} 314}
305 315
306void 316void
307compile_car(Object *obj) { 317compile_car(Object *obj) {
308 printf(" ;; --> compile_car\n"); 318 context_printf(" ;; --> compile_car\n");
309 compile_object(obj->head); 319 compile_object(obj->head);
310 printf(" pop rax\n"); 320 context_printf(" pop rax\n");
311 printf(" and rax, %zu\n", ~PAIR_MASK); 321 context_printf(" and rax, %zu\n", ~PAIR_MASK);
312 printf(" mov rdx, [rax]\n"); 322 context_printf(" mov rdx, [rax]\n");
313 printf(" push rdx\n"); 323 context_printf(" push rdx\n");
314 printf(" ;; <-- compile_car\n"); 324 context_printf(" ;; <-- compile_car\n");
315} 325}
316 326
317void 327void
318compile_cdr(Object *obj) { 328compile_cdr(Object *obj) {
319 printf(" ;; --> compile_cdr\n"); 329 context_printf(" ;; --> compile_cdr\n");
320 compile_object(obj->head); 330 compile_object(obj->head);
321 printf(" pop rax\n"); 331 context_printf(" pop rax\n");
322 printf(" and rax, %zu\n", ~PAIR_MASK); 332 context_printf(" and rax, %zu\n", ~PAIR_MASK);
323 printf(" mov rdx, [rax + 8]\n"); 333 context_printf(" mov rdx, [rax + 8]\n");
324 printf(" push rdx\n"); 334 context_printf(" push rdx\n");
325 printf(" ;; <-- compile_cdr\n"); 335 context_printf(" ;; <-- compile_cdr\n");
326} 336}
327 337
328void 338void
@@ -349,8 +359,8 @@ compile_proc_call(Object *obj) {
349 compile_type_predicate(OP_IS_BOOL, obj->tail); 359 compile_type_predicate(OP_IS_BOOL, obj->tail);
350 } else if (sv_equal(&obj->head->text, &STRING("display"))) { 360 } else if (sv_equal(&obj->head->text, &STRING("display"))) {
351 compile_object(obj->tail->head); 361 compile_object(obj->tail->head);
352 printf(" pop rdi\n"); 362 context_printf(" pop rdi\n");
353 printf(" call display\n"); 363 context_printf(" call display\n");
354 } else if (sv_equal(&obj->head->text, &STRING("not"))) { 364 } else if (sv_equal(&obj->head->text, &STRING("not"))) {
355 compile_not(obj->tail); 365 compile_not(obj->tail);
356 } else if (sv_equal(&obj->head->text, &STRING("and"))) { 366 } else if (sv_equal(&obj->head->text, &STRING("and"))) {
@@ -383,24 +393,24 @@ void
383compile_if(Object *obj) { 393compile_if(Object *obj) {
384 char *lab_false = generate_label("BDLL"); 394 char *lab_false = generate_label("BDLL");
385 compile_object(obj->condition); 395 compile_object(obj->condition);
386 printf(" pop rax\n"); 396 context_printf(" pop rax\n");
387 printf(" cmp rax, FALSE_VAL\n"); 397 context_printf(" cmp rax, FALSE_VAL\n");
388 printf(" je %s\n", lab_false); 398 context_printf(" je %s\n", lab_false);
389 compile_object(obj->expr_true); 399 compile_object(obj->expr_true);
390 if (obj->expr_false != NULL) { 400 if (obj->expr_false != NULL) {
391 char *lab_exit = generate_label("BDLL"); 401 char *lab_exit = generate_label("BDLL");
392 printf(" jmp %s\n", lab_exit); 402 context_printf(" jmp %s\n", lab_exit);
393 printf("%s:\n", lab_false); 403 context_printf("%s:\n", lab_false);
394 compile_object(obj->expr_false); 404 compile_object(obj->expr_false);
395 printf("%s:\n", lab_exit); 405 context_printf("%s:\n", lab_exit);
396 } else { 406 } else {
397 printf("%s:\n", lab_false); 407 context_printf("%s:\n", lab_false);
398 } 408 }
399} 409}
400 410
401void 411void
402compile_string(Object *obj) { 412compile_string(Object *obj) {
403 printf(" ;; --> compile_string\n"); 413 context_printf(" ;; --> compile_string\n");
404 Constant c; 414 Constant c;
405 415
406 // Check if the string is already stored as a constant. 416 // Check if the string is already stored as a constant.
@@ -422,10 +432,33 @@ compile_string(Object *obj) {
422 } 432 }
423 433
424 // Create a tagged pointer to the label. 434 // Create a tagged pointer to the label.
425 printf(" mov rax, %s\n", c.label); 435 context_printf(" mov rax, %s\n", c.label);
426 printf(" or rax, STRING_TAG\n"); 436 context_printf(" or rax, STRING_TAG\n");
427 printf(" push rax\n"); 437 context_printf(" push rax\n");
428 printf(" ;; <-- compile_string\n"); 438 context_printf(" ;; <-- compile_string\n");
439}
440
441void
442compile_lambda(Object *obj) {
443 // Create a new compilation context.
444 char *prev_context = current_context;
445 current_context = NULL;
446 array_init(current_context, 0);
447
448 char *name = generate_label("BDLP");
449 context_printf("%s:\n", name);
450 for (size_t i = 0; i < array_size(obj->body); i++) {
451 compile_object(obj->body[i]);
452 }
453 context_printf(" ret\n");
454 context_printf("\n");
455
456 // Restore previous compilation context.
457 array_push(procedures, current_context);
458 current_context = prev_context;
459
460 // TODO: Create tagged pointer with this lambda procedure.
461 // TODO: Push compiled object to the stack.
429} 462}
430 463
431void 464void
@@ -438,6 +471,7 @@ compile_object(Object *obj) {
438 case OBJ_TYPE_PAIR: { compile_proc_call(obj); } break; 471 case OBJ_TYPE_PAIR: { compile_proc_call(obj); } break;
439 case OBJ_TYPE_STRING: { compile_string(obj); } break; 472 case OBJ_TYPE_STRING: { compile_string(obj); } break;
440 case OBJ_TYPE_IF: { compile_if(obj); } break; 473 case OBJ_TYPE_IF: { compile_if(obj); } break;
474 case OBJ_TYPE_LAMBDA: { compile_lambda(obj); } break;
441 default: break; 475 default: break;
442 } 476 }
443} 477}
@@ -478,8 +512,16 @@ compile(Root *roots) {
478 // Prepare compilation variables. 512 // Prepare compilation variables.
479 array_init(constants, 0); 513 array_init(constants, 0);
480 array_init(labels, 0); 514 array_init(labels, 0);
515 array_init(procedures, 0);
516 array_init(current_context, 0);
481 517
482 // Prelude. 518 // Compile program.
519 for (size_t i = 0; i < array_size(roots); i++) {
520 Object *root = roots[i];
521 compile_object(root);
522 }
523
524 // Base defines.
483 printf("%%define NIL_VAL %zu\n", NIL_VAL); 525 printf("%%define NIL_VAL %zu\n", NIL_VAL);
484 printf("%%define TRUE_VAL %zu\n", TRUE_VAL); 526 printf("%%define TRUE_VAL %zu\n", TRUE_VAL);
485 printf("%%define FALSE_VAL %zu\n", FALSE_VAL); 527 printf("%%define FALSE_VAL %zu\n", FALSE_VAL);
@@ -496,12 +538,26 @@ compile(Root *roots) {
496 printf("%%define STRING_TAG %zu\n", STRING_TAG); 538 printf("%%define STRING_TAG %zu\n", STRING_TAG);
497 printf("%%define HEAP_SIZE %zu\n", HEAP_SIZE); 539 printf("%%define HEAP_SIZE %zu\n", HEAP_SIZE);
498 printf("\n"); 540 printf("\n");
541
542 // Prelude.
499 emit_file(PRELUDE_FILE); 543 emit_file(PRELUDE_FILE);
544 printf("\n");
500 545
501 // Compile program. 546 // Function definitions.
502 for (size_t i = 0; i < array_size(roots); i++) { 547 for (size_t i = 0; i < array_size(procedures); i++) {
503 Object *root = roots[i]; 548 char *ctx = procedures[i];
504 compile_object(root); 549 for (size_t i = 0; i < array_size(ctx); i++) {
550 putchar(ctx[i]);
551 }
552 }
553
554 // Main context.
555 printf("global _start\n");
556 printf("_start:\n");
557 printf(" mov r15, bdl_heap\n");
558 printf(" push NIL_VAL\n");
559 for (size_t i = 0; i < array_size(current_context); i++) {
560 putchar(current_context[i]);
505 } 561 }
506 562
507 // Postlude. 563 // Postlude.
@@ -515,6 +571,10 @@ compile(Root *roots) {
515 free(labels[i]); 571 free(labels[i]);
516 } 572 }
517 array_free(labels); 573 array_free(labels);
574 for (size_t i = 0; i < array_size(procedures); i++) {
575 array_free(procedures[i]);
576 }
577 array_free(procedures);
518} 578}
519 579
520#endif // BDL_COMPILER_H 580#endif // BDL_COMPILER_H
diff --git a/src/x86_64/prelude.asm b/src/x86_64/prelude.asm
index c9ef823..05762b9 100644
--- a/src/x86_64/prelude.asm
+++ b/src/x86_64/prelude.asm
@@ -108,14 +108,9 @@ not_string:
108 108
109 ;; is fixnum? 109 ;; is fixnum?
110 mov rax, rdi 110 mov rax, rdi
111 and rax, FIXNUM_MASK
112 cmp rax, FIXNUM_TAG
113 jne display_end
111 call printdln 114 call printdln
112display_end: 115display_end:
113 ret 116 ret
114
115global _start
116_start:
117 ;; point `rdi` to the start of the heap.
118 mov r15, bdl_heap
119
120 ;; make sure the last element in the stack is the nil value.
121 push NIL_VAL