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:
parent
49fceff6af
commit
62231e91d0
@ -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) {
|
||||
|
113
src/cmd/6g/gen.c
113
src/cmd/6g/gen.c
@ -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;
|
||||
}
|
||||
|
190
src/cmd/gc/dcl.c
190
src/cmd/gc/dcl.c
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user