}
// Collects and returns and array of Node*s for functions arguments and local
-// variables. TODO(cshapiro): only return pointer containing nodes if we are
-// not also generating a dead value map.
+// variables.
static Array*
-getvariables(Node *fn)
+getvariables(Node *fn, int allvalues)
{
Array *result;
NodeList *ll;
result = arraynew(0, sizeof(Node*));
for(ll = fn->dcl; ll != nil; ll = ll->next) {
if(ll->n->op == ONAME) {
- switch(ll->n->class & ~PHEAP) {
+ switch(ll->n->class) {
case PAUTO:
case PPARAM:
case PPARAMOUT:
- arrayadd(result, &ll->n);
+ if(haspointers(ll->n->type) || allvalues)
+ arrayadd(result, &ll->n);
+ break;
}
}
}
case PPARAMOUT:
pos = arrayindexof(vars, from->node);
if(pos == -1)
- fatal("progeffects: variable %N is unknown", prog->from.node);
+ goto Next;
if(info.flags & (LeftRead | LeftAddr))
bvset(uevar, pos);
if(info.flags & LeftWrite)
}
}
}
+Next:
if(info.flags & (RightRead | RightWrite | RightAddr)) {
to = &prog->to;
if (to->node != nil && to->sym != nil && !isfunny(to->node)) {
case PPARAMOUT:
pos = arrayindexof(vars, to->node);
if(pos == -1)
- fatal("progeffects: variable %N is unknown", to->node);
+ goto Next1;
if(info.flags & (RightRead | RightAddr))
bvset(uevar, pos);
if(info.flags & RightWrite)
}
}
}
+Next1:;
}
// Constructs a new liveness structure used to hold the global state of the
livenessepilogue(Liveness *lv)
{
BasicBlock *bb;
- Bvec *livein;
- Bvec *liveout;
- Bvec *uevar;
- Bvec *varkill;
- Bvec *args;
- Bvec *locals;
+ Bvec *livein, *liveout, *uevar, *varkill, *args, *locals;
Prog *p, *next;
- int32 i;
- int32 nvars;
- int32 pos;
+ int32 i, j, nmsg, nvars, pos;
+ char **msg;
+ Fmt fmt;
nvars = arraylength(lv->vars);
livein = bvalloc(nvars);
liveout = bvalloc(nvars);
uevar = bvalloc(nvars);
varkill = bvalloc(nvars);
+ msg = nil;
+ nmsg = 0;
for(i = 0; i < arraylength(lv->cfg); i++) {
bb = *(BasicBlock**)arrayget(lv->cfg, i);
arrayadd(lv->deadvalues, &locals);
}
}
+
+ if(debuglive) {
+ nmsg = arraylength(lv->livepointers);
+ msg = xmalloc(nmsg*sizeof msg[0]);
+ for(j=0; j<nmsg; j++)
+ msg[j] = nil;
+ }
// walk backward, emit pcdata and populate the maps
pos = arraylength(lv->livepointers) - 1;
}
if(issafepoint(p)) {
// Found an interesting instruction, record the
- // corresponding liveness information. Only
- // CALL instructions need a PCDATA annotation.
+ // corresponding liveness information.
+
+ if(debuglive) {
+ fmtstrinit(&fmt);
+ fmtprint(&fmt, "%L: live at ", p->lineno);
+ if(p->as == ACALL)
+ fmtprint(&fmt, "CALL %lS:", p->to.sym);
+ else
+ fmtprint(&fmt, "TEXT %lS:", p->from.sym);
+ for(j = 0; j < arraylength(lv->vars); j++)
+ if(bvget(liveout, j))
+ fmtprint(&fmt, " %N", *(Node**)arrayget(lv->vars, j));
+ fmtprint(&fmt, "\n");
+ msg[pos] = fmtstrflush(&fmt);
+ }
+
+ // Record live pointers.
+ args = *(Bvec**)arrayget(lv->argslivepointers, pos);
+ locals = *(Bvec**)arrayget(lv->livepointers, pos);
+ twobitlivepointermap(lv, liveout, lv->vars, args, locals);
+
+ // Record dead values.
+ if(lv->deadvalues != nil) {
+ args = *(Bvec**)arrayget(lv->argsdeadvalues, pos);
+ locals = *(Bvec**)arrayget(lv->deadvalues, pos);
+ twobitdeadvaluemap(lv, liveout, lv->vars, args, locals);
+ }
+
+ // Only CALL instructions need a PCDATA annotation.
// The TEXT instruction annotation is implicit.
if(p->as == ACALL) {
if(isdeferreturn(p)) {
}
}
- // Record live pointers.
- args = *(Bvec**)arrayget(lv->argslivepointers, pos);
- locals = *(Bvec**)arrayget(lv->livepointers, pos);
- twobitlivepointermap(lv, liveout, lv->vars, args, locals);
-
- // Record dead values.
- if(lv->deadvalues != nil) {
- args = *(Bvec**)arrayget(lv->argsdeadvalues, pos);
- locals = *(Bvec**)arrayget(lv->deadvalues, pos);
- twobitdeadvaluemap(lv, liveout, lv->vars, args, locals);
- }
-
pos--;
}
}
+ if(debuglive) {
+ for(j=0; j<nmsg; j++)
+ if(msg[j] != nil)
+ print("%s", msg[j]);
+ free(msg);
+ msg = nil;
+ nmsg = 0;
+ }
}
free(livein);
// Construct the global liveness state.
cfg = newcfg(firstp);
if(0) printcfg(cfg);
- vars = getvariables(fn);
+ vars = getvariables(fn, deadsym != nil);
lv = newliveness(fn, firstp, cfg, vars, deadsym != nil);
// Run the dataflow framework.