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:
M | ir.c | | | 26 | +++++++++++++++++--------- |
M | x64.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);
}