diff options
author | dec05eba <dec05eba@protonmail.com> | 2019-03-12 01:27:54 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2020-07-25 14:36:46 +0200 |
commit | b35b3e1bf70bf764940498247b1db5bb02761160 (patch) | |
tree | 07ad41028fd3d162e9e681a03b75df1cfc740606 /src/ssa | |
parent | 79bf40f909cefdc611bfa13f70ae55b52ac41d23 (diff) |
Starting on ssa
Diffstat (limited to 'src/ssa')
-rw-r--r-- | src/ssa/ssa.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c new file mode 100644 index 0000000..3433e8d --- /dev/null +++ b/src/ssa/ssa.c @@ -0,0 +1,165 @@ +#include "../../include/ssa/ssa.h" +#include "../../include/std/mem.h" +#include "../../include/std/log.h" +#include <assert.h> + +static int compare_number(const void *a, const void *b) { + const SsaNumber *lhs; + const SsaNumber *rhs; + lhs = a; + rhs = b; + if(rhs->type == lhs->type && rhs->value == lhs->value) + return 0; + return 1; +} + +static usize hash_number(const u8 *data, usize size) { + SsaNumber number; + assert(size == sizeof(SsaNumber)); + am_memcpy(&number, data, size); + return number.value; +} + +SsaNumber create_ssa_number(i64 value, SsaNumberType type) { + SsaNumber result; + result.value = value; + result.type = type; + return result; +} + +int ssa_init(Ssa *self, ScopedAllocator *allocator) { + return_if_error(buffer_init(&self->instructions, allocator)); + return_if_error(hash_map_init(&self->intermediates, allocator, sizeof(SsaIntermediateIndex), compare_number, hash_number)); + self->intermediate_counter = 0; + self->reg_counter = 0; + self->func_counter = 0; + return 0; +} + +int ssa_get_unique_reg(Ssa *self, SsaRegister *result) { + /* Overflow */ + if(self->reg_counter + 1 < self->reg_counter) + return -1; + *result = self->reg_counter++; + return 0; +} + +static CHECK_RESULT int ssa_try_add_intermediate(Ssa *self, i64 intermediate, SsaNumberType number_type, SsaIntermediateIndex *result_index) { + SsaNumber number; + bool exists; + BufferView key; + + assert(result_index); + number = create_ssa_number(intermediate, number_type); + key = create_buffer_view((const char*)&number, sizeof(number)); + + exists = hash_map_get(&self->intermediates, key, result_index); + if(exists) + return 0; + + /* Overflow */ + if(self->intermediate_counter + 1 < self->intermediate_counter) + return -1; + + *result_index = self->intermediate_counter; + ++self->intermediate_counter; + return hash_map_insert(&self->intermediates, key, result_index); +} + +static CHECK_RESULT int ssa_add_ins_form1(Ssa *self, SsaInstructionType ins_type, SsaRegister lhs, u16 rhs) { + usize index; + index = self->instructions.size; + + return_if_error(buffer_append(&self->instructions, NULL, sizeof(u8) + sizeof(SsaRegister) + sizeof(u16))); + self->instructions.data[index + 0] = ins_type; + *(SsaRegister*)&self->instructions.data[index + 1] = lhs; + *(u16*)&self->instructions.data[index + 3] = rhs; + return 0; +} + +static CHECK_RESULT int ssa_add_ins_form2(Ssa *self, SsaInstructionType ins_type, SsaRegister lhs, SsaRegister rhs, SsaRegister *result) { + usize index; + index = self->instructions.size; + + /* Overflow */ + if(self->reg_counter + 1 < self->reg_counter) + return -1; + + assert(result); + return_if_error(buffer_append(&self->instructions, NULL, sizeof(u8) + sizeof(SsaRegister) + sizeof(SsaRegister) + sizeof(SsaRegister))); + *result = self->reg_counter++; + self->instructions.data[index + 0] = ins_type; + *(SsaRegister*)&self->instructions.data[index + 1] = *result; + *(SsaRegister*)&self->instructions.data[index + 3] = lhs; + *(SsaRegister*)&self->instructions.data[index + 5] = rhs; + amal_log_debug("r%u = r%u + r%u", *result, lhs, rhs); + return 0; +} + +int ssa_ins_assign_inter(Ssa *self, SsaRegister dest, SsaNumber number) { + SsaIntermediateIndex index; + return_if_error(ssa_try_add_intermediate(self, number.value, number.type, &index)); + amal_log_debug("r%u = i%u", dest, index); + return ssa_add_ins_form1(self, SSA_ASSIGN_INTER, dest, index); +} + +int ssa_ins_assign_reg(Ssa *self, SsaRegister dest, SsaRegister src) { + amal_log_debug("r%u = r%u", dest, src); + return ssa_add_ins_form1(self, SSA_ASSIGN_INTER, dest, src); +} + +int ssa_ins_binop(Ssa *self, SsaInstructionType binop_type, SsaRegister lhs, SsaRegister rhs, SsaRegister *result) { + assert(binop_type >= SSA_ADD && binop_type <= SSA_DIV); + return ssa_add_ins_form2(self, binop_type, lhs, rhs, result); +} + +int ssa_ins_func_start(Ssa *self, u8 num_args, SsaFuncIndex *result) { + usize index; + index = self->instructions.size; + + /* Overflow */ + if(self->func_counter + 1 < self->func_counter) + return -1; + + return_if_error(buffer_append(&self->instructions, NULL, sizeof(u8) + sizeof(SsaFuncIndex) + sizeof(u8))); + *result = self->func_counter++; + self->instructions.data[index + 0] = SSA_FUNC_START; + *(SsaFuncIndex*)&self->instructions.data[index + 1] = *result; + self->instructions.data[index + 3] = num_args; + amal_log_debug("FUNC_START f%u(%u)", *result, num_args); + return 0; +} + +int ssa_ins_func_end(Ssa *self) { + SsaInstructionType ins; + ins = SSA_FUNC_END; + return buffer_append(&self->instructions, &ins, 1); +} + +int ssa_ins_push(Ssa *self, SsaRegister reg) { + usize index; + index = self->instructions.size; + + return_if_error(buffer_append(&self->instructions, NULL, sizeof(u8) + sizeof(SsaRegister))); + self->instructions.data[index + 0] = SSA_PUSH; + *(SsaRegister*)&self->instructions.data[index + 1] = reg; + amal_log_debug("PUSH r%u", reg); + return 0; +} + +int ssa_ins_call(Ssa *self, SsaFuncIndex func, SsaRegister *result) { + usize index; + index = self->instructions.size; + + /* Overflow */ + if(self->reg_counter + 1 < self->reg_counter) + return -1; + + return_if_error(buffer_append(&self->instructions, NULL, sizeof(u8) + sizeof(SsaFuncIndex) + sizeof(SsaRegister))); + *result = self->reg_counter++; + self->instructions.data[index + 0] = SSA_CALL; + *(SsaFuncIndex*)&self->instructions.data[index + 1] = func; + *(SsaRegister*)&self->instructions.data[index + 3] = *result; + amal_log_debug("r%u = CALL f%u", *result, func); + return 0; +} |