aboutsummaryrefslogtreecommitdiff
path: root/alias.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <[email protected]>2017-02-24 12:00:38 -0500
committerQuentin Carbonneaux <[email protected]>2017-02-24 12:00:38 -0500
commita35dc8c495467306ca149d642b2d2983922d7a9d (patch)
treeb6c7958a7252fd489f7aac02ecc17e1b54948614 /alias.c
parent5165fcae767801a20316530c0ec9f096158aa2e4 (diff)
fix pretty bad bug in alias analysis
When a temporary marked local is escaping, the whole slot must be marked as such. To solve this, Alias now holds a pointer to the alias information of the slot. For simplicity of the code, this pointer is always valid and fetching ->type out of it is meaningful.
Diffstat (limited to 'alias.c')
-rw-r--r--alias.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/alias.c b/alias.c
index a24d9b3..ed64501 100644
--- a/alias.c
+++ b/alias.c
@@ -10,6 +10,7 @@ getalias(Alias *a, Ref r, Fn *fn)
die("unreachable");
case RTmp:
*a = fn->tmp[r.val].alias;
+ a->type = a->slot->type;
assert(a->type != ABot);
break;
case RCon:
@@ -20,6 +21,7 @@ getalias(Alias *a, Ref r, Fn *fn)
} else
a->type = ACon;
a->offset = c->bits.i;
+ a->slot = a;
break;
}
}
@@ -79,9 +81,12 @@ alias(Ref p, int sp, Ref q, int sq, int *delta, Fn *fn)
int
escapes(Ref r, Fn *fn)
{
+ Alias *a;
+
if (rtype(r) != RTmp)
return 1;
- return fn->tmp[r.val].alias.type != ALoc;
+ a = &fn->tmp[r.val].alias;
+ return !(a->type & 1) || a->slot->type == AEsc;
}
static void
@@ -92,9 +97,8 @@ esc(Ref r, Fn *fn)
assert(rtype(r) <= RType);
if (rtype(r) == RTmp) {
a = &fn->tmp[r.val].alias;
- assert(a->type != ABot);
- if (a->type == ALoc)
- a->type = AEsc;
+ if (a->slot->type == ALoc)
+ a->slot->type = AEsc;
}
}
@@ -116,6 +120,7 @@ fillalias(Fn *fn)
a->type = AUnk;
a->base = p->to;
a->offset = 0;
+ a->slot = a;
}
for (i=b->ins; i<&b->ins[b->nins]; ++i) {
a = 0;
@@ -129,6 +134,7 @@ fillalias(Fn *fn)
a->type = AUnk;
a->base = i->to;
a->offset = 0;
+ a->slot = a;
}
if (i->op == Ocopy) {
assert(a);