diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-19 16:25:56 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-19 16:25:56 +0200 |
commit | c2c93cc4de5f7195d2c62af8984d6f41b96b0b1c (patch) | |
tree | 243fbcbf2b4f32db0bd71d3fc2c12ea55ed892ac /src/main.c | |
parent | 211515623f498d952d507e4bbbf5869a26a8419c (diff) | |
download | bdl-c2c93cc4de5f7195d2c62af8984d6f41b96b0b1c.tar.gz bdl-c2c93cc4de5f7195d2c62af8984d6f41b96b0b1c.zip |
Add proper LD instruction to lit int value type
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 109 |
1 files changed, 81 insertions, 28 deletions
@@ -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 | ||
305 | sz reg_idx = 0; | 310 | typedef enum { |
306 | sz compile_expr(Chunk *chunk, Node *node, Arena *a); | 311 | COMP_CONST, |
307 | 312 | COMP_REG, | |
308 | sz | 313 | COMP_ERR, |
309 | compile_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); | 316 | typedef struct CompResult { |
312 | sz reg_dst = reg_idx++; | 317 | sz idx; |
318 | CompResultType type; | ||
319 | } CompResult; | ||
320 | |||
321 | CompResult compile_expr(Chunk *chunk, Node *node); | ||
322 | |||
323 | // #define EMIT_OP(OP, CHUNK, ARENA) | ||
324 | |||
325 | CompResult | ||
326 | compile_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 | ||
319 | sz | 366 | CompResult |
320 | compile_expr(Chunk *chunk, Node *node, Arena *a) { | 367 | compile_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 | ||
336 | void | 388 | void |
@@ -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 | ||
421 | stop: | 474 | stop: |
422 | // Free up resources. | 475 | // Free up resources. |