aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-19 16:25:56 +0200
committerBad Diode <bd@badd10de.dev>2024-06-19 16:25:56 +0200
commitc2c93cc4de5f7195d2c62af8984d6f41b96b0b1c (patch)
tree243fbcbf2b4f32db0bd71d3fc2c12ea55ed892ac
parent211515623f498d952d507e4bbbf5869a26a8419c (diff)
downloadbdl-c2c93cc4de5f7195d2c62af8984d6f41b96b0b1c.tar.gz
bdl-c2c93cc4de5f7195d2c62af8984d6f41b96b0b1c.zip
Add proper LD instruction to lit int value type
-rw-r--r--src/main.c109
-rw-r--r--tests/expressions.bad3
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 {
39 Instruction *code; 39 Instruction *code;
40 Constant *constants; 40 Constant *constants;
41 Str file_name; 41 Str file_name;
42 sz reg_idx;
43 sz const_idx;
44 Arena *storage;
42 // TODO: line/col info for debugging. 45 // TODO: line/col info for debugging.
43} Chunk; 46} Chunk;
44 47
@@ -218,7 +221,7 @@ disassemble_chunk(Chunk chunk) {
218 if (array_size(chunk.constants) > 0) { 221 if (array_size(chunk.constants) > 0) {
219 println("%s: ======= constants ======", chunk.file_name); 222 println("%s: ======= constants ======", chunk.file_name);
220 for (sz i = 0; i < array_size(chunk.constants); i++) { 223 for (sz i = 0; i < array_size(chunk.constants); i++) {
221 println("%s: %x{2}: %f", chunk.file_name, i, chunk.constants[i]); 224 println("%s: %x{2}: %x", chunk.file_name, i, chunk.constants[i]);
222 } 225 }
223 } 226 }
224} 227}
@@ -236,9 +239,6 @@ vm_init(VM *vm, Chunk *chunk) {
236 assert(chunk); 239 assert(chunk);
237 assert(chunk->code); 240 assert(chunk->code);
238 vm->chunk = chunk; 241 vm->chunk = chunk;
239 for (sz i = 0; i < N_CONST; i++) {
240 vm->regs[i] = chunk->constants[i];
241 }
242 vm->ip = vm->chunk->code; 242 vm->ip = vm->chunk->code;
243} 243}
244 244
@@ -275,6 +275,11 @@ vm_run(VM *vm) {
275#endif 275#endif
276 276
277 switch (instruction.op) { 277 switch (instruction.op) {
278 case OP_LD64K: {
279 u8 dst = instruction.dst;
280 u8 src_a = instruction.a;
281 vm->regs[dst].i = vm->chunk->constants[src_a].i;
282 } break;
278 case OP_ADD: OP_ARITHMETIC(+, i) break; 283 case OP_ADD: OP_ARITHMETIC(+, i) break;
279 case OP_SUB: OP_ARITHMETIC(-, i) break; 284 case OP_SUB: OP_ARITHMETIC(-, i) break;
280 case OP_MUL: OP_ARITHMETIC(*, i) break; 285 case OP_MUL: OP_ARITHMETIC(*, i) break;
@@ -302,35 +307,82 @@ vm_run(VM *vm) {
302 } 307 }
303} 308}
304 309
305sz reg_idx = 0; 310typedef enum {
306sz compile_expr(Chunk *chunk, Node *node, Arena *a); 311 COMP_CONST,
307 312 COMP_REG,
308sz 313 COMP_ERR,
309compile_binary(OpCode op, Chunk *chunk, Node *node, Arena *a) { 314} CompResultType;
310 sz reg_a = compile_expr(chunk, node->left, a); 315
311 sz reg_b = compile_expr(chunk, node->right, a); 316typedef struct CompResult {
312 sz reg_dst = reg_idx++; 317 sz idx;
318 CompResultType type;
319} CompResult;
320
321CompResult compile_expr(Chunk *chunk, Node *node);
322
323// #define EMIT_OP(OP, CHUNK, ARENA)
324
325CompResult
326compile_binary(OpCode op, Chunk *chunk, Node *node) {
327 CompResult comp_a = compile_expr(chunk, node->left);
328 CompResult comp_b = compile_expr(chunk, node->right);
329 sz reg_dst = chunk->reg_idx++;
330 sz reg_a;
331 sz reg_b;
332 switch (comp_a.type) {
333 case COMP_CONST: {
334 reg_a = chunk->reg_idx++;
335 Instruction inst =
336 (Instruction){.op = OP_LD64K, .dst = reg_a, .a = comp_a.idx};
337 array_push(chunk->code, inst, chunk->storage);
338 } break;
339 case COMP_REG: {
340 reg_a = comp_a.idx;
341 } break;
342 default: {
343 return (CompResult){.type = COMP_ERR};
344 } break;
345 }
346 switch (comp_b.type) {
347 case COMP_CONST: {
348 reg_b = chunk->reg_idx++;
349 Instruction inst =
350 (Instruction){.op = OP_LD64K, .dst = reg_b, .a = comp_b.idx};
351 array_push(chunk->code, inst, chunk->storage);
352 } break;
353 case COMP_REG: {
354 reg_b = comp_b.idx;
355 } break;
356 default: {
357 return (CompResult){.type = COMP_ERR};
358 } break;
359 }
313 Instruction inst = 360 Instruction inst =
314 (Instruction){.op = op, .dst = reg_dst, .a = reg_a, .b = reg_b}; 361 (Instruction){.op = op, .dst = reg_dst, .a = reg_a, .b = reg_b};
315 array_push(chunk->code, inst, a); 362 array_push(chunk->code, inst, chunk->storage);
316 return reg_dst; 363 return (CompResult){.type = COMP_REG, .idx = reg_dst};
317} 364}
318 365
319sz 366CompResult
320compile_expr(Chunk *chunk, Node *node, Arena *a) { 367compile_expr(Chunk *chunk, Node *node) {
321 switch (node->kind) { 368 switch (node->kind) {
322 case NODE_ADD: return compile_binary(OP_ADD, chunk, node, a); break; 369 case NODE_ADD: return compile_binary(OP_ADD, chunk, node); break;
323 case NODE_SUB: return compile_binary(OP_SUB, chunk, node, a); break; 370 case NODE_SUB: return compile_binary(OP_SUB, chunk, node); break;
324 case NODE_MUL: return compile_binary(OP_MUL, chunk, node, a); break; 371 case NODE_MUL: return compile_binary(OP_MUL, chunk, node); break;
325 case NODE_DIV: return compile_binary(OP_DIV, chunk, node, a); break; 372 case NODE_DIV: return compile_binary(OP_DIV, chunk, node); break;
326 case NODE_MOD: return compile_binary(OP_MOD, chunk, node, a); break; 373 case NODE_MOD: return compile_binary(OP_MOD, chunk, node); break;
374 case NODE_NUM_FLOAT:
327 case NODE_NUM_INT: { 375 case NODE_NUM_INT: {
328 chunk->constants[reg_idx] = (Constant){.i = node->value.i}; 376 Constant c = (Constant){.i = node->value.i};
329 return reg_idx++; 377 array_push(chunk->constants, c, chunk->storage);
378 return (CompResult){
379 .type = COMP_CONST,
380 .idx = chunk->const_idx++,
381 };
330 } break; 382 } break;
331 default: break; 383 default: break;
332 } 384 }
333 return -1; 385 return (CompResult){.type = COMP_ERR};
334} 386}
335 387
336void 388void
@@ -398,25 +450,26 @@ process_file(Str path) {
398 450
399 // Compile roots. 451 // Compile roots.
400 Arena bytecode_arena = arena_create(LEXER_MEM, os_allocator); 452 Arena bytecode_arena = arena_create(LEXER_MEM, os_allocator);
401 Chunk chunk = {.file_name = path}; 453 Chunk chunk = {.file_name = path, .storage = &bytecode_arena};
402 array_zero(chunk.constants, 256, &bytecode_arena); 454 array_zero(chunk.constants, 256, &bytecode_arena);
403 array_zero(chunk.code, 0xffff, &bytecode_arena); 455 array_zero(chunk.code, 0xffff, &bytecode_arena);
404 sz n_roots = array_size(parser.nodes); 456 sz n_roots = array_size(parser.nodes);
405 for (sz i = 0; i < n_roots; i++) { 457 for (sz i = 0; i < n_roots; i++) {
406 // The parser stores the root nodes as a stack. 458 // The parser stores the root nodes as a stack.
407 Node *root = parser.nodes[i]; 459 Node *root = parser.nodes[i];
408 compile_expr(&chunk, root, &bytecode_arena); 460 compile_expr(&chunk, root);
409 } 461 }
410 array_push(chunk.code, (Instruction){.op = OP_HALT}, &bytecode_arena); 462 array_push(chunk.code, (Instruction){.op = OP_HALT}, &bytecode_arena);
411 463
412 // Run bytecode on VM. 464 // Run bytecode on VM.
413 VM vm = {0}; 465 VM vm = {0};
414 vm_init(&vm, &chunk); 466 vm_init(&vm, &chunk);
415 println("VM REGISTERS BEFORE:\n%{Mem}", 467 // println("VM REGISTERS BEFORE:\n%{Mem}",
416 &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)}); 468 // &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)});
417 vm_run(&vm); 469 vm_run(&vm);
418 println("VM REGISTERS AFTER:\n%{Mem}", 470 println("VM REGISTERS AFTER:\n%{Mem}",
419 &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)}); 471 &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)});
472 disassemble_chunk(chunk);
420 473
421stop: 474stop:
422 // Free up resources. 475 // 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 @@
11 + -2 1; 1 + -2
269 + 1
2 3
3; 1 + 2 * 3 4; 1 + 2 * 3
4 5