commit 503c672d47695afe62fdf3439732ec96a68903b0
parent 462e49fd5c8ff82a341212d9a66621727c70fe1d
Author: Quentin Carbonneaux <quentin@c9x.me>
Date: Sun, 17 Oct 2021 20:56:25 +0200
amd64/sysv: unbreak env calls
Env calls were disfunctional from the
start. This fixes them on amd64, but
they remain to do on arm64. A new
test shows how to use them.
Diffstat:
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/amd64/sysv.c b/amd64/sysv.c
@@ -203,7 +203,7 @@ argsclass(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret, Ref *env)
break;
}
- return ((6-nint) << 4) | ((8-nsse) << 8);
+ return (!req(R, *env) << 12) | ((6-nint) << 4) | ((8-nsse) << 8);
}
int amd64_sysv_rsave[] = {
@@ -362,7 +362,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap)
varc = i1->op == Ovacall;
if (varc && envc)
err("sysv abi does not support variadic env calls");
- ca |= (varc | envc) << 12;
+ ca |= varc << 12; /* envc set in argsclass() */
emit(Ocall, i1->cls, R, i1->arg[0], CALL(ca));
if (envc)
emit(Ocopy, Kl, TMP(RAX), env, R);
@@ -373,7 +373,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap)
if (ra && aret.inmem)
emit(Ocopy, Kl, rarg(Kl, &ni, &ns), ra->i.to, R); /* pass hidden argument */
for (i=i0, a=ac; i<i1; i++, a++) {
- if (a->inmem)
+ if (a->inmem || i->op == Oarge)
continue;
r1 = rarg(a->cls[0], &ni, &ns);
if (i->op == Oargc) {
@@ -466,6 +466,8 @@ selpar(Fn *fn, Ins *i0, Ins *i1)
s += 2;
continue;
}
+ if (i->op == Opare)
+ continue;
r = rarg(a->cls[0], &ni, &ns);
if (i->op == Oparc) {
emit(Ocopy, a->cls[0], a->ref[0], r, R);
diff --git a/test/env.ssa b/test/env.ssa
@@ -0,0 +1,21 @@
+# sanity checks for env calls
+
+function l $epar(env %e, l %i) {
+@start
+ %x =l add %e, %i
+ ret %x
+}
+
+export function l $earg(l %a, l %b) {
+@start
+ %r1 =l call $epar(env %a, l %b)
+ # okay to call a regular function
+ # with an env argument
+ %r2 =l call $labs(env 113, l %r1)
+ ret %r2
+}
+
+# >>> driver
+# extern long earg(long, long);
+# int main(void) { return !(earg(2, -44) == 42); }
+# <<<