From c2c93cc4de5f7195d2c62af8984d6f41b96b0b1c Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Wed, 19 Jun 2024 16:25:56 +0200 Subject: Add proper LD instruction to lit int value type --- src/main.c | 109 +++++++++++++++++++++++++++++++++++++------------- tests/expressions.bad | 3 +- 2 files changed, 83 insertions(+), 29 deletions(-) diff --git a/src/main.c b/src/main.c index 8d0cb6e..d2bbe67 100644 --- a/src/main.c +++ b/src/main.c @@ -39,6 +39,9 @@ typedef struct Chunk { Instruction *code; Constant *constants; Str file_name; + sz reg_idx; + sz const_idx; + Arena *storage; // TODO: line/col info for debugging. } Chunk; @@ -218,7 +221,7 @@ disassemble_chunk(Chunk chunk) { if (array_size(chunk.constants) > 0) { println("%s: ======= constants ======", chunk.file_name); for (sz i = 0; i < array_size(chunk.constants); i++) { - println("%s: %x{2}: %f", chunk.file_name, i, chunk.constants[i]); + println("%s: %x{2}: %x", chunk.file_name, i, chunk.constants[i]); } } } @@ -236,9 +239,6 @@ vm_init(VM *vm, Chunk *chunk) { assert(chunk); assert(chunk->code); vm->chunk = chunk; - for (sz i = 0; i < N_CONST; i++) { - vm->regs[i] = chunk->constants[i]; - } vm->ip = vm->chunk->code; } @@ -275,6 +275,11 @@ vm_run(VM *vm) { #endif switch (instruction.op) { + case OP_LD64K: { + u8 dst = instruction.dst; + u8 src_a = instruction.a; + vm->regs[dst].i = vm->chunk->constants[src_a].i; + } break; case OP_ADD: OP_ARITHMETIC(+, i) break; case OP_SUB: OP_ARITHMETIC(-, i) break; case OP_MUL: OP_ARITHMETIC(*, i) break; @@ -302,35 +307,82 @@ vm_run(VM *vm) { } } -sz reg_idx = 0; -sz compile_expr(Chunk *chunk, Node *node, Arena *a); - -sz -compile_binary(OpCode op, Chunk *chunk, Node *node, Arena *a) { - sz reg_a = compile_expr(chunk, node->left, a); - sz reg_b = compile_expr(chunk, node->right, a); - sz reg_dst = reg_idx++; +typedef enum { + COMP_CONST, + COMP_REG, + COMP_ERR, +} CompResultType; + +typedef struct CompResult { + sz idx; + CompResultType type; +} CompResult; + +CompResult compile_expr(Chunk *chunk, Node *node); + +// #define EMIT_OP(OP, CHUNK, ARENA) + +CompResult +compile_binary(OpCode op, Chunk *chunk, Node *node) { + CompResult comp_a = compile_expr(chunk, node->left); + CompResult comp_b = compile_expr(chunk, node->right); + sz reg_dst = chunk->reg_idx++; + sz reg_a; + sz reg_b; + switch (comp_a.type) { + case COMP_CONST: { + reg_a = chunk->reg_idx++; + Instruction inst = + (Instruction){.op = OP_LD64K, .dst = reg_a, .a = comp_a.idx}; + array_push(chunk->code, inst, chunk->storage); + } break; + case COMP_REG: { + reg_a = comp_a.idx; + } break; + default: { + return (CompResult){.type = COMP_ERR}; + } break; + } + switch (comp_b.type) { + case COMP_CONST: { + reg_b = chunk->reg_idx++; + Instruction inst = + (Instruction){.op = OP_LD64K, .dst = reg_b, .a = comp_b.idx}; + array_push(chunk->code, inst, chunk->storage); + } break; + case COMP_REG: { + reg_b = comp_b.idx; + } break; + default: { + return (CompResult){.type = COMP_ERR}; + } break; + } Instruction inst = (Instruction){.op = op, .dst = reg_dst, .a = reg_a, .b = reg_b}; - array_push(chunk->code, inst, a); - return reg_dst; + array_push(chunk->code, inst, chunk->storage); + return (CompResult){.type = COMP_REG, .idx = reg_dst}; } -sz -compile_expr(Chunk *chunk, Node *node, Arena *a) { +CompResult +compile_expr(Chunk *chunk, Node *node) { switch (node->kind) { - case NODE_ADD: return compile_binary(OP_ADD, chunk, node, a); break; - case NODE_SUB: return compile_binary(OP_SUB, chunk, node, a); break; - case NODE_MUL: return compile_binary(OP_MUL, chunk, node, a); break; - case NODE_DIV: return compile_binary(OP_DIV, chunk, node, a); break; - case NODE_MOD: return compile_binary(OP_MOD, chunk, node, a); break; + case NODE_ADD: return compile_binary(OP_ADD, chunk, node); break; + case NODE_SUB: return compile_binary(OP_SUB, chunk, node); break; + case NODE_MUL: return compile_binary(OP_MUL, chunk, node); break; + case NODE_DIV: return compile_binary(OP_DIV, chunk, node); break; + case NODE_MOD: return compile_binary(OP_MOD, chunk, node); break; + case NODE_NUM_FLOAT: case NODE_NUM_INT: { - chunk->constants[reg_idx] = (Constant){.i = node->value.i}; - return reg_idx++; + Constant c = (Constant){.i = node->value.i}; + array_push(chunk->constants, c, chunk->storage); + return (CompResult){ + .type = COMP_CONST, + .idx = chunk->const_idx++, + }; } break; default: break; } - return -1; + return (CompResult){.type = COMP_ERR}; } void @@ -398,25 +450,26 @@ process_file(Str path) { // Compile roots. Arena bytecode_arena = arena_create(LEXER_MEM, os_allocator); - Chunk chunk = {.file_name = path}; + Chunk chunk = {.file_name = path, .storage = &bytecode_arena}; array_zero(chunk.constants, 256, &bytecode_arena); array_zero(chunk.code, 0xffff, &bytecode_arena); sz n_roots = array_size(parser.nodes); for (sz i = 0; i < n_roots; i++) { // The parser stores the root nodes as a stack. Node *root = parser.nodes[i]; - compile_expr(&chunk, root, &bytecode_arena); + compile_expr(&chunk, root); } array_push(chunk.code, (Instruction){.op = OP_HALT}, &bytecode_arena); // Run bytecode on VM. VM vm = {0}; vm_init(&vm, &chunk); - println("VM REGISTERS BEFORE:\n%{Mem}", - &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)}); + // println("VM REGISTERS BEFORE:\n%{Mem}", + // &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)}); vm_run(&vm); println("VM REGISTERS AFTER:\n%{Mem}", &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)}); + disassemble_chunk(chunk); stop: // Free up resources. diff --git a/tests/expressions.bad b/tests/expressions.bad index 0213694..512da0a 100644 --- a/tests/expressions.bad +++ b/tests/expressions.bad @@ -1,4 +1,5 @@ -1 + -2 +; 1 + -2 +69 + 1 ; 1 + 2 * 3 -- cgit v1.2.1