aboutsummaryrefslogtreecommitdiff
path: root/src/bytecode
diff options
context:
space:
mode:
Diffstat (limited to 'src/bytecode')
-rw-r--r--src/bytecode/bytecode.c126
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(&reg, 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);
+}