commit 82f5ba58cf76bc431afe0c738cdcfe1f5998ae95
parent b4a98c3fa8b880f58b04f5d632ab89ad15725bd4
Author: Quentin Carbonneaux <quentin@c9x.me>
Date: Fri, 26 Apr 2019 12:05:47 +0200
restore some code from b4a98c
I had forgotten that %rip can only be
used as base when there is no index.
I also added a test which stresses
addressing selection with and without
constants.
Diffstat:
2 files changed, 82 insertions(+), 1 deletion(-)
diff --git a/amd64/isel.c b/amd64/isel.c
@@ -62,7 +62,7 @@ static void
fixarg(Ref *r, int k, int op, Fn *fn)
{
char buf[32];
- Addr a;
+ Addr a, *m;
Ref r0, r1;
int s, n, cpy, mem;
@@ -110,6 +110,22 @@ fixarg(Ref *r, int k, int op, Fn *fn)
r1 = newtmp("isel", Kl, fn);
emit(Oaddr, Kl, r1, r0, R);
}
+ else if (rtype(r0) == RMem) {
+ /* eliminate memory operands of
+ * the form $foo(%rip, ...)
+ */
+ m = &fn->mem[r0.val];
+ if (req(m->base, R))
+ if (m->offset.type == CAddr) {
+ n = fn->ncon;
+ vgrow(&fn->con, ++fn->ncon);
+ fn->con[n] = m->offset;
+ m->offset.type = CUndef;
+ r0 = newtmp("isel", Kl, fn);
+ emit(Oaddr, Kl, r0, CON(n), R);
+ m->base = r0;
+ }
+ }
*r = r1;
}
diff --git a/test/conaddr.ssa b/test/conaddr.ssa
@@ -0,0 +1,65 @@
+# test amd64 addressing modes
+
+export
+function w $f0(l %o) {
+@start
+ %addr =l add $a, %o
+ %char =w loadub %addr
+ ret %char
+}
+
+export
+function w $f1(l %o) {
+@start
+ %o1 =l mul %o, 1
+ %addr =l add 10, %o1
+ %char =w loadub %addr
+ ret %char
+}
+
+export
+function w $f2(l %o1, l %o2) {
+@start
+ %o22 =l mul %o2, 2
+ %o =l add %o1, %o22
+ %addr =l add $a, %o
+ %char =w loadub %addr
+ ret %char
+}
+
+export
+function l $f3(l %o) {
+@start
+ %addr =l add %o, $a
+ ret %addr
+}
+
+export
+function $writeto0() {
+@start
+ storel 0, 0
+ ret
+}
+
+# >>> driver
+# #include <stdlib.h>
+# #include <signal.h>
+# char a[] = "qbe rocks";
+# int ok = 1;
+# extern unsigned f0(long), f1(long), f2(long, long);
+# extern char *f3(long);
+# extern void writeto0();
+# void h(int sig, siginfo_t *si, void *unused) {
+# ok &= si->si_addr == 0;
+# exit(!ok);
+# }
+# int main() {
+# struct sigaction sa = {.sa_flags=SA_SIGINFO, .sa_sigaction=h};
+# sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, 0);
+# ok &= f0(2) == 'e';
+# ok &= f1((long)a-5) == 'o';
+# ok &= f2(4, 2) == 's';
+# ok &= *f3(0) == 'q';
+# writeto0(); /* will segfault */
+# }
+# <<<