diff options
author | Bad Diode <bd@badd10de.dev> | 2024-07-02 23:23:57 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-07-02 23:23:57 +0200 |
commit | 203e955a38fbb1321571444463eeac8ab2d31437 (patch) | |
tree | 4931f7586ea674a89ec8cd3353d7a20fcaef855c /src/compiler.c | |
parent | 3b37ecc2357251b99d8b99b3532cff343ece6971 (diff) | |
download | bdl-203e955a38fbb1321571444463eeac8ab2d31437.tar.gz bdl-203e955a38fbb1321571444463eeac8ab2d31437.zip |
Change AR layout
Diffstat (limited to 'src/compiler.c')
-rw-r--r-- | src/compiler.c | 90 |
1 files changed, 67 insertions, 23 deletions
diff --git a/src/compiler.c b/src/compiler.c index d1c56b3..9b6a458 100644 --- a/src/compiler.c +++ b/src/compiler.c | |||
@@ -96,8 +96,11 @@ typedef enum OpCode { | |||
96 | OP_CALL, // call fx ; Bumps the stack pointer by cx | 96 | OP_CALL, // call fx ; Bumps the stack pointer by cx |
97 | OP_RET, // ret ; Returns from current function | 97 | OP_RET, // ret ; Returns from current function |
98 | OP_RESERVE, // reserve cx ; Increments the stack pointer by cx bytes | 98 | OP_RESERVE, // reserve cx ; Increments the stack pointer by cx bytes |
99 | OP_POP, // pop cx ; Decrements the stack pointer by cx bytes | 99 | OP_POP, // pop rx ; Pops the last value of the stack into rx. |
100 | OP_SPVAL, // val rx, cx ; u64 *stack; rx = stack[cx] | 100 | OP_PUSH, // push rx ; Push the rx value to the stack. |
101 | OP_PUSHI, // pushi cx ; Push the cx value to the stack. | ||
102 | OP_PUTRET, // putret rx ; Put rx into the return value memory. | ||
103 | OP_PUTRETI, // putreti cx ; Put cx into the return value memory. | ||
101 | // Printing values with builtin print/println functions. | 104 | // Printing values with builtin print/println functions. |
102 | OP_PRINTSTR, // p rx | 105 | OP_PRINTSTR, // p rx |
103 | OP_PRINTS64, // p rx | 106 | OP_PRINTS64, // p rx |
@@ -202,12 +205,15 @@ Str op_str[] = { | |||
202 | [OP_PRINTF64] = cstr("PRNTF64 "), | 205 | [OP_PRINTF64] = cstr("PRNTF64 "), |
203 | [OP_PRINTS64I] = cstr("PRNTS64I"), | 206 | [OP_PRINTS64I] = cstr("PRNTS64I"), |
204 | [OP_PRINTF64I] = cstr("PRNTF64I"), | 207 | [OP_PRINTF64I] = cstr("PRNTF64I"), |
208 | [OP_PUTRET] = cstr("PUTRET "), | ||
209 | [OP_PUTRETI] = cstr("PUTRETI "), | ||
205 | // Functions. | 210 | // Functions. |
206 | [OP_CALL] = cstr("CALL "), | 211 | [OP_CALL] = cstr("CALL "), |
207 | [OP_RET] = cstr("RET "), | 212 | [OP_RET] = cstr("RET "), |
208 | [OP_RESERVE] = cstr("RESERVE "), | 213 | [OP_RESERVE] = cstr("RESERVE "), |
209 | [OP_POP] = cstr("POP "), | 214 | [OP_POP] = cstr("POP "), |
210 | [OP_SPVAL] = cstr("SPVAL "), | 215 | [OP_PUSH] = cstr("PUSH "), |
216 | [OP_PUSHI] = cstr("PUSHI "), | ||
211 | // Load ops. | 217 | // Load ops. |
212 | [OP_LD8K] = cstr("LD8K "), | 218 | [OP_LD8K] = cstr("LD8K "), |
213 | [OP_LD16K] = cstr("LD16K "), | 219 | [OP_LD16K] = cstr("LD16K "), |
@@ -831,33 +837,57 @@ compile_funcall(Chunk *chunk, Node *node) { | |||
831 | } | 837 | } |
832 | Function fun = map->val; | 838 | Function fun = map->val; |
833 | 839 | ||
834 | // TODO: prologue (how much space do we actually need)? we need the symbol | 840 | // Reserve space for the return value if needed. |
835 | // table, arity and return parameters boy. | 841 | if (fun.return_arity > 0) { |
836 | // FIXME: assuming all values are 8 bytes for now... | 842 | // Put the return data into a register |
837 | sz alloc_size = (fun.param_arity + fun.return_arity) * 8; | 843 | sz ret_size = add_constant(chunk, 8); |
838 | sz alloc_const = add_constant(chunk, alloc_size); | 844 | EMIT_OP(OP_RESERVE, ret_size, 0, 0, node, chunk); |
839 | if (alloc_size > 0) { | 845 | } |
840 | EMIT_OP(OP_RESERVE, alloc_const, 0, 0, node, chunk); | 846 | |
847 | // Send parameters to the stack. | ||
848 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
849 | Node *expr = node->elements[i]; | ||
850 | CompResult result = compile_expr(chunk, expr); | ||
851 | // TODO: Assuming all values are 8 bytes... again. | ||
852 | switch (result.type) { | ||
853 | case COMP_CONST: { | ||
854 | EMIT_OP(OP_PUSHI, result.idx, 0, 0, expr, chunk); | ||
855 | } break; | ||
856 | case COMP_REG: { | ||
857 | EMIT_OP(OP_PUSH, result.idx, 0, 0, expr, chunk); | ||
858 | } break; | ||
859 | default: { | ||
860 | return (CompResult){.type = COMP_ERR}; | ||
861 | } break; | ||
862 | } | ||
841 | } | 863 | } |
842 | 864 | ||
843 | // println("FUNCALL: unique name: %s", node->unique_name); | 865 | // // TODO: prologue (how much space do we actually need)? we need the |
844 | // println("FUN: param_arity: %d", fun.param_arity); | 866 | // symbol |
845 | // println("FUN: return_arity: %d", fun.return_arity); | 867 | // // table, arity and return parameters boy. |
868 | // // FIXME: assuming all values are 8 bytes for now... | ||
869 | // sz alloc_size = (fun.param_arity + fun.return_arity) * 8; | ||
870 | // sz alloc_const = add_constant(chunk, alloc_size); | ||
871 | // if (alloc_size > 0) { | ||
872 | // // EMIT_OP(OP_RESERVE, alloc_const, 0, 0, node, chunk); | ||
873 | // } | ||
874 | |||
875 | // // println("FUNCALL: unique name: %s", node->unique_name); | ||
876 | // // println("FUN: param_arity: %d", fun.param_arity); | ||
877 | // // println("FUN: return_arity: %d", fun.return_arity); | ||
846 | EMIT_OP(OP_CALL, fun.index, 0, 0, node, chunk); | 878 | EMIT_OP(OP_CALL, fun.index, 0, 0, node, chunk); |
847 | 879 | ||
848 | // Only one return parameter for now. | 880 | // Only one return parameter for now. |
849 | if (fun.return_arity > 0) { | 881 | if (fun.return_arity > 0) { |
850 | // Put the return data into a register | 882 | // Put the return data into a register |
851 | sz reg_dst = chunk->reg_idx++; | 883 | sz reg_dst = chunk->reg_idx++; |
852 | sz ret_offset = add_constant(chunk, -fun.return_arity); | 884 | EMIT_OP(OP_POP, reg_dst, 0, 0, node, chunk); |
853 | EMIT_OP(OP_SPVAL, reg_dst, ret_offset, 0, node, chunk); | ||
854 | EMIT_OP(OP_POP, alloc_const, 0, 0, node, chunk); | ||
855 | return (CompResult){.type = COMP_REG, .idx = reg_dst}; | 885 | return (CompResult){.type = COMP_REG, .idx = reg_dst}; |
856 | } | 886 | } |
857 | 887 | ||
858 | if (alloc_size > 0) { | 888 | // if (alloc_size > 0) { |
859 | EMIT_OP(OP_POP, alloc_const, 0, 0, node, chunk); | 889 | // // EMIT_OP(OP_POP, alloc_const, 0, 0, node, chunk); |
860 | } | 890 | // } |
861 | // TODO: epilogue (how much space do we actually need)? we need to remove | 891 | // TODO: epilogue (how much space do we actually need)? we need to remove |
862 | // the AR data here after using it. If we only have one return parameter we | 892 | // the AR data here after using it. If we only have one return parameter we |
863 | // can put it in a register but what if that's not actually the case? | 893 | // can put it in a register but what if that's not actually the case? |
@@ -887,8 +917,19 @@ compile_function(Chunk *chunk, Node *node) { | |||
887 | }; | 917 | }; |
888 | funcmap_insert(&chunk->funmap, func->name, fun, chunk->storage); | 918 | funcmap_insert(&chunk->funmap, func->name, fun, chunk->storage); |
889 | array_push(chunk->functions, func, chunk->storage); | 919 | array_push(chunk->functions, func, chunk->storage); |
890 | // TODO: put return values into memory. | 920 | |
891 | compile_expr(func, node->func_body); | 921 | // Put return values into memory. |
922 | CompResult res = compile_expr(func, node->func_body); | ||
923 | switch (res.type) { | ||
924 | case COMP_CONST: { | ||
925 | EMIT_OP(OP_PUTRETI, res.idx, 0, 0, node, func); | ||
926 | } break; | ||
927 | case COMP_REG: { | ||
928 | EMIT_OP(OP_PUTRET, res.idx, 0, 0, node, func); | ||
929 | } break; | ||
930 | default: break; | ||
931 | } | ||
932 | |||
892 | // TODO: handle captured locals/globals? | 933 | // TODO: handle captured locals/globals? |
893 | EMIT_OP(OP_RET, 0, 0, 0, node, func); | 934 | EMIT_OP(OP_RET, 0, 0, 0, node, func); |
894 | return (CompResult){.type = COMP_NIL}; | 935 | return (CompResult){.type = COMP_NIL}; |
@@ -1159,7 +1200,6 @@ disassemble_instruction(Instruction instruction) { | |||
1159 | case OP_LD16K: | 1200 | case OP_LD16K: |
1160 | case OP_LD32K: | 1201 | case OP_LD32K: |
1161 | case OP_LD64K: | 1202 | case OP_LD64K: |
1162 | case OP_SPVAL: | ||
1163 | println("%s r%d, c%d", op_str[instruction.op], instruction.dst, | 1203 | println("%s r%d, c%d", op_str[instruction.op], instruction.dst, |
1164 | instruction.a, instruction.b); | 1204 | instruction.a, instruction.b); |
1165 | break; | 1205 | break; |
@@ -1264,13 +1304,17 @@ disassemble_instruction(Instruction instruction) { | |||
1264 | case OP_PRINTS64: | 1304 | case OP_PRINTS64: |
1265 | case OP_PRINTF64: | 1305 | case OP_PRINTF64: |
1266 | case OP_PRINTSTR: | 1306 | case OP_PRINTSTR: |
1307 | case OP_PUSH: | ||
1308 | case OP_POP: | ||
1309 | case OP_PUTRET: | ||
1267 | println("%s r%d", op_str[instruction.op], instruction.dst, | 1310 | println("%s r%d", op_str[instruction.op], instruction.dst, |
1268 | instruction.a, instruction.b); | 1311 | instruction.a, instruction.b); |
1269 | break; | 1312 | break; |
1270 | case OP_PRINTS64I: | 1313 | case OP_PRINTS64I: |
1271 | case OP_PRINTF64I: | 1314 | case OP_PRINTF64I: |
1272 | case OP_RESERVE: | 1315 | case OP_RESERVE: |
1273 | case OP_POP: | 1316 | case OP_PUSHI: |
1317 | case OP_PUTRETI: | ||
1274 | println("%s c%d", op_str[instruction.op], instruction.dst, | 1318 | println("%s c%d", op_str[instruction.op], instruction.dst, |
1275 | instruction.a, instruction.b); | 1319 | instruction.a, instruction.b); |
1276 | break; | 1320 | break; |