diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler.h | 34 |
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"); |