From 82f5ba58cf76bc431afe0c738cdcfe1f5998ae95 Mon Sep 17 00:00:00 2001 From: Quentin Carbonneaux Date: Fri, 26 Apr 2019 12:05:47 +0200 Subject: 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. --- amd64/isel.c | 18 +++++++++++++++- test/conaddr.ssa | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 test/conaddr.ssa diff --git a/amd64/isel.c b/amd64/isel.c index ce0c98f..e5202cb 100644 --- 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 new file mode 100644 index 0000000..3f0aba7 --- /dev/null +++ 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 +# #include +# 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 */ +# } +# <<< -- cgit 1.4.1