1
0
mirror of https://github.com/golang/go synced 2024-11-25 13:57:57 -07:00

composit literal under

init function context.
also moved composit literal
code from walk.c to sinit.c

R=rsc
OCL=34503
CL=34503
This commit is contained in:
Ken Thompson 2009-09-09 17:48:55 -07:00
parent aa6e81dd71
commit 0631d65dc5
5 changed files with 573 additions and 485 deletions

View File

@ -1093,6 +1093,9 @@ gen_as_init(Node *n)
default:
goto no;
case OCONVSLICE:
goto slice;
case OLITERAL:
break;
}
@ -1143,6 +1146,34 @@ gen_as_init(Node *n)
yes:
return 1;
slice:
p = gins(ANOP, N, N); // in case the data is the dest of a goto
nr = n->right->left;
if(nr == N || nr->op != OADDR)
goto no;
nr = nr->left;
if(nr == N || nr->op != ONAME)
goto no;
// nr is the array being converted to a slice
if(nr->type == T || nr->type->etype != TARRAY || nr->type->bound < 0)
goto no;
nam.xoffset += Array_array;
p = gins(ADATA, &nam, n->right->left);
p->from.scale = types[tptr]->width;
nam.xoffset += Array_nel-Array_array;
nodconst(&nod1, types[TINT32], nr->type->bound);
p = gins(ADATA, &nam, &nod1);
p->from.scale = types[TINT32]->width;
nam.xoffset += Array_cap-Array_nel;
p = gins(ADATA, &nam, &nod1);
p->from.scale = types[TINT32]->width;
goto yes;
no:
if(n->dodata == 2) {
dump("\ngen_as_init", n);

View File

@ -205,6 +205,8 @@ dowidth(Type *t)
w = sizeof_Array;
else
fatal("dowidth %T", t); // probably [...]T
if(w == 0)
w = maxround;
break;
case TSTRUCT:

View File

@ -1020,6 +1020,7 @@ void colasdefn(NodeList*, Node*);
NodeList* reorder1(NodeList*);
NodeList* reorder3(NodeList*);
NodeList* reorder4(NodeList*);
int vmatch1(Node*, Node*);
void anylit(Node*, Node*, NodeList**);
int oaslit(Node*, NodeList**);
void heapmoves(void);

View File

@ -95,3 +95,542 @@ initfix(NodeList *l)
initreorder(l, &lout);
return lout;
}
/*
* from here down is the walk analysis
* of composit literals.
* most of the work is to generate
* data statements for the constant
* part of the composit literal.
*/
static int
isliteral(Node *n)
{
if(n->op == OLITERAL)
if(n->val.ctype != CTNIL)
return 1;
return 0;
}
static int
simplename(Node *n)
{
if(n->op != ONAME)
goto no;
if(!n->addable)
goto no;
if(n->class & PHEAP)
goto no;
if(n->class == PPARAMREF)
goto no;
return 1;
no:
return 0;
}
static void arraylit(Node *n, Node *var, int pass, NodeList **init);
static void
structlit(Node *n, Node *var, int pass, NodeList **init)
{
Node *r, *a;
NodeList *nl;
Node *index, *value;
for(nl=n->list; nl; nl=nl->next) {
r = nl->n;
if(r->op != OKEY)
fatal("structlit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
switch(value->op) {
case OARRAYLIT:
if(value->type->bound < 0)
break;
a = nod(ODOT, var, newname(index->sym));
arraylit(value, a, pass, init);
continue;
case OSTRUCTLIT:
a = nod(ODOT, var, newname(index->sym));
structlit(value, a, pass, init);
continue;
}
if(isliteral(value)) {
if(pass == 2)
continue;
} else
if(pass == 1)
continue;
// build list of var.field = expr
a = nod(ODOT, var, newname(index->sym));
a = nod(OAS, a, value);
typecheck(&a, Etop);
walkexpr(&a, init);
if(pass == 1) {
if(a->op != OAS)
fatal("structlit: not as");
a->dodata = 2;
}
*init = list(*init, a);
}
}
static void
arraylit(Node *n, Node *var, int pass, NodeList **init)
{
Node *r, *a;
NodeList *l;
Node *index, *value;
for(l=n->list; l; l=l->next) {
r = l->n;
if(r->op != OKEY)
fatal("arraylit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
switch(value->op) {
case OARRAYLIT:
if(value->type->bound < 0)
break;
a = nod(OINDEX, var, index);
arraylit(value, a, pass, init);
continue;
case OSTRUCTLIT:
a = nod(OINDEX, var, index);
structlit(value, a, pass, init);
continue;
}
if(isliteral(index) && isliteral(value)) {
if(pass == 2)
continue;
} else
if(pass == 1)
continue;
// build list of var[index] = value
a = nod(OINDEX, var, index);
a = nod(OAS, a, value);
typecheck(&a, Etop);
walkexpr(&a, init); // add any assignments in r to top
if(pass == 1) {
if(a->op != OAS)
fatal("structlit: not as");
a->dodata = 2;
}
*init = list(*init, a);
}
}
static void
slicelit(Node *n, Node *var, NodeList **init)
{
Node *r, *a;
NodeList *l;
Type *t;
Node *vstat, *vheap;
Node *index, *value;
// make an array type
t = shallow(n->type);
t->bound = mpgetfix(n->right->val.u.xval);
t->width = 0;
dowidth(t);
// make static initialized array
vstat = staticname(t);
arraylit(n, vstat, 1, init);
// make new *array heap
vheap = nod(OXXX, N, N);
tempname(vheap, ptrto(t));
a = nod(ONEW, N, N);
a->list = list1(typenod(t));
a = nod(OAS, vheap, a);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// copy static to heap
a = nod(OIND, vheap, N);
a = nod(OAS, a, vstat);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// make slice out of heap
a = nod(OAS, var, vheap);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// put dynamics into slice
for(l=n->list; l; l=l->next) {
r = l->n;
if(r->op != OKEY)
fatal("slicelit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
switch(value->op) {
case OARRAYLIT:
if(value->type->bound < 0)
break;
a = nod(OINDEX, var, index);
arraylit(value, a, 2, init);
continue;
case OSTRUCTLIT:
a = nod(OINDEX, var, index);
structlit(value, a, 2, init);
continue;
}
if(isliteral(index) && isliteral(value))
continue;
// build list of var[c] = expr
a = nod(OINDEX, var, index);
a = nod(OAS, a, value);
typecheck(&a, Etop);
walkexpr(&a, init); // add any assignments in r to top
*init = list(*init, a);
}
}
static void
maplit(Node *n, Node *var, NodeList **init)
{
Node *r, *a;
NodeList *l;
int nerr, b;
Type *t, *tk, *tv, *t1;
Node *vstat, *index, *value;
Sym *syma, *symb;
// make the map var
nerr = nerrors;
a = nod(OMAKE, N, N);
a->list = list1(typenod(n->type));
a = nod(OAS, var, a);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// count the initializers
b = 0;
for(l=n->list; l; l=l->next) {
r = l->n;
if(r->op != OKEY)
fatal("slicelit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
if(isliteral(index) && isliteral(value))
b++;
}
t = T;
if(b != 0) {
// build type [count]struct { a Tindex, b Tvalue }
t = n->type;
tk = t->down;
tv = t->type;
symb = lookup("b");
t = typ(TFIELD);
t->type = tv;
t->sym = symb;
syma = lookup("a");
t1 = t;
t = typ(TFIELD);
t->type = tk;
t->sym = syma;
t->down = t1;
t1 = t;
t = typ(TSTRUCT);
t->type = t1;
t1 = t;
t = typ(TARRAY);
t->bound = b;
t->type = t1;
dowidth(t);
// make and initialize static array
vstat = staticname(t);
b = 0;
for(l=n->list; l; l=l->next) {
r = l->n;
if(r->op != OKEY)
fatal("slicelit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
if(isliteral(index) && isliteral(value)) {
// build vstat[b].a = key;
a = nodintconst(b);
a = nod(OINDEX, vstat, a);
a = nod(ODOT, a, newname(syma));
a = nod(OAS, a, index);
typecheck(&a, Etop);
walkexpr(&a, init);
a->dodata = 2;
*init = list(*init, a);
// build vstat[b].b = value;
a = nodintconst(b);
a = nod(OINDEX, vstat, a);
a = nod(ODOT, a, newname(symb));
a = nod(OAS, a, value);
typecheck(&a, Etop);
walkexpr(&a, init);
a->dodata = 2;
*init = list(*init, a);
b++;
}
}
// loop adding structure elements to map
// for i = 0; i < len(vstat); i++ {
// map[vstat[i].a] = vstat[i].b
// }
index = nod(OXXX, N, N);
tempname(index, types[TINT]);
a = nod(OINDEX, vstat, index);
a = nod(ODOT, a, newname(symb));
r = nod(OINDEX, vstat, index);
r = nod(ODOT, r, newname(syma));
r = nod(OINDEX, var, r);
r = nod(OAS, r, a);
a = nod(OFOR, N, N);
a->nbody = list1(r);
a->ninit = list1(nod(OAS, index, nodintconst(0)));
a->ntest = nod(OLT, index, nodintconst(t->bound));
a->nincr = nod(OASOP, index, nodintconst(1));
a->nincr->etype = OADD;
typecheck(&a, Etop);
walkstmt(&a);
*init = list(*init, a);
}
// put in dynamic entries one-at-a-time
for(l=n->list; l; l=l->next) {
r = l->n;
if(r->op != OKEY)
fatal("slicelit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
if(isliteral(index) && isliteral(value))
continue;
// build list of var[c] = expr
a = nod(OINDEX, var, r->left);
a = nod(OAS, a, r->right);
typecheck(&a, Etop);
walkexpr(&a, init);
if(nerr != nerrors)
break;
*init = list(*init, a);
}
}
void
anylit(Node *n, Node *var, NodeList **init)
{
Type *t;
Node *a, *vstat;
t = n->type;
switch(n->op) {
default:
fatal("anylit: not lit");
case OSTRUCTLIT:
if(t->etype != TSTRUCT)
fatal("anylit: not struct");
if(simplename(var)) {
// lay out static data
vstat = staticname(t);
structlit(n, vstat, 1, init);
// copy static to automatic
a = nod(OAS, var, vstat);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// add expressions to automatic
structlit(n, var, 2, init);
break;
}
// initialize of not completely specified
if(count(n->list) < structcount(t)) {
a = nod(OAS, var, N);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
}
structlit(n, var, 3, init);
break;
case OARRAYLIT:
if(t->etype != TARRAY)
fatal("anylit: not array");
if(t->bound < 0) {
slicelit(n, var, init);
break;
}
if(simplename(var)) {
// lay out static data
vstat = staticname(t);
arraylit(n, vstat, 1, init);
// copy static to automatic
a = nod(OAS, var, vstat);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// add expressions to automatic
arraylit(n, var, 2, init);
break;
}
// initialize of not completely specified
if(count(n->list) < t->bound) {
a = nod(OAS, var, N);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
}
arraylit(n, var, 3, init);
break;
case OMAPLIT:
if(t->etype != TMAP)
fatal("anylit: not map");
maplit(n, var, init);
break;
}
}
int
oaslit(Node *n, NodeList **init)
{
Type *t;
Node *vstat, *a;
if(n->left == N || n->right == N)
goto no;
if(n->left->type == T || n->right->type == T)
goto no;
if(!simplename(n->left))
goto no;
if(!eqtype(n->left->type, n->right->type))
goto no;
if(n->dodata == 1)
goto initctxt;
switch(n->right->op) {
default:
goto no;
case OSTRUCTLIT:
case OARRAYLIT:
case OMAPLIT:
if(vmatch1(n->left, n->right))
goto no;
anylit(n->right, n->left, init);
break;
}
n->op = OEMPTY;
return 1;
no:
// not a special composit literal assignment
return 0;
initctxt:
// in the initialization context
// we are trying to put data statements
// right into the initialized variables
switch(n->right->op) {
default:
goto no;
case OSTRUCTLIT:
structlit(n->right, n->left, 1, init);
structlit(n->right, n->left, 2, init);
break;
case OARRAYLIT:
t = n->right->type;
if(t == T)
goto no;
if(t->bound >= 0) {
arraylit(n->right, n->left, 1, init);
arraylit(n->right, n->left, 2, init);
break;
}
// make a static slice
// make an array type
t = shallow(t);
t->bound = mpgetfix(n->right->right->val.u.xval);
t->width = 0;
dowidth(t);
// make static initialized array
vstat = staticname(t);
arraylit(n->right, vstat, 1, init);
arraylit(n->right, vstat, 2, init);
// copy static to slice
a = nod(OADDR, vstat, N);
a = nod(OAS, n->left, a);
typecheck(&a, Etop);
// turns into a function that is hard to parse
// in ggen where it is turned into DATA statements
// walkexpr(&a, init);
a->dodata = 2;
*init = list(*init, a);
break;
case OMAPLIT:
maplit(n->right, n->left, init);
break;
}
n->op = OEMPTY;
return 1;
}

View File

@ -1971,491 +1971,6 @@ reorder4(NodeList *ll)
return ll;
}
static int
isliteral(Node *n)
{
if(n->op == OLITERAL)
if(n->val.ctype != CTNIL)
return 1;
return 0;
}
void arraylit(Node *n, Node *var, int pass, NodeList **init);
void
structlit(Node *n, Node *var, int pass, NodeList **init)
{
Node *r, *a;
NodeList *nl;
Node *index, *value;
for(nl=n->list; nl; nl=nl->next) {
r = nl->n;
if(r->op != OKEY)
fatal("structlit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
switch(value->op) {
case OARRAYLIT:
if(value->type->bound < 0)
break;
a = nod(ODOT, var, newname(index->sym));
arraylit(value, a, pass, init);
continue;
case OSTRUCTLIT:
a = nod(ODOT, var, newname(index->sym));
structlit(value, a, pass, init);
continue;
}
if(isliteral(value)) {
if(pass == 2)
continue;
} else
if(pass == 1)
continue;
// build list of var.field = expr
a = nod(ODOT, var, newname(index->sym));
a = nod(OAS, a, value);
typecheck(&a, Etop);
walkexpr(&a, init);
if(pass == 1) {
if(a->op != OAS)
fatal("structlit: not as");
a->dodata = 2;
}
*init = list(*init, a);
}
}
void
arraylit(Node *n, Node *var, int pass, NodeList **init)
{
Node *r, *a;
NodeList *l;
Node *index, *value;
for(l=n->list; l; l=l->next) {
r = l->n;
if(r->op != OKEY)
fatal("arraylit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
switch(value->op) {
case OARRAYLIT:
if(value->type->bound < 0)
break;
a = nod(OINDEX, var, index);
arraylit(value, a, pass, init);
continue;
case OSTRUCTLIT:
a = nod(OINDEX, var, index);
structlit(value, a, pass, init);
continue;
}
if(isliteral(index) && isliteral(value)) {
if(pass == 2)
continue;
} else
if(pass == 1)
continue;
// build list of var[index] = value
a = nod(OINDEX, var, index);
a = nod(OAS, a, value);
typecheck(&a, Etop);
walkexpr(&a, init); // add any assignments in r to top
if(pass == 1) {
if(a->op != OAS)
fatal("structlit: not as");
a->dodata = 2;
}
*init = list(*init, a);
}
}
void
slicelit(Node *n, Node *var, NodeList **init)
{
Node *r, *a;
NodeList *l;
Type *t;
Node *vstat, *vheap;
Node *index, *value;
// make an array type
t = shallow(n->type);
t->bound = mpgetfix(n->right->val.u.xval);
t->width = 0;
dowidth(t);
// make static initialized array
vstat = staticname(t);
arraylit(n, vstat, 1, init);
// make new *array heap
vheap = nod(OXXX, N, N);
tempname(vheap, ptrto(t));
a = nod(ONEW, N, N);
a->list = list1(typenod(t));
a = nod(OAS, vheap, a);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// copy static to heap
a = nod(OIND, vheap, N);
a = nod(OAS, a, vstat);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// make slice out of heap
a = nod(OAS, var, vheap);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// put dynamics into slice
for(l=n->list; l; l=l->next) {
r = l->n;
if(r->op != OKEY)
fatal("slicelit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
switch(value->op) {
case OARRAYLIT:
if(value->type->bound < 0)
break;
a = nod(OINDEX, var, index);
arraylit(value, a, 2, init);
continue;
case OSTRUCTLIT:
a = nod(OINDEX, var, index);
structlit(value, a, 2, init);
continue;
}
if(isliteral(index) && isliteral(value))
continue;
// build list of var[c] = expr
a = nod(OINDEX, var, index);
a = nod(OAS, a, value);
typecheck(&a, Etop);
walkexpr(&a, init); // add any assignments in r to top
*init = list(*init, a);
}
}
void
maplit(Node *n, Node *var, NodeList **init)
{
Node *r, *a;
NodeList *l;
int nerr, b;
Type *t, *tk, *tv, *t1;
Node *vstat, *index, *value;
Sym *syma, *symb;
// make the map var
nerr = nerrors;
a = nod(OMAKE, N, N);
a->list = list1(typenod(n->type));
a = nod(OAS, var, a);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// count the initializers
b = 0;
for(l=n->list; l; l=l->next) {
r = l->n;
if(r->op != OKEY)
fatal("slicelit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
if(isliteral(index) && isliteral(value))
b++;
}
t = T;
if(b != 0) {
// build type [count]struct { a Tindex, b Tvalue }
t = n->type;
tk = t->down;
tv = t->type;
symb = lookup("b");
t = typ(TFIELD);
t->type = tv;
t->sym = symb;
syma = lookup("a");
t1 = t;
t = typ(TFIELD);
t->type = tk;
t->sym = syma;
t->down = t1;
t1 = t;
t = typ(TSTRUCT);
t->type = t1;
t1 = t;
t = typ(TARRAY);
t->bound = b;
t->type = t1;
dowidth(t);
// make and initialize static array
vstat = staticname(t);
b = 0;
for(l=n->list; l; l=l->next) {
r = l->n;
if(r->op != OKEY)
fatal("slicelit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
if(isliteral(index) && isliteral(value)) {
// build vstat[b].a = key;
a = nodintconst(b);
a = nod(OINDEX, vstat, a);
a = nod(ODOT, a, newname(syma));
a = nod(OAS, a, index);
typecheck(&a, Etop);
walkexpr(&a, init);
a->dodata = 2;
*init = list(*init, a);
// build vstat[b].b = value;
a = nodintconst(b);
a = nod(OINDEX, vstat, a);
a = nod(ODOT, a, newname(symb));
a = nod(OAS, a, value);
typecheck(&a, Etop);
walkexpr(&a, init);
a->dodata = 2;
*init = list(*init, a);
b++;
}
}
// loop adding structure elements to map
// for i = 0; i < len(vstat); i++ {
// map[vstat[i].a] = vstat[i].b
// }
index = nod(OXXX, N, N);
tempname(index, types[TINT]);
a = nod(OINDEX, vstat, index);
a = nod(ODOT, a, newname(symb));
r = nod(OINDEX, vstat, index);
r = nod(ODOT, r, newname(syma));
r = nod(OINDEX, var, r);
r = nod(OAS, r, a);
a = nod(OFOR, N, N);
a->nbody = list1(r);
a->ninit = list1(nod(OAS, index, nodintconst(0)));
a->ntest = nod(OLT, index, nodintconst(t->bound));
a->nincr = nod(OASOP, index, nodintconst(1));
a->nincr->etype = OADD;
typecheck(&a, Etop);
walkstmt(&a);
*init = list(*init, a);
}
// put in dynamic entries one-at-a-time
for(l=n->list; l; l=l->next) {
r = l->n;
if(r->op != OKEY)
fatal("slicelit: rhs not OKEY: %N", r);
index = r->left;
value = r->right;
if(isliteral(index) && isliteral(value))
continue;
// build list of var[c] = expr
a = nod(OINDEX, var, r->left);
a = nod(OAS, a, r->right);
typecheck(&a, Etop);
walkexpr(&a, init);
if(nerr != nerrors)
break;
*init = list(*init, a);
}
}
static int
simplename(Node *n)
{
if(n->op != ONAME)
goto no;
if(!n->addable)
goto no;
if(n->class & PHEAP)
goto no;
if(n->class == PPARAMREF)
goto no;
return 1;
no:
return 0;
}
void
anylit(Node *n, Node *var, NodeList **init)
{
Type *t;
Node *a, *vstat;
t = n->type;
switch(n->op) {
default:
fatal("anylit: not lit");
case OSTRUCTLIT:
if(t->etype != TSTRUCT)
fatal("anylit: not struct");
if(simplename(var)) {
// lay out static data
vstat = staticname(t);
structlit(n, vstat, 1, init);
// copy static to automatic
a = nod(OAS, var, vstat);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// add expressions to automatic
structlit(n, var, 2, init);
break;
}
// initialize of not completely specified
if(count(n->list) < structcount(t)) {
a = nod(OAS, var, N);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
}
structlit(n, var, 3, init);
break;
case OARRAYLIT:
if(t->etype != TARRAY)
fatal("anylit: not array");
if(t->bound < 0) {
slicelit(n, var, init);
break;
}
if(simplename(var)) {
// lay out static data
vstat = staticname(t);
arraylit(n, vstat, 1, init);
// copy static to automatic
a = nod(OAS, var, vstat);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
// add expressions to automatic
arraylit(n, var, 2, init);
break;
}
// initialize of not completely specified
if(count(n->list) < t->bound) {
a = nod(OAS, var, N);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
}
arraylit(n, var, 3, init);
break;
case OMAPLIT:
if(t->etype != TMAP)
fatal("anylit: not map");
maplit(n, var, init);
break;
}
}
int
oaslit(Node *n, NodeList **init)
{
Type *t;
if(n->left == N || n->right == N)
goto no;
if(!simplename(n->left))
goto no;
if(n->dodata == 1)
goto initctxt;
no:
// not a special composit literal assignment
return 0;
initctxt:
switch(n->right->op) {
default:
goto no;
case OSTRUCTLIT:
structlit(n->right, n->left, 3, init);
break;
case OARRAYLIT:
t = n->right->type;
if(t == T)
goto no;
if(t->bound < 0) {
slicelit(n->right, n->left, init);
break;
}
arraylit(n->right, n->left, 3, init);
break;
case OMAPLIT:
maplit(n->right, n->left, init);
break;
}
n->op = OEMPTY;
return 1;
}
/*
* walk through argin parameters.
* generate and return code to allocate