aboutsummaryrefslogtreecommitdiff
path: root/amd64/isel.c
diff options
context:
space:
mode:
authorRichard McCormack <[email protected]>2026-01-07 06:23:46 -0500
committerQuentin Carbonneaux <[email protected]>2026-01-13 21:24:31 +0100
commitcf06ce159d149b625a4eee2fdf2be0d54ccca49d (patch)
tree47a245a725044b716f37555e86292ba7dd4c3169 /amd64/isel.c
parent640c78d0dadffdaf309bc148ef02075676200657 (diff)
Modify amd64 fixarg to fix calling constant addressesHEADmaster
On x86_64, direct calls are always PC-relative. This means that in order to call an absolute address, the call must be indirect. To accomplish this, update fixarg to introduce a temporary before emitting.
Diffstat (limited to 'amd64/isel.c')
-rw-r--r--amd64/isel.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/amd64/isel.c b/amd64/isel.c
index 73e0860..889c647 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -96,6 +96,14 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn)
a.offset.sym.id = intern(buf);
fn->mem[fn->nmem-1] = a;
}
+ else if (op == Ocall && r == &i->arg[0]
+ && rtype(r0) == RCon && fn->con[r0.val].type != CAddr) {
+ /* use a temporary register so that we
+ * produce an indirect call
+ */
+ r1 = newtmp("isel", Kl, fn);
+ emit(Ocopy, Kl, r1, r0, R);
+ }
else if (op != Ocopy && k == Kl && noimm(r0, fn)) {
/* load constants that do not fit in
* a 32bit signed integer into a