From 80d745c842b4dafe02a69a6eb15e4f8ff72d42fa Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Mon, 1 Jun 2026 19:32:52 -0700 Subject: [PATCH] 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 --- arm64/emit.c | 9 +++++---- arm64/isel.c | 22 ++++++++++++---------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/arm64/emit.c b/arm64/emit.c index 64d85f7..5da9be9 100644 --- a/arm64/emit.c +++ b/arm64/emit.c @@ -292,12 +292,13 @@ loadaddr(Con *c, char *rn, E *e) "\tadd\tR, R, #:tprel_lo12_nc:SO\n"; break; case SExt: + assert(c->bits.i == 0); if (T.apple) - s = "\tadrp\tR, S@gotpageO\n" - "\tldr\tR, [R, S@gotpageoffO]\n"; + s = "\tadrp\tR, S@gotpage\n" + "\tldr\tR, [R, S@gotpageoff]\n"; else - s = "\tadrp\tR, :got:SO\n" - "\tldr\tR, [R, #:got_lo12:SO]\n"; + s = "\tadrp\tR, :got:S\n" + "\tldr\tR, [R, #:got_lo12:S]\n"; break; } diff --git a/arm64/isel.c b/arm64/isel.c index 7b78202..7ab4a48 100644 --- a/arm64/isel.c +++ b/arm64/isel.c @@ -78,9 +78,8 @@ fixarg(Ref *pr, int k, int phi, Fn *fn) switch (rtype(r0)) { case RCon: c = &fn->con[r0.val]; - if (T.apple - && c->type == CAddr - && (c->sym.type & SThr)) { + if (c->type == CAddr && ((c->sym.type & SExt) + || (T.apple && (c->sym.type & SThr)))) { r1 = newtmp("isel", Kl, fn); *pr = r1; if (c->bits.i) { @@ -91,16 +90,19 @@ fixarg(Ref *pr, int k, int phi, Fn *fn) emit(Oadd, Kl, r1, r2, r3); r1 = r2; } - emit(Ocopy, Kl, r1, TMP(R0), R); - r1 = newtmp("isel", Kl, fn); - r2 = newtmp("isel", Kl, fn); - emit(Ocall, 0, R, r1, CALL(33)); - emit(Ocopy, Kl, TMP(R0), r2, R); - emit(Oload, Kl, r1, r2, R); + if (T.apple && (c->sym.type & SThr)) { + emit(Ocopy, Kl, r1, TMP(R0), R); + r1 = newtmp("isel", Kl, fn); + r2 = newtmp("isel", Kl, fn); + emit(Ocall, 0, R, r1, CALL(33)); + emit(Ocopy, Kl, TMP(R0), r2, R); + emit(Oload, Kl, r1, r2, R); + r1 = r2; + } cc = *c; cc.bits.i = 0; r3 = newcon(&cc, fn); - emit(Ocopy, Kl, r2, r3, R); + emit(Ocopy, Kl, r1, r3, R); break; } if (KBASE(k) == 0 && phi)