diff options
author | Bad Diode <bd@badd10de.dev> | 2021-11-16 20:49:01 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-11-16 20:49:01 +0100 |
commit | 92f33efa0cb88654e1b182416dbac631abf2be49 (patch) | |
tree | 8f70b736c11b23697f510d9c26a37933d9195dbd | |
parent | 3481ac42896ae7c5a7b40bf456cd203edeeefe4a (diff) | |
download | bdl-92f33efa0cb88654e1b182416dbac631abf2be49.tar.gz bdl-92f33efa0cb88654e1b182416dbac631abf2be49.zip |
Move ret pointer before closed vars in proc calls
The previous call convention we had the following before the function
call:
[ PROC_ADDR | CLOSED_VARS | ARGS | RP ]
This was made to be compatible with the `call` instruction and the
`cdecl` calling convention. This commit changes the structure to:
[ RP | PROC_ADDR | CLOSED_VARS | ARGS ]
With this convention, the stack frame can be discarded in its entirety
if we have a tail optimized procedure.
-rw-r--r-- | src/compiler.h | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/src/compiler.h b/src/compiler.h index d1952ed..1ef81e3 100644 --- a/src/compiler.h +++ b/src/compiler.h | |||
@@ -343,6 +343,13 @@ compile_cdr(Object *obj) { | |||
343 | void | 343 | void |
344 | compile_call(Object *obj) { | 344 | compile_call(Object *obj) { |
345 | context_printf(" ;; --> compile_call\n"); | 345 | context_printf(" ;; --> compile_call\n"); |
346 | |||
347 | // Prepare return pointer. | ||
348 | char *lab_end = generate_label("BDLL"); | ||
349 | context_printf(" lea rcx, [%s]\n", lab_end); | ||
350 | context_printf(" push rcx\n"); | ||
351 | |||
352 | // Compile operator. | ||
346 | compile_object(obj->head); | 353 | compile_object(obj->head); |
347 | context_printf(" pop rax\n"); | 354 | context_printf(" pop rax\n"); |
348 | context_printf(" mov rcx, PTR_MASK\n"); | 355 | context_printf(" mov rcx, PTR_MASK\n"); |
@@ -379,10 +386,7 @@ compile_call(Object *obj) { | |||
379 | compile_object(obj->head); | 386 | compile_object(obj->head); |
380 | } | 387 | } |
381 | 388 | ||
382 | char *lab_end = generate_label("BDLL"); | ||
383 | context_printf(" mov rax, [rsp + %zu]\n", 8 * offset); | 389 | context_printf(" mov rax, [rsp + %zu]\n", 8 * offset); |
384 | context_printf(" lea rcx, [%s]\n", lab_end); | ||
385 | context_printf(" push rcx\n"); | ||
386 | context_printf(" jmp rax\n"); | 390 | context_printf(" jmp rax\n"); |
387 | context_printf("%s:\n", lab_end); | 391 | context_printf("%s:\n", lab_end); |
388 | 392 | ||
@@ -535,7 +539,11 @@ compile_lambda(Object *obj) { | |||
535 | context_printf(" pop rax\n"); | 539 | context_printf(" pop rax\n"); |
536 | 540 | ||
537 | // Restore the previous call frame. | 541 | // Restore the previous call frame. |
538 | context_printf(" mov rdi, [rbp + 8]\n"); | 542 | size_t n_locals = array_size(current_env->locals); |
543 | size_t n_params = array_size(current_env->params); | ||
544 | size_t n_captured = array_size(current_env->captured); | ||
545 | size_t offset = 8 * (n_locals + n_params + n_captured + 2); | ||
546 | context_printf(" mov rdi, [rbp + %zu]\n", offset); | ||
539 | context_printf(" mov rsp, rbp\n"); | 547 | context_printf(" mov rsp, rbp\n"); |
540 | context_printf(" add rsp, %zu\n", 8 * array_size(current_env->locals)); | 548 | context_printf(" add rsp, %zu\n", 8 * array_size(current_env->locals)); |
541 | context_printf(" pop rbp\n"); | 549 | context_printf(" pop rbp\n"); |
@@ -602,7 +610,7 @@ compile_symbol(Object *obj) { | |||
602 | size_t n_locals = array_size(current_env->locals); | 610 | size_t n_locals = array_size(current_env->locals); |
603 | size_t n_params = array_size(current_env->params); | 611 | size_t n_params = array_size(current_env->params); |
604 | size_t n_cap = array_size(current_env->captured); | 612 | size_t n_cap = array_size(current_env->captured); |
605 | size_t offset = 8 * (n_locals + n_params + n_cap - idx + 1); | 613 | size_t offset = 8 * (n_locals + n_params + n_cap - idx); |
606 | context_printf(" mov rcx, [rbp + %ld]\n", offset); | 614 | context_printf(" mov rcx, [rbp + %ld]\n", offset); |
607 | context_printf(" mov rax, [rcx]\n"); | 615 | context_printf(" mov rax, [rcx]\n"); |
608 | context_printf(" push rax\n"); | 616 | context_printf(" push rax\n"); |
@@ -624,7 +632,7 @@ compile_symbol(Object *obj) { | |||
624 | if (idx != -1) { | 632 | if (idx != -1) { |
625 | size_t n_locals = array_size(current_env->locals); | 633 | size_t n_locals = array_size(current_env->locals); |
626 | size_t n_params = array_size(current_env->params); | 634 | size_t n_params = array_size(current_env->params); |
627 | size_t offset = 8 * (n_locals + n_params - idx + 1); | 635 | size_t offset = 8 * (n_locals + n_params - idx); |
628 | context_printf(" mov rax, [rbp + %ld]\n", offset); | 636 | context_printf(" mov rax, [rbp + %ld]\n", offset); |
629 | context_printf(" push rax\n"); | 637 | context_printf(" push rax\n"); |
630 | context_printf(" ;; <-- compile_symbol\n"); | 638 | context_printf(" ;; <-- compile_symbol\n"); |