aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-11-22 19:32:24 +0100
committerlemon <lsof@mailbox.org>2025-11-22 19:40:25 +0100
commitd030198aea96012b635b559fc6021fd954205395 (patch)
treed4105f373c5b38f6b8bc680cf7c919602bd9945e
parent8cf560c502542af972eabd201a5b7bf05c891078 (diff)
make sure indirect function call pointer does not end up in clobber reg
-rw-r--r--amd64/isel.c5
-rw-r--r--ir/regalloc.c4
2 files changed, 7 insertions, 2 deletions
diff --git a/amd64/isel.c b/amd64/isel.c
index 6541c10..26ee6e0 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -147,6 +147,11 @@ selcall(struct function *fn, struct instr *ins, struct block *blk, int *curi)
++*curi;
insertinstr(blk, *curi+1, (struct instr){Oadd, KPTR, .keep=1, .reg = RSP+1, .l=mkref(RREG,RSP), disp});
}
+ if (call->vararg >= 0 && ins->l.t == RTMP) {
+ /* variadic calls write number of sse regs used to AL, so mark it as clobbered such that
+ * the function pointer of an indirect calls does not get allocated to RAX by regalloc */
+ insertinstr(blk, (*curi)++, mkinstr(Omove, KPTR, mkref(RREG, RAX), mkref(RREG, RAX)));
+ }
cls = ins->cls;
ins->cls = 0;
if (cls) {
diff --git a/ir/regalloc.c b/ir/regalloc.c
index f859cdd..d3c1ee0 100644
--- a/ir/regalloc.c
+++ b/ir/regalloc.c
@@ -519,7 +519,7 @@ usereg(struct rega *ra, int reg, struct block *blk, int pos)
if (rstest(mctarg->rglob, reg)) return; /* regalloc never allocates globally live regs, so don't need intervals for those */
for (struct fixinterval *fxit = ra->intervals.fixed; fxit; fxit = fxit->next) {
if (fxit->range.from > pos) break;
- if (fxit->rs == 1<<reg && fxit->range.from <= pos && pos <= fxit->range.to) {
+ if (fxit->rs == 1<<reg && fxit->range.from <= pos && pos < fxit->range.to) {
/* contained by existing interval */
fxit->range.from = blk->inumstart;
return;
@@ -619,7 +619,7 @@ buildintervals(struct rega *ra)
if (ins->op == Omove) {
assert(ins->l.t == RREG);
if (ins->l.bits == ins->r.bits) /* special case `move Rx,Rx`: clobber reg, not a real use */
- usereg(ra, ins->l.i, blk, pos+1); /* +1 to avoid empty interval [pos,pos) */
+ usereg(ra, ins->l.i, blk, pos);
defreg(ra, ins->l.i, pos);
if (ins->l.bits == ins->r.bits)
continue;