diff options
author | Quentin Carbonneaux <quentin@c9x.me> | 2019-04-30 11:02:42 +0200 |
---|---|---|
committer | Quentin Carbonneaux <quentin@c9x.me> | 2019-04-30 11:21:45 +0200 |
commit | 4b7f02c09710b379a706708ae5880a1811519539 (patch) | |
tree | fa13857c28209bf6ecc837a6532adc176720e66e | |
parent | 660a8d9dfa44050897b2f5ead823554893d79f24 (diff) | |
download | roux-4b7f02c09710b379a706708ae5880a1811519539.tar.gz |
isel fix for amd64 memory stores
The value argument of store instructions was handled incorrectly.
-rw-r--r-- | amd64/isel.c | 37 | ||||
-rw-r--r-- | test/conaddr.ssa | 14 |
2 files changed, 31 insertions, 20 deletions
diff --git a/amd64/isel.c b/amd64/isel.c index 22e1e14..56e4cf3 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -59,17 +59,16 @@ rslot(Ref r, Fn *fn) } static void -fixarg(Ref *r, int k, int op, Fn *fn) +fixarg(Ref *r, int k, Ins *i, Fn *fn) { char buf[32]; Addr a, *m; Ref r0, r1; - int s, n, cpy, mem; + int s, n, op; r1 = r0 = *r; s = rslot(r0, fn); - cpy = op == Ocopy || op == -1; - mem = isstore(op) || isload(op) || op == Ocall; + op = i ? i->op : Ocopy; if (KBASE(k) == 1 && rtype(r0) == RCon) { /* load floating points from memory * slots, they can't be used as @@ -85,7 +84,7 @@ fixarg(Ref *r, int k, int op, Fn *fn) a.offset.label = intern(buf); fn->mem[fn->nmem-1] = a; } - else if (!cpy && k == Kl && noimm(r0, fn)) { + else if (op != Ocopy && k == Kl && noimm(r0, fn)) { /* load constants that do not fit in * a 32bit signed integer into a * long temporary @@ -101,7 +100,8 @@ fixarg(Ref *r, int k, int op, Fn *fn) r1 = newtmp("isel", Kl, fn); emit(Oaddr, Kl, r1, SLOT(s), R); } - else if (!mem && rtype(r0) == RCon + else if (!(isstore(op) && r == &i->arg[1]) + && !isload(op) && op != Ocall && rtype(r0) == RCon && fn->con[r0.val].type == CAddr) { /* apple as does not support 32-bit * absolute addressing, use a rip- @@ -168,7 +168,8 @@ static int selcmp(Ref arg[2], int k, Fn *fn) { int swap; - Ref r, *iarg; + Ref r; + Ins *icmp; swap = rtype(arg[0]) == RCon; if (swap) { @@ -177,21 +178,21 @@ selcmp(Ref arg[2], int k, Fn *fn) arg[0] = r; } emit(Oxcmp, k, R, arg[1], arg[0]); - iarg = curi->arg; + icmp = curi; if (rtype(arg[0]) == RCon) { assert(k == Kl); - iarg[1] = newtmp("isel", k, fn); - emit(Ocopy, k, iarg[1], arg[0], R); + icmp->arg[1] = newtmp("isel", k, fn); + emit(Ocopy, k, icmp->arg[1], arg[0], R); } - fixarg(&iarg[0], k, Oxcmp, fn); - fixarg(&iarg[1], k, Oxcmp, fn); + fixarg(&icmp->arg[0], k, icmp, fn); + fixarg(&icmp->arg[1], k, icmp, fn); return swap; } static void sel(Ins i, ANum *an, Fn *fn) { - Ref r0, r1, *iarg; + Ref r0, r1; int x, k, kc; int64_t sz; Ins *i0, *i1; @@ -236,7 +237,7 @@ sel(Ins i, ANum *an, Fn *fn) emit(Ocopy, k, TMP(RDX), CON_Z, R); } emit(Ocopy, k, TMP(RAX), i.arg[0], R); - fixarg(&curi->arg[0], k, Ocopy, fn); + fixarg(&curi->arg[0], k, curi, fn); if (rtype(i.arg[1]) == RCon) emit(Ocopy, k, r0, i.arg[1], R); break; @@ -290,9 +291,9 @@ sel(Ins i, ANum *an, Fn *fn) case_OExt: Emit: emiti(i); - iarg = curi->arg; /* fixarg() can change curi */ - fixarg(&iarg[0], argcls(&i, 0), i.op, fn); - fixarg(&iarg[1], argcls(&i, 1), i.op, fn); + i1 = curi; /* fixarg() can change curi */ + fixarg(&i1->arg[0], argcls(&i, 0), i1, fn); + fixarg(&i1->arg[1], argcls(&i, 1), i1, fn); break; case Oalloc: case Oalloc+1: @@ -604,7 +605,7 @@ amd64_isel(Fn *fn) for (p=(*sb)->phi; p; p=p->link) { for (a=0; p->blk[a] != b; a++) assert(a+1 < p->narg); - fixarg(&p->arg[a], p->cls, -1, fn); + fixarg(&p->arg[a], p->cls, 0, fn); } memset(ainfo, 0, n * sizeof ainfo[0]); anumber(ainfo, b, fn->con); diff --git a/test/conaddr.ssa b/test/conaddr.ssa index 43177ba..9e24d49 100644 --- a/test/conaddr.ssa +++ b/test/conaddr.ssa @@ -35,6 +35,13 @@ function l $f3(l %o) { } export +function $f4() { +@start + storel $p, $p + ret +} + +export function $writeto0() { @start storel 0, 0 @@ -45,13 +52,14 @@ function $writeto0() { # #include <stdlib.h> # #include <signal.h> # char a[] = "qbe rocks"; +# void *p; # int ok; # extern unsigned f0(long), f1(long), f2(long, long); # extern char *f3(long); -# extern void writeto0(); +# extern void f4(), writeto0(); # void h(int sig, siginfo_t *si, void *unused) { # ok += si->si_addr == 0; -# exit(!(ok == 5)); +# exit(!(ok == 6)); # } # int main() { # struct sigaction sa = {.sa_flags=SA_SIGINFO, .sa_sigaction=h}; @@ -60,6 +68,8 @@ function $writeto0() { # ok += f1((long)a-5) == 'o'; # ok += f2(4, 2) == 's'; # ok += *f3(0) == 'q'; +# f4(); +# ok += p == &p; # writeto0(); /* will segfault */ # } # <<< |