Commit 6fceadbb authored by Ken Thompson's avatar Ken Thompson

cleanup getting ready for static init

R=rsc
OCL=34090
CL=34090
parent 3c098e27
......@@ -32,19 +32,22 @@ renameinit(Node *n)
* hand-craft the following initialization code
* var initdone·<file> uint8 (1)
* func Init·<file>() (2)
* if initdone·<file> { (3)
* if initdone·<file> != 0 { (3)
* if initdone·<file> == 2 (4)
* return
* throw(); (5)
* }
* initdone.<file>++; (6)
* initdone.<file> += 1; (6)
* // over all matching imported symbols
* <pkg>.init·<file>() (7)
* { <init stmts> } (8)
* init·<file>() // if any (9)
* initdone.<file>++; (10)
* initdone.<file> += 1; (10)
* return (11)
* }
* note that this code cannot have an assignment
* statement or, because of the initflag, it will
* be converted into a data statement.
*/
int
anyinit(NodeList *n)
......@@ -119,7 +122,6 @@ fninit(NodeList *n)
// (2)
maxarg = 0;
snprint(namebuf, sizeof(namebuf), "Init·");
// this is a botch since we need a known name to
......@@ -196,14 +198,9 @@ fninit(NodeList *n)
fn->nbody = r;
//dump("b", fn);
//dump("r", fn->nbody);
initflag = 1; // flag for loader static initialization
funcbody(fn);
typecheck(&fn, Etop);
funccompile(fn);
initflag = 0;
}
......@@ -8,455 +8,6 @@
#include "go.h"
static struct
{
NodeList* list;
Node* mapname;
Type* type;
} xxx;
enum
{
TC_xxx,
TC_unknown, // class
TC_struct,
TC_array,
TC_slice,
TC_map,
TS_start, // state
TS_middle,
TS_end,
};
/*
* 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 int
typeclass(Type *t)
{
if(t != T)
switch(t->etype) {
case TSTRUCT:
return TC_struct;
case TARRAY:
if(t->bound >= 0)
return TC_array;
return TC_slice;
case TMAP:
return TC_map;
}
return TC_unknown;
}
void
initlin(NodeList *l)
{
Node *n;
for(; l; l=l->next) {
n = l->n;
switch(n->op) {
case ODCLFUNC:
case ODCLCONST:
case ODCLTYPE:
continue;
}
initlin(n->ninit);
n->ninit = nil;
xxx.list = list(xxx.list, n);
switch(n->op) {
default:
print("o = %O\n", n->op);
break;
case OCALL:
// call to mapassign1
case OAS:
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, "autotmp_", 8) == 0)
return 1;
return 0;
}
int
sametmp(Node *n1, Node *n2)
{
if(inittmp(n1))
if(n1->xoffset == n2->xoffset)
return 1;
return 0;
}
Node*
findarg(Node *n, char *arg, char *fn)
{
Node *a;
NodeList *l;
if(n == N || n->op != OCALL ||
n->left == N || n->left->sym == S ||
strcmp(n->left->sym->name, fn) != 0)
return N;
for(l=n->list; l; l=l->next) {
a = l->n;
if(a->op == OAS &&
a->left != N && a->right != N &&
a->left->op == OINDREG &&
a->left->sym != S)
if(strcmp(a->left->sym->name, arg) == 0)
return a->right;
}
return N;
}
Node*
slicerewrite(Node *n)
{
Node *nel;
Type *t;
int b;
Node *a;
while(n->op == OCONVNOP)
n = n->left;
// call to makeslice - find nel argument
nel = findarg(n, "nel", "makeslice");
if(nel == N || !isslice(n->type))
goto no;
b = mpgetfix(nel->val.u.xval);
t = shallow(n->type);
t->bound = b;
// special hack for zero-size array
// invent an l-value to point at
if(b == 0)
a = staticname(types[TBOOL]);
else
a = staticname(t);
a = nod(OCOMPSLICE, a, N);
a->type = n->type;
return a;
no:
return N;
}
Node*
maprewrite(Node *n)
{
Node *nel;
Type *ta, *tb;
Node *a;
// call to makemap - find len argument
nel = findarg(n, "hint", "makemap");
if(nel == N)
goto no;
ta = n->type;
if(ta->etype != TMAP)
goto no;
// create a new type from map[index]value
// [0]struct { a index; b value) }
tb = typ(TFIELD);
tb->type = ta->down;
tb->sym = lookup("key");
tb->nname = newname(tb->sym);
tb->down = typ(TFIELD);
tb->down->type = ta->type;
tb->down->sym = lookup("val");
tb->down->nname = newname(tb->down->sym);
ta = typ(TSTRUCT);
ta->type = tb;
tb = typ(TARRAY);
tb->type = ta;
tb->bound = 0;
dowidth(tb);
a = staticname(tb);
a = nod(OCOMPMAP, a, N);
a->type = n->type;
// save stuff for this iteration
xxx.mapname = a->left;
xxx.type = tb;
return a;
no:
return N;
}
// convert the call to mapassign1
// into static[i].key = k, static[i].val = v
Node*
mapindex(Node *n)
{
Node *index, *val, *key, *a, *b, *r;
// pull all the primatives
key = findarg(n, "key", "mapassign1");
if(key == N)
return N;
val = findarg(n, "val", "mapassign1");
if(val == N)
return N;
index = nodintconst(xxx.type->bound);
xxx.type->bound++;
dowidth(xxx.type);
// build tree
a = nod(OINDEX, xxx.mapname, index);
a = nod(ODOT, a, newname(lookup("key")));
a = nod(OAS, a, key);
b = nod(OINDEX, xxx.mapname, index);
b = nod(ODOT, b, newname(lookup("val")));
b = nod(OAS, b, val);
r = liststmt(list(list1(a), b));
walkstmt(&r);
return r;
}
// for a copy out reference, A = B,
// look through the whole structure
// and substitute references of B to A.
// some rewrite goes on also.
void
initsub(Node *n, Node *nam)
{
Node *r, *w, *c;
NodeList *l;
int class, state;
// we could probably get a little more
// out of this if we allow minimal simple
// expression on the right (eg OADDR-ONAME)
if(n->op != ONAME)
return;
class = typeclass(nam->type);
state = TS_start;
switch(class) {
case TC_struct:
goto str;
case TC_array:
goto ary;
case TC_slice:
goto sli;
case TC_map:
goto map;
}
return;
str:
for(l=xxx.list; l; l=l->next) {
r = l->n;
if(r->op != OAS && r->op != OEMPTY)
continue;
// optional first usage "nam = N"
if(r->right == N && sametmp(r->left, nam)) {
if(state != TS_start) {
dump("", r);
fatal("initsub: str-first and state=%d", state);
}
state = TS_middle;
r->op = OEMPTY;
continue;
}
// last usage "n = nam"
if(r->left != N && sametmp(r->right, nam)) {
if(state == TS_end) {
dump("", r);
fatal("initsub: str-last and state=%d", state);
}
state = TS_end;
r->op = OEMPTY;
continue;
}
// middle usage "(nam DOT name) AS expr"
if(r->left->op != ODOT || !sametmp(r->left->left, nam))
continue;
if(state == TS_end) {
dump("", r);
fatal("initsub: str-middle and state=%d", state);
}
state = TS_middle;
r->left->left = n;
}
return;
ary:
for(l=xxx.list; l; l=l->next) {
r = l->n;
if(r->op != OAS && r->op != OEMPTY)
continue;
// optional first usage "nam = N"
if(r->right == N && sametmp(r->left, nam)) {
if(state != TS_start) {
dump("", r);
fatal("initsub: ary-first and state=%d", state);
}
state = TS_middle;
r->op = OEMPTY;
continue;
}
// last usage "n = nam"
if(r->left != N && sametmp(r->right, nam)) {
if(state == TS_end) {
dump("", r);
fatal("initsub: ary-last and state=%d", state);
}
state = TS_end;
r->op = OEMPTY;
continue;
}
// middle usage "(nam INDEX literal) = expr"
if(r->left->op != OINDEX || !sametmp(r->left->left, nam))
continue;
if(state == TS_end) {
dump("", r);
fatal("initsub: ary-middle and state=%d", state);
}
state = TS_middle;
r->left->left = n;
}
return;
sli:
w = N;
for(l=xxx.list; l; l=l->next) {
r = l->n;
if(r->op != OAS && r->op != OEMPTY)
continue;
// first usage "nam = (makeslice CALL args)"
if(r->right != N && sametmp(r->left, nam)) {
w = slicerewrite(r->right);
if(w == N)
continue;
if(state != TS_start) {
dump("", r);
fatal("initsub: sli-first and state=%d", state);
}
state = TS_middle;
r->right = w;
r->left = n;
continue;
}
// last usage "n = nam"
if(r->left != N && sametmp(r->right, nam)) {
if(state != TS_middle) {
dump("", r);
setlineno(r);
fatal("initsub: sli-last and state=%d", state);
}
state = TS_end;
r->op = OEMPTY;
continue;
}
// middle usage "(nam INDEX literal) = expr"
if(r->left->op != OINDEX || !sametmp(r->left->left, nam))
continue;
if(state != TS_middle) {
dump("", r);
fatal("initsub: sli-middle and state=%d", state);
}
state = TS_middle;
r->left->left = w->left;
}
return;
map:
return;
w = N;
for(l=xxx.list; l; l=l->next) {
r = l->n;
if(r->op == OCALL) {
// middle usage "(CALL mapassign1 key, val, map)"
c = mapindex(r);
if(c == N)
continue;
state = TS_middle;
*r = *c;
continue;
}
if(r->op != OAS && r->op != OEMPTY)
continue;
// first usage "nam = (makemap CALL args)"
if(r->right != N && sametmp(r->left, nam)) {
w = maprewrite(r->right);
if(w == N)
continue;
if(state != TS_start) {
dump("", r);
fatal("initsub: map-first and state=%d", state);
}
state = TS_middle;
r->right = w;
r->left = n;
continue;
}
// last usage "n = nam"
if(r->left != N && sametmp(r->right, nam)) {
if(state != TS_middle) {
dump("", r);
fatal("initsub: map-last and state=%d", state);
}
state = TS_end;
r->op = OEMPTY;
continue;
}
}
return;
}
static void
init1(Node *n, NodeList **out)
{
......@@ -489,16 +40,17 @@ init1(Node *n, NodeList **out)
n->initorder = 2;
if(n->defn != N) {
switch(n->defn->op) {
default:
goto bad;
case ODCLFUNC:
for(l=n->defn->nbody; l; l=l->next)
init1(l->n, out);
break;
case OAS:
if(n->defn->left != n) {
default:
dump("defn", n->defn);
fatal("bad defn");
}
if(n->defn->left != n)
goto bad;
init1(n->defn->right, out);
if(debug['j'])
print("%S\n", n->sym);
......@@ -508,6 +60,10 @@ init1(Node *n, NodeList **out)
}
n->initorder = 1;
return;
bad:
dump("defn", n->defn);
fatal("bad defn");
}
static void
......@@ -532,23 +88,9 @@ initreorder(NodeList *l, NodeList **out)
NodeList*
initfix(NodeList *l)
{
Node *r;
NodeList *lout;
xxx.list = nil;
initreorder(l, &xxx.list);
if(0)
return xxx.list;
if(nerrors != 0)
return xxx.list;
// look for the copy-out reference
for(l=xxx.list; l; l=l->next) {
r = l->n;
if(r->op == OAS)
if(inittmp(r->right))
initsub(r->left, r->right);
}
return xxx.list;
lout = nil;
initreorder(l, &lout);
return lout;
}
......@@ -609,7 +609,7 @@ dodump(Node *n, int dep)
print("%O-rlist\n", n->op);
dodumplist(n->rlist, dep+1);
}
if(n->nbody != nil) {
if(n->op != OIF && n->nbody != nil) {
indent(dep);
print("%O-nbody\n", n->op);
dodumplist(n->nbody, dep+1);
......
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