aboutsummaryrefslogtreecommitdiffstats
path: root/src/compiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler.c')
-rw-r--r--src/compiler.c209
1 files changed, 208 insertions, 1 deletions
diff --git a/src/compiler.c b/src/compiler.c
index e303cee..04afd5d 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -5,6 +5,15 @@
5 5
6#include "parser.c" 6#include "parser.c"
7 7
8typedef struct Variable {
9 Str name;
10 Str type;
11 sz size;
12 sz offset;
13} Variable;
14
15MAPDEF(StrVarMap, varmap, Str, Variable, str_hash, str_eq)
16
8typedef struct Instruction { 17typedef struct Instruction {
9 u8 dst; 18 u8 dst;
10 u8 a; 19 u8 a;
@@ -33,6 +42,11 @@ typedef struct Chunk {
33 StrIntMap *strmap; 42 StrIntMap *strmap;
34 sz str_idx; 43 sz str_idx;
35 44
45 // Global/Local variables.
46 Variable *vars;
47 StrVarMap *varmap;
48 sz var_off;
49
36 // Number of registers currently used in this chunk. 50 // Number of registers currently used in this chunk.
37 sz reg_idx; 51 sz reg_idx;
38 52
@@ -46,7 +60,9 @@ typedef enum OpCode {
46 // OP DST A B 60 // OP DST A B
47 // --------------------------------------------------------------- 61 // ---------------------------------------------------------------
48 // VM/high level instructions. 62 // VM/high level instructions.
49 OP_HALT, // halt 63 OP_HALT, // halt
64 OP_STVARI, // stvari vx, ca
65 OP_STVAR, // stvar vx, ra
50 // Load/Store instructions. 66 // Load/Store instructions.
51 OP_LD8K, // ld8k rx, ca -> u8 rx = ca 67 OP_LD8K, // ld8k rx, ca -> u8 rx = ca
52 OP_LD16K, // ld16k rx, ca -> u16 rx = ca 68 OP_LD16K, // ld16k rx, ca -> u16 rx = ca
@@ -129,6 +145,8 @@ typedef enum OpCode {
129 145
130Str op_str[] = { 146Str op_str[] = {
131 [OP_HALT] = cstr("HALT "), 147 [OP_HALT] = cstr("HALT "),
148 [OP_STVAR] = cstr("STVAR "),
149 [OP_STVARI] = cstr("STVARI "),
132 // Load ops. 150 // Load ops.
133 [OP_LD8K] = cstr("LD8K "), 151 [OP_LD8K] = cstr("LD8K "),
134 [OP_LD16K] = cstr("LD16K "), 152 [OP_LD16K] = cstr("LD16K "),
@@ -210,6 +228,7 @@ Str op_str[] = {
210}; 228};
211 229
212typedef enum { 230typedef enum {
231 COMP_NIL,
213 COMP_CONST, 232 COMP_CONST,
214 COMP_STRING, 233 COMP_STRING,
215 COMP_REG, 234 COMP_REG,
@@ -464,6 +483,54 @@ compile_expr(Chunk *chunk, Node *node) {
464 .idx = map->val, 483 .idx = map->val,
465 }; 484 };
466 } break; 485 } break;
486 case NODE_LET: {
487 sz idx = array_size(chunk->vars);
488 Str name = node->unique_name;
489 Str type = node->var_name->type;
490 sz size = 8;
491 // TODO: get type storage from a table to consider all the basic
492 // types as well as user defined ones.
493 if (str_eq(type, cstr("str"))) {
494 size = 16;
495 }
496 Variable var = (Variable){
497 .name = name,
498 .type = type,
499 .size = size,
500 .offset = chunk->var_off,
501 };
502 varmap_insert(&chunk->varmap, name, var, chunk->storage);
503 array_push(chunk->vars, var, chunk->storage);
504 chunk->var_off += size;
505
506 // Value.
507 if (node->var_val) {
508 CompResult res = compile_expr(chunk, node->var_val);
509 switch (res.type) {
510 case COMP_CONST: {
511 EMIT_OP(OP_STVARI, idx, res.idx, 0, node->var_val,
512 chunk);
513 } break;
514 case COMP_REG: {
515 EMIT_OP(OP_STVAR, idx, res.idx, 0, node->var_val,
516 chunk);
517 } break;
518 default: {
519 return (CompResult){.type = COMP_ERR};
520 } break;
521 }
522 }
523
524 return (CompResult){.type = COMP_NIL};
525 } break;
526 case NODE_BLOCK: {
527 CompResult res;
528 for (sz i = 0; i < array_size(node->elements); i++) {
529 Node *root = node->elements[i];
530 res = compile_expr(chunk, root);
531 }
532 return res;
533 } break;
467 default: { 534 default: {
468 eprintln("error: compilation not implemented for node %s", 535 eprintln("error: compilation not implemented for node %s",
469 node_str[node->kind]); 536 node_str[node->kind]);
@@ -473,4 +540,144 @@ compile_expr(Chunk *chunk, Node *node) {
473 return (CompResult){.type = COMP_ERR}; 540 return (CompResult){.type = COMP_ERR};
474} 541}
475 542
543void
544disassemble_instruction(Instruction instruction) {
545 switch (instruction.op) {
546 case OP_MOV8:
547 case OP_MOV16:
548 case OP_MOV32:
549 case OP_MOV64:
550 println("%s r%d, r%d", op_str[instruction.op], instruction.dst,
551 instruction.a, instruction.b);
552 break;
553 case OP_LD8K:
554 case OP_LD16K:
555 case OP_LD32K:
556 case OP_LD64K:
557 println("%s r%d, c%d", op_str[instruction.op], instruction.dst,
558 instruction.a, instruction.b);
559 break;
560 case OP_LD8I:
561 case OP_LD16I:
562 case OP_LD32I:
563 case OP_LD64I:
564 case OP_ST8I:
565 case OP_ST16I:
566 case OP_ST32I:
567 case OP_ST64I:
568 case OP_ADDI:
569 case OP_SUBI:
570 case OP_MULI:
571 case OP_DIVI:
572 case OP_MODI:
573 case OP_ADDFI:
574 case OP_SUBFI:
575 case OP_MULFI:
576 case OP_DIVFI:
577 case OP_MODFI:
578 case OP_EQI:
579 case OP_NEQI:
580 case OP_LTI:
581 case OP_GTI:
582 case OP_LEI:
583 case OP_GEI:
584 case OP_ANDI:
585 case OP_ORI:
586 case OP_BITLSHIFTI:
587 case OP_BITRSHIFTI:
588 case OP_BITANDI:
589 case OP_BITORI:
590 println("%s r%d, r%d, c%d", op_str[instruction.op], instruction.dst,
591 instruction.a, instruction.b);
592 break;
593 case OP_LD8:
594 case OP_LD16:
595 case OP_LD32:
596 case OP_LD64:
597 case OP_ST8:
598 case OP_ST16:
599 case OP_ST32:
600 case OP_ST64:
601 case OP_ADD:
602 case OP_SUB:
603 case OP_MUL:
604 case OP_DIV:
605 case OP_MOD:
606 case OP_ADDF:
607 case OP_SUBF:
608 case OP_MULF:
609 case OP_DIVF:
610 case OP_MODF:
611 case OP_EQ:
612 case OP_NEQ:
613 case OP_LT:
614 case OP_GT:
615 case OP_LE:
616 case OP_GE:
617 case OP_AND:
618 case OP_OR:
619 case OP_BITLSHIFT:
620 case OP_BITRSHIFT:
621 case OP_BITAND:
622 case OP_BITOR:
623 println("%s r%d, r%d, r%d", op_str[instruction.op], instruction.dst,
624 instruction.a, instruction.b);
625 break;
626 case OP_STVAR:
627 println("%s v%d, r%d", op_str[instruction.op], instruction.dst,
628 instruction.a, instruction.b);
629 break;
630 case OP_STVARI:
631 println("%s v%d, c%d", op_str[instruction.op], instruction.dst,
632 instruction.a, instruction.b);
633 break;
634 case OP_BITNOTI:
635 case OP_NOTI:
636 println("%s r%d, c%d", op_str[instruction.op], instruction.dst,
637 instruction.a, instruction.b);
638 break;
639 case OP_BITNOT:
640 case OP_NOT:
641 println("%s r%d, r%d", op_str[instruction.op], instruction.dst,
642 instruction.a, instruction.b);
643 break;
644 case OP_HALT: println("%s", op_str[instruction.op]); break;
645 default: println("Unknown opcode %d", instruction.op); break;
646 }
647}
648
649void
650disassemble_chunk(Chunk chunk) {
651 println("%s: =========== code ===========", chunk.file_name);
652 for (sz i = 0; i < array_size(chunk.code); i++) {
653 print("%s: %x{4}: ", chunk.file_name, i);
654 disassemble_instruction(chunk.code[i]);
655 }
656 if (array_size(chunk.constants) > 0) {
657 println("%s: ========= constants ========", chunk.file_name);
658 for (sz i = 0; i < array_size(chunk.constants); i++) {
659 println("%s: %x{2}: %x{8}", chunk.file_name, i,
660 chunk.constants[i]);
661 }
662 }
663 if (array_size(chunk.strings) > 0) {
664 println("%s: ========== strings =========", chunk.file_name);
665 for (sz i = 0; i < array_size(chunk.strings); i++) {
666 println("%s: %x{2}: %s", chunk.file_name, i, chunk.strings[i]);
667 }
668 }
669 if (array_size(chunk.vars) > 0) {
670 println("%s: ========= variables ========", chunk.file_name);
671 for (sz i = 0; i < array_size(chunk.vars); i++) {
672 println("%s: %x{2}: [%x{4}:%x{4}] %s: %s", chunk.file_name, i,
673 chunk.vars[i].offset,
674 chunk.vars[i].offset + chunk.vars[i].size,
675 chunk.vars[i].name, chunk.vars[i].type);
676 }
677 }
678 println("n_regs: %d, n_vars: %d, n_strings: %d, n_consts: %d",
679 chunk.reg_idx, array_size(chunk.vars), chunk.str_idx,
680 chunk.const_idx);
681}
682
476#endif // COMPILER_C 683#endif // COMPILER_C