fix amd64 addressing mode matcher

The numberer made some arranging choices when
numbering arguments of an instruction, but these
decisions were ignored when matching.  The fix
is to reconcile numbering and matching.
This commit is contained in:
Quentin Carbonneaux 2019-02-21 14:42:01 +01:00
parent cf9f2e8ef7
commit a877ba986b
2 changed files with 39 additions and 20 deletions

View file

@ -25,7 +25,7 @@ struct ANum {
Ins *i;
};
static void amatch(Addr *, Ref, ANum *, Fn *, int);
static int amatch(Addr *, Ref, int, ANum *, Fn *);
static int
noimm(Ref r, Fn *fn)
@ -131,8 +131,8 @@ seladdr(Ref *r, ANum *an, Fn *fn)
r0 = *r;
if (rtype(r0) == RTmp) {
amatch(&a, r0, an, fn, 1);
if (req(a.base, r0))
memset(&a, 0, sizeof a);
if (!amatch(&a, r0, an[r0.val].n, an, fn))
return;
if (a.offset.type == CAddr)
if (!req(a.base, R)) {
@ -488,18 +488,16 @@ anumber(ANum *ai, Blk *b, Con *con)
}
}
static void
amatch(Addr *a, Ref r, ANum *ai, Fn *fn, int top)
static int
amatch(Addr *a, Ref r, int n, ANum *ai, Fn *fn)
{
Ins *i;
int nl, nr, t, s;
Ref al, ar;
if (top)
memset(a, 0, sizeof *a);
if (rtype(r) == RCon) {
addcon(&a->offset, &fn->con[r.val]);
return;
return 1;
}
assert(rtype(r) == RTmp);
i = ai[r.val].i;
@ -515,14 +513,11 @@ amatch(Addr *a, Ref r, ANum *ai, Fn *fn, int top)
ar = i->arg[1];
}
}
switch (ai[r.val].n) {
switch (n) {
case 3: /* s * i */
if (!top) {
a->index = al;
a->scale = fn->con[ar.val].bits.i;
} else
a->base = r;
break;
a->index = al;
a->scale = fn->con[ar.val].bits.i;
return 0;
case 4: /* b + s * i */
switch (nr) {
case 0:
@ -534,7 +529,7 @@ amatch(Addr *a, Ref r, ANum *ai, Fn *fn, int top)
a->scale = 1;
break;
case 3:
amatch(a, ar, ai, fn, 0);
amatch(a, ar, nr, ai, fn);
break;
}
r = al;
@ -544,14 +539,14 @@ amatch(Addr *a, Ref r, ANum *ai, Fn *fn, int top)
if (s != -1)
r = SLOT(s);
a->base = r;
break;
return n || s != -1;
case 2: /* constants */
case 5: /* o + s * i */
case 6: /* o + b */
case 7: /* o + b + s * i */
amatch(a, ar, ai, fn, 0);
amatch(a, al, ai, fn, 0);
break;
amatch(a, ar, nr, ai, fn);
amatch(a, al, nl, ai, fn);
return 1;
default:
die("unreachable");
}