summaryrefslogtreecommitdiff
path: root/src/cmd/gc/sinit.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-09-17 19:15:54 -0700
committerRuss Cox <rsc@golang.org>2009-09-17 19:15:54 -0700
commit66faa8ea80cda530644b4a12712eead17d1b9f3b (patch)
treed53c65e13bedaabc25a73358a06c5a641c033c00 /src/cmd/gc/sinit.c
parent4e382ea1719742f9e8a88632de4eb968cf97de36 (diff)
downloadgolang-66faa8ea80cda530644b4a12712eead17d1b9f3b.tar.gz
move static init code from 6g into gc.
hook up to 8g and 5g too. R=ken OCL=34768 CL=34768
Diffstat (limited to 'src/cmd/gc/sinit.c')
-rw-r--r--src/cmd/gc/sinit.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index 4ae82ba2c..c22a582e1 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -634,3 +634,156 @@ initctxt:
n->op = OEMPTY;
return 1;
}
+
+int
+getlit(Node *lit)
+{
+ 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 n->addable;
+
+ 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 *n)
+{
+ Node *nr, *nl;
+ Node nam, nod1;
+
+ 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;
+ goto yes;
+ }
+
+ 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 OCONVSLICE:
+ goto slice;
+
+ case OLITERAL:
+ break;
+ }
+
+ switch(nr->type->etype) {
+ default:
+ goto no;
+
+ case TBOOL:
+ case TINT8:
+ case TUINT8:
+ case TINT16:
+ case TUINT16:
+ case TINT32:
+ case TUINT32:
+ case TINT64:
+ case TUINT64:
+ case TINT:
+ case TUINT:
+ case TUINTPTR:
+ case TPTR32:
+ case TPTR64:
+ case TFLOAT32:
+ case TFLOAT64:
+ case TFLOAT:
+ gused(N); // in case the data is the dest of a goto
+ gdata(&nam, nr, nr->type->width);
+ break;
+
+ case TSTRING:
+ gused(N); // in case the data is the dest of a goto
+ gdatastring(&nam, nr->val.u.sval);
+ break;
+ }
+
+yes:
+ return 1;
+
+slice:
+ gused(N); // in case the data is the dest of a goto
+ nr = n->right->left;
+ if(nr == N || nr->op != OADDR)
+ goto no;
+ nr = nr->left;
+ if(nr == N || nr->op != ONAME)
+ goto no;
+
+ // nr is the array being converted to a slice
+ if(nr->type == T || nr->type->etype != TARRAY || nr->type->bound < 0)
+ goto no;
+
+ nam.xoffset += Array_array;
+ gdata(&nam, n->right->left, types[tptr]->width);
+
+ nam.xoffset += Array_nel-Array_array;
+ nodconst(&nod1, types[TINT32], nr->type->bound);
+ gdata(&nam, &nod1, types[TINT32]->width);
+
+ nam.xoffset += Array_cap-Array_nel;
+ gdata(&nam, &nod1, types[TINT32]->width);
+
+ goto yes;
+
+no:
+ if(n->dodata == 2) {
+ dump("\ngen_as_init", n);
+ fatal("gen_as_init couldnt make data statement");
+ }
+ return 0;
+}
+