diff options
Diffstat (limited to 'src/bytecode')
-rw-r--r-- | src/bytecode/bytecode.c | 103 |
1 files changed, 95 insertions, 8 deletions
diff --git a/src/bytecode/bytecode.c b/src/bytecode/bytecode.c index 7feb185..6774a54 100644 --- a/src/bytecode/bytecode.c +++ b/src/bytecode/bytecode.c @@ -2,7 +2,11 @@ #include "../../include/std/mem.h" #include "../../include/ssa/ssa.h" #include "../../include/parser.h" +#include "../../include/compiler.h" #include <assert.h> +#include <stdio.h> /* TODO: Remove this */ +#include <stdlib.h> +#include <string.h> #define throw(result) do { throw_debug_msg; longjmp(self->env, (result)); } while(0) #define throw_if_error(result) \ @@ -62,6 +66,8 @@ static void add_intermediates(BytecodeCompilerContext *self) { } } +#define NUM_MAX_REGS 256 + static void add_instructions(BytecodeCompilerContext *self) { Ssa *ssa; u8 *instruction; @@ -70,10 +76,26 @@ static void add_instructions(BytecodeCompilerContext *self) { SsaInsForm2 ssa_ins_form2; SsaInsFuncStart ssa_ins_func_start; SsaInsFuncCall ssa_ins_func_call; + FILE *file; + char *filename; + LhsExpr *reg_types[NUM_MAX_REGS]; /* TODO: Remove this. Encode this data in the register itself */ ssa = self->parser->ssa; instruction = buffer_begin(&ssa->instructions); instructions_end = buffer_end(&ssa->instructions); + /*#warning "dont forget to remove this" */ + filename = malloc(self->parser->tokenizer.code_name.size + 3); + filename[0] = '\0'; + strcat(filename, self->parser->tokenizer.code_name.data); + strcat(filename, ".z"); + file = fopen(filename, "wb"); + free(filename); + #ifdef DEBUG + am_memset(reg_types, 0, sizeof(reg_types)); + #endif + + fputs("typedef i64 signed long long;\n", file); + fputs("typedef f64 double;\n", file); while(instruction != instructions_end) { switch(*instruction++) { @@ -81,43 +103,108 @@ static void add_instructions(BytecodeCompilerContext *self) { SsaNumber number; instruction += ssa_extract_form1(instruction, &ssa_ins_form1); number = ssa_get_intermediate(ssa, ssa_ins_form1.rhs); - (void)number; + assert(ssa_ins_form1.lhs < NUM_MAX_REGS); + if(number.type == SSA_NUMBER_TYPE_INTEGER) { + fprintf(file, "i64 r%d = %zu;\n", ssa_ins_form1.lhs, number.value.integer); + reg_types[ssa_ins_form1.lhs] = self->parser->compiler->default_types.i64; + } else if(number.type == SSA_NUMBER_TYPE_FLOAT) { + fprintf(file, "f64 r%d = %f;\n", ssa_ins_form1.lhs, number.value.floating); + reg_types[ssa_ins_form1.lhs] = self->parser->compiler->default_types.f64; + } else { + assert(bool_false && "TODO: Implement"); + } break; } - case SSA_ASSIGN_STRING: + case SSA_ASSIGN_STRING: { + BufferView str; instruction += ssa_extract_form1(instruction, &ssa_ins_form1); + str = ssa_get_string(ssa, ssa_ins_form1.rhs); + fprintf(file, "const char* r%d = \"%.*s\";\n", ssa_ins_form1.lhs, (int)str.size, str.data); + assert(ssa_ins_form1.lhs < NUM_MAX_REGS); + reg_types[ssa_ins_form1.lhs] = self->parser->compiler->default_types.str; break; - case SSA_ASSIGN_REG: + } + case SSA_ASSIGN_REG: { + LhsExpr *rhs_type; + const char *rhs_type_name; instruction += ssa_extract_form1(instruction, &ssa_ins_form1); + assert(ssa_ins_form1.rhs < NUM_MAX_REGS); + rhs_type = reg_types[ssa_ins_form1.rhs]; + if(rhs_type == self->parser->compiler->default_types.i64) { + rhs_type_name = "i64"; + } else if(rhs_type == self->parser->compiler->default_types.f64) { + rhs_type_name = "f64"; + } else if(rhs_type == self->parser->compiler->default_types.str) { + rhs_type_name = "const char*"; + } else { + amal_log_error("Invalid rhs type %p for reg %d", rhs_type, ssa_ins_form1.rhs); + assert(bool_false && "TODO: Implement"); + } + fprintf(file, "%s r%d = r%d;\n", rhs_type_name, ssa_ins_form1.lhs, ssa_ins_form1.rhs); break; - case SSA_ADD: + } + case SSA_ADD: { instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + fprintf(file, "r%d = r%d + r%d;\n", ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs); + assert(ssa_ins_form2.result < NUM_MAX_REGS); + assert(ssa_ins_form2.rhs < NUM_MAX_REGS); + reg_types[ssa_ins_form2.result] = reg_types[ssa_ins_form2.rhs]; break; - case SSA_SUB: + } + case SSA_SUB: { instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + fprintf(file, "r%d = r%d - r%d;\n", ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs); + assert(ssa_ins_form2.result < NUM_MAX_REGS); + assert(ssa_ins_form2.rhs < NUM_MAX_REGS); + reg_types[ssa_ins_form2.result] = reg_types[ssa_ins_form2.rhs]; break; - case SSA_MUL: + } + case SSA_MUL: { instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + fprintf(file, "r%d = r%d * r%d;\n", ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs); + assert(ssa_ins_form2.result < NUM_MAX_REGS); + assert(ssa_ins_form2.rhs < NUM_MAX_REGS); + reg_types[ssa_ins_form2.result] = reg_types[ssa_ins_form2.rhs]; break; - case SSA_DIV: + } + case SSA_DIV: { instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + fprintf(file, "r%d = r%d / r%d;\n", ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs); + assert(ssa_ins_form2.result < NUM_MAX_REGS); + assert(ssa_ins_form2.rhs < NUM_MAX_REGS); + reg_types[ssa_ins_form2.result] = reg_types[ssa_ins_form2.rhs]; break; - case SSA_FUNC_START: + } + case SSA_FUNC_START: { + int i; instruction += ssa_extract_func_start(instruction, &ssa_ins_func_start); + fprintf(file, "void f%zu(", ssa_ins_func_start.func_index); + fputs(") {\n", file); + for(i = 0; i < ssa_ins_func_start.num_args; ++i) { + if(i > 0) + fputs(", ", file); + fprintf(file, "p%d", i); + } break; + } case SSA_FUNC_END: + fputs("}\n", file); break; case SSA_PUSH: { SsaRegister reg; am_memcpy(®, instruction, sizeof(SsaRegister)); instruction += sizeof(SsaRegister); + fprintf(file, "PUSH r%d ***\n", reg); break; } case SSA_CALL: instruction += ssa_extract_func_call(instruction, &ssa_ins_func_call); + fprintf(file, "r%d = CALL %p ***\n", ssa_ins_func_call.result, ssa_ins_func_call.func_decl); break; } } + + fclose(file); } void generate_bytecode_from_ssa(BytecodeCompilerContext *self) { |