mirror of
https://github.com/golang/go.git
synced 2025-05-10 18:13:12 +00:00
cmd/gc: handle variable initialization by block move in liveness
Any initialization of a variable by a block copy or block zeroing or by multiple assignments (componentwise copying or zeroing of a multiword variable) needs to emit a VARDEF. These cases were not. Fixes #7205. TBR=iant CC=golang-codereviews https://golang.org/cl/63650044
This commit is contained in:
parent
7addda685d
commit
91b1f7cb15
@ -1414,6 +1414,7 @@ sgen(Node *n, Node *res, int64 w)
|
|||||||
int32 c, odst, osrc;
|
int32 c, odst, osrc;
|
||||||
int dir, align, op;
|
int dir, align, op;
|
||||||
Prog *p, *ploop;
|
Prog *p, *ploop;
|
||||||
|
NodeList *l;
|
||||||
|
|
||||||
if(debug['g']) {
|
if(debug['g']) {
|
||||||
print("\nsgen w=%lld\n", w);
|
print("\nsgen w=%lld\n", w);
|
||||||
@ -1439,6 +1440,17 @@ sgen(Node *n, Node *res, int64 w)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record site of definition of ns for liveness analysis.
|
||||||
|
if(res->op == ONAME && res->class != PEXTERN)
|
||||||
|
gvardef(res);
|
||||||
|
|
||||||
|
// If copying .args, that's all the results, so record definition sites
|
||||||
|
// for them for the liveness analysis.
|
||||||
|
if(res->op == ONAME && strcmp(res->sym->name, ".args") == 0)
|
||||||
|
for(l = curfn->dcl; l != nil; l = l->next)
|
||||||
|
if(l->n->class == PPARAMOUT)
|
||||||
|
gvardef(l->n);
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
if(componentgen(n, res))
|
if(componentgen(n, res))
|
||||||
return;
|
return;
|
||||||
|
@ -1337,6 +1337,7 @@ sgen(Node *n, Node *ns, int64 w)
|
|||||||
{
|
{
|
||||||
Node nodl, nodr, nodsi, noddi, cx, oldcx, tmp;
|
Node nodl, nodr, nodsi, noddi, cx, oldcx, tmp;
|
||||||
vlong c, q, odst, osrc;
|
vlong c, q, odst, osrc;
|
||||||
|
NodeList *l;
|
||||||
|
|
||||||
if(debug['g']) {
|
if(debug['g']) {
|
||||||
print("\nsgen w=%lld\n", w);
|
print("\nsgen w=%lld\n", w);
|
||||||
@ -1349,6 +1350,17 @@ sgen(Node *n, Node *ns, int64 w)
|
|||||||
|
|
||||||
if(w < 0)
|
if(w < 0)
|
||||||
fatal("sgen copy %lld", w);
|
fatal("sgen copy %lld", w);
|
||||||
|
|
||||||
|
// Record site of definition of ns for liveness analysis.
|
||||||
|
if(ns->op == ONAME && ns->class != PEXTERN)
|
||||||
|
gvardef(ns);
|
||||||
|
|
||||||
|
// If copying .args, that's all the results, so record definition sites
|
||||||
|
// for them for the liveness analysis.
|
||||||
|
if(ns->op == ONAME && strcmp(ns->sym->name, ".args") == 0)
|
||||||
|
for(l = curfn->dcl; l != nil; l = l->next)
|
||||||
|
if(l->n->class == PPARAMOUT)
|
||||||
|
gvardef(l->n);
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
if(componentgen(n, ns))
|
if(componentgen(n, ns))
|
||||||
|
@ -1203,6 +1203,7 @@ sgen(Node *n, Node *res, int64 w)
|
|||||||
{
|
{
|
||||||
Node dst, src, tdst, tsrc;
|
Node dst, src, tdst, tsrc;
|
||||||
int32 c, q, odst, osrc;
|
int32 c, q, odst, osrc;
|
||||||
|
NodeList *l;
|
||||||
|
|
||||||
if(debug['g']) {
|
if(debug['g']) {
|
||||||
print("\nsgen w=%lld\n", w);
|
print("\nsgen w=%lld\n", w);
|
||||||
@ -1223,6 +1224,17 @@ sgen(Node *n, Node *res, int64 w)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record site of definition of ns for liveness analysis.
|
||||||
|
if(res->op == ONAME && res->class != PEXTERN)
|
||||||
|
gvardef(res);
|
||||||
|
|
||||||
|
// If copying .args, that's all the results, so record definition sites
|
||||||
|
// for them for the liveness analysis.
|
||||||
|
if(res->op == ONAME && strcmp(res->sym->name, ".args") == 0)
|
||||||
|
for(l = curfn->dcl; l != nil; l = l->next)
|
||||||
|
if(l->n->class == PPARAMOUT)
|
||||||
|
gvardef(l->n);
|
||||||
|
|
||||||
// Avoid taking the address for simple enough types.
|
// Avoid taking the address for simple enough types.
|
||||||
if(componentgen(n, res))
|
if(componentgen(n, res))
|
||||||
return;
|
return;
|
||||||
|
@ -34,8 +34,8 @@ makefuncdatasym(char *namefmt, int64 funcdatakind)
|
|||||||
void
|
void
|
||||||
gvardef(Node *n)
|
gvardef(Node *n)
|
||||||
{
|
{
|
||||||
if(n == N || !isfat(n->type))
|
if(n == N)
|
||||||
fatal("gvardef: node is not fat");
|
fatal("gvardef nil");
|
||||||
switch(n->class) {
|
switch(n->class) {
|
||||||
case PAUTO:
|
case PAUTO:
|
||||||
case PPARAM:
|
case PPARAM:
|
||||||
|
@ -621,7 +621,7 @@ freecfg(Array *cfg)
|
|||||||
static int
|
static int
|
||||||
isfunny(Node *node)
|
isfunny(Node *node)
|
||||||
{
|
{
|
||||||
char *names[] = { ".fp", ".args", "_", nil };
|
char *names[] = { ".fp", ".args", nil };
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(node->sym != nil && node->sym->name != nil)
|
if(node->sym != nil && node->sym->name != nil)
|
||||||
@ -696,8 +696,8 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
|
|||||||
}
|
}
|
||||||
if(info.flags & (LeftRead | LeftWrite | LeftAddr)) {
|
if(info.flags & (LeftRead | LeftWrite | LeftAddr)) {
|
||||||
from = &prog->from;
|
from = &prog->from;
|
||||||
if (from->node != nil && !isfunny(from->node) && from->sym != nil) {
|
if (from->node != nil && from->sym != nil) {
|
||||||
switch(prog->from.node->class & ~PHEAP) {
|
switch(from->node->class & ~PHEAP) {
|
||||||
case PAUTO:
|
case PAUTO:
|
||||||
case PPARAM:
|
case PPARAM:
|
||||||
case PPARAMOUT:
|
case PPARAMOUT:
|
||||||
@ -710,7 +710,7 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
|
|||||||
if(info.flags & (LeftRead | LeftAddr))
|
if(info.flags & (LeftRead | LeftAddr))
|
||||||
bvset(uevar, pos);
|
bvset(uevar, pos);
|
||||||
if(info.flags & LeftWrite)
|
if(info.flags & LeftWrite)
|
||||||
if(from->node != nil && (!isfat(from->node->type) || prog->as == AVARDEF))
|
if(from->node != nil && !isfat(from->node->type))
|
||||||
bvset(varkill, pos);
|
bvset(varkill, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -719,8 +719,8 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
|
|||||||
Next:
|
Next:
|
||||||
if(info.flags & (RightRead | RightWrite | RightAddr)) {
|
if(info.flags & (RightRead | RightWrite | RightAddr)) {
|
||||||
to = &prog->to;
|
to = &prog->to;
|
||||||
if (to->node != nil && to->sym != nil && !isfunny(to->node)) {
|
if (to->node != nil && to->sym != nil) {
|
||||||
switch(prog->to.node->class & ~PHEAP) {
|
switch(to->node->class & ~PHEAP) {
|
||||||
case PAUTO:
|
case PAUTO:
|
||||||
case PPARAM:
|
case PPARAM:
|
||||||
case PPARAMOUT:
|
case PPARAMOUT:
|
||||||
@ -728,10 +728,9 @@ Next:
|
|||||||
if(pos == -1)
|
if(pos == -1)
|
||||||
goto Next1;
|
goto Next1;
|
||||||
if(to->node->addrtaken) {
|
if(to->node->addrtaken) {
|
||||||
//if(prog->as == AKILL)
|
bvset(avarinit, pos);
|
||||||
// bvset(varkill, pos);
|
if(prog->as == AVARDEF)
|
||||||
//else
|
bvset(varkill, pos);
|
||||||
bvset(avarinit, pos);
|
|
||||||
} else {
|
} else {
|
||||||
if(info.flags & (RightRead | RightAddr))
|
if(info.flags & (RightRead | RightAddr))
|
||||||
bvset(uevar, pos);
|
bvset(uevar, pos);
|
||||||
|
18
test/live.go
18
test/live.go
@ -95,3 +95,21 @@ func f7() (x string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignoring block returns used to cause "live at entry to f8: x, y".
|
||||||
|
|
||||||
|
func f8() (x, y string) {
|
||||||
|
return g8()
|
||||||
|
}
|
||||||
|
|
||||||
|
func g8() (string, string)
|
||||||
|
|
||||||
|
// ignoring block assignments used to cause "live at entry to f9: x"
|
||||||
|
// issue 7205
|
||||||
|
|
||||||
|
var i9 interface{}
|
||||||
|
|
||||||
|
func f9() bool {
|
||||||
|
g8()
|
||||||
|
x := i9
|
||||||
|
return x != 99
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user