From 3272b5d83d2e2167eed24748557df88bd66584ee Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Fri, 5 Jan 2018 23:42:24 +0100 Subject: There's actually a chance that, correctly stringified, this will work --- to_assembly.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 to_assembly.c (limited to 'to_assembly.c') diff --git a/to_assembly.c b/to_assembly.c new file mode 100644 index 0000000..ab5c845 --- /dev/null +++ b/to_assembly.c @@ -0,0 +1,71 @@ +#include +#include "to_assembly.h" + + +static bool is_function_label(const char *lbl) { + return memcmp(lbl, "__", 2) != 0; +} + +static void fix_everything(struct ir *ir, const int startidx, struct allocation *ral) { + int spillspace = 0; + + for (int idx = startidx + 1; idx < ir->len; idx++) { + struct irins *ins = ir->inss[idx]; + + if (ins->type == INS_LBL && is_function_label(ins->name)) break; + + if (ins->type == INS_CALLV) { + ins->type = INS_CALL; + ir_insert_before(ir, idx + 1, irins_make_01(INS_MOV, ins->r0, ref_reg(REG_A))); + idx--; + continue; + } + if (ins->type == INS_RETV) { + ir_insert_before(ir, idx, irins_make_01(INS_MOV, ref_reg(REG_A), ins->r1)); + ins->type = INS_RET; + idx--; + continue; + } + + bool haveref[3]; + irins_which_refs(ins, haveref); + for (int ri = 0; ri < 3; ri++) { + struct ref *ref = &ins->three_refs[ri]; + if (haveref[ri] && ref->type == REF_REG && ref->reg >= 0) { + if (ral->allocs[ref->reg].spill) { + *ref = ref_mem(REG_BP, spillspace + 1, REFREL_ZERO); + spillspace++; + } else { + ref->reg = ral->allocs[ref->reg].reg; + } + } + } + } + + if (spillspace == 0) return; + + ir_insert_before(ir, startidx + 1, irins_make_1(INS_PUSH, ref_reg(REG_BP))); + ir_insert_before(ir, startidx + 2, irins_make_01(INS_MOV, ref_reg(REG_BP), ref_reg(REG_SP))); + ir_insert_before(ir, startidx + 3, + irins_make_012(INS_SUB, ref_reg(REG_SP), ref_reg(REG_SP), ref_imm(spillspace))); + + for (int idx = startidx + 1; idx < ir->len; idx++) { + struct irins *ins = ir->inss[idx]; + + if (ins->type == INS_LBL && is_function_label(ins->name)) break; + + if (ins->type == INS_RET) { + ir_insert_before(ir, idx++, irins_make_01(INS_MOV, ref_reg(REG_SP), ref_reg(REG_BP))); + ir_insert_before(ir, idx++, irins_make_0(INS_POP, ref_reg(REG_BP))); + continue; + } + } +} + +void to_assembly(struct ir *ir, struct allocation *ral) { + for (int idx = 0; idx < ir->len; idx++) { + if (ir->inss[idx]->type == INS_LBL && is_function_label(ir->inss[idx]->name)) { + fix_everything(ir, idx, ral); + } + } +} -- cgit v1.2.3-54-g00ecf