summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Thompson <ken@golang.org>2009-09-05 20:32:24 -0700
committerKen Thompson <ken@golang.org>2009-09-05 20:32:24 -0700
commit3e1759a758d14be6e09f7241feb19e37a2258ad4 (patch)
tree3e030b4eb47778c52614ffdb1441d94d396cb241
parent4bd5147e35a0e4bd529a1ca2ae7b31fc9f0ab47e (diff)
downloadgolang-3e1759a758d14be6e09f7241feb19e37a2258ad4.tar.gz
composit literals
plateau - more to come R=rsc OCL=34413 CL=34413
-rw-r--r--src/cmd/6g/cgen.c4
-rw-r--r--src/cmd/6g/gg.h2
-rw-r--r--src/cmd/6g/ggen.c65
-rw-r--r--src/cmd/gc/gen.c5
-rw-r--r--src/cmd/gc/go.h10
-rw-r--r--src/cmd/gc/init.c9
-rw-r--r--src/cmd/gc/sinit.c3
-rw-r--r--src/cmd/gc/subr.c3
-rw-r--r--src/cmd/gc/walk.c265
9 files changed, 216 insertions, 150 deletions
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
index 2f2b2d9eb..0b01ada3d 100644
--- a/src/cmd/6g/cgen.c
+++ b/src/cmd/6g/cgen.c
@@ -31,10 +31,6 @@ cgen(Node *n, Node *res)
while(n->op == OCONVNOP)
n = n->left;
- // static initializations
- if(initflag && gen_as_init(n, res))
- goto ret;
-
// inline slices
if(cgen_inline(n, res))
goto ret;
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
index 39b56d04a..388a1069a 100644
--- a/src/cmd/6g/gg.h
+++ b/src/cmd/6g/gg.h
@@ -79,7 +79,7 @@ void genconv(Type*, Type*);
void allocparams(void);
void checklabels();
void ginscall(Node*, int);
-int gen_as_init(Node*, Node*);
+int gen_as_init(Node*);
/*
* cgen
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index c7a1f2d77..8fd3a49d9 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -1031,6 +1031,7 @@ stataddr(Node *nam, Node *n)
goto no;
switch(n->op) {
+
case ONAME:
*nam = *n;
return n->addable;
@@ -1060,58 +1061,31 @@ no:
}
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;
@@ -1120,20 +1094,14 @@ gen_as_init(Node *nr, Node *nl)
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:
@@ -1144,14 +1112,19 @@ lit:
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;
@@ -1168,10 +1141,14 @@ lit:
}
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
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index d13af7a66..1259b030a 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -324,6 +324,8 @@ gen(Node *n)
break;
case OAS:
+ if(gen_as_init(n))
+ break;
cgen_as(n->left, n->right);
break;
@@ -456,8 +458,6 @@ cgen_as(Node *nl, Node *nr)
return;
if(nl->class & PHEAP)
return;
- if(gen_as_init(nr, nl))
- return;
}
tl = nl->type;
@@ -612,4 +612,3 @@ tempname(Node *n, Type *t)
stksize = rnd(stksize, w);
n->xoffset = -stksize;
}
-
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index e9dd4bc33..4f58fc00a 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -196,6 +196,7 @@ struct Node
uchar typecheck;
uchar local;
uchar initorder;
+ uchar dodata; // compile literal assignment as data statement
// most nodes
Node* left;
@@ -329,7 +330,6 @@ enum
OCLOSURE,
OCMPIFACE, OCMPSTR,
OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
- OCOMPSLICE, OCOMPMAP,
OCONV, OCONVNOP, OCONVIFACE, OCONVSLICE,
ODCL, ODCLFUNC, ODCLFIELD, ODCLCONST, ODCLTYPE,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
@@ -653,7 +653,6 @@ EXTERN NodeList* exportlist;
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;
@@ -826,7 +825,6 @@ Node* syslook(char*, int);
Node* treecopy(Node*);
NodeList* listtreecopy(NodeList*);
int isselect(Node*);
-void tempname(Node*, Type*);
Node* staticname(Type*);
int iscomposite(Type*);
Node* callnew(Type*);
@@ -1013,9 +1011,7 @@ void colasdefn(NodeList*, Node*);
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*);
@@ -1171,5 +1167,5 @@ int duint64(Sym *s, int off, uint64 v);
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*);
diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c
index 6e31b7325..ef97459eb 100644
--- a/src/cmd/gc/init.c
+++ b/src/cmd/gc/init.c
@@ -152,8 +152,7 @@ fninit(NodeList *n)
a->nbody = list(a->nbody, b);
// (6)
- a = nod(OASOP, gatevar, nodintconst(1));
- a->etype = OADD;
+ a = nod(OAS, gatevar, nodintconst(1));
r = list(r, a);
// (7)
@@ -186,8 +185,7 @@ fninit(NodeList *n)
}
// (10)
- a = nod(OASOP, gatevar, nodintconst(1));
- a->etype = OADD;
+ a = nod(OAS, gatevar, nodintconst(2));
r = list(r, a);
// (11)
@@ -197,10 +195,7 @@ fninit(NodeList *n)
exportsym(fn->nname);
fn->nbody = r;
-
- initflag = 1; // flag for loader static initialization
funcbody(fn);
typecheck(&fn, Etop);
funccompile(fn);
- initflag = 0;
}
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index da3084341..d8d2bc69b 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -51,6 +51,7 @@ init1(Node *n, NodeList **out)
case OAS:
if(n->defn->left != n)
goto bad;
+ n->dodata = 1;
init1(n->defn->right, out);
if(debug['j'])
print("%S\n", n->sym);
@@ -63,7 +64,7 @@ init1(Node *n, NodeList **out)
bad:
dump("defn", n->defn);
- fatal("bad defn");
+ fatal("init1: bad defn");
}
static void
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 1cc568f4b..7ef113d2f 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -866,6 +866,9 @@ Jconv(Fmt *fp)
if(n->typecheck != 0)
fmtprint(fp, " tc(%d)", n->typecheck);
+ if(n->dodata != 0)
+ fmtprint(fp, " dd(%d)", n->dodata);
+
return 0;
}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 8776d34ae..5fc135c2d 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -812,21 +812,10 @@ walkexpr(Node **np, NodeList **init)
// 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;
}
@@ -963,15 +952,12 @@ walkexpr(Node **np, NodeList **init)
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:
@@ -1982,79 +1968,102 @@ reorder4(NodeList *ll)
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);
@@ -2062,31 +2071,20 @@ arraylit(Node *n, Node *var, NodeList **init)
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);
@@ -2105,7 +2103,108 @@ maplit(Node *n, Node *var, NodeList **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;
+ }
}
/*