nooc

nooc programming language compiler
git clone git://git.nihaljere.xyz/nooc
Log | Files | Refs | LICENSE

commit 509c198f3ffb2130e492465f74be59c4a5b551e9
parent 4108fc4dede83faa443c8d50e17284c7b7f0abc2
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Thu, 20 Jan 2022 14:37:20 -0600

x64: handle backward jumps

Rather than using the `end_label` parameter, since we keep track of
label locations now, we can just determine the label location and
use that value as the end instruction in emitblock.

Diffstat:
Mir.c | 26+++++++++++++++++---------
Mx64.c | 23+++++++++++++----------
2 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/ir.c b/ir.c @@ -19,6 +19,7 @@ extern struct assgns assgns; extern struct toplevel toplevel; #define STARTINS(op, val, valtype) putins((out), (op), (val), (valtype)) ; curi++ ; +#define LABEL(l) array_addlit((&out->labels), reali); STARTINS(IR_LABEL, l, VT_LABEL); #define NEWTMP tmpi++; interval.start = curi + 1; interval.end = curi + 1; array_add((&out->temps), interval); #define PTRSIZE 8 @@ -28,6 +29,7 @@ extern struct target targ; static uint64_t tmpi; static uint64_t labeli; static uint64_t curi; +static uint64_t reali; static struct temp interval; static uint16_t regs; // used register bitfield @@ -139,12 +141,12 @@ putins(struct iproc *out, int op, uint64_t val, int valtype) } array_add(out, ins); + reali++; } static uint64_t bumplabel(struct iproc *out) { - array_add((&out->labels), curi); return labeli++; } @@ -193,7 +195,7 @@ static int genexpr(struct iproc *out, size_t expri, uint64_t *val) { struct expr *expr = &exprs.data[expri]; - uint64_t temp2 = 0; + uint64_t temp2 = 0, temp; switch (expr->kind) { case EXPR_LIT: switch (expr->class) { @@ -307,16 +309,21 @@ genexpr(struct iproc *out, size_t expri, uint64_t *val) case EXPR_COND: { uint64_t condtmp; int valtype = genexpr(out, expr->d.cond.cond, &condtmp); - size_t elselabel = bumplabel(out); size_t endlabel = bumplabel(out); - STARTINS(IR_CONDJUMP, elselabel, VT_LABEL); - putins(out, IR_EXTRA, condtmp, valtype); - genblock(out, &expr->d.cond.bif); - STARTINS(IR_JUMP, endlabel, VT_LABEL); if (expr->d.cond.belse.len) { - putins(out, IR_LABEL, elselabel, VT_LABEL); + size_t elselabel = bumplabel(out); + STARTINS(IR_CONDJUMP, elselabel, VT_LABEL); + putins(out, IR_EXTRA, condtmp, valtype); + genblock(out, &expr->d.cond.bif); + STARTINS(IR_JUMP, endlabel, VT_LABEL); + LABEL(elselabel); genblock(out, &expr->d.cond.belse); - putins(out, IR_LABEL, endlabel, VT_LABEL); + LABEL(endlabel); + } else { + STARTINS(IR_CONDJUMP, endlabel, VT_LABEL); + putins(out, IR_EXTRA, condtmp, valtype); + genblock(out, &expr->d.cond.bif); + LABEL(endlabel); } return VT_EMPTY; } @@ -424,6 +431,7 @@ size_t genproc(struct decl *decl, struct proc *proc) { tmpi = labeli = curi = 1; + reali = 0; regs = targ.reserved; struct type *type; struct iproc iproc = { diff --git a/x64.c b/x64.c @@ -795,14 +795,14 @@ emitsyscall(struct data *text, uint8_t paramcount) } size_t -emitblock(struct data *text, struct iproc *proc, struct instr *start, struct instr *end, uint64_t end_label, uint16_t active, uint16_t curi) +emitblock(struct data *text, struct iproc *proc, struct instr *start, struct instr *end, uint16_t active, uint16_t curi) { struct instr *ins = start ? start : proc->data; end = end ? end : &proc->data[proc->len]; uint64_t dest, src, size, count, label; int64_t offset; - uint64_t localalloc = 0, curlabel = 0; + uint64_t localalloc = 0; size_t total = 0; if (!start) { @@ -820,11 +820,14 @@ emitblock(struct data *text, struct iproc *proc, struct instr *start, struct ins active |= 1 << proc->temps.data[j].reg; } switch (ins->op) { - // FIXME: we don't handle jumps backward yet case IR_JUMP: assert(ins->valtype == VT_LABEL); label = ins->val; - total += jmp(text, emitblock(NULL, proc, ins + 1, end, label, active, curi)); + if (ins < &proc->data[proc->labels.data[label]]) { + total += jmp(text, emitblock(NULL, proc, ins + 1, &proc->data[proc->labels.data[label]], active, curi)); + } else { + total += jmp(text, emitblock(NULL, proc, start, &proc->data[proc->labels.data[label]], 0, 0) - total - 2); // FIXME: 2 = size of short jump + } NEXT; break; case IR_CONDJUMP: @@ -835,7 +838,11 @@ emitblock(struct data *text, struct iproc *proc, struct instr *start, struct ins assert(ins->op == IR_EXTRA); assert(ins->valtype == VT_TEMP); total += cmp_r8_imm(text, proc->temps.data[ins->val].reg, 0); - total += je(text, emitblock(NULL, proc, ins + 1, end, label, active, curi)); + if (ins < &proc->data[proc->labels.data[label]]) { + total += je(text, emitblock(NULL, proc, ins + 1, &proc->data[proc->labels.data[label]], active, curi)); + } else { + total += je(text, emitblock(NULL, proc, start, &proc->data[proc->labels.data[label]], 0, 0)- total - 2); // FIXME: 2 = size of short jump + } NEXT; break; case IR_RETURN: @@ -1008,10 +1015,6 @@ emitblock(struct data *text, struct iproc *proc, struct instr *start, struct ins break; case IR_LABEL: assert(ins->valtype == VT_LABEL); - if (ins->val == end_label) - goto done; - - curlabel = ins->val; NEXT; break; case IR_IMM: @@ -1029,5 +1032,5 @@ done: size_t emitproc(struct data *text, struct iproc *proc) { - return emitblock(text, proc, NULL, NULL, 0, 0, 0); + return emitblock(text, proc, NULL, NULL, 0, 0); }