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)
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;
......
......@@ -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
......
......@@ -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
......
......@@ -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;
}
......@@ -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*);
......@@ -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;
}
......@@ -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
......
......@@ -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;
}
......
......@@ -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;
}
}
/*
......
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