From d30601a02fe1af1eb43f15eabf6a427baedfce14 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Fri, 22 Apr 2022 22:49:59 -0300 Subject: Add initial BASM generation for arithmetic ops --- src/ir.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++------ src/main.c | 4 +++ src/viz.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 8 deletions(-) diff --git a/src/ir.c b/src/ir.c index 4c85792..4eeb07b 100644 --- a/src/ir.c +++ b/src/ir.c @@ -47,23 +47,24 @@ typedef enum OperandType { OP_TYPE_LABEL, } OperandType; +static size_t reg_gen_id = 0; + +#define NEW_REG() (Operand){ .type = OP_TYPE_REG, .id = reg_gen_id++ } +#define NEW_S64(C) (Operand){ .type = OP_TYPE_CONST, .constant.sval = (C) } + typedef struct Operand { OperandType type; union { - struct { - size_t num; - } reg; - - struct { - size_t num; - } label; + // REG/LABEL + size_t id; + // s64 constant; struct { union { u64 uval; s64 sval; }; - } const; + } constant; }; } Operand; @@ -83,3 +84,68 @@ typedef struct ProgramBASM { Instruction *inst; LineInfo *lines; } ProgramBASM; + +Operand +emit_basm(ProgramBASM *program, Node *node) { + switch (node->type) { + case NODE_NUMBER: { + // TODO: ldX depending on type of number. + Instruction inst = (Instruction){ + .op = OP_LD64, + .dst = NEW_REG(), + .src_a = NEW_S64(node->number.integral), + }; + LineInfo line = (LineInfo){.line = node->line, .col = node->col}; + array_push(program->inst, inst); + array_push(program->lines, line); + return inst.dst; + } break; + case NODE_BUILTIN: { + Operator op; + switch (node->builtin.type) { + case TOKEN_ADD: { op = OP_ADD; } break; + case TOKEN_SUB: { op = OP_SUB; } break; + case TOKEN_MUL: { op = OP_MUL; } break; + case TOKEN_DIV: { op = OP_DIV; } break; + case TOKEN_MOD: { op = OP_MOD; } break; + default: break; + } + Operand reg_a = emit_basm(program, node->builtin.args[0]); + Operand reg_b; + for (size_t i = 1; i < array_size(node->builtin.args); ++i) { + Node *arg = node->builtin.args[i]; + reg_b = emit_basm(program, arg); + Instruction inst = (Instruction){ + .op = op, + .dst = NEW_REG(), + .src_a = reg_a, + .src_b = reg_b, + }; + reg_a = inst.dst; + LineInfo line = (LineInfo){ + .line = node->line, + .col = node->col, + }; + array_push(program->inst, inst); + array_push(program->lines, line); + } + return reg_a; + } break; + default: { + printf("UNIMPLEMENTED\n"); + return (Operand){0}; + } break; + } +} + +ProgramBASM * +generate_basm(ParseTree *parse_tree) { + ProgramBASM *program = malloc(sizeof(ProgramBASM)); + array_init(program->inst, 0); + array_init(program->lines, 0); + for (size_t i = 0; i < array_size(parse_tree->roots); ++i) { + Node *root = parse_tree->roots[i]; + emit_basm(program, root); + } + return program; +} diff --git a/src/main.c b/src/main.c index 0fbabdb..72aac77 100644 --- a/src/main.c +++ b/src/main.c @@ -62,6 +62,10 @@ process_source(const StringView *source, const char *file_name) { viz_symtables(parse_tree->scopes); return; } + + ProgramBASM *program = generate_basm(parse_tree); + check_errors(file_name); + viz_basm(program); } void diff --git a/src/viz.c b/src/viz.c index ea8a817..eb5631b 100644 --- a/src/viz.c +++ b/src/viz.c @@ -235,3 +235,96 @@ viz_symtables(Scope **scopes) { } printf("}\n"); } + +static const char* basm_op_str[] = { + [OP_ADD] = "add ", + [OP_SUB] = "sub ", + [OP_MUL] = "mul ", + [OP_DIV] = "div ", + [OP_MOD] = "mod ", + [OP_LD8] = "ld8 ", + [OP_LD16] = "ld16 ", + [OP_LD32] = "ld32 ", + [OP_LD64] = "ld64 ", + [OP_ST8] = "st8 ", + [OP_ST16] = "st16 ", + [OP_ST32] = "st32 ", + [OP_ST64] = "st64 ", + [OP_CP8] = "cp8 ", + [OP_CP16] = "cp16 ", + [OP_CP32] = "cp32 ", + [OP_CP64] = "cp64 ", + [OP_NOT] = "not ", + [OP_AND] = "and ", + [OP_OR] = "or ", + [OP_XOR] = "xor ", + [OP_LSHIFT] = "lshift", + [OP_RSHIFT] = "rshift", + [OP_LROT] = "lrot ", + [OP_RROT] = "rrot ", + [OP_LABEL] = "lab ", + [OP_JMP] = "jmp ", + [OP_JMP_EQ] = "jeq ", + [OP_JMP_NEQ] = "jne ", + [OP_JMP_GT] = "jgt ", + [OP_JMP_LT] = "jlt ", + [OP_JMP_GE] = "jge ", + [OP_JMP_LE] = "jle ", +}; + +void +viz_operand(Operand op) { + switch (op.type) { + case OP_TYPE_LABEL: { + printf("l%zu", op.id); + } break; + case OP_TYPE_REG: { + printf("r%zu", op.id); + } break; + case OP_TYPE_CONST: { + printf("%lld", op.constant.uval); + } break; + } +} + +void +viz_instruction(Instruction *inst, LineInfo *line) { + printf("[%6ld:%-6ld] ", line->line, line->col); + printf("%s", basm_op_str[inst->op]); + switch (inst->op) { + case OP_ST8: + case OP_ST16: + case OP_ST32: + case OP_ST64: + case OP_LD8: + case OP_LD16: + case OP_LD32: + case OP_LD64: { + printf(" "); + viz_operand(inst->dst); + printf(", "); + viz_operand(inst->src_a); + if (inst->src_a.type != OP_TYPE_CONST) { + printf(", "); + viz_operand(inst->src_b); + } + } break; + default: { + printf(" "); + viz_operand(inst->dst); + printf(", "); + viz_operand(inst->src_a); + printf(", "); + viz_operand(inst->src_b); + } break; + } + printf("\n"); +} + +void +viz_basm(ProgramBASM *program) { + for (size_t i = 0; i < array_size(program->inst); ++i) { + viz_instruction(&program->inst[i], &program->lines[i]); + } + +} -- cgit v1.2.1