// Do not edit. Bootstrap copy of /tmp/go/src/cmd/compile/internal/gc/sinit.go

//line /tmp/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
}
