// Do not edit. Bootstrap copy of /Volumes/Android/buildbot/src/android/build-tools/out/obj/go/src/cmd/compile/internal/gc/sinit.go

//line /Volumes/Android/buildbot/src/android/build-tools/out/obj/go/src/cmd/compile/internal/gc/sinit.go:1
// 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.

package gc

import (
	"bootstrap/internal/obj"
	"fmt"
)

/*
 * static initialization
 */
const (
	InitNotStarted = 0
	InitDone       = 1
	InitPending    = 2
)

var (
	initlist  *NodeList
	initplans map[*Node]*InitPlan
	inittemps = make(map[*Node]*Node)
)

// init1 walks the AST starting at n, and accumulates in out
// the list of definitions needing init code in dependency order.
func init1(n *Node, out **NodeList) {
	if n == nil {
		return
	}
	init1(n.Left, out)
	init1(n.Right, out)
	for l := n.List; l != nil; l = l.Next {
		init1(l.N, out)
	}

	if n.Left != nil && n.Type != nil && 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, PFUNC:
		break

	default:
		if isblank(n) && n.Name.Curfn == nil && n.Name.Defn != nil && n.Name.Defn.Initorder == InitNotStarted {
			// blank names initialization is part of init() but not
			// when they are inside a function.
			break
		}

		return
	}

	if n.Initorder == InitDone {
		return
	}
	if n.Initorder == InitPending {
		// Since mutually recursive sets of functions are allowed,
		// we don't necessarily raise an error if n depends on a node
		// which is already waiting for its dependencies to be visited.
		//
		// initlist contains a cycle of identifiers referring to each other.
		// If this cycle contains a variable, then this variable refers to itself.
		// Conversely, if there exists an initialization cycle involving
		// a variable in the program, the tree walk will reach a cycle
		// involving that variable.
		var nv *Node
		if n.Class != PFUNC {
			nv = n
			goto foundinitloop
		}

		for l := initlist; l.N != n; l = l.Next {
			if l.N.Class != PFUNC {
				nv = l.N
				goto foundinitloop
			}
		}

		// The loop involves only functions, ok.
		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.
	foundinitloop:
		Flusherrors()

		if nerrors > 0 {
			errorexit()
		}

		// There is a loop involving nv. We know about
		// n and initlist = n1 <- ... <- nv <- ... <- n <- ...
		fmt.Printf("%v: initialization loop:\n", nv.Line())

		// Build back pointers in initlist.
		for l := initlist; l != nil; l = l.Next {
			if l.Next != nil {
				l.Next.End = l
			}
		}

		// Print nv -> ... -> n1 -> n.
		var l *NodeList
		for l = initlist; l.N != nv; l = l.Next {
		}
		for ; l != nil; l = l.End {
			fmt.Printf("\t%v %v refers to\n", l.N.Line(), l.N.Sym)
		}

		// Print n -> ... -> nv.
		for l = initlist; l.N != n; l = l.Next {
		}
		for ; l.N != nv; l = l.End {
			fmt.Printf("\t%v %v refers to\n", l.N.Line(), l.N.Sym)
		}
		fmt.Printf("\t%v %v\n", nv.Line(), nv.Sym)
		errorexit()
	}

	// reached a new unvisited node.
	n.Initorder = InitPending

	l := new(NodeList)
	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 defn := n.Name.Defn; defn != nil {
		switch defn.Op {
		default:
			goto bad

		case ODCLFUNC:
			init2list(defn.Nbody, out)

		case OAS:
			if defn.Left != n {
				goto bad
			}
			if isblank(defn.Left) && candiscard(defn.Right) {
				defn.Op = OEMPTY
				defn.Left = nil
				defn.Right = nil
				break
			}

			init2(defn.Right, out)
			if Debug['j'] != 0 {
				fmt.Printf("%v\n", n.Sym)
			}
			if isblank(n) || !staticinit(n, out) {
				if Debug['%'] != 0 {
					Dump("nonstatic", defn)
				}
				*out = list(*out, defn)
			}

		case OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV:
			if defn.Initorder != InitNotStarted {
				break
			}
			defn.Initorder = InitDone
			for l := defn.Rlist; l != nil; l = l.Next {
				init1(l.N, out)
			}
			if Debug['%'] != 0 {
				Dump("nonstatic", defn)
			}
			*out = list(*out, defn)
		}
	}

	l = initlist
	initlist = l.Next
	if l.N != n {
		Fatal("bad initlist")
	}

	n.Initorder = InitDone
	return

bad:
	Dump("defn", n.Name.Defn)
	Fatal("init1: bad defn")
}

// recurse over n, doing init1 everywhere.
func init2(n *Node, out **NodeList) {
	if n == nil || n.Initorder == InitDone {
		return
	}

	if n.Op == ONAME && n.Ninit != nil {
		Fatal("name %v with ninit: %v\n", n.Sym, Nconv(n, obj.FmtSign))
	}

	init1(n, out)
	init2(n.Left, out)
	init2(n.Right, out)
	init2list(n.Ninit, out)
	init2list(n.List, out)
	init2list(n.Rlist, out)
	init2list(n.Nbody, out)

	if n.Op == OCLOSURE {
		init2list(n.Func.Closure.Nbody, out)
	}
	if n.Op == ODOTMETH || n.Op == OCALLPART {
		init2(n.Type.Nname, out)
	}
}

func init2list(l *NodeList, out **NodeList) {
	for ; l != nil; l = l.Next {
		init2(l.N, out)
	}
}

func initreorder(l *NodeList, out **NodeList) {
	var n *Node

	for ; l != nil; l = l.Next {
		n = l.N
		switch n.Op {
		case ODCLFUNC, ODCLCONST, ODCLTYPE:
			continue
		}

		initreorder(n.Ninit, out)
		n.Ninit = nil
		init1(n, out)
	}
}

// initfix computes initialization order for a list l of top-level
// declarations and outputs the corresponding list of statements
// to include in the init() function body.
func initfix(l *NodeList) *NodeList {
	var lout *NodeList
	initplans = make(map[*Node]*InitPlan)
	lno := int(lineno)
	initreorder(l, &lout)
	lineno = int32(lno)
	initplans = nil
	return lout
}

/*
 * compilation of top-level (static) assignments
 * into DATA statements if at all possible.
 */
func staticinit(n *Node, out **NodeList) bool {
	if n.Op != ONAME || n.Class != PEXTERN || n.Name.Defn == nil || n.Name.Defn.Op != OAS {
		Fatal("staticinit")
	}

	lineno = n.Lineno
	l := n.Name.Defn.Left
	r := n.Name.Defn.Right
	return staticassign(l, r, out)
}

// like staticassign but we are copying an already
// initialized value r.
func staticcopy(l *Node, r *Node, out **NodeList) bool {
	if r.Op != ONAME {
		return false
	}
	if r.Class == PFUNC {
		gdata(l, r, Widthptr)
		return true
	}
	if r.Class != PEXTERN || r.Sym.Pkg != localpkg {
		return false
	}
	if r.Name.Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value
		return false
	}
	if r.Name.Defn.Op != OAS {
		return false
	}
	orig := r
	r = r.Name.Defn.Right

	for r.Op == OCONVNOP {
		r = r.Left
	}

	switch r.Op {
	case ONAME:
		if staticcopy(l, r, out) {
			return true
		}
		*out = list(*out, Nod(OAS, l, r))
		return true

	case OLITERAL:
		if iszero(r) {
			return true
		}
		gdata(l, r, int(l.Type.Width))
		return true

	case OADDR:
		switch r.Left.Op {
		case ONAME:
			gdata(l, r, int(l.Type.Width))
			return true
		}

	case OPTRLIT:
		switch r.Left.Op {
		//dump("not static addr", r);
		default:
			break

			// copy pointer
		case OARRAYLIT, OSTRUCTLIT, OMAPLIT:
			gdata(l, Nod(OADDR, inittemps[r], nil), int(l.Type.Width))

			return true
		}

	case OARRAYLIT:
		if Isslice(r.Type) {
			// copy slice
			a := inittemps[r]

			n1 := *l
			n1.Xoffset = l.Xoffset + int64(Array_array)
			gdata(&n1, Nod(OADDR, a, nil), Widthptr)
			n1.Xoffset = l.Xoffset + int64(Array_nel)
			gdata(&n1, r.Right, Widthint)
			n1.Xoffset = l.Xoffset + int64(Array_cap)
			gdata(&n1, r.Right, Widthint)
			return true
		}
		fallthrough

		// fall through
	case OSTRUCTLIT:
		p := initplans[r]

		n1 := *l
		var e *InitEntry
		var ll *Node
		var rr *Node
		for i := 0; i < len(p.E); 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, int(n1.Type.Width))
			} else {
				ll = Nod(OXXX, nil, nil)
				*ll = n1
				ll.Orig = ll // completely separate copy
				if !staticassign(ll, e.Expr, out) {
					// Requires computation, but we're
					// copying someone else's computation.
					rr = Nod(OXXX, nil, nil)

					*rr = *orig
					rr.Orig = rr // completely separate copy
					rr.Type = ll.Type
					rr.Xoffset += e.Xoffset
					setlineno(rr)
					*out = list(*out, Nod(OAS, ll, rr))
				}
			}
		}

		return true
	}

	return false
}

func staticassign(l *Node, r *Node, out **NodeList) bool {
	var n1 Node

	for r.Op == OCONVNOP {
		r = r.Left
	}

	switch r.Op {
	//dump("not static", r);
	default:
		break

	case ONAME:
		return staticcopy(l, r, out)

	case OLITERAL:
		if iszero(r) {
			return true
		}
		gdata(l, r, int(l.Type.Width))
		return true

	case OADDR:
		var nam Node
		if stataddr(&nam, r.Left) {
			n1 := *r
			n1.Left = &nam
			gdata(l, &n1, int(l.Type.Width))
			return true
		}
		fallthrough

	case OPTRLIT:
		switch r.Left.Op {
		//dump("not static ptrlit", r);
		default:
			break

			// Init pointer.
		case OARRAYLIT, OMAPLIT, OSTRUCTLIT:
			a := staticname(r.Left.Type, 1)

			inittemps[r] = a
			gdata(l, Nod(OADDR, a, nil), int(l.Type.Width))

			// Init underlying literal.
			if !staticassign(a, r.Left, out) {
				*out = list(*out, Nod(OAS, a, r.Left))
			}
			return true
		}

	case OSTRARRAYBYTE:
		if l.Class == PEXTERN && r.Left.Op == OLITERAL {
			sval := r.Left.Val().U.(string)
			slicebytes(l, sval, len(sval))
			return true
		}

	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.(*Mpint))
			a := staticname(ta, 1)
			inittemps[r] = a
			n1 = *l
			n1.Xoffset = l.Xoffset + int64(Array_array)
			gdata(&n1, Nod(OADDR, a, nil), Widthptr)
			n1.Xoffset = l.Xoffset + int64(Array_nel)
			gdata(&n1, r.Right, Widthint)
			n1.Xoffset = l.Xoffset + int64(Array_cap)
			gdata(&n1, r.Right, Widthint)

			// Fall through to init underlying array.
			l = a
		}
		fallthrough

		// fall through
	case OSTRUCTLIT:
		initplan(r)

		p := initplans[r]
		n1 = *l
		var e *InitEntry
		var a *Node
		for i := 0; i < len(p.E); 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, int(n1.Type.Width))
			} else {
				setlineno(e.Expr)
				a = Nod(OXXX, nil, nil)
				*a = n1
				a.Orig = a // completely separate copy
				if !staticassign(a, e.Expr, out) {
					*out = list(*out, Nod(OAS, a, e.Expr))
				}
			}
		}

		return true

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

	return false
}

/*
 * 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.
 */
func staticname(t *Type, ctxt int) *Node {
	n := newname(Lookupf("statictmp_%.4d", statuniqgen))
	statuniqgen++
	if ctxt == 0 {
		n.Name.Readonly = true
	}
	addvar(n, t, PEXTERN)
	return n
}

func isliteral(n *Node) bool {
	if n.Op == OLITERAL {
		if n.Val().Ctype() != CTNIL {
			return true
		}
	}
	return false
}

func simplename(n *Node) bool {
	if n.Op != ONAME {
		return false
	}
	if !n.Addable {
		return false
	}
	if n.Class&PHEAP != 0 {
		return false
	}
	if n.Class == PPARAMREF {
		return false
	}
	return true
}

func litas(l *Node, r *Node, init **NodeList) {
	a := Nod(OAS, l, r)
	typecheck(&a, Etop)
	walkexpr(&a, init)
	*init = list(*init, a)
}

const (
	MODEDYNAM = 1
	MODECONST = 2
)

func getdyn(n *Node, top int) int {
	mode := 0
	switch n.Op {
	default:
		if isliteral(n) {
			return MODECONST
		}
		return MODEDYNAM

	case OARRAYLIT:
		if top == 0 && n.Type.Bound < 0 {
			return MODEDYNAM
		}
		fallthrough

	case OSTRUCTLIT:
		break
	}

	var value *Node
	for nl := n.List; nl != nil; nl = nl.Next {
		value = nl.N.Right
		mode |= getdyn(value, 0)
		if mode == MODEDYNAM|MODECONST {
			break
		}
	}

	return mode
}

func structlit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
	var r *Node
	var a *Node
	var index *Node
	var value *Node

	for nl := n.List; nl != nil; nl = nl.Next {
		r = nl.N
		if r.Op != OKEY {
			Fatal("structlit: rhs not OKEY: %v", 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
		setlineno(value)
		a = Nod(ODOT, var_, newname(index.Sym))

		a = Nod(OAS, a, value)
		typecheck(&a, Etop)
		if pass == 1 {
			walkexpr(&a, init) // add any assignments in r to top
			if a.Op != OAS {
				Fatal("structlit: not as")
			}
			a.Dodata = 2
		} else {
			orderstmtinplace(&a)
			walkstmt(&a)
		}

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

func arraylit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
	var r *Node
	var a *Node
	var index *Node
	var value *Node

	for l := n.List; l != nil; l = l.Next {
		r = l.N
		if r.Op != OKEY {
			Fatal("arraylit: rhs not OKEY: %v", 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
		setlineno(value)
		a = Nod(OINDEX, var_, index)

		a = Nod(OAS, a, value)
		typecheck(&a, Etop)
		if pass == 1 {
			walkexpr(&a, init)
			if a.Op != OAS {
				Fatal("arraylit: not as")
			}
			a.Dodata = 2
		} else {
			orderstmtinplace(&a)
			walkstmt(&a)
		}

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

func slicelit(ctxt int, n *Node, var_ *Node, init **NodeList) {
	// make an array type
	t := shallow(n.Type)

	t.Bound = Mpgetfix(n.Right.Val().U.(*Mpint))
	t.Width = 0
	t.Sym = nil
	t.Haspointers = 0
	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, nil, nil))

		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)
	var vstat *Node

	mode := getdyn(n, 1)
	if mode&MODECONST != 0 {
		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)
	var a *Node
	if x := prealloc[n]; x != nil {
		// temp allocated during order.c for dddarg
		x.Type = t

		if vstat == nil {
			a = Nod(OAS, x, nil)
			typecheck(&a, Etop)
			*init = list(*init, a) // zero new temp
		}

		a = Nod(OADDR, x, nil)
	} else if n.Esc == EscNone {
		a = temp(t)
		if vstat == nil {
			a = Nod(OAS, temp(t), nil)
			typecheck(&a, Etop)
			*init = list(*init, a) // zero new temp
			a = a.Left
		}

		a = Nod(OADDR, a, nil)
	} else {
		a = Nod(ONEW, nil, nil)
		a.List = list1(typenod(t))
	}

	a = Nod(OAS, vauto, a)
	typecheck(&a, Etop)
	walkexpr(&a, init)
	*init = list(*init, a)

	if vstat != nil {
		// copy static to heap (4)
		a = Nod(OIND, vauto, nil)

		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, nil, nil)))

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

	// put dynamics into slice (6)
	var value *Node
	var r *Node
	var index *Node
	for l := n.List; l != nil; l = l.Next {
		r = l.N
		if r.Op != OKEY {
			Fatal("slicelit: rhs not OKEY: %v", r)
		}
		index = r.Left
		value = r.Right
		a = Nod(OINDEX, var_, index)
		a.Bounded = true

		// 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
		setlineno(value)
		a = Nod(OAS, a, value)

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

func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
	var r *Node
	var index *Node
	var value *Node

	ctxt = 0

	// make the map var
	nerr := nerrors

	a := Nod(OMAKE, nil, nil)
	a.List = list1(typenod(n.Type))
	litas(var_, a, init)

	// count the initializers
	b := int64(0)

	for l := n.List; l != nil; l = l.Next {
		r = l.N

		if r.Op != OKEY {
			Fatal("maplit: rhs not OKEY: %v", 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 := int64(0)
		var index *Node
		var r *Node
		var value *Node
		for l := n.List; l != nil; l = l.Next {
			r = l.N

			if r.Op != OKEY {
				Fatal("maplit: rhs not OKEY: %v", r)
			}
			index = r.Left
			value = r.Right

			if isliteral(index) && isliteral(value) {
				// build vstat[b].a = key;
				setlineno(index)
				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;
				setlineno(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 = true
		a = Nod(ODOT, a, newname(symb))

		r = Nod(OINDEX, vstat, index)
		r.Bounded = true
		r = Nod(ODOT, r, newname(syma))
		r = Nod(OINDEX, var_, r)

		r = Nod(OAS, r, a)

		a = Nod(OFOR, nil, nil)
		a.Nbody = list1(r)

		a.Ninit = list1(Nod(OAS, index, Nodintconst(0)))
		a.Left = Nod(OLT, index, Nodintconst(t.Bound))
		a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))

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

	// put in dynamic entries one-at-a-time
	var key *Node

	var val *Node
	for l := n.List; l != nil; l = l.Next {
		r = l.N

		if r.Op != OKEY {
			Fatal("maplit: rhs not OKEY: %v", r)
		}
		index = r.Left
		value = r.Right

		if isliteral(index) && isliteral(value) {
			continue
		}

		// build list of var[c] = expr.
		// use temporary so that mapassign1 can have addressable key, val.
		if key == nil {
			key = temp(var_.Type.Down)
			val = temp(var_.Type.Type)
		}

		setlineno(r.Left)
		a = Nod(OAS, key, r.Left)
		typecheck(&a, Etop)
		walkstmt(&a)
		*init = list(*init, a)
		setlineno(r.Right)
		a = Nod(OAS, val, r.Right)
		typecheck(&a, Etop)
		walkstmt(&a)
		*init = list(*init, a)

		setlineno(val)
		a = Nod(OAS, Nod(OINDEX, var_, key), val)
		typecheck(&a, Etop)
		walkstmt(&a)
		*init = list(*init, a)

		if nerr != nerrors {
			break
		}
	}

	if key != nil {
		a = Nod(OVARKILL, key, nil)
		typecheck(&a, Etop)
		*init = list(*init, a)
		a = Nod(OVARKILL, val, nil)
		typecheck(&a, Etop)
		*init = list(*init, a)
	}
}

func anylit(ctxt int, n *Node, var_ *Node, init **NodeList) {
	t := n.Type
	switch n.Op {
	default:
		Fatal("anylit: not lit")

	case OPTRLIT:
		if !Isptr[t.Etype] {
			Fatal("anylit: not ptr")
		}

		var r *Node
		if n.Right != nil {
			r = Nod(OADDR, n.Right, nil)
			typecheck(&r, Erv)
		} else {
			r = Nod(ONEW, nil, nil)
			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_, nil)
		typecheck(&var_, Erv|Easgn)
		anylit(ctxt, n.Left, var_, init)

	case OSTRUCTLIT:
		if t.Etype != TSTRUCT {
			Fatal("anylit: not struct")
		}

		if simplename(var_) && count(n.List) > 4 {
			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 simplename(var_) || count(n.List) < structcount(t) {
			a := Nod(OAS, var_, nil)
			typecheck(&a, Etop)
			walkexpr(&a, init)
			*init = list(*init, a)
		}

		structlit(ctxt, 3, n, var_, init)

	case OARRAYLIT:
		if t.Etype != TARRAY {
			Fatal("anylit: not array")
		}
		if t.Bound < 0 {
			slicelit(ctxt, n, var_, init)
			break
		}

		if simplename(var_) && count(n.List) > 4 {
			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 simplename(var_) || int64(count(n.List)) < t.Bound {
			a := Nod(OAS, var_, nil)
			typecheck(&a, Etop)
			walkexpr(&a, init)
			*init = list(*init, a)
		}

		arraylit(ctxt, 3, n, var_, init)

	case OMAPLIT:
		if t.Etype != TMAP {
			Fatal("anylit: not map")
		}
		maplit(ctxt, n, var_, init)
	}
}

func oaslit(n *Node, init **NodeList) bool {
	if n.Left == nil || n.Right == nil {
		// not a special composit literal assignment
		return false
	}
	if n.Left.Type == nil || n.Right.Type == nil {
		// not a special composit literal assignment
		return false
	}
	if !simplename(n.Left) {
		// not a special composit literal assignment
		return false
	}
	if !Eqtype(n.Left.Type, n.Right.Type) {
		// not a special composit literal assignment
		return false
	}

	// 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:
		// not a special composit literal assignment
		return false

	case OSTRUCTLIT, OARRAYLIT, OMAPLIT:
		if vmatch1(n.Left, n.Right) {
			// not a special composit literal assignment
			return false
		}
		anylit(ctxt, n.Right, n.Left, init)
	}

	n.Op = OEMPTY
	n.Right = nil
	return true
}

func getlit(lit *Node) int {
	if Smallintconst(lit) {
		return int(Mpgetfix(lit.Val().U.(*Mpint)))
	}
	return -1
}

func stataddr(nam *Node, n *Node) bool {
	if n == nil {
		return false
	}

	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 true

	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 && Thearch.MAXWIDTH/n.Type.Width <= int64(l) {
			break
		}
		nam.Xoffset += int64(l) * n.Type.Width
		nam.Type = n.Type
		return true
	}

	return false
}

func initplan(n *Node) {
	if initplans[n] != nil {
		return
	}
	p := new(InitPlan)
	initplans[n] = p
	switch n.Op {
	default:
		Fatal("initplan")

	case OARRAYLIT:
		var a *Node
		for l := n.List; l != nil; 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.(*Mpint)), nil, a.Right)
		}

	case OSTRUCTLIT:
		var a *Node
		for l := n.List; l != nil; l = l.Next {
			a = l.N
			if a.Op != OKEY || a.Left.Type == nil {
				Fatal("initplan structlit")
			}
			addvalue(p, a.Left.Type.Width, nil, a.Right)
		}

	case OMAPLIT:
		var a *Node
		for l := n.List; l != nil; l = l.Next {
			a = l.N
			if a.Op != OKEY {
				Fatal("initplan maplit")
			}
			addvalue(p, -1, a.Left, a.Right)
		}
	}
}

func addvalue(p *InitPlan, xoffset int64, key *Node, n *Node) {
	// 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 := initplans[n]
		var e *InitEntry
		for i := 0; i < len(q.E); 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
}

func iszero(n *Node) bool {
	switch n.Op {
	case OLITERAL:
		switch n.Val().Ctype() {
		default:
			Dump("unexpected literal", n)
			Fatal("iszero")

		case CTNIL:
			return true

		case CTSTR:
			return n.Val().U.(string) == ""

		case CTBOOL:
			return !n.Val().U.(bool)

		case CTINT, CTRUNE:
			return mpcmpfixc(n.Val().U.(*Mpint), 0) == 0

		case CTFLT:
			return mpcmpfltc(n.Val().U.(*Mpflt), 0) == 0

		case CTCPLX:
			return mpcmpfltc(&n.Val().U.(*Mpcplx).Real, 0) == 0 && mpcmpfltc(&n.Val().U.(*Mpcplx).Imag, 0) == 0
		}

	case OARRAYLIT:
		if Isslice(n.Type) {
			break
		}
		fallthrough

		// fall through
	case OSTRUCTLIT:
		for l := n.List; l != nil; l = l.Next {
			if !iszero(l.N.Right) {
				return false
			}
		}
		return true
	}

	return false
}

func isvaluelit(n *Node) bool {
	return (n.Op == OARRAYLIT && Isfixedarray(n.Type)) || n.Op == OSTRUCTLIT
}

func entry(p *InitPlan) *InitEntry {
	p.E = append(p.E, InitEntry{})
	return &p.E[len(p.E)-1]
}

func gen_as_init(n *Node) bool {
	var nr *Node
	var nl *Node
	var nam Node

	if n.Dodata == 0 {
		goto no
	}

	nr = n.Right
	nl = n.Left
	if nr == nil {
		var nam Node
		if !stataddr(&nam, nl) {
			goto no
		}
		if nam.Class != PEXTERN {
			goto no
		}
		return true
	}

	if nr.Type == nil || !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 == nil || nr.Op != OSLICEARR {
			goto no
		}
		fallthrough

		// fall through
	case OSLICEARR:
		if nr.Right.Op == OKEY && nr.Right.Left == nil && nr.Right.Right == nil {
			nr = nr.Left
			gused(nil) // in case the data is the dest of a goto
			nl := nr
			if nr == nil || nr.Op != OADDR {
				goto no
			}
			nr = nr.Left
			if nr == nil || nr.Op != ONAME {
				goto no
			}

			// nr is the array being converted to a slice
			if nr.Type == nil || nr.Type.Etype != TARRAY || nr.Type.Bound < 0 {
				goto no
			}

			nam.Xoffset += int64(Array_array)
			gdata(&nam, nl, int(Types[Tptr].Width))

			nam.Xoffset += int64(Array_nel) - int64(Array_array)
			var nod1 Node
			Nodconst(&nod1, Types[TINT], nr.Type.Bound)
			gdata(&nam, &nod1, Widthint)

			nam.Xoffset += int64(Array_cap) - int64(Array_nel)
			gdata(&nam, &nod1, Widthint)

			return true
		}

		goto no

	case OLITERAL:
		break
	}

	switch nr.Type.Etype {
	default:
		goto no

	case TBOOL,
		TINT8,
		TUINT8,
		TINT16,
		TUINT16,
		TINT32,
		TUINT32,
		TINT64,
		TUINT64,
		TINT,
		TUINT,
		TUINTPTR,
		TPTR32,
		TPTR64,
		TFLOAT32,
		TFLOAT64:
		gdata(&nam, nr, int(nr.Type.Width))

	case TCOMPLEX64, TCOMPLEX128:
		gdatacomplex(&nam, nr.Val().U.(*Mpcplx))

	case TSTRING:
		gdatastring(&nam, nr.Val().U.(string))
	}

	return true

no:
	if n.Dodata == 2 {
		Dump("\ngen_as_init", n)
		Fatal("gen_as_init couldnt make data statement")
	}

	return false
}
