diff options
| author | 2025-11-22 19:32:24 +0100 | |
|---|---|---|
| committer | 2025-11-22 19:40:25 +0100 | |
| commit | d030198aea96012b635b559fc6021fd954205395 (patch) | |
| tree | d4105f373c5b38f6b8bc680cf7c919602bd9945e | |
| parent | 8cf560c502542af972eabd201a5b7bf05c891078 (diff) | |
make sure indirect function call pointer does not end up in clobber reg
| -rw-r--r-- | amd64/isel.c | 5 | ||||
| -rw-r--r-- | ir/regalloc.c | 4 |
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; |