// 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, 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;

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

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

		a = nod(OAS, var, callnew(t->type));
		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;
		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++];
}
