arm64: fix extern with offset

We need to add the offset after loading from the GOT.

This is a fix for the issue reported in [0], and removes the offsets
in isel to avoid the problem with large offsets in the naive patch.
This is similar to what is done on amd64.

Tested with cproc bootstrap using extern on aarch64.

[0] https://lists.sr.ht/~mpu/qbe/%3Cd71fac06-1208-4e4f-85a4-e5edc7fd979c@app.fastmail.com%3E#%3C2F4DUTRJ9GA5V.3VK2QXK848F7U@mforney.org%3E
This commit is contained in:
Michael Forney 2026-06-01 19:32:52 -07:00 committed by Quentin Carbonneaux
parent fa19d3c974
commit 80d745c842
2 changed files with 17 additions and 14 deletions

View File

@ -292,12 +292,13 @@ loadaddr(Con *c, char *rn, E *e)
"\tadd\tR, R, #:tprel_lo12_nc:SO\n"; "\tadd\tR, R, #:tprel_lo12_nc:SO\n";
break; break;
case SExt: case SExt:
assert(c->bits.i == 0);
if (T.apple) if (T.apple)
s = "\tadrp\tR, S@gotpageO\n" s = "\tadrp\tR, S@gotpage\n"
"\tldr\tR, [R, S@gotpageoffO]\n"; "\tldr\tR, [R, S@gotpageoff]\n";
else else
s = "\tadrp\tR, :got:SO\n" s = "\tadrp\tR, :got:S\n"
"\tldr\tR, [R, #:got_lo12:SO]\n"; "\tldr\tR, [R, #:got_lo12:S]\n";
break; break;
} }

View File

@ -78,9 +78,8 @@ fixarg(Ref *pr, int k, int phi, Fn *fn)
switch (rtype(r0)) { switch (rtype(r0)) {
case RCon: case RCon:
c = &fn->con[r0.val]; c = &fn->con[r0.val];
if (T.apple if (c->type == CAddr && ((c->sym.type & SExt)
&& c->type == CAddr || (T.apple && (c->sym.type & SThr)))) {
&& (c->sym.type & SThr)) {
r1 = newtmp("isel", Kl, fn); r1 = newtmp("isel", Kl, fn);
*pr = r1; *pr = r1;
if (c->bits.i) { if (c->bits.i) {
@ -91,16 +90,19 @@ fixarg(Ref *pr, int k, int phi, Fn *fn)
emit(Oadd, Kl, r1, r2, r3); emit(Oadd, Kl, r1, r2, r3);
r1 = r2; r1 = r2;
} }
if (T.apple && (c->sym.type & SThr)) {
emit(Ocopy, Kl, r1, TMP(R0), R); emit(Ocopy, Kl, r1, TMP(R0), R);
r1 = newtmp("isel", Kl, fn); r1 = newtmp("isel", Kl, fn);
r2 = newtmp("isel", Kl, fn); r2 = newtmp("isel", Kl, fn);
emit(Ocall, 0, R, r1, CALL(33)); emit(Ocall, 0, R, r1, CALL(33));
emit(Ocopy, Kl, TMP(R0), r2, R); emit(Ocopy, Kl, TMP(R0), r2, R);
emit(Oload, Kl, r1, r2, R); emit(Oload, Kl, r1, r2, R);
r1 = r2;
}
cc = *c; cc = *c;
cc.bits.i = 0; cc.bits.i = 0;
r3 = newcon(&cc, fn); r3 = newcon(&cc, fn);
emit(Ocopy, Kl, r2, r3, R); emit(Ocopy, Kl, r1, r3, R);
break; break;
} }
if (KBASE(k) == 0 && phi) if (KBASE(k) == 0 && phi)