aboutsummaryrefslogtreecommitdiff
path: root/arm64
diff options
context:
space:
mode:
authorQuentin Carbonneaux <[email protected]>2022-09-01 19:03:53 +0200
committerQuentin Carbonneaux <[email protected]>2022-09-01 19:03:53 +0200
commitf135a0b1fdfd22b0f32e5021ab4e486e681129a1 (patch)
tree001a0107513023c73b2034a75374bfa26b646bd8 /arm64
parent8dddb971d923fa19dced39013e6d4a39676e065a (diff)
use direct bl calls on arm64
This generates tidier code and is pic friendly because it lets the linker trampoline calls to dynlinked libs.
Diffstat (limited to 'arm64')
-rw-r--r--arm64/emit.c16
-rw-r--r--arm64/isel.c21
2 files changed, 35 insertions, 2 deletions
diff --git a/arm64/emit.c b/arm64/emit.c
index ec4d350..694abf3 100644
--- a/arm64/emit.c
+++ b/arm64/emit.c
@@ -306,10 +306,11 @@ fixarg(Ref *pr, int sz, E *e)
static void
emitins(Ins *i, E *e)
{
- char *rn;
+ char *l, *p, *rn;
uint64_t s;
int o;
Ref r;
+ Con *c;
switch (i->op) {
default:
@@ -355,7 +356,8 @@ emitins(Ins *i, E *e)
assert(isreg(i->to));
switch (rtype(i->arg[0])) {
case RCon:
- loadcon(&e->fn->con[i->arg[0].val], i->to.val, i->cls, e->f);
+ c = &e->fn->con[i->arg[0].val];
+ loadcon(c, i->to.val, i->cls, e->f);
break;
case RSlot:
i->op = Oload;
@@ -386,6 +388,16 @@ emitins(Ins *i, E *e)
rn, s & 0xFFFF, rn, s >> 16, rn, rn
);
break;
+ case Ocall:
+ if (rtype(i->arg[0]) != RCon)
+ goto Table;
+ c = &e->fn->con[i->arg[0].val];
+ if (c->type != CAddr || c->bits.i)
+ die("invalid call argument");
+ l = str(c->label);
+ p = l[0] == '"' ? "" : T.assym;
+ fprintf(e->f, "\tbl\t%s%s\n", p, l);
+ break;
case Osalloc:
emitf("sub sp, sp, %0", i, e);
if (!req(i->to, R))
diff --git a/arm64/isel.c b/arm64/isel.c
index f064321..c80e481 100644
--- a/arm64/isel.c
+++ b/arm64/isel.c
@@ -156,6 +156,22 @@ selcmp(Ref arg[2], int k, Fn *fn)
return swap;
}
+static int
+callable(Ref r, Fn *fn)
+{
+ Con *c;
+
+ if (rtype(r) == RTmp)
+ return 1;
+ if (rtype(r) == RCon) {
+ c = &fn->con[r.val];
+ if (c->type == CAddr)
+ if (c->bits.i == 0)
+ return 1;
+ }
+ return 0;
+}
+
static void
sel(Ins i, Fn *fn)
{
@@ -178,6 +194,11 @@ sel(Ins i, Fn *fn)
i0->op += cc;
return;
}
+ if (i.op == Ocall)
+ if (callable(i.arg[0], fn)) {
+ emiti(i);
+ return;
+ }
if (i.op != Onop) {
emiti(i);
iarg = curi->arg; /* fixarg() can change curi */