Commit 18f2e360 authored by Ken Thompson's avatar Ken Thompson

composit literals

plateau - more to come

R=rsc
OCL=34413
CL=34413
parent eabcb10a
...@@ -31,10 +31,6 @@ cgen(Node *n, Node *res) ...@@ -31,10 +31,6 @@ cgen(Node *n, Node *res)
while(n->op == OCONVNOP) while(n->op == OCONVNOP)
n = n->left; n = n->left;
// static initializations
if(initflag && gen_as_init(n, res))
goto ret;
// inline slices // inline slices
if(cgen_inline(n, res)) if(cgen_inline(n, res))
goto ret; goto ret;
......
...@@ -79,7 +79,7 @@ void genconv(Type*, Type*); ...@@ -79,7 +79,7 @@ void genconv(Type*, Type*);
void allocparams(void); void allocparams(void);
void checklabels(); void checklabels();
void ginscall(Node*, int); void ginscall(Node*, int);
int gen_as_init(Node*, Node*); int gen_as_init(Node*);
/* /*
* cgen * cgen
......
...@@ -1031,6 +1031,7 @@ stataddr(Node *nam, Node *n) ...@@ -1031,6 +1031,7 @@ stataddr(Node *nam, Node *n)
goto no; goto no;
switch(n->op) { switch(n->op) {
case ONAME: case ONAME:
*nam = *n; *nam = *n;
return n->addable; return n->addable;
...@@ -1060,58 +1061,31 @@ no: ...@@ -1060,58 +1061,31 @@ no:
} }
int int
gen_as_init(Node *nr, Node *nl) gen_as_init(Node *n)
{ {
Node *nr, *nl;
Node nam, nod1; Node nam, nod1;
Prog *p; Prog *p;
if(!initflag) if(n->dodata == 0)
goto no; goto no;
nr = n->right;
nl = n->left;
if(nr == N) { if(nr == N) {
if(!stataddr(&nam, nl)) if(!stataddr(&nam, nl))
goto no; goto no;
if(nam.class != PEXTERN) if(nam.class != PEXTERN)
goto no; 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; goto yes;
} }
if(nr->op == OCOMPMAP) { if(nr->type == T || !eqtype(nl->type, nr->type))
goto yes;
}
if(nr->type == T ||
!eqtype(nl->type, nr->type))
goto no; goto no;
if(!stataddr(&nam, nl)) if(!stataddr(&nam, nl))
goto no; goto no;
if(nam.class != PEXTERN) if(nam.class != PEXTERN)
goto no; goto no;
...@@ -1120,20 +1094,14 @@ gen_as_init(Node *nr, Node *nl) ...@@ -1120,20 +1094,14 @@ gen_as_init(Node *nr, Node *nl)
goto no; goto no;
case OLITERAL: case OLITERAL:
goto lit; break;
} }
no:
return 0;
lit:
switch(nr->type->etype) { switch(nr->type->etype) {
default: default:
goto no; goto no;
case TBOOL: case TBOOL:
if(memcmp(nam.sym->name, "initdone·", 9) == 0)
goto no;
case TINT8: case TINT8:
case TUINT8: case TUINT8:
case TINT16: case TINT16:
...@@ -1144,14 +1112,19 @@ lit: ...@@ -1144,14 +1112,19 @@ lit:
case TUINT64: case TUINT64:
case TINT: case TINT:
case TUINT: case TUINT:
case TUINTPTR:
case TPTR32:
case TPTR64:
case TFLOAT32: case TFLOAT32:
case TFLOAT64: case TFLOAT64:
case TFLOAT: case TFLOAT:
p = gins(ANOP, N, N); // in case the data is the dest of a goto
p = gins(ADATA, &nam, nr); p = gins(ADATA, &nam, nr);
p->from.scale = nr->type->width; p->from.scale = nr->type->width;
break; break;
case TSTRING: case TSTRING:
gins(ANOP, N, N); // in case the data is the dest of a goto
p = gins(ADATA, &nam, N); p = gins(ADATA, &nam, N);
datastring(nr->val.u.sval->s, nr->val.u.sval->len, &p->to); datastring(nr->val.u.sval->s, nr->val.u.sval->len, &p->to);
p->from.scale = types[tptr]->width; p->from.scale = types[tptr]->width;
...@@ -1168,10 +1141,14 @@ lit: ...@@ -1168,10 +1141,14 @@ lit:
} }
yes: yes:
//dump("\ngen_as_init", nl);
//dump("", nr);
//print("%P\n", p);
return 1; return 1;
no:
if(n->dodata == 2) {
dump("\ngen_as_init", n);
fatal("gen_as_init couldnt make data statement");
}
return 0;
} }
static int static int
......
...@@ -324,6 +324,8 @@ gen(Node *n) ...@@ -324,6 +324,8 @@ gen(Node *n)
break; break;
case OAS: case OAS:
if(gen_as_init(n))
break;
cgen_as(n->left, n->right); cgen_as(n->left, n->right);
break; break;
...@@ -456,8 +458,6 @@ cgen_as(Node *nl, Node *nr) ...@@ -456,8 +458,6 @@ cgen_as(Node *nl, Node *nr)
return; return;
if(nl->class & PHEAP) if(nl->class & PHEAP)
return; return;
if(gen_as_init(nr, nl))
return;
} }
tl = nl->type; tl = nl->type;
...@@ -612,4 +612,3 @@ tempname(Node *n, Type *t) ...@@ -612,4 +612,3 @@ tempname(Node *n, Type *t)
stksize = rnd(stksize, w); stksize = rnd(stksize, w);
n->xoffset = -stksize; n->xoffset = -stksize;
} }
...@@ -196,6 +196,7 @@ struct Node ...@@ -196,6 +196,7 @@ struct Node
uchar typecheck; uchar typecheck;
uchar local; uchar local;
uchar initorder; uchar initorder;
uchar dodata; // compile literal assignment as data statement
// most nodes // most nodes
Node* left; Node* left;
...@@ -329,7 +330,6 @@ enum ...@@ -329,7 +330,6 @@ enum
OCLOSURE, OCLOSURE,
OCMPIFACE, OCMPSTR, OCMPIFACE, OCMPSTR,
OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
OCOMPSLICE, OCOMPMAP,
OCONV, OCONVNOP, OCONVIFACE, OCONVSLICE, OCONV, OCONVNOP, OCONVIFACE, OCONVSLICE,
ODCL, ODCLFUNC, ODCLFIELD, ODCLCONST, ODCLTYPE, ODCL, ODCLFUNC, ODCLFIELD, ODCLCONST, ODCLTYPE,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
...@@ -653,7 +653,6 @@ EXTERN NodeList* exportlist; ...@@ -653,7 +653,6 @@ EXTERN NodeList* exportlist;
EXTERN NodeList* typelist; EXTERN NodeList* typelist;
EXTERN int dclcontext; // PEXTERN/PAUTO EXTERN int dclcontext; // PEXTERN/PAUTO
EXTERN int inimportsys; EXTERN int inimportsys;
EXTERN int initflag; // compiling the init fn
EXTERN int statuniqgen; // name generator for static temps EXTERN int statuniqgen; // name generator for static temps
EXTERN int loophack; EXTERN int loophack;
...@@ -826,7 +825,6 @@ Node* syslook(char*, int); ...@@ -826,7 +825,6 @@ Node* syslook(char*, int);
Node* treecopy(Node*); Node* treecopy(Node*);
NodeList* listtreecopy(NodeList*); NodeList* listtreecopy(NodeList*);
int isselect(Node*); int isselect(Node*);
void tempname(Node*, Type*);
Node* staticname(Type*); Node* staticname(Type*);
int iscomposite(Type*); int iscomposite(Type*);
Node* callnew(Type*); Node* callnew(Type*);
...@@ -1013,9 +1011,7 @@ void colasdefn(NodeList*, Node*); ...@@ -1013,9 +1011,7 @@ void colasdefn(NodeList*, Node*);
NodeList* reorder1(NodeList*); NodeList* reorder1(NodeList*);
NodeList* reorder3(NodeList*); NodeList* reorder3(NodeList*);
NodeList* reorder4(NodeList*); NodeList* reorder4(NodeList*);
Node* structlit(Node*, Node*, NodeList**); void anylit(Node*, Node*, NodeList**);
Node* arraylit(Node*, Node*, NodeList**);
Node* maplit(Node*, Node*, NodeList**);
void heapmoves(void); void heapmoves(void);
void walkdeflist(NodeList*); void walkdeflist(NodeList*);
void walkdef(Node*); void walkdef(Node*);
...@@ -1171,5 +1167,5 @@ int duint64(Sym *s, int off, uint64 v); ...@@ -1171,5 +1167,5 @@ int duint64(Sym *s, int off, uint64 v);
int duintptr(Sym *s, int off, uint64 v); int duintptr(Sym *s, int off, uint64 v);
int duintxx(Sym *s, int off, uint64 v, int wid); int duintxx(Sym *s, int off, uint64 v, int wid);
void genembedtramp(Type*, Type*, Sym*); void genembedtramp(Type*, Type*, Sym*);
int gen_as_init(Node*, Node*); int gen_as_init(Node*);
...@@ -152,8 +152,7 @@ fninit(NodeList *n) ...@@ -152,8 +152,7 @@ fninit(NodeList *n)
a->nbody = list(a->nbody, b); a->nbody = list(a->nbody, b);
// (6) // (6)
a = nod(OASOP, gatevar, nodintconst(1)); a = nod(OAS, gatevar, nodintconst(1));
a->etype = OADD;
r = list(r, a); r = list(r, a);
// (7) // (7)
...@@ -186,8 +185,7 @@ fninit(NodeList *n) ...@@ -186,8 +185,7 @@ fninit(NodeList *n)
} }
// (10) // (10)
a = nod(OASOP, gatevar, nodintconst(1)); a = nod(OAS, gatevar, nodintconst(2));
a->etype = OADD;
r = list(r, a); r = list(r, a);
// (11) // (11)
...@@ -197,10 +195,7 @@ fninit(NodeList *n) ...@@ -197,10 +195,7 @@ fninit(NodeList *n)
exportsym(fn->nname); exportsym(fn->nname);
fn->nbody = r; fn->nbody = r;
initflag = 1; // flag for loader static initialization
funcbody(fn); funcbody(fn);
typecheck(&fn, Etop); typecheck(&fn, Etop);
funccompile(fn); funccompile(fn);
initflag = 0;
} }
...@@ -51,6 +51,7 @@ init1(Node *n, NodeList **out) ...@@ -51,6 +51,7 @@ init1(Node *n, NodeList **out)
case OAS: case OAS:
if(n->defn->left != n) if(n->defn->left != n)
goto bad; goto bad;
n->dodata = 1;
init1(n->defn->right, out); init1(n->defn->right, out);
if(debug['j']) if(debug['j'])
print("%S\n", n->sym); print("%S\n", n->sym);
...@@ -63,7 +64,7 @@ init1(Node *n, NodeList **out) ...@@ -63,7 +64,7 @@ init1(Node *n, NodeList **out)
bad: bad:
dump("defn", n->defn); dump("defn", n->defn);
fatal("bad defn"); fatal("init1: bad defn");
} }
static void static void
......
...@@ -866,6 +866,9 @@ Jconv(Fmt *fp) ...@@ -866,6 +866,9 @@ Jconv(Fmt *fp)
if(n->typecheck != 0) if(n->typecheck != 0)
fmtprint(fp, " tc(%d)", n->typecheck); fmtprint(fp, " tc(%d)", n->typecheck);
if(n->dodata != 0)
fmtprint(fp, " dd(%d)", n->dodata);
return 0; return 0;
} }
......
...@@ -812,21 +812,10 @@ walkexpr(Node **np, NodeList **init) ...@@ -812,21 +812,10 @@ walkexpr(Node **np, NodeList **init)
// and replace expression with nvar // and replace expression with nvar
switch(n->left->op) { switch(n->left->op) {
case OARRAYLIT: case OARRAYLIT:
nvar = makenewvar(n->type, init, &nstar);
arraylit(n->left, nstar, init);
n = nvar;
goto ret;
case OMAPLIT: case OMAPLIT:
nvar = makenewvar(n->type, init, &nstar);
maplit(n->left, nstar, init);
n = nvar;
goto ret;
case OSTRUCTLIT: case OSTRUCTLIT:
nvar = makenewvar(n->type, init, &nstar); nvar = makenewvar(n->type, init, &nstar);
structlit(n->left, nstar, init); anylit(n->left, nstar, init);
n = nvar; n = nvar;
goto ret; goto ret;
} }
...@@ -963,15 +952,12 @@ walkexpr(Node **np, NodeList **init) ...@@ -963,15 +952,12 @@ walkexpr(Node **np, NodeList **init)
goto ret; goto ret;
case OARRAYLIT: case OARRAYLIT:
n = arraylit(n, N, init);
goto ret;
case OMAPLIT: case OMAPLIT:
n = maplit(n, N, init);
goto ret;
case OSTRUCTLIT: case OSTRUCTLIT:
n = structlit(n, N, init); nvar = nod(OXXX, N, N);
tempname(nvar, n->type);
anylit(n, nvar, init);
n = nvar;
goto ret; goto ret;
case OSEND: case OSEND:
...@@ -1982,79 +1968,102 @@ reorder4(NodeList *ll) ...@@ -1982,79 +1968,102 @@ reorder4(NodeList *ll)
return ll; return ll;
} }
Node* static int
structlit(Node *n, Node *var, NodeList **init) 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; Node *r, *a;
NodeList *nl; NodeList *nl;
Node *index, *value;
t = n->type; for(nl=n->list; nl; nl=nl->next) {
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) {
r = nl->n; 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 // build list of var.field = expr
a = nod(ODOT, var, newname(r->left->sym)); a = nod(ODOT, var, newname(index->sym));
a = nod(OAS, a, r->right); a = nod(OAS, a, value);
typecheck(&a, Etop); typecheck(&a, Etop);
walkexpr(&a, init); walkexpr(&a, init);
if(pass == 1) {
if(a->op != OAS)
fatal("structlit: not as");
a->dodata = 2;
}
*init = list(*init, a); *init = list(*init, a);
} }
return var;
} }
Node* void
arraylit(Node *n, Node *var, NodeList **init) arraylit(Node *n, Node *var, int pass, NodeList **init)
{ {
Type *t;
Node *r, *a; Node *r, *a;
NodeList *l; NodeList *l;
Node *index, *value;
t = n->type; for(l=n->list; l; l=l->next) {
r = l->n;
if(var == N) { if(r->op != OKEY)
var = nod(OXXX, N, N); fatal("arraylit: rhs not OKEY: %N", r);
tempname(var, t); index = r->left;
} value = r->right;
if(t->bound < 0) { if(isliteral(index) && isliteral(value)) {
// slice if(pass == 2)
a = nod(OMAKE, N, N); continue;
a->list = list(list1(typenod(t)), n->right); } else
a = nod(OAS, var, a); if(pass == 1)
continue;
// build list of var[index] = value
a = nod(OINDEX, var, index);
a = nod(OAS, a, value);
typecheck(&a, Etop); typecheck(&a, Etop);
walkexpr(&a, init); walkexpr(&a, init); // add any assignments in r to top
*init = list(*init, a); if(pass == 1) {
} else { if(a->op != OAS)
// if entire array isnt initialized, fatal("structlit: not as");
// then clear the array a->dodata = 2;
if(count(n->list) < t->bound) {
a = nod(OAS, var, N);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
} }
*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) { for(l=n->list; l; l=l->next) {
r = l->n; r = l->n;
// build list of var[c] = expr // build list of var[c] = expr
a = nod(OINDEX, var, r->left); a = nod(OINDEX, var, r->left);
a = nod(OAS, a, r->right); a = nod(OAS, a, r->right);
...@@ -2062,31 +2071,20 @@ arraylit(Node *n, Node *var, NodeList **init) ...@@ -2062,31 +2071,20 @@ arraylit(Node *n, Node *var, NodeList **init)
walkexpr(&a, init); // add any assignments in r to top walkexpr(&a, init); // add any assignments in r to top
*init = list(*init, a); *init = list(*init, a);
} }
return var;
} }
Node* void
maplit(Node *n, Node *var, NodeList **init) maplit(Node *n, Node *var, NodeList **init)
{ {
Type *t;
Node *r, *a; Node *r, *a;
Node* hash[101]; Node* hash[101];
NodeList *l; NodeList *l;
int nerr; int nerr;
nerr = nerrors; 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 = nod(OMAKE, N, N);
a->list = list1(typenod(t)); a->list = list1(typenod(n->type));
a = nod(OAS, var, a); a = nod(OAS, var, a);
typecheck(&a, Etop); typecheck(&a, Etop);
walkexpr(&a, init); walkexpr(&a, init);
...@@ -2105,7 +2103,108 @@ maplit(Node *n, Node *var, NodeList **init) ...@@ -2105,7 +2103,108 @@ maplit(Node *n, Node *var, NodeList **init)
*init = list(*init, a); *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;
}
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment