diff options
| author | 2026-02-28 09:12:18 +0100 | |
|---|---|---|
| committer | 2026-02-28 09:12:18 +0100 | |
| commit | c0db7d92c14b242daf008f7e3731a5d080e23fa1 (patch) | |
| tree | 67dd8011f4e5d2a5dda5df559b7617b9e8e4dd96 | |
| parent | 441dad512b47a4ff3998f4f1c81068d40d32dc75 (diff) | |
regalloc: fix defn of spilled var with immediate
With `i64 %a = copy 0xabcdef12345`, if `%a` was spilled, this would turn
into a `storei64` instruction with an unencondable immediate operand
(larger than 32 bits in x86, non-zero in aarch64).
| -rw-r--r-- | aarch64/emit.c | 3 | ||||
| -rw-r--r-- | ir/regalloc.c | 15 |
2 files changed, 16 insertions, 2 deletions
diff --git a/aarch64/emit.c b/aarch64/emit.c index 3fd3278..fdcb866 100644 --- a/aarch64/emit.c +++ b/aarch64/emit.c @@ -831,7 +831,8 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc case Ostorei32: cls = KI32; X2 = Xstr; goto Store; case Ostorei64: cls = KI64; X2 = Xstr; Store: - X2(pcode, cls, ref2oper(ins->r), mkmemoper(1<<(ins->op-Ostorei8), ins->l)); + X2(pcode, cls, ins->r.bits == ZEROREF.bits ? REGZR : ref2oper(ins->r), + mkmemoper(1<<(ins->op-Ostorei8), ins->l)); break; case Ostoref32: case Ostoref64: Xfstr(pcode, KF32 + ins->op-Ostoref32, ref2oper(ins->r), mkmemoper(ins->op == Oloadf32 ? 4 : 8, ins->l)); diff --git a/ir/regalloc.c b/ir/regalloc.c index 85b6a65..aa18e10 100644 --- a/ir/regalloc.c +++ b/ir/regalloc.c @@ -1033,6 +1033,19 @@ linearscan(struct rega *ra) DBG("\n"); } +static bool +isstoreimm(union ref r) +{ + if (r.t == RTMP) return 1; /* register OK */ + if (isintcon(r)) switch (target.arch) { + case ISxxx: assert(0); + /* TODO don't hard code this architecture dependent dispatch */ + case ISx86_64: return concls(r) == KI32; /* x86: MOV [addr], imm32 */ + case ISaarch64: return r.i == 0; /* arm doesn't have STR <imm>, but has zero register */ + } + return 0; +} + /* replace temps with physical regs, add loads & stores for spilled temps */ static bool devirt(struct rega *ra, struct block *blk) @@ -1139,7 +1152,7 @@ devirt(struct rega *ra, struct block *blk) enum irclass cls = insrescls(*ins); int store = cls2store[cls]; /* t was spilled, gen store */ - if (ins->op == Ocopy && ins->l.t != RADDR && !isaddrcon(ins->l,0)) { + if (ins->op == Ocopy && isstoreimm(ins->l)) { ins->op = store; ins->r = ins->l; addstkslotref(temp, alloc->a*8); |