nixify
This commit is contained in:
222
alias.c
Normal file
222
alias.c
Normal file
@@ -0,0 +1,222 @@
|
||||
#include "all.h"
|
||||
|
||||
void
|
||||
getalias(Alias *a, Ref r, Fn *fn)
|
||||
{
|
||||
Con *c;
|
||||
|
||||
switch (rtype(r)) {
|
||||
default:
|
||||
die("unreachable");
|
||||
case RTmp:
|
||||
*a = fn->tmp[r.val].alias;
|
||||
if (astack(a->type))
|
||||
a->type = a->slot->type;
|
||||
assert(a->type != ABot);
|
||||
break;
|
||||
case RCon:
|
||||
c = &fn->con[r.val];
|
||||
if (c->type == CAddr) {
|
||||
a->type = ASym;
|
||||
a->u.sym = c->sym;
|
||||
} else
|
||||
a->type = ACon;
|
||||
a->offset = c->bits.i;
|
||||
a->slot = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
alias(Ref p, int op, int sp, Ref q, int sq, int *delta, Fn *fn)
|
||||
{
|
||||
Alias ap, aq;
|
||||
int ovlap;
|
||||
|
||||
getalias(&ap, p, fn);
|
||||
getalias(&aq, q, fn);
|
||||
ap.offset += op;
|
||||
/* when delta is meaningful (ovlap == 1),
|
||||
* we do not overflow int because sp and
|
||||
* sq are bounded by 2^28 */
|
||||
*delta = ap.offset - aq.offset;
|
||||
ovlap = ap.offset < aq.offset + sq && aq.offset < ap.offset + sp;
|
||||
|
||||
if (astack(ap.type) && astack(aq.type)) {
|
||||
/* if both are offsets of the same
|
||||
* stack slot, they alias iif they
|
||||
* overlap */
|
||||
if (ap.base == aq.base && ovlap)
|
||||
return MustAlias;
|
||||
return NoAlias;
|
||||
}
|
||||
|
||||
if (ap.type == ASym && aq.type == ASym) {
|
||||
/* they conservatively alias if the
|
||||
* symbols are different, or they
|
||||
* alias for sure if they overlap */
|
||||
if (!symeq(ap.u.sym, aq.u.sym))
|
||||
return MayAlias;
|
||||
if (ovlap)
|
||||
return MustAlias;
|
||||
return NoAlias;
|
||||
}
|
||||
|
||||
if ((ap.type == ACon && aq.type == ACon)
|
||||
|| (ap.type == aq.type && ap.base == aq.base)) {
|
||||
assert(ap.type == ACon || ap.type == AUnk);
|
||||
/* if they have the same base, we
|
||||
* can rely on the offsets only */
|
||||
if (ovlap)
|
||||
return MustAlias;
|
||||
return NoAlias;
|
||||
}
|
||||
|
||||
/* if one of the two is unknown
|
||||
* there may be aliasing unless
|
||||
* the other is provably local */
|
||||
if (ap.type == AUnk && aq.type != ALoc)
|
||||
return MayAlias;
|
||||
if (aq.type == AUnk && ap.type != ALoc)
|
||||
return MayAlias;
|
||||
|
||||
return NoAlias;
|
||||
}
|
||||
|
||||
int
|
||||
escapes(Ref r, Fn *fn)
|
||||
{
|
||||
Alias *a;
|
||||
|
||||
if (rtype(r) != RTmp)
|
||||
return 1;
|
||||
a = &fn->tmp[r.val].alias;
|
||||
return !astack(a->type) || a->slot->type == AEsc;
|
||||
}
|
||||
|
||||
static void
|
||||
esc(Ref r, Fn *fn)
|
||||
{
|
||||
Alias *a;
|
||||
|
||||
assert(rtype(r) <= RType);
|
||||
if (rtype(r) == RTmp) {
|
||||
a = &fn->tmp[r.val].alias;
|
||||
if (astack(a->type))
|
||||
a->slot->type = AEsc;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
store(Ref r, int sz, Fn *fn)
|
||||
{
|
||||
Alias *a;
|
||||
int64_t off;
|
||||
bits m;
|
||||
|
||||
if (rtype(r) == RTmp) {
|
||||
a = &fn->tmp[r.val].alias;
|
||||
if (a->slot) {
|
||||
assert(astack(a->type));
|
||||
off = a->offset;
|
||||
if (sz >= NBit
|
||||
|| (off < 0 || off >= NBit))
|
||||
m = -1;
|
||||
else
|
||||
m = (BIT(sz) - 1) << off;
|
||||
a->slot->u.loc.m |= m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fillalias(Fn *fn)
|
||||
{
|
||||
uint n;
|
||||
int t, sz;
|
||||
int64_t x;
|
||||
Blk *b;
|
||||
Phi *p;
|
||||
Ins *i;
|
||||
Con *c;
|
||||
Alias *a, a0, a1;
|
||||
|
||||
for (t=0; t<fn->ntmp; t++)
|
||||
fn->tmp[t].alias.type = ABot;
|
||||
for (n=0; n<fn->nblk; ++n) {
|
||||
b = fn->rpo[n];
|
||||
for (p=b->phi; p; p=p->link) {
|
||||
assert(rtype(p->to) == RTmp);
|
||||
a = &fn->tmp[p->to.val].alias;
|
||||
assert(a->type == ABot);
|
||||
a->type = AUnk;
|
||||
a->base = p->to.val;
|
||||
a->offset = 0;
|
||||
a->slot = 0;
|
||||
}
|
||||
for (i=b->ins; i<&b->ins[b->nins]; ++i) {
|
||||
a = 0;
|
||||
if (!req(i->to, R)) {
|
||||
assert(rtype(i->to) == RTmp);
|
||||
a = &fn->tmp[i->to.val].alias;
|
||||
assert(a->type == ABot);
|
||||
if (Oalloc <= i->op && i->op <= Oalloc1) {
|
||||
a->type = ALoc;
|
||||
a->slot = a;
|
||||
a->u.loc.sz = -1;
|
||||
if (rtype(i->arg[0]) == RCon) {
|
||||
c = &fn->con[i->arg[0].val];
|
||||
x = c->bits.i;
|
||||
if (c->type == CBits)
|
||||
if (0 <= x && x <= NBit)
|
||||
a->u.loc.sz = x;
|
||||
}
|
||||
} else {
|
||||
a->type = AUnk;
|
||||
a->slot = 0;
|
||||
}
|
||||
a->base = i->to.val;
|
||||
a->offset = 0;
|
||||
}
|
||||
if (i->op == Ocopy) {
|
||||
assert(a);
|
||||
getalias(a, i->arg[0], fn);
|
||||
}
|
||||
if (i->op == Oadd) {
|
||||
getalias(&a0, i->arg[0], fn);
|
||||
getalias(&a1, i->arg[1], fn);
|
||||
if (a0.type == ACon) {
|
||||
*a = a1;
|
||||
a->offset += a0.offset;
|
||||
}
|
||||
else if (a1.type == ACon) {
|
||||
*a = a0;
|
||||
a->offset += a1.offset;
|
||||
}
|
||||
}
|
||||
if (req(i->to, R) || a->type == AUnk)
|
||||
if (i->op != Oblit0) {
|
||||
if (!isload(i->op))
|
||||
esc(i->arg[0], fn);
|
||||
if (!isstore(i->op))
|
||||
if (i->op != Oargc)
|
||||
esc(i->arg[1], fn);
|
||||
}
|
||||
if (i->op == Oblit0) {
|
||||
++i;
|
||||
assert(i->op == Oblit1);
|
||||
assert(rtype(i->arg[0]) == RInt);
|
||||
sz = abs(rsval(i->arg[0]));
|
||||
store((i-1)->arg[1], sz, fn);
|
||||
}
|
||||
if (isstore(i->op))
|
||||
store(i->arg[1], storesz(i), fn);
|
||||
}
|
||||
if (b->jmp.type != Jretc)
|
||||
esc(b->jmp.arg, fn);
|
||||
}
|
||||
for (b=fn->start; b; b=b->link)
|
||||
for (p=b->phi; p; p=p->link)
|
||||
for (n=0; n<p->narg; n++)
|
||||
esc(p->arg[n], fn);
|
||||
}
|
||||
Reference in New Issue
Block a user