mirror of
https://github.com/golang/go
synced 2024-11-25 13:17:56 -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:
parent
aa6e81dd71
commit
0631d65dc5
@ -1093,6 +1093,9 @@ gen_as_init(Node *n)
|
|||||||
default:
|
default:
|
||||||
goto no;
|
goto no;
|
||||||
|
|
||||||
|
case OCONVSLICE:
|
||||||
|
goto slice;
|
||||||
|
|
||||||
case OLITERAL:
|
case OLITERAL:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1143,6 +1146,34 @@ gen_as_init(Node *n)
|
|||||||
yes:
|
yes:
|
||||||
return 1;
|
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:
|
no:
|
||||||
if(n->dodata == 2) {
|
if(n->dodata == 2) {
|
||||||
dump("\ngen_as_init", n);
|
dump("\ngen_as_init", n);
|
||||||
|
@ -205,6 +205,8 @@ dowidth(Type *t)
|
|||||||
w = sizeof_Array;
|
w = sizeof_Array;
|
||||||
else
|
else
|
||||||
fatal("dowidth %T", t); // probably [...]T
|
fatal("dowidth %T", t); // probably [...]T
|
||||||
|
if(w == 0)
|
||||||
|
w = maxround;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TSTRUCT:
|
case TSTRUCT:
|
||||||
|
@ -1020,6 +1020,7 @@ void colasdefn(NodeList*, Node*);
|
|||||||
NodeList* reorder1(NodeList*);
|
NodeList* reorder1(NodeList*);
|
||||||
NodeList* reorder3(NodeList*);
|
NodeList* reorder3(NodeList*);
|
||||||
NodeList* reorder4(NodeList*);
|
NodeList* reorder4(NodeList*);
|
||||||
|
int vmatch1(Node*, Node*);
|
||||||
void anylit(Node*, Node*, NodeList**);
|
void anylit(Node*, Node*, NodeList**);
|
||||||
int oaslit(Node*, NodeList**);
|
int oaslit(Node*, NodeList**);
|
||||||
void heapmoves(void);
|
void heapmoves(void);
|
||||||
|
@ -95,3 +95,542 @@ initfix(NodeList *l)
|
|||||||
initreorder(l, &lout);
|
initreorder(l, &lout);
|
||||||
return 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;
|
||||||
|
}
|
||||||
|
@ -1971,491 +1971,6 @@ reorder4(NodeList *ll)
|
|||||||
return 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.
|
* walk through argin parameters.
|
||||||
* generate and return code to allocate
|
* generate and return code to allocate
|
||||||
|
Loading…
Reference in New Issue
Block a user