aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-11-17 10:23:44 +0100
committerBad Diode <bd@badd10de.dev>2021-11-17 10:23:44 +0100
commit9c5fb457fe6063b7545515397aa45cecb7af66bf (patch)
treec4fc34912b4bb490063f6c7ebc838414b4fbbcd0
parent4344d214a99321f81e2af6d075ef789a6a324c0e (diff)
downloadbdl-9c5fb457fe6063b7545515397aa45cecb7af66bf.tar.gz
bdl-9c5fb457fe6063b7545515397aa45cecb7af66bf.zip
Fix local variables on recursive calls
-rw-r--r--src/compiler.h34
1 files changed, 26 insertions, 8 deletions
diff --git a/src/compiler.h b/src/compiler.h
index e0d071c..6ca4467 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -378,9 +378,6 @@ compile_call_body(Object *obj) {
378 obj = obj->tail; 378 obj = obj->tail;
379 compile_object(obj->head); 379 compile_object(obj->head);
380 } 380 }
381 context_printf(" mov rax, [rsp + %zu]\n", 8 * offset);
382 context_printf(" jmp rax\n");
383
384 return offset; 381 return offset;
385} 382}
386 383
@@ -397,6 +394,10 @@ compile_call(Object *obj) {
397 // Function call compilation without start/end. 394 // Function call compilation without start/end.
398 size_t offset = compile_call_body(obj); 395 size_t offset = compile_call_body(obj);
399 396
397 // Call function.
398 context_printf(" mov rdi, [rsp + %zu]\n", 8 * offset);
399 context_printf(" jmp rdi\n");
400
400 // Restore stack to previous location and store the result on top. 401 // Restore stack to previous location and store the result on top.
401 context_printf("%s:\n", lab_end); 402 context_printf("%s:\n", lab_end);
402 context_printf(" add rsp, %zu\n", 8 * (offset + 2)); 403 context_printf(" add rsp, %zu\n", 8 * (offset + 2));
@@ -528,7 +529,6 @@ compile_lambda(Object *obj) {
528 size_t n_locals = array_size(current_env->locals); 529 size_t n_locals = array_size(current_env->locals);
529 size_t n_params = array_size(current_env->params); 530 size_t n_params = array_size(current_env->params);
530 size_t n_captured = array_size(current_env->captured); 531 size_t n_captured = array_size(current_env->captured);
531 size_t offset = 8 * (n_locals + n_params + n_captured + 1);
532 532
533 // Initialize function call frame. 533 // Initialize function call frame.
534 context_printf(" sub rsp, %zu\n", 8 * n_locals); 534 context_printf(" sub rsp, %zu\n", 8 * n_locals);
@@ -546,25 +546,43 @@ compile_lambda(Object *obj) {
546 for (size_t i = 0; i < array_size(obj->body) - 1; i++) { 546 for (size_t i = 0; i < array_size(obj->body) - 1; i++) {
547 compile_object(obj->body[i]); 547 compile_object(obj->body[i]);
548 } 548 }
549 compile_nil();
550 Object *last_expr = obj->body[array_size(obj->body) - 1]; 549 Object *last_expr = obj->body[array_size(obj->body) - 1];
551 550
552 // Tail Call Optimization. 551 // Tail Call Optimization.
553 // TODO: also for if statements 552 // TODO: also for if statements
553 // FIXME: only pairs that are not primitives.
554 if (IS_PAIR(last_expr)) { 554 if (IS_PAIR(last_expr)) {
555 // Discard the previous stack frame. 555 // Discard the previous stack frame.
556 context_printf(" mov rsp, rbp\n"); 556 context_printf(" mov rsp, rbp\n");
557 context_printf(" add rsp, %zu\n", offset);
558 557
559 compile_call_body(last_expr); 558 size_t old_offset = n_locals + n_captured + n_params;
559 size_t new_offset = compile_call_body(last_expr);
560 context_printf(" mov rdi, [rbp - 8]\n");
561 for (size_t i = 0; i < new_offset + 1; i++) {
562 context_printf(" mov rax, [rbp - 8 * %zu]\n", i + 1);
563 context_printf(" mov [rbp + 8 * %zu], rax\n", old_offset - i);
564 }
565
566 // Set the stack pointer at the end of given parameters.
567 context_printf(" mov rsp, rbp\n");
568 ssize_t offset_diff = old_offset - new_offset;
569 if (offset_diff > 0) {
570 context_printf(" add rsp, 8 * %zu\n", offset_diff);
571 } else {
572 context_printf(" sub rsp, 8 * %zu\n", offset_diff);
573 }
574
575 context_printf(" jmp rdi\n");
560 } else { 576 } else {
577 compile_nil();
561 compile_object(last_expr); 578 compile_object(last_expr);
562 579
563 // Return is stored in the `rax`. 580 // Return is stored in the `rax`.
564 context_printf(" pop rax\n"); 581 context_printf(" pop rax\n");
565 582
566 // Restore the previous call frame. 583 // Restore the previous call frame.
567 context_printf(" mov rdi, [rbp + %zu]\n", offset); 584 size_t rp_offset = (n_locals + n_params + n_captured + 1);
585 context_printf(" mov rdi, [rbp + %zu]\n", 8 * rp_offset);
568 context_printf(" mov rsp, rbp\n"); 586 context_printf(" mov rsp, rbp\n");
569 context_printf(" add rsp, %zu\n", 8 * n_locals); 587 context_printf(" add rsp, %zu\n", 8 * n_locals);
570 context_printf(" jmp rdi\n"); 588 context_printf(" jmp rdi\n");