goto no;
switch(n->op) {
+
case ONAME:
*nam = *n;
return n->addable;
}
int
-gen_as_init(Node *nr, Node *nl)
+gen_as_init(Node *n)
{
+ Node *nr, *nl;
Node nam, nod1;
Prog *p;
- if(!initflag)
+ if(n->dodata == 0)
goto no;
+ nr = n->right;
+ nl = n->left;
if(nr == N) {
if(!stataddr(&nam, nl))
goto no;
if(nam.class != PEXTERN)
goto no;
- return 1;
- }
-
- if(nr->op == OCOMPSLICE) {
- // create a slice pointing to an array
- if(!stataddr(&nam, nl)) {
- dump("stataddr", nl);
- goto no;
- }
-
- p = gins(ADATA, &nam, nr->left);
- p->from.scale = types[tptr]->width;
- p->to.index = p->to.type;
- p->to.type = D_ADDR;
-//print("%P\n", p);
-
- nodconst(&nod1, types[TINT32], nr->left->type->bound);
- p = gins(ADATA, &nam, &nod1);
- p->from.scale = types[TINT32]->width;
- p->from.offset += types[tptr]->width;
-//print("%P\n", p);
-
- p = gins(ADATA, &nam, &nod1);
- p->from.scale = types[TINT32]->width;
- p->from.offset += types[tptr]->width+types[TINT32]->width;
-
goto yes;
}
- if(nr->op == OCOMPMAP) {
- goto yes;
- }
-
- if(nr->type == T ||
- !eqtype(nl->type, nr->type))
+ if(nr->type == T || !eqtype(nl->type, nr->type))
goto no;
if(!stataddr(&nam, nl))
goto no;
+
if(nam.class != PEXTERN)
goto no;
goto no;
case OLITERAL:
- goto lit;
+ break;
}
-no:
- return 0;
-
-lit:
switch(nr->type->etype) {
default:
goto no;
case TBOOL:
- if(memcmp(nam.sym->name, "initdoneĀ·", 9) == 0)
- goto no;
case TINT8:
case TUINT8:
case TINT16:
case TUINT64:
case TINT:
case TUINT:
+ case TUINTPTR:
+ case TPTR32:
+ case TPTR64:
case TFLOAT32:
case TFLOAT64:
case TFLOAT:
+ p = gins(ANOP, N, N); // in case the data is the dest of a goto
p = gins(ADATA, &nam, nr);
p->from.scale = nr->type->width;
break;
case TSTRING:
+ gins(ANOP, N, N); // in case the data is the dest of a goto
p = gins(ADATA, &nam, N);
datastring(nr->val.u.sval->s, nr->val.u.sval->len, &p->to);
p->from.scale = types[tptr]->width;
}
yes:
-//dump("\ngen_as_init", nl);
-//dump("", nr);
-//print("%P\n", p);
return 1;
+
+no:
+ if(n->dodata == 2) {
+ dump("\ngen_as_init", n);
+ fatal("gen_as_init couldnt make data statement");
+ }
+ return 0;
}
static int
uchar typecheck;
uchar local;
uchar initorder;
+ uchar dodata; // compile literal assignment as data statement
// most nodes
Node* left;
OCLOSURE,
OCMPIFACE, OCMPSTR,
OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
- OCOMPSLICE, OCOMPMAP,
OCONV, OCONVNOP, OCONVIFACE, OCONVSLICE,
ODCL, ODCLFUNC, ODCLFIELD, ODCLCONST, ODCLTYPE,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
EXTERN NodeList* typelist;
EXTERN int dclcontext; // PEXTERN/PAUTO
EXTERN int inimportsys;
-EXTERN int initflag; // compiling the init fn
EXTERN int statuniqgen; // name generator for static temps
EXTERN int loophack;
Node* treecopy(Node*);
NodeList* listtreecopy(NodeList*);
int isselect(Node*);
-void tempname(Node*, Type*);
Node* staticname(Type*);
int iscomposite(Type*);
Node* callnew(Type*);
NodeList* reorder1(NodeList*);
NodeList* reorder3(NodeList*);
NodeList* reorder4(NodeList*);
-Node* structlit(Node*, Node*, NodeList**);
-Node* arraylit(Node*, Node*, NodeList**);
-Node* maplit(Node*, Node*, NodeList**);
+void anylit(Node*, Node*, NodeList**);
void heapmoves(void);
void walkdeflist(NodeList*);
void walkdef(Node*);
int duintptr(Sym *s, int off, uint64 v);
int duintxx(Sym *s, int off, uint64 v, int wid);
void genembedtramp(Type*, Type*, Sym*);
-int gen_as_init(Node*, Node*);
+int gen_as_init(Node*);
// and replace expression with nvar
switch(n->left->op) {
case OARRAYLIT:
- nvar = makenewvar(n->type, init, &nstar);
- arraylit(n->left, nstar, init);
- n = nvar;
- goto ret;
-
case OMAPLIT:
- nvar = makenewvar(n->type, init, &nstar);
- maplit(n->left, nstar, init);
- n = nvar;
- goto ret;
-
-
case OSTRUCTLIT:
nvar = makenewvar(n->type, init, &nstar);
- structlit(n->left, nstar, init);
+ anylit(n->left, nstar, init);
n = nvar;
goto ret;
}
goto ret;
case OARRAYLIT:
- n = arraylit(n, N, init);
- goto ret;
-
case OMAPLIT:
- n = maplit(n, N, init);
- goto ret;
-
case OSTRUCTLIT:
- n = structlit(n, N, init);
+ nvar = nod(OXXX, N, N);
+ tempname(nvar, n->type);
+ anylit(n, nvar, init);
+ n = nvar;
goto ret;
case OSEND:
return ll;
}
-Node*
-structlit(Node *n, Node *var, NodeList **init)
+static int
+isliteral(Node *n)
+{
+ if(n->op == OLITERAL)
+ if(n->val.ctype != CTNIL)
+ return 1;
+ return 0;
+}
+
+void
+structlit(Node *n, Node *var, int pass, NodeList **init)
{
- Type *t;
Node *r, *a;
NodeList *nl;
+ Node *index, *value;
- t = n->type;
- if(t->etype != TSTRUCT)
- fatal("structlit: not struct");
-
- if(var == N) {
- var = nod(OXXX, N, N);
- tempname(var, t);
- }
-
- nl = n->list;
-
- if(count(n->list) < structcount(t)) {
- a = nod(OAS, var, N);
- typecheck(&a, Etop);
- walkexpr(&a, init);
- *init = list(*init, a);
- }
-
- for(; nl; nl=nl->next) {
+ 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;
+
+ if(isliteral(value)) {
+ if(pass == 2)
+ continue;
+ } else
+ if(pass == 1)
+ continue;
// build list of var.field = expr
- a = nod(ODOT, var, newname(r->left->sym));
- a = nod(OAS, a, r->right);
+ 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);
}
- return var;
}
-Node*
-arraylit(Node *n, Node *var, NodeList **init)
+void
+arraylit(Node *n, Node *var, int pass, NodeList **init)
{
- Type *t;
Node *r, *a;
NodeList *l;
+ Node *index, *value;
- t = n->type;
-
- if(var == N) {
- var = nod(OXXX, N, N);
- tempname(var, t);
- }
-
- if(t->bound < 0) {
- // slice
- a = nod(OMAKE, N, N);
- a->list = list(list1(typenod(t)), n->right);
- a = nod(OAS, var, a);
+ 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;
+
+ 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);
- *init = list(*init, a);
- } else {
- // if entire array isnt initialized,
- // then clear the array
- if(count(n->list) < t->bound) {
- a = nod(OAS, var, N);
- typecheck(&a, Etop);
- walkexpr(&a, init);
- *init = list(*init, a);
+ 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;
+
+ // slice
+ a = nod(OMAKE, N, N);
+ a->list = list(list1(typenod(n->type)), n->right);
+ a = nod(OAS, var, a);
+ typecheck(&a, Etop);
+ walkexpr(&a, init);
+ *init = list(*init, a);
for(l=n->list; l; l=l->next) {
r = l->n;
+
// build list of var[c] = expr
a = nod(OINDEX, var, r->left);
a = nod(OAS, a, r->right);
walkexpr(&a, init); // add any assignments in r to top
*init = list(*init, a);
}
-
- return var;
}
-Node*
+void
maplit(Node *n, Node *var, NodeList **init)
{
- Type *t;
Node *r, *a;
Node* hash[101];
NodeList *l;
int nerr;
nerr = nerrors;
- t = n->type;
- if(t->etype != TMAP)
- fatal("maplit: not map");
-
- if(var == N) {
- var = nod(OXXX, N, N);
- tempname(var, t);
- }
a = nod(OMAKE, N, N);
- a->list = list1(typenod(t));
+ a->list = list1(typenod(n->type));
a = nod(OAS, var, a);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
}
- return var;
+}
+
+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;
+ }
}
/*