mirror of
https://github.com/golang/go
synced 2024-11-23 00:10:07 -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");
|
fatal("cgen: res nil");
|
||||||
|
|
||||||
// static initializations
|
// static initializations
|
||||||
if(gen_as_init(n, res))
|
if(initflag && gen_as_init(n, res))
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
if(n->ullman >= UINF) {
|
if(n->ullman >= UINF) {
|
||||||
|
113
src/cmd/6g/gen.c
113
src/cmd/6g/gen.c
@ -699,7 +699,118 @@ clearfat(Node *nl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
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;
|
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
|
void
|
||||||
fninit(Node *n)
|
fninit(Node *n)
|
||||||
{
|
{
|
||||||
@ -1389,7 +1577,7 @@ fninit(Node *n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// (6)
|
// (6)
|
||||||
r = list(r, n);
|
r = list(r, initfix(n));
|
||||||
|
|
||||||
// (7)
|
// (7)
|
||||||
// could check that it is fn of no args/returns
|
// could check that it is fn of no args/returns
|
||||||
|
@ -444,6 +444,8 @@ 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;
|
||||||
|
@ -588,28 +588,28 @@ loop:
|
|||||||
l = n->left;
|
l = n->left;
|
||||||
if(l == N)
|
if(l == N)
|
||||||
goto ret;
|
goto ret;
|
||||||
walktype(l, Erv);
|
|
||||||
|
|
||||||
// structure literal
|
switch(t->etype) {
|
||||||
if(t->etype == TSTRUCT) {
|
default:
|
||||||
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);
|
yyerror("invalid type for composite literal: %T", t);
|
||||||
goto ret;
|
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);
|
||||||
|
goto ret;
|
||||||
|
|
||||||
case ORETURN:
|
case ORETURN:
|
||||||
if(top != Etop)
|
if(top != Etop)
|
||||||
goto nottop;
|
goto nottop;
|
||||||
@ -926,18 +926,19 @@ loop:
|
|||||||
goto nottop;
|
goto nottop;
|
||||||
defaultlit(n->left, T);
|
defaultlit(n->left, T);
|
||||||
if(n->left->op == OCOMPOS && n->left->type != 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.
|
// turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
|
||||||
// initialize with
|
// initialize with
|
||||||
// nvar := new(*Point);
|
// nvar := new(*Point);
|
||||||
// *nvar = Point(1, 2);
|
// *nvar = Point(1, 2);
|
||||||
// and replace expression with nvar
|
// 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);
|
nvar = nod(OXXX, N, N);
|
||||||
tempname(nvar, ptrto(n->left->type));
|
tempname(nvar, ptrto(n->left->type));
|
||||||
|
|
||||||
nas = nod(OAS, nvar, callnew(n->left->type));
|
nas = nod(OAS, nvar, callnew(n->left->type));
|
||||||
|
walktype(nas, Etop);
|
||||||
addtop = list(addtop, nas);
|
addtop = list(addtop, nas);
|
||||||
|
|
||||||
nstar = nod(OIND, nvar, N);
|
nstar = nod(OIND, nvar, N);
|
||||||
@ -957,6 +958,7 @@ loop:
|
|||||||
goto badlit;
|
goto badlit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
walktype(n->left->left, Erv);
|
||||||
indir(n, nvar);
|
indir(n, nvar);
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
@ -3837,8 +3839,8 @@ arraylit(Node *n, Node *var)
|
|||||||
{
|
{
|
||||||
Iter saver;
|
Iter saver;
|
||||||
Type *t;
|
Type *t;
|
||||||
Node *r, *a, *nnew;
|
Node *r, *a;
|
||||||
int idx, ninit, b;
|
int ninit, b;
|
||||||
|
|
||||||
t = n->type;
|
t = n->type;
|
||||||
if(t->etype != TARRAY)
|
if(t->etype != TARRAY)
|
||||||
@ -3867,13 +3869,12 @@ arraylit(Node *n, Node *var)
|
|||||||
tempname(var, t);
|
tempname(var, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
nnew = nil;
|
|
||||||
if(b < 0) {
|
if(b < 0) {
|
||||||
// slice
|
// slice
|
||||||
nnew = nod(OMAKE, N, N);
|
a = nod(OMAKE, N, N);
|
||||||
nnew->type = t;
|
a->type = t;
|
||||||
|
a->left = nodintconst(ninit);
|
||||||
a = nod(OAS, var, nnew);
|
a = nod(OAS, var, a);
|
||||||
addtop = list(addtop, a);
|
addtop = list(addtop, a);
|
||||||
} else {
|
} else {
|
||||||
// if entire array isnt initialized,
|
// if entire array isnt initialized,
|
||||||
@ -3884,21 +3885,20 @@ arraylit(Node *n, Node *var)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = 0;
|
ninit = 0;
|
||||||
r = listfirst(&saver, &n->left);
|
r = listfirst(&saver, &n->left);
|
||||||
if(r != N && r->op == OEMPTY)
|
if(r != N && r->op == OEMPTY)
|
||||||
r = N;
|
r = N;
|
||||||
while(r != N) {
|
while(r != N) {
|
||||||
// build list of var[c] = expr
|
// build list of var[c] = expr
|
||||||
a = nodintconst(idx);
|
a = nodintconst(ninit);
|
||||||
a = nod(OINDEX, var, a);
|
a = nod(OINDEX, var, a);
|
||||||
a = nod(OAS, a, r);
|
a = nod(OAS, a, r);
|
||||||
|
walktype(a, Etop); // add any assignments in r to addtop
|
||||||
addtop = list(addtop, a);
|
addtop = list(addtop, a);
|
||||||
idx++;
|
ninit++;
|
||||||
r = listnext(&saver);
|
r = listnext(&saver);
|
||||||
}
|
}
|
||||||
if(b < 0)
|
|
||||||
nnew->left = nodintconst(idx);
|
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3941,6 +3941,7 @@ loop:
|
|||||||
|
|
||||||
a = nod(OINDEX, var, r->left);
|
a = nod(OINDEX, var, r->left);
|
||||||
a = nod(OAS, a, r->right);
|
a = nod(OAS, a, r->right);
|
||||||
|
walktype(a, Etop); // add any assignments in r to addtop
|
||||||
addtop = list(addtop, a);
|
addtop = list(addtop, a);
|
||||||
|
|
||||||
r = listnext(&saver);
|
r = listnext(&saver);
|
||||||
|
Loading…
Reference in New Issue
Block a user