1
0
mirror of https://github.com/golang/go synced 2024-11-22 17:14:41 -07:00

static initialization with DATA statements

structs and arrays are done
slices and maps are yet to do

R=r
OCL=28977
CL=28977
This commit is contained in:
Ken Thompson 2009-05-17 19:16:16 -07:00
parent 49fceff6af
commit 62231e91d0
5 changed files with 338 additions and 36 deletions

View File

@ -29,7 +29,7 @@ cgen(Node *n, Node *res)
fatal("cgen: res nil");
// static initializations
if(gen_as_init(n, res))
if(initflag && gen_as_init(n, res))
goto ret;
if(n->ullman >= UINF) {

View File

@ -699,7 +699,118 @@ clearfat(Node *nl)
}
int
gen_as_init(Node *nr, Node *nl)
getlit(Node *lit)
{
int l;
if(smallintconst(lit))
return mpgetfix(lit->val.u.xval);
return -1;
}
int
stataddr(Node *nam, Node *n)
{
int l;
if(n == N)
goto no;
switch(n->op) {
case ONAME:
*nam = *n;
return 1;
case ODOT:
if(!stataddr(nam, n->left))
break;
nam->xoffset += n->xoffset;
nam->type = n->type;
return 1;
case OINDEX:
if(n->left->type->bound < 0)
break;
if(!stataddr(nam, n->left))
break;
l = getlit(n->right);
if(l < 0)
break;
nam->xoffset += l*n->type->width;
nam->type = n->type;
return 1;
}
no:
return 0;
}
int
gen_as_init(Node *nr, Node *nl)
{
Node nam;
Prog *p;
if(!initflag)
goto no;
if(nr == N) {
if(!stataddr(&nam, nl))
goto no;
if(nam.class != PEXTERN)
goto no;
return 1;
}
if(nr->type == T ||
!eqtype(nl->type, nr->type))
goto no;
if(!stataddr(&nam, nl))
goto no;
if(nam.class != PEXTERN)
goto no;
switch(nr->op) {
default:
goto no;
case OLITERAL:
goto lit;
}
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 TUINT16:
case TINT32:
case TUINT32:
case TINT64:
case TUINT64:
case TINT:
case TUINT:
case TFLOAT32:
case TFLOAT64:
case TFLOAT:
p = gins(ADATA, &nam, nr);
p->from.scale = nr->type->width;
break;
}
yes:
//dump("\ngen_as_init", nl);
//dump("", nr);
//print("%P\n", p);
return 1;
}

View File

@ -1322,6 +1322,194 @@ anyinit(Node *n)
return 0;
}
/*
* the init code (thru initfix) reformats the
* var = ...
* statements, rewriting the automatic
* variables with the static variables.
* this allows the code generator to
* generate DATA statements instead
* of assignment statements.
* it is quadradic, may need to change.
* it is extremely fragile knowing exactly
* how the code from (struct|array|map)lit
* will look. ideally the lit routines could
* write the code in this form, but ...
*/
static Node* xxx;
void
initlin(Node* n)
{
if(n == N)
return;
initlin(n->ninit);
switch(n->op) {
default:
print("o = %O\n", n->op);
n->ninit = N;
xxx = list(xxx, n);
break;
case OCALL:
// call to mapassign1
if(n->left->op != ONAME ||
n->right->op != OLIST ||
n->right->left->op != OAS ||
n->right->right->op != OLIST ||
n->right->right->left->op != OAS ||
n->right->right->right->op != OAS ||
memcmp(n->left->sym->name, "mapassign1", 10) != 0)
dump("o=call", n);
n->ninit = N;
xxx = list(xxx, n);
break;
case OAS:
n->ninit = N;
xxx = list(xxx, n);
break;
case OLIST:
initlin(n->left);
initlin(n->right);
break;
}
}
int
inittmp(Node *n)
{
if(n != N)
if(n->op == ONAME)
if(n->sym != S)
if(n->class == PAUTO)
if(memcmp(n->sym->name, "!tmpname", 8) == 0)
return 1;
return 0;
}
int
sametmp(Node *n1, Node *n2)
{
if(inittmp(n1))
if(n1->xoffset == n2->xoffset)
return 1;
return 0;
}
int
indsametmp(Node *n1, Node *n2)
{
if(n1->op == OIND)
if(inittmp(n1->left))
if(n1->left->xoffset == n2->xoffset)
return 1;
return 0;
}
int
initsub(Node *n, Node *nam)
{
Iter iter;
Node *r;
int any, i;
any = 0;
r = listfirst(&iter, &xxx);
while(r != N) {
switch(r->op) {
case OAS:
case OEMPTY:
if(r->left != N)
switch(r->left->op) {
case ONAME:
if(sametmp(r->left, nam)) {
any = 1;
r->left = n;
}
break;
case ODOT:
if(sametmp(r->left->left, nam)) {
any = 1;
r->left->left = n;
}
if(indsametmp(r->left->left, nam)) {
any = 1;
r->left->left->left = n;
}
break;
case OINDEX:
if(sametmp(r->left->left, nam)) {
any = 1;
r->left->left = n;
}
if(indsametmp(r->left->left, nam)) {
any = 1;
r->left->left->left = n;
}
break;
}
break;
case OCALL:
// call to mapassign1
// look through all three parameters
for(i=0; i<2; i++) {
r = r->right;
if(r == N || r->op != OLIST)
break;
if(sametmp(r->left->right, nam)) {
any = 1;
r->left->right = n;
}
if(indsametmp(r->left->right, nam)) {
any = 1;
r->left->left->right = n;
}
if(sametmp(r->right->right, nam)) {
any = 1;
r->right->right = n;
}
if(indsametmp(r->right->right, nam)) {
any = 1;
r->right->left->right = n;
}
}
break;
}
r = listnext(&iter);
}
return any;
}
Node*
initfix(Node* n)
{
Iter iter;
Node *r;
//dump("prelin", n);
xxx = N;
initlin(n);
xxx = rev(xxx);
//dump("preinitfix", xxx);
// look for the copy-out reference
r = listfirst(&iter, &xxx);
while(r != N) {
if(r->op == OAS)
if(inittmp(r->right)) {
if(initsub(r->left, r->right))
r->op = OEMPTY;
}
r = listnext(&iter);
}
//dump("postinitfix", xxx);
return xxx;
}
void
fninit(Node *n)
{
@ -1389,7 +1577,7 @@ fninit(Node *n)
}
// (6)
r = list(r, n);
r = list(r, initfix(n));
// (7)
// could check that it is fn of no args/returns

View File

@ -444,6 +444,8 @@ cgen_as(Node *nl, Node *nr)
return;
if(nl->class & PHEAP)
return;
if(gen_as_init(nr, nl))
return;
}
tl = nl->type;

View File

@ -588,26 +588,26 @@ loop:
l = n->left;
if(l == N)
goto ret;
switch(t->etype) {
default:
yyerror("invalid type for composite literal: %T", t);
goto ret;
case TSTRUCT:
r = structlit(n, N);
break;
case TARRAY:
r = arraylit(n, N);
break;
case TMAP:
r = maplit(n, N);
break;
}
indir(n, r);
walktype(l, Erv);
// structure literal
if(t->etype == TSTRUCT) {
indir(n, structlit(n, N));
goto ret;
}
// array literal
if(t->etype == TARRAY) {
indir(n, arraylit(n, N));
goto ret;
}
// map literal
if(t->etype == TMAP) {
indir(n, maplit(n, N));
goto ret;
}
yyerror("invalid type for composite literal: %T", t);
goto ret;
case ORETURN:
@ -926,18 +926,19 @@ loop:
goto nottop;
defaultlit(n->left, T);
if(n->left->op == OCOMPOS && n->left->type != T) {
Node *nvar, *nas, *nstar;
// turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
// initialize with
// nvar := new(*Point);
// *nvar = Point(1, 2);
// and replace expression with nvar
; // stupid c syntax - case label must be on stmt, not decl
Node *nvar, *nas, *nstar;
nvar = nod(OXXX, N, N);
tempname(nvar, ptrto(n->left->type));
nas = nod(OAS, nvar, callnew(n->left->type));
walktype(nas, Etop);
addtop = list(addtop, nas);
nstar = nod(OIND, nvar, N);
@ -957,6 +958,7 @@ loop:
goto badlit;
}
walktype(n->left->left, Erv);
indir(n, nvar);
goto ret;
}
@ -3837,8 +3839,8 @@ arraylit(Node *n, Node *var)
{
Iter saver;
Type *t;
Node *r, *a, *nnew;
int idx, ninit, b;
Node *r, *a;
int ninit, b;
t = n->type;
if(t->etype != TARRAY)
@ -3867,13 +3869,12 @@ arraylit(Node *n, Node *var)
tempname(var, t);
}
nnew = nil;
if(b < 0) {
// slice
nnew = nod(OMAKE, N, N);
nnew->type = t;
a = nod(OAS, var, nnew);
a = nod(OMAKE, N, N);
a->type = t;
a->left = nodintconst(ninit);
a = nod(OAS, var, a);
addtop = list(addtop, a);
} else {
// if entire array isnt initialized,
@ -3884,21 +3885,20 @@ arraylit(Node *n, Node *var)
}
}
idx = 0;
ninit = 0;
r = listfirst(&saver, &n->left);
if(r != N && r->op == OEMPTY)
r = N;
while(r != N) {
// build list of var[c] = expr
a = nodintconst(idx);
a = nodintconst(ninit);
a = nod(OINDEX, var, a);
a = nod(OAS, a, r);
walktype(a, Etop); // add any assignments in r to addtop
addtop = list(addtop, a);
idx++;
ninit++;
r = listnext(&saver);
}
if(b < 0)
nnew->left = nodintconst(idx);
return var;
}
@ -3941,6 +3941,7 @@ loop:
a = nod(OINDEX, var, r->left);
a = nod(OAS, a, r->right);
walktype(a, Etop); // add any assignments in r to addtop
addtop = list(addtop, a);
r = listnext(&saver);