aboutsummaryrefslogtreecommitdiffstats
path: root/src/compiler.c
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-07-02 23:23:57 +0200
committerBad Diode <bd@badd10de.dev>2024-07-02 23:23:57 +0200
commit203e955a38fbb1321571444463eeac8ab2d31437 (patch)
tree4931f7586ea674a89ec8cd3353d7a20fcaef855c /src/compiler.c
parent3b37ecc2357251b99d8b99b3532cff343ece6971 (diff)
downloadbdl-203e955a38fbb1321571444463eeac8ab2d31437.tar.gz
bdl-203e955a38fbb1321571444463eeac8ab2d31437.zip
Change AR layout
Diffstat (limited to 'src/compiler.c')
-rw-r--r--src/compiler.c90
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;