diff options
Diffstat (limited to 'src/bytecode')
-rw-r--r-- | src/bytecode/bytecode.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/bytecode/bytecode.c b/src/bytecode/bytecode.c new file mode 100644 index 0000000..7feb185 --- /dev/null +++ b/src/bytecode/bytecode.c @@ -0,0 +1,126 @@ +#include "../../include/bytecode/bytecode.h" +#include "../../include/std/mem.h" +#include "../../include/ssa/ssa.h" +#include "../../include/parser.h" +#include <assert.h> + +#define throw(result) do { throw_debug_msg; longjmp(self->env, (result)); } while(0) +#define throw_if_error(result) \ + do { \ + int return_if_result; \ + return_if_result = (result); \ + if((return_if_result) != 0) \ + throw(return_if_result); \ + } while(0) + +int bytecode_init(Bytecode *self, ScopedAllocator *allocator) { + return buffer_init(&self->instructions, allocator); +} + +static CHECK_RESULT usize ssa_extract_form1(u8 *instruction_data, SsaInsForm1 *result) { + am_memcpy(&result->lhs, instruction_data, sizeof(result->lhs)); + am_memcpy(&result->rhs, instruction_data + sizeof(result->lhs), sizeof(result->rhs)); + return sizeof(result->lhs) + sizeof(result->rhs); +} + +static CHECK_RESULT usize ssa_extract_form2(u8 *instruction_data, SsaInsForm2 *result) { + am_memcpy(&result->result, instruction_data, sizeof(result->result)); + am_memcpy(&result->lhs, instruction_data + sizeof(result->result), sizeof(result->lhs)); + am_memcpy(&result->rhs, instruction_data + sizeof(result->result) + sizeof(result->lhs), sizeof(result->rhs)); + return sizeof(result->result) + sizeof(result->lhs) + sizeof(result->rhs); +} + +static CHECK_RESULT usize ssa_extract_func_start(u8 *instruction_data, SsaInsFuncStart *result) { + am_memcpy(&result->func_index, instruction_data, sizeof(result->func_index)); + am_memcpy(&result->num_args, instruction_data + sizeof(result->func_index), sizeof(result->num_args)); + return sizeof(result->func_index) + sizeof(result->num_args); +} + +static CHECK_RESULT usize ssa_extract_func_call(u8 *instruction_data, SsaInsFuncCall *result) { + am_memcpy(&result->result, instruction_data, sizeof(result->result)); + am_memcpy(&result->func_decl, instruction_data + sizeof(result->result), sizeof(result->func_decl)); + return sizeof(result->result) + sizeof(result->func_decl); +} + +static void add_intermediates(BytecodeCompilerContext *self) { + Ssa *ssa; + Buffer *instructions; + SsaNumber *intermediate; + SsaNumber *intermediates_end; + + ssa = self->parser->ssa; + instructions = &self->bytecode->instructions; + intermediate = buffer_begin(&ssa->intermediates); + intermediates_end = buffer_end(&ssa->intermediates); + + throw_if_error(buffer_expand(instructions, + sizeof(u16) + (sizeof(u8) + sizeof(u64)) * ssa->intermediates.size)); + throw_if_error(buffer_append(instructions, &ssa->intermediates.size, sizeof(u16))); + for(; intermediate != intermediates_end; ++intermediate) { + throw_if_error(buffer_append(instructions, &intermediate->type, sizeof(u8))); + throw_if_error(buffer_append(instructions, &intermediate->value.integer, sizeof(u64))); + } +} + +static void add_instructions(BytecodeCompilerContext *self) { + Ssa *ssa; + u8 *instruction; + u8 *instructions_end; + SsaInsForm1 ssa_ins_form1; + SsaInsForm2 ssa_ins_form2; + SsaInsFuncStart ssa_ins_func_start; + SsaInsFuncCall ssa_ins_func_call; + + ssa = self->parser->ssa; + instruction = buffer_begin(&ssa->instructions); + instructions_end = buffer_end(&ssa->instructions); + + while(instruction != instructions_end) { + switch(*instruction++) { + case SSA_ASSIGN_INTER: { + SsaNumber number; + instruction += ssa_extract_form1(instruction, &ssa_ins_form1); + number = ssa_get_intermediate(ssa, ssa_ins_form1.rhs); + (void)number; + break; + } + case SSA_ASSIGN_STRING: + instruction += ssa_extract_form1(instruction, &ssa_ins_form1); + break; + case SSA_ASSIGN_REG: + instruction += ssa_extract_form1(instruction, &ssa_ins_form1); + break; + case SSA_ADD: + instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + break; + case SSA_SUB: + instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + break; + case SSA_MUL: + instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + break; + case SSA_DIV: + instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + break; + case SSA_FUNC_START: + instruction += ssa_extract_func_start(instruction, &ssa_ins_func_start); + break; + case SSA_FUNC_END: + break; + case SSA_PUSH: { + SsaRegister reg; + am_memcpy(®, instruction, sizeof(SsaRegister)); + instruction += sizeof(SsaRegister); + break; + } + case SSA_CALL: + instruction += ssa_extract_func_call(instruction, &ssa_ins_func_call); + break; + } + } +} + +void generate_bytecode_from_ssa(BytecodeCompilerContext *self) { + add_intermediates(self); + add_instructions(self); +} |