// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
 * static initialization
 */

#include	<u.h>
#include	<libc.h>
#include	"go.h"

enum
{
	InitNotStarted = 0,
	InitDone = 1,
	InitPending = 2,
};

static int iszero(Node*);
static void initplan(Node*);
static NodeList *initlist;
static void init2(Node*, NodeList**);
static void init2list(NodeList*, NodeList**);
static int staticinit(Node*, NodeList**);
static Node *staticname(Type*, int);

static void
init1(Node *n, NodeList **out)
{
	NodeList *l;

	if(n == N)
		return;
	init1(n->left, out);
	init1(n->right, out);
	for(l=n->list; l; l=l->next)
		init1(l->n, out);

	if(n->left && n->type && n->left->op == OTYPE && n->class == PFUNC) {
		// Methods called as Type.Method(receiver, ...).
		// Definitions for method expressions are stored in type->nname.
		init1(n->type->nname, out);
	}

	if(n->op != ONAME)
		return;
	switch(n->class) {
	case PEXTERN:
	case PFUNC:
		break;
	default:
		if(isblank(n) && n->defn != N && n->defn->initorder == InitNotStarted) {
			n->defn->initorder = InitDone;
			*out = list(*out, n->defn);
		}
		return;
	}

	if(n->initorder == InitDone)
		return;
	if(n->initorder == InitPending) {
		if(n->class == PFUNC)
			return;
		
		// if there have already been errors printed,
		// those errors probably confused us and
		// there might not be a loop.  let the user
		// fix those first.
		flusherrors();
		if(nerrors > 0)
			errorexit();

		print("%L: initialization loop:\n", n->lineno);
		for(l=initlist;; l=l->next) {
			if(l->next == nil)
				break;
			l->next->end = l;
		}
		for(; l; l=l->end)
			print("\t%L %S refers to\n", l->n->lineno, l->n->sym);
		print("\t%L %S\n", n->lineno, n->sym);
		errorexit();
	}
	n->initorder = InitPending;
	l = malloc(sizeof *l);
	if(l == nil) {
		flusherrors();
		yyerror("out of memory");
		errorexit();
	}
	l->next = initlist;
	l->n = n;
	l->end = nil;
	initlist = l;

	// make sure that everything n depends on is initialized.
	// n->defn is an assignment to n
	if(n->defn != N) {
		switch(n->defn->op) {
		default:
			goto bad;

		case ODCLFUNC:
			init2list(n->defn->nbody, out);
			break;

		case OAS:
			if(n->defn->left != n)
				goto bad;
			if(isblank(n->defn->left) && candiscard(n->defn->right)) {
				n->defn->op = OEMPTY;
				n->defn->left = N;
				n->defn->right = N;
				break;
			}

		/*
			n->defn->dodata = 1;
			init1(n->defn->right, out);
			if(debug['j'])
				print("%S\n", n->sym);
			*out = list(*out, n->defn);
			break;
		*/
			if(1) {
				init2(n->defn->right, out);
				if(debug['j'])
					print("%S\n", n->sym);
				if(!staticinit(n, out)) {
if(debug['%']) dump("nonstatic", n->defn);
					*out = list(*out, n->defn);
				}
			} else if(0) {
				n->defn->dodata = 1;
				init1(n->defn->right, out);
				if(debug['j'])
					print("%S\n", n->sym);
				*out = list(*out, n->defn);
			}
			break;
		
		case OAS2FUNC:
		case OAS2MAPR:
		case OAS2DOTTYPE:
		case OAS2RECV:
			if(n->defn->initorder != InitNotStarted)
				break;
			n->defn->initorder = InitDone;
			for(l=n->defn->rlist; l; l=l->next)
				init1(l->n, out);
			*out = list(*out, n->defn);
			break;
		}
	}
	l = initlist;
	initlist = l->next;
	if(l->n != n)
		fatal("bad initlist");
	free(l);
	n->initorder = InitDone;
	return;

bad:
	dump("defn", n->defn);
	fatal("init1: bad defn");
}

// recurse over n, doing init1 everywhere.
static void
init2(Node *n, NodeList **out)
{
	if(n == N || n->initorder == InitDone)
		return;

	if(n->op == ONAME && n->ninit)
		fatal("name %S with ninit: %+N\n", n->sym, n);

	init1(n, out);
	init2(n->left, out);
	init2(n->right, out);
	init2(n->ntest, out);
	init2list(n->ninit, out);
	init2list(n->list, out);
	init2list(n->rlist, out);
	init2list(n->nbody, out);
	init2list(n->nelse, out);
	
	if(n->op == OCLOSURE)
		init2list(n->closure->nbody, out);
	if(n->op == ODOTMETH)
		init2(n->type->nname, out);
}

static void
init2list(NodeList *l, NodeList **out)
{
	for(; l; l=l->next)
		init2(l->n, out);
}

static void
initreorder(NodeList *l, NodeList **out)
{
	Node *n;

	for(; l; l=l->next) {
		n = l->n;
		switch(n->op) {
		case ODCLFUNC:
		case ODCLCONST:
		case ODCLTYPE:
			continue;
		}
		initreorder(n->ninit, out);
		n->ninit = nil;
		init1(n, out);
	}
}

NodeList*
initfix(NodeList *l)
{
	NodeList *lout;
	int lno;

	lout = nil;
	lno = lineno;
	initreorder(l, &lout);
	lineno = lno;
	return lout;
}

/*
 * compilation of top-level (static) assignments
 * into DATA statements if at all possible.
 */

static int staticassign(Node*, Node*, NodeList**);

static int
staticinit(Node *n, NodeList **out)
{
	Node *l, *r;

	if(n->op != ONAME || n->class != PEXTERN || n->defn == N || n->defn->op != OAS)
		fatal("staticinit");

	lineno = n->lineno;
	l = n->defn->left;
	r = n->defn->right;
	return staticassign(l, r, out);
}

// like staticassign but we are copying an already
// initialized value r.
static int
staticcopy(Node *l, Node *r, NodeList **out)
{
	int i;
	InitEntry *e;
	InitPlan *p;
	Node *a, *ll, *rr, *orig, n1;

	if(r->op != ONAME || r->class != PEXTERN || r->sym->pkg != localpkg)
		return 0;
	if(r->defn == N)	// zeroed
		return 1;
	if(r->defn->op != OAS)
		return 0;
	orig = r;
	r = r->defn->right;
	
	switch(r->op) {
	case ONAME:
		if(staticcopy(l, r, out))
			return 1;
		*out = list(*out, nod(OAS, l, r));
		return 1;
	
	case OLITERAL:
		if(iszero(r))
			return 1;
		gdata(l, r, l->type->width);
		return 1;

	case OADDR:
		switch(r->left->op) {
		case ONAME:
			gdata(l, r, l->type->width);
			return 1;
		}
		break;
	
	case OPTRLIT:
		switch(r->left->op) {
		default:
			//dump("not static addr", r);
			break;
		case OARRAYLIT:
		case OSTRUCTLIT:
		case OMAPLIT:
			// copy pointer
			gdata(l, nod(OADDR, r->nname, N), l->type->width);
			return 1;
		}
		break;

	case OARRAYLIT:
		if(isslice(r->type)) {
			// copy slice
			a = r->nname;
			n1 = *l;
			n1.xoffset = l->xoffset + Array_array;
			gdata(&n1, nod(OADDR, a, N), widthptr);
			n1.xoffset = l->xoffset + Array_nel;
			gdata(&n1, r->right, widthint);
			n1.xoffset = l->xoffset + Array_cap;
			gdata(&n1, r->right, widthint);
			return 1;
		}
		// fall through
	case OSTRUCTLIT:
		p = r->initplan;
		n1 = *l;
		for(i=0; i<p->len; i++) {
			e = &p->e[i];
			n1.xoffset = l->xoffset + e->xoffset;
			n1.type = e->expr->type;
			if(e->expr->op == OLITERAL)
				gdata(&n1, e->expr, n1.type->width);
			else {
				ll = nod(OXXX, N, N);
				*ll = n1;
				if(!staticassign(ll, e->expr, out)) {
					// Requires computation, but we're
					// copying someone else's computation.
					rr = nod(OXXX, N, N);
					*rr = *orig;
					rr->type = ll->type;
					rr->xoffset += e->xoffset;
					*out = list(*out, nod(OAS, ll, rr));
				}
			}
		}
		return 1;
	}
	return 0;
}

static int
staticassign(Node *l, Node *r, NodeList **out)
{
	Node *a, n1;
	Type *ta;
	InitPlan *p;
	InitEntry *e;
	int i;
	
	switch(r->op) {
	default:
		//dump("not static", r);
		break;
	
	case ONAME:
		if(r->class == PEXTERN && r->sym->pkg == localpkg)
			return staticcopy(l, r, out);
		break;

	case OLITERAL:
		if(iszero(r))
			return 1;
		gdata(l, r, l->type->width);
		return 1;

	case OADDR:
		switch(r->left->op) {
		default:
			//dump("not static addr", r);
			break;

		case ONAME:
			gdata(l, r, l->type->width);
			return 1;
		}
	
	case OPTRLIT:
		switch(r->left->op) {
		default:
			//dump("not static ptrlit", r);
			break;

		case OARRAYLIT:
		case OMAPLIT:
		case OSTRUCTLIT:
			// Init pointer.
			a = staticname(r->left->type, 1);
			r->nname = a;
			gdata(l, nod(OADDR, a, N), l->type->width);
			// Init underlying literal.
			if(!staticassign(a, r->left, out))
				*out = list(*out, nod(OAS, a, r->left));
			return 1;
		}
		break;

	case OARRAYLIT:
		initplan(r);
		if(isslice(r->type)) {
			// Init slice.
			ta = typ(TARRAY);
			ta->type = r->type->type;
			ta->bound = mpgetfix(r->right->val.u.xval);
			a = staticname(ta, 1);
			r->nname = a;
			n1 = *l;
			n1.xoffset = l->xoffset + Array_array;
			gdata(&n1, nod(OADDR, a, N), widthptr);
			n1.xoffset = l->xoffset + Array_nel;
			gdata(&n1, r->right, widthint);
			n1.xoffset = l->xoffset + Array_cap;
			gdata(&n1, r->right, widthint);
			// Fall through to init underlying array.
			l = a;
		}
		// fall through
	case OSTRUCTLIT:
		initplan(r);
		p = r->initplan;
		n1 = *l;
		for(i=0; i<p->len; i++) {
			e = &p->e[i];
			n1.xoffset = l->xoffset + e->xoffset;
			n1.type = e->expr->type;
			if(e->expr->op == OLITERAL)
				gdata(&n1, e->expr, n1.type->width);
			else {
				a = nod(OXXX, N, N);
				*a = n1;
				if(!staticassign(a, e->expr, out))
					*out = list(*out, nod(OAS, a, e->expr));
			}
		}
		return 1;

	case OMAPLIT:
		// TODO: Table-driven map insert.
		break;
	}
	return 0;
}

/*
 * from here down is the walk analysis
 * of composite literals.
 * most of the work is to generate
 * data statements for the constant
 * part of the composite literal.
 */

static	void	structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
static	void	arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
static	void	slicelit(int ctxt, Node *n, Node *var, NodeList **init);
static	void	maplit(int ctxt, Node *n, Node *var, NodeList **init);

static Node*
staticname(Type *t, int ctxt)
{
	Node *n;

	snprint(namebuf, sizeof(namebuf), "statictmp_%.4d", statuniqgen);
	statuniqgen++;
	n = newname(lookup(namebuf));
	if(!ctxt)
		n->readonly = 1;
	addvar(n, t, PEXTERN);
	return n;
}

static int
isliteral(Node *n)
{
	if(n->op == OLITERAL)
		if(n->val.ctype != CTNIL)
			return 1;
	return 0;
}

static int
simplename(Node *n)
{
	if(n->op != ONAME)
		goto no;
	if(!n->addable)
		goto no;
	if(n->class & PHEAP)
		goto no;
	if(n->class == PPARAMREF)
		goto no;
	return 1;

no:
	return 0;
}

static void
litas(Node *l, Node *r, NodeList **init)
{
	Node *a;

	a = nod(OAS, l, r);
	typecheck(&a, Etop);
	walkexpr(&a, init);
	*init = list(*init, a);
}

enum
{
	MODEDYNAM	= 1,
	MODECONST	= 2,
};

static int
getdyn(Node *n, int top)
{
	NodeList *nl;
	Node *value;
	int mode;

	mode = 0;
	switch(n->op) {
	default:
		if(isliteral(n))
			return MODECONST;
		return MODEDYNAM;
	case OARRAYLIT:
		if(!top && n->type->bound < 0)
			return MODEDYNAM;
	case OSTRUCTLIT:
		break;
	}

	for(nl=n->list; nl; nl=nl->next) {
		value = nl->n->right;
		mode |= getdyn(value, 0);
		if(mode == (MODEDYNAM|MODECONST))
			break;
	}
	return mode;
}

static void
structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *nl;
	Node *index, *value;

	for(nl=n->list; nl; nl=nl->next) {
		r = nl->n;
		if(r->op != OKEY)
			fatal("structlit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;

		switch(value->op) {
		case OARRAYLIT:
			if(value->type->bound < 0) {
				if(pass == 1 && ctxt != 0) {
					a = nod(ODOT, var, newname(index->sym));
					slicelit(ctxt, value, a, init);
				} else
				if(pass == 2 && ctxt == 0) {
					a = nod(ODOT, var, newname(index->sym));
					slicelit(ctxt, value, a, init);
				} else
				if(pass == 3)
					break;
				continue;
			}
			a = nod(ODOT, var, newname(index->sym));
			arraylit(ctxt, pass, value, a, init);
			continue;

		case OSTRUCTLIT:
			a = nod(ODOT, var, newname(index->sym));
			structlit(ctxt, pass, value, a, init);
			continue;
		}

		if(isliteral(value)) {
			if(pass == 2)
				continue;
		} else
			if(pass == 1)
				continue;

		// build list of var.field = expr
		a = nod(ODOT, var, newname(index->sym));
		a = nod(OAS, a, value);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		if(pass == 1) {
			if(a->op != OAS)
				fatal("structlit: not as");
			a->dodata = 2;
		}
		*init = list(*init, a);
	}
}

static void
arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *l;
	Node *index, *value;

	for(l=n->list; l; l=l->next) {
		r = l->n;
		if(r->op != OKEY)
			fatal("arraylit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;

		switch(value->op) {
		case OARRAYLIT:
			if(value->type->bound < 0) {
				if(pass == 1 && ctxt != 0) {
					a = nod(OINDEX, var, index);
					slicelit(ctxt, value, a, init);
				} else
				if(pass == 2 && ctxt == 0) {
					a = nod(OINDEX, var, index);
					slicelit(ctxt, value, a, init);
				} else
				if(pass == 3)
					break;
				continue;
			}
			a = nod(OINDEX, var, index);
			arraylit(ctxt, pass, value, a, init);
			continue;

		case OSTRUCTLIT:
			a = nod(OINDEX, var, index);
			structlit(ctxt, pass, value, a, init);
			continue;
		}

		if(isliteral(index) && isliteral(value)) {
			if(pass == 2)
				continue;
		} else
			if(pass == 1)
				continue;

		// build list of var[index] = value
		a = nod(OINDEX, var, index);
		a = nod(OAS, a, value);
		typecheck(&a, Etop);
		walkexpr(&a, init);	// add any assignments in r to top
		if(pass == 1) {
			if(a->op != OAS)
				fatal("structlit: not as");
			a->dodata = 2;
		}
		*init = list(*init, a);
	}
}

static void
slicelit(int ctxt, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *l;
	Type *t;
	Node *vstat, *vauto;
	Node *index, *value;
	int mode;

	// make an array type
	t = shallow(n->type);
	t->bound = mpgetfix(n->right->val.u.xval);
	t->width = 0;
	t->sym = nil;
	dowidth(t);

	if(ctxt != 0) {
		// put everything into static array
		vstat = staticname(t, ctxt);
		arraylit(ctxt, 1, n, vstat, init);
		arraylit(ctxt, 2, n, vstat, init);

		// copy static to slice
		a = nod(OSLICE, vstat, nod(OKEY, N, N));
		a = nod(OAS, var, a);
		typecheck(&a, Etop);
		a->dodata = 2;
		*init = list(*init, a);
		return;
	}

	// recipe for var = []t{...}
	// 1. make a static array
	//	var vstat [...]t
	// 2. assign (data statements) the constant part
	//	vstat = constpart{}
	// 3. make an auto pointer to array and allocate heap to it
	//	var vauto *[...]t = new([...]t)
	// 4. copy the static array to the auto array
	//	*vauto = vstat
	// 5. assign slice of allocated heap to var
	//	var = [0:]*auto
	// 6. for each dynamic part assign to the slice
	//	var[i] = dynamic part
	//
	// an optimization is done if there is no constant part
	//	3. var vauto *[...]t = new([...]t)
	//	5. var = [0:]*auto
	//	6. var[i] = dynamic part

	// if the literal contains constants,
	// make static initialized array (1),(2)
	vstat = N;
	mode = getdyn(n, 1);
	if(mode & MODECONST) {
		vstat = staticname(t, ctxt);
		arraylit(ctxt, 1, n, vstat, init);
	}

	// make new auto *array (3 declare)
	vauto = temp(ptrto(t));

	// set auto to point at new temp or heap (3 assign)
	if(n->esc == EscNone) {
		a = nod(OAS, temp(t), N);
		typecheck(&a, Etop);
		*init = list(*init, a);  // zero new temp
		a = nod(OADDR, a->left, N);
	} else {
		a = nod(ONEW, N, N);
		a->list = list1(typenod(t));
	}
	a = nod(OAS, vauto, a);
	typecheck(&a, Etop);
	walkexpr(&a, init);
	*init = list(*init, a);

	if(vstat != N) {
		// copy static to heap (4)
		a = nod(OIND, vauto, N);
		a = nod(OAS, a, vstat);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		*init = list(*init, a);
	}

	// make slice out of heap (5)
	a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N)));
	typecheck(&a, Etop);
	walkexpr(&a, init);
	*init = list(*init, a);

	// put dynamics into slice (6)
	for(l=n->list; l; l=l->next) {
		r = l->n;
		if(r->op != OKEY)
			fatal("slicelit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;
		a = nod(OINDEX, var, index);
		a->bounded = 1;
		// TODO need to check bounds?

		switch(value->op) {
		case OARRAYLIT:
			if(value->type->bound < 0)
				break;
			arraylit(ctxt, 2, value, a, init);
			continue;

		case OSTRUCTLIT:
			structlit(ctxt, 2, value, a, init);
			continue;
		}

		if(isliteral(index) && isliteral(value))
			continue;

		// build list of var[c] = expr
		a = nod(OAS, a, value);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		*init = list(*init, a);
	}
}

static void
maplit(int ctxt, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *l;
	int nerr;
	int64 b;
	Type *t, *tk, *tv, *t1;
	Node *vstat, *index, *value;
	Sym *syma, *symb;

USED(ctxt);
ctxt = 0;

	// make the map var
	nerr = nerrors;

	a = nod(OMAKE, N, N);
	a->list = list1(typenod(n->type));
	litas(var, a, init);

	// count the initializers
	b = 0;
	for(l=n->list; l; l=l->next) {
		r = l->n;

		if(r->op != OKEY)
			fatal("slicelit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;

		if(isliteral(index) && isliteral(value))
			b++;
	}

	if(b != 0) {
		// build type [count]struct { a Tindex, b Tvalue }
		t = n->type;
		tk = t->down;
		tv = t->type;

		symb = lookup("b");
		t = typ(TFIELD);
		t->type = tv;
		t->sym = symb;

		syma = lookup("a");
		t1 = t;
		t = typ(TFIELD);
		t->type = tk;
		t->sym = syma;
		t->down = t1;

		t1 = t;
		t = typ(TSTRUCT);
		t->type = t1;

		t1 = t;
		t = typ(TARRAY);
		t->bound = b;
		t->type = t1;

		dowidth(t);

		// make and initialize static array
		vstat = staticname(t, ctxt);
		b = 0;
		for(l=n->list; l; l=l->next) {
			r = l->n;

			if(r->op != OKEY)
				fatal("slicelit: rhs not OKEY: %N", r);
			index = r->left;
			value = r->right;

			if(isliteral(index) && isliteral(value)) {
				// build vstat[b].a = key;
				a = nodintconst(b);
				a = nod(OINDEX, vstat, a);
				a = nod(ODOT, a, newname(syma));
				a = nod(OAS, a, index);
				typecheck(&a, Etop);
				walkexpr(&a, init);
				a->dodata = 2;
				*init = list(*init, a);

				// build vstat[b].b = value;
				a = nodintconst(b);
				a = nod(OINDEX, vstat, a);
				a = nod(ODOT, a, newname(symb));
				a = nod(OAS, a, value);
				typecheck(&a, Etop);
				walkexpr(&a, init);
				a->dodata = 2;
				*init = list(*init, a);

				b++;
			}
		}

		// loop adding structure elements to map
		// for i = 0; i < len(vstat); i++ {
		//	map[vstat[i].a] = vstat[i].b
		// }
		index = temp(types[TINT]);

		a = nod(OINDEX, vstat, index);
		a->bounded = 1;
		a = nod(ODOT, a, newname(symb));

		r = nod(OINDEX, vstat, index);
		r->bounded = 1;
		r = nod(ODOT, r, newname(syma));
		r = nod(OINDEX, var, r);

		r = nod(OAS, r, a);

		a = nod(OFOR, N, N);
		a->nbody = list1(r);

		a->ninit = list1(nod(OAS, index, nodintconst(0)));
		a->ntest = nod(OLT, index, nodintconst(t->bound));
		a->nincr = nod(OASOP, index, nodintconst(1));
		a->nincr->etype = OADD;

		typecheck(&a, Etop);
		walkstmt(&a);
		*init = list(*init, a);
	}

	// put in dynamic entries one-at-a-time
	for(l=n->list; l; l=l->next) {
		r = l->n;

		if(r->op != OKEY)
			fatal("slicelit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;

		if(isliteral(index) && isliteral(value))
			continue;

		// build list of var[c] = expr
		a = nod(OINDEX, var, r->left);
		a = nod(OAS, a, r->right);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		if(nerr != nerrors)
			break;

		*init = list(*init, a);
	}
}

void
anylit(int ctxt, Node *n, Node *var, NodeList **init)
{
	Type *t;
	Node *a, *vstat, *r;

	t = n->type;
	switch(n->op) {
	default:
		fatal("anylit: not lit");

	case OPTRLIT:
		if(!isptr[t->etype])
			fatal("anylit: not ptr");

		r = nod(ONEW, N, N);
		r->typecheck = 1;
		r->type = t;
		r->esc = n->esc;
		walkexpr(&r, init);

		a = nod(OAS, var, r);

		typecheck(&a, Etop);
		*init = list(*init, a);

		var = nod(OIND, var, N);
		typecheck(&var, Erv | Easgn);
		anylit(ctxt, n->left, var, init);
		break;

	case OSTRUCTLIT:
		if(t->etype != TSTRUCT)
			fatal("anylit: not struct");

		if(simplename(var)) {

			if(ctxt == 0) {
				// lay out static data
				vstat = staticname(t, ctxt);
				structlit(ctxt, 1, n, vstat, init);

				// copy static to var
				a = nod(OAS, var, vstat);
				typecheck(&a, Etop);
				walkexpr(&a, init);
				*init = list(*init, a);

				// add expressions to automatic
				structlit(ctxt, 2, n, var, init);
				break;
			}
			structlit(ctxt, 1, n, var, init);
			structlit(ctxt, 2, n, var, init);
			break;
		}

		// initialize of not completely specified
		if(count(n->list) < structcount(t)) {
			a = nod(OAS, var, N);
			typecheck(&a, Etop);
			walkexpr(&a, init);
			*init = list(*init, a);
		}
		structlit(ctxt, 3, n, var, init);
		break;

	case OARRAYLIT:
		if(t->etype != TARRAY)
			fatal("anylit: not array");
		if(t->bound < 0) {
			slicelit(ctxt, n, var, init);
			break;
		}

		if(simplename(var)) {

			if(ctxt == 0) {
				// lay out static data
				vstat = staticname(t, ctxt);
				arraylit(1, 1, n, vstat, init);

				// copy static to automatic
				a = nod(OAS, var, vstat);
				typecheck(&a, Etop);
				walkexpr(&a, init);
				*init = list(*init, a);

				// add expressions to automatic
				arraylit(ctxt, 2, n, var, init);
				break;
			}
			arraylit(ctxt, 1, n, var, init);
			arraylit(ctxt, 2, n, var, init);
			break;
		}

		// initialize of not completely specified
		if(count(n->list) < t->bound) {
			a = nod(OAS, var, N);
			typecheck(&a, Etop);
			walkexpr(&a, init);
			*init = list(*init, a);
		}
		arraylit(ctxt, 3, n, var, init);
		break;

	case OMAPLIT:
		if(t->etype != TMAP)
			fatal("anylit: not map");
		maplit(ctxt, n, var, init);
		break;
	}
}

int
oaslit(Node *n, NodeList **init)
{
	int ctxt;

	if(n->left == N || n->right == N)
		goto no;
	if(n->left->type == T || n->right->type == T)
		goto no;
	if(!simplename(n->left))
		goto no;
	if(!eqtype(n->left->type, n->right->type))
		goto no;

	// context is init() function.
	// implies generated data executed
	// exactly once and not subject to races.
	ctxt = 0;
//	if(n->dodata == 1)
//		ctxt = 1;

	switch(n->right->op) {
	default:
		goto no;

	case OSTRUCTLIT:
	case OARRAYLIT:
	case OMAPLIT:
		if(vmatch1(n->left, n->right))
			goto no;
		anylit(ctxt, n->right, n->left, init);
		break;
	}
	n->op = OEMPTY;
	return 1;

no:
	// not a special composit literal assignment
	return 0;
}

static 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;
		// Check for overflow.
		if(n->type->width != 0 && MAXWIDTH/n->type->width <= l)
			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 OCONVNOP:
		nr = nr->left;
		if(nr == N || nr->op != OSLICEARR)
			goto no;
		// fall through
	
	case OSLICEARR:
		if(nr->right->op == OKEY && nr->right->left == N && nr->right->right == N) {
			nr = nr->left;
			goto slice;
		}
		goto no;

	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:
		gdata(&nam, nr, nr->type->width);
		break;

	case TCOMPLEX64:
	case TCOMPLEX128:
		gdatacomplex(&nam, nr->val.u.cval);
		break;

	case TSTRING:
		gdatastring(&nam, nr->val.u.sval);
		break;
	}

yes:
	return 1;

slice:
	gused(N); // in case the data is the dest of a goto
	nl = nr;
	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, nl, types[tptr]->width);

	nam.xoffset += Array_nel-Array_array;
	nodconst(&nod1, types[TINT], nr->type->bound);
	gdata(&nam, &nod1, widthint);

	nam.xoffset += Array_cap-Array_nel;
	gdata(&nam, &nod1, widthint);

	goto yes;

no:
	if(n->dodata == 2) {
		dump("\ngen_as_init", n);
		fatal("gen_as_init couldnt make data statement");
	}
	return 0;
}

static int iszero(Node*);
static int isvaluelit(Node*);
static InitEntry* entry(InitPlan*);
static void addvalue(InitPlan*, vlong, Node*, Node*);

static void
initplan(Node *n)
{
	InitPlan *p;
	Node *a;
	NodeList *l;

	if(n->initplan != nil)
		return;
	p = mal(sizeof *p);
	n->initplan = p;
	switch(n->op) {
	default:
		fatal("initplan");
	case OARRAYLIT:
		for(l=n->list; l; l=l->next) {
			a = l->n;
			if(a->op != OKEY || !smallintconst(a->left))
				fatal("initplan arraylit");
			addvalue(p, n->type->type->width*mpgetfix(a->left->val.u.xval), N, a->right);
		}
		break;
	case OSTRUCTLIT:
		for(l=n->list; l; l=l->next) {
			a = l->n;
			if(a->op != OKEY || a->left->type == T)
				fatal("initplan structlit");
			addvalue(p, a->left->type->width, N, a->right);
		}
		break;
	case OMAPLIT:
		for(l=n->list; l; l=l->next) {
			a = l->n;
			if(a->op != OKEY)
				fatal("initplan maplit");
			addvalue(p, -1, a->left, a->right);
		}
		break;
	}
}

static void
addvalue(InitPlan *p, vlong xoffset, Node *key, Node *n)
{
	int i;
	InitPlan *q;
	InitEntry *e;

	USED(key);

	// special case: zero can be dropped entirely
	if(iszero(n)) {
		p->zero += n->type->width;
		return;
	}
	
	// special case: inline struct and array (not slice) literals
	if(isvaluelit(n)) {
		initplan(n);
		q = n->initplan;
		for(i=0; i<q->len; i++) {
			e = entry(p);
			*e = q->e[i];
			e->xoffset += xoffset;
		}
		return;
	}
	
	// add to plan
	if(n->op == OLITERAL)
		p->lit += n->type->width;
	else
		p->expr += n->type->width;

	e = entry(p);
	e->xoffset = xoffset;
	e->expr = n;
}

static int
iszero(Node *n)
{
	NodeList *l;

	switch(n->op) {
	case OLITERAL:
		switch(n->val.ctype) {
		default:
			dump("unexpected literal", n);
			fatal("iszero");
	
		case CTNIL:
			return 1;
		
		case CTSTR:
			return n->val.u.sval == nil || n->val.u.sval->len == 0;
	
		case CTBOOL:
			return n->val.u.bval == 0;
			
		case CTINT:
		case CTRUNE:
			return mpcmpfixc(n->val.u.xval, 0) == 0;
	
		case CTFLT:
			return mpcmpfltc(n->val.u.fval, 0) == 0;
	
		case CTCPLX:
			return mpcmpfltc(&n->val.u.cval->real, 0) == 0 && mpcmpfltc(&n->val.u.cval->imag, 0) == 0;
		}
		break;
	case OARRAYLIT:
		if(isslice(n->type))
			break;
		// fall through
	case OSTRUCTLIT:
		for(l=n->list; l; l=l->next)
			if(!iszero(l->n->right))
				return 0;
		return 1;
	}
	return 0;
}

static int
isvaluelit(Node *n)
{
	return (n->op == OARRAYLIT && isfixedarray(n->type)) || n->op == OSTRUCTLIT;
}

static InitEntry*
entry(InitPlan *p)
{
	if(p->len >= p->cap) {
		if(p->cap == 0)
			p->cap = 4;
		else
			p->cap *= 2;
		p->e = realloc(p->e, p->cap*sizeof p->e[0]);
		if(p->e == nil)
			fatal("out of memory");
	}
	return &p->e[p->len++];
}
