Home | History | Annotate | Download | only in gc
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package gc
      6 
      7 import (
      8 	"cmd/internal/obj"
      9 	"fmt"
     10 )
     11 
     12 /*
     13  * static initialization
     14  */
     15 const (
     16 	InitNotStarted = 0
     17 	InitDone       = 1
     18 	InitPending    = 2
     19 )
     20 
     21 var (
     22 	initlist  *NodeList
     23 	initplans map[*Node]*InitPlan
     24 	inittemps = make(map[*Node]*Node)
     25 )
     26 
     27 // init1 walks the AST starting at n, and accumulates in out
     28 // the list of definitions needing init code in dependency order.
     29 func init1(n *Node, out **NodeList) {
     30 	if n == nil {
     31 		return
     32 	}
     33 	init1(n.Left, out)
     34 	init1(n.Right, out)
     35 	for l := n.List; l != nil; l = l.Next {
     36 		init1(l.N, out)
     37 	}
     38 
     39 	if n.Left != nil && n.Type != nil && n.Left.Op == OTYPE && n.Class == PFUNC {
     40 		// Methods called as Type.Method(receiver, ...).
     41 		// Definitions for method expressions are stored in type->nname.
     42 		init1(n.Type.Nname, out)
     43 	}
     44 
     45 	if n.Op != ONAME {
     46 		return
     47 	}
     48 	switch n.Class {
     49 	case PEXTERN, PFUNC:
     50 		break
     51 
     52 	default:
     53 		if isblank(n) && n.Name.Curfn == nil && n.Name.Defn != nil && n.Name.Defn.Initorder == InitNotStarted {
     54 			// blank names initialization is part of init() but not
     55 			// when they are inside a function.
     56 			break
     57 		}
     58 
     59 		return
     60 	}
     61 
     62 	if n.Initorder == InitDone {
     63 		return
     64 	}
     65 	if n.Initorder == InitPending {
     66 		// Since mutually recursive sets of functions are allowed,
     67 		// we don't necessarily raise an error if n depends on a node
     68 		// which is already waiting for its dependencies to be visited.
     69 		//
     70 		// initlist contains a cycle of identifiers referring to each other.
     71 		// If this cycle contains a variable, then this variable refers to itself.
     72 		// Conversely, if there exists an initialization cycle involving
     73 		// a variable in the program, the tree walk will reach a cycle
     74 		// involving that variable.
     75 		var nv *Node
     76 		if n.Class != PFUNC {
     77 			nv = n
     78 			goto foundinitloop
     79 		}
     80 
     81 		for l := initlist; l.N != n; l = l.Next {
     82 			if l.N.Class != PFUNC {
     83 				nv = l.N
     84 				goto foundinitloop
     85 			}
     86 		}
     87 
     88 		// The loop involves only functions, ok.
     89 		return
     90 
     91 		// if there have already been errors printed,
     92 		// those errors probably confused us and
     93 		// there might not be a loop.  let the user
     94 		// fix those first.
     95 	foundinitloop:
     96 		Flusherrors()
     97 
     98 		if nerrors > 0 {
     99 			errorexit()
    100 		}
    101 
    102 		// There is a loop involving nv. We know about
    103 		// n and initlist = n1 <- ... <- nv <- ... <- n <- ...
    104 		fmt.Printf("%v: initialization loop:\n", nv.Line())
    105 
    106 		// Build back pointers in initlist.
    107 		for l := initlist; l != nil; l = l.Next {
    108 			if l.Next != nil {
    109 				l.Next.End = l
    110 			}
    111 		}
    112 
    113 		// Print nv -> ... -> n1 -> n.
    114 		var l *NodeList
    115 		for l = initlist; l.N != nv; l = l.Next {
    116 		}
    117 		for ; l != nil; l = l.End {
    118 			fmt.Printf("\t%v %v refers to\n", l.N.Line(), l.N.Sym)
    119 		}
    120 
    121 		// Print n -> ... -> nv.
    122 		for l = initlist; l.N != n; l = l.Next {
    123 		}
    124 		for ; l.N != nv; l = l.End {
    125 			fmt.Printf("\t%v %v refers to\n", l.N.Line(), l.N.Sym)
    126 		}
    127 		fmt.Printf("\t%v %v\n", nv.Line(), nv.Sym)
    128 		errorexit()
    129 	}
    130 
    131 	// reached a new unvisited node.
    132 	n.Initorder = InitPending
    133 
    134 	l := new(NodeList)
    135 	if l == nil {
    136 		Flusherrors()
    137 		Yyerror("out of memory")
    138 		errorexit()
    139 	}
    140 
    141 	l.Next = initlist
    142 	l.N = n
    143 	l.End = nil
    144 	initlist = l
    145 
    146 	// make sure that everything n depends on is initialized.
    147 	// n->defn is an assignment to n
    148 	if defn := n.Name.Defn; defn != nil {
    149 		switch defn.Op {
    150 		default:
    151 			goto bad
    152 
    153 		case ODCLFUNC:
    154 			init2list(defn.Nbody, out)
    155 
    156 		case OAS:
    157 			if defn.Left != n {
    158 				goto bad
    159 			}
    160 			if isblank(defn.Left) && candiscard(defn.Right) {
    161 				defn.Op = OEMPTY
    162 				defn.Left = nil
    163 				defn.Right = nil
    164 				break
    165 			}
    166 
    167 			init2(defn.Right, out)
    168 			if Debug['j'] != 0 {
    169 				fmt.Printf("%v\n", n.Sym)
    170 			}
    171 			if isblank(n) || !staticinit(n, out) {
    172 				if Debug['%'] != 0 {
    173 					Dump("nonstatic", defn)
    174 				}
    175 				*out = list(*out, defn)
    176 			}
    177 
    178 		case OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV:
    179 			if defn.Initorder != InitNotStarted {
    180 				break
    181 			}
    182 			defn.Initorder = InitDone
    183 			for l := defn.Rlist; l != nil; l = l.Next {
    184 				init1(l.N, out)
    185 			}
    186 			if Debug['%'] != 0 {
    187 				Dump("nonstatic", defn)
    188 			}
    189 			*out = list(*out, defn)
    190 		}
    191 	}
    192 
    193 	l = initlist
    194 	initlist = l.Next
    195 	if l.N != n {
    196 		Fatal("bad initlist")
    197 	}
    198 
    199 	n.Initorder = InitDone
    200 	return
    201 
    202 bad:
    203 	Dump("defn", n.Name.Defn)
    204 	Fatal("init1: bad defn")
    205 }
    206 
    207 // recurse over n, doing init1 everywhere.
    208 func init2(n *Node, out **NodeList) {
    209 	if n == nil || n.Initorder == InitDone {
    210 		return
    211 	}
    212 
    213 	if n.Op == ONAME && n.Ninit != nil {
    214 		Fatal("name %v with ninit: %v\n", n.Sym, Nconv(n, obj.FmtSign))
    215 	}
    216 
    217 	init1(n, out)
    218 	init2(n.Left, out)
    219 	init2(n.Right, out)
    220 	init2list(n.Ninit, out)
    221 	init2list(n.List, out)
    222 	init2list(n.Rlist, out)
    223 	init2list(n.Nbody, out)
    224 
    225 	if n.Op == OCLOSURE {
    226 		init2list(n.Func.Closure.Nbody, out)
    227 	}
    228 	if n.Op == ODOTMETH || n.Op == OCALLPART {
    229 		init2(n.Type.Nname, out)
    230 	}
    231 }
    232 
    233 func init2list(l *NodeList, out **NodeList) {
    234 	for ; l != nil; l = l.Next {
    235 		init2(l.N, out)
    236 	}
    237 }
    238 
    239 func initreorder(l *NodeList, out **NodeList) {
    240 	var n *Node
    241 
    242 	for ; l != nil; l = l.Next {
    243 		n = l.N
    244 		switch n.Op {
    245 		case ODCLFUNC, ODCLCONST, ODCLTYPE:
    246 			continue
    247 		}
    248 
    249 		initreorder(n.Ninit, out)
    250 		n.Ninit = nil
    251 		init1(n, out)
    252 	}
    253 }
    254 
    255 // initfix computes initialization order for a list l of top-level
    256 // declarations and outputs the corresponding list of statements
    257 // to include in the init() function body.
    258 func initfix(l *NodeList) *NodeList {
    259 	var lout *NodeList
    260 	initplans = make(map[*Node]*InitPlan)
    261 	lno := int(lineno)
    262 	initreorder(l, &lout)
    263 	lineno = int32(lno)
    264 	initplans = nil
    265 	return lout
    266 }
    267 
    268 /*
    269  * compilation of top-level (static) assignments
    270  * into DATA statements if at all possible.
    271  */
    272 func staticinit(n *Node, out **NodeList) bool {
    273 	if n.Op != ONAME || n.Class != PEXTERN || n.Name.Defn == nil || n.Name.Defn.Op != OAS {
    274 		Fatal("staticinit")
    275 	}
    276 
    277 	lineno = n.Lineno
    278 	l := n.Name.Defn.Left
    279 	r := n.Name.Defn.Right
    280 	return staticassign(l, r, out)
    281 }
    282 
    283 // like staticassign but we are copying an already
    284 // initialized value r.
    285 func staticcopy(l *Node, r *Node, out **NodeList) bool {
    286 	if r.Op != ONAME {
    287 		return false
    288 	}
    289 	if r.Class == PFUNC {
    290 		gdata(l, r, Widthptr)
    291 		return true
    292 	}
    293 	if r.Class != PEXTERN || r.Sym.Pkg != localpkg {
    294 		return false
    295 	}
    296 	if r.Name.Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value
    297 		return false
    298 	}
    299 	if r.Name.Defn.Op != OAS {
    300 		return false
    301 	}
    302 	orig := r
    303 	r = r.Name.Defn.Right
    304 
    305 	for r.Op == OCONVNOP {
    306 		r = r.Left
    307 	}
    308 
    309 	switch r.Op {
    310 	case ONAME:
    311 		if staticcopy(l, r, out) {
    312 			return true
    313 		}
    314 		*out = list(*out, Nod(OAS, l, r))
    315 		return true
    316 
    317 	case OLITERAL:
    318 		if iszero(r) {
    319 			return true
    320 		}
    321 		gdata(l, r, int(l.Type.Width))
    322 		return true
    323 
    324 	case OADDR:
    325 		switch r.Left.Op {
    326 		case ONAME:
    327 			gdata(l, r, int(l.Type.Width))
    328 			return true
    329 		}
    330 
    331 	case OPTRLIT:
    332 		switch r.Left.Op {
    333 		//dump("not static addr", r);
    334 		default:
    335 			break
    336 
    337 			// copy pointer
    338 		case OARRAYLIT, OSTRUCTLIT, OMAPLIT:
    339 			gdata(l, Nod(OADDR, inittemps[r], nil), int(l.Type.Width))
    340 
    341 			return true
    342 		}
    343 
    344 	case OARRAYLIT:
    345 		if Isslice(r.Type) {
    346 			// copy slice
    347 			a := inittemps[r]
    348 
    349 			n1 := *l
    350 			n1.Xoffset = l.Xoffset + int64(Array_array)
    351 			gdata(&n1, Nod(OADDR, a, nil), Widthptr)
    352 			n1.Xoffset = l.Xoffset + int64(Array_nel)
    353 			gdata(&n1, r.Right, Widthint)
    354 			n1.Xoffset = l.Xoffset + int64(Array_cap)
    355 			gdata(&n1, r.Right, Widthint)
    356 			return true
    357 		}
    358 		fallthrough
    359 
    360 		// fall through
    361 	case OSTRUCTLIT:
    362 		p := initplans[r]
    363 
    364 		n1 := *l
    365 		var e *InitEntry
    366 		var ll *Node
    367 		var rr *Node
    368 		for i := 0; i < len(p.E); i++ {
    369 			e = &p.E[i]
    370 			n1.Xoffset = l.Xoffset + e.Xoffset
    371 			n1.Type = e.Expr.Type
    372 			if e.Expr.Op == OLITERAL {
    373 				gdata(&n1, e.Expr, int(n1.Type.Width))
    374 			} else {
    375 				ll = Nod(OXXX, nil, nil)
    376 				*ll = n1
    377 				ll.Orig = ll // completely separate copy
    378 				if !staticassign(ll, e.Expr, out) {
    379 					// Requires computation, but we're
    380 					// copying someone else's computation.
    381 					rr = Nod(OXXX, nil, nil)
    382 
    383 					*rr = *orig
    384 					rr.Orig = rr // completely separate copy
    385 					rr.Type = ll.Type
    386 					rr.Xoffset += e.Xoffset
    387 					setlineno(rr)
    388 					*out = list(*out, Nod(OAS, ll, rr))
    389 				}
    390 			}
    391 		}
    392 
    393 		return true
    394 	}
    395 
    396 	return false
    397 }
    398 
    399 func staticassign(l *Node, r *Node, out **NodeList) bool {
    400 	var n1 Node
    401 
    402 	for r.Op == OCONVNOP {
    403 		r = r.Left
    404 	}
    405 
    406 	switch r.Op {
    407 	//dump("not static", r);
    408 	default:
    409 		break
    410 
    411 	case ONAME:
    412 		return staticcopy(l, r, out)
    413 
    414 	case OLITERAL:
    415 		if iszero(r) {
    416 			return true
    417 		}
    418 		gdata(l, r, int(l.Type.Width))
    419 		return true
    420 
    421 	case OADDR:
    422 		var nam Node
    423 		if stataddr(&nam, r.Left) {
    424 			n1 := *r
    425 			n1.Left = &nam
    426 			gdata(l, &n1, int(l.Type.Width))
    427 			return true
    428 		}
    429 		fallthrough
    430 
    431 	case OPTRLIT:
    432 		switch r.Left.Op {
    433 		//dump("not static ptrlit", r);
    434 		default:
    435 			break
    436 
    437 			// Init pointer.
    438 		case OARRAYLIT, OMAPLIT, OSTRUCTLIT:
    439 			a := staticname(r.Left.Type, 1)
    440 
    441 			inittemps[r] = a
    442 			gdata(l, Nod(OADDR, a, nil), int(l.Type.Width))
    443 
    444 			// Init underlying literal.
    445 			if !staticassign(a, r.Left, out) {
    446 				*out = list(*out, Nod(OAS, a, r.Left))
    447 			}
    448 			return true
    449 		}
    450 
    451 	case OSTRARRAYBYTE:
    452 		if l.Class == PEXTERN && r.Left.Op == OLITERAL {
    453 			sval := r.Left.Val().U.(string)
    454 			slicebytes(l, sval, len(sval))
    455 			return true
    456 		}
    457 
    458 	case OARRAYLIT:
    459 		initplan(r)
    460 		if Isslice(r.Type) {
    461 			// Init slice.
    462 			ta := typ(TARRAY)
    463 
    464 			ta.Type = r.Type.Type
    465 			ta.Bound = Mpgetfix(r.Right.Val().U.(*Mpint))
    466 			a := staticname(ta, 1)
    467 			inittemps[r] = a
    468 			n1 = *l
    469 			n1.Xoffset = l.Xoffset + int64(Array_array)
    470 			gdata(&n1, Nod(OADDR, a, nil), Widthptr)
    471 			n1.Xoffset = l.Xoffset + int64(Array_nel)
    472 			gdata(&n1, r.Right, Widthint)
    473 			n1.Xoffset = l.Xoffset + int64(Array_cap)
    474 			gdata(&n1, r.Right, Widthint)
    475 
    476 			// Fall through to init underlying array.
    477 			l = a
    478 		}
    479 		fallthrough
    480 
    481 		// fall through
    482 	case OSTRUCTLIT:
    483 		initplan(r)
    484 
    485 		p := initplans[r]
    486 		n1 = *l
    487 		var e *InitEntry
    488 		var a *Node
    489 		for i := 0; i < len(p.E); i++ {
    490 			e = &p.E[i]
    491 			n1.Xoffset = l.Xoffset + e.Xoffset
    492 			n1.Type = e.Expr.Type
    493 			if e.Expr.Op == OLITERAL {
    494 				gdata(&n1, e.Expr, int(n1.Type.Width))
    495 			} else {
    496 				setlineno(e.Expr)
    497 				a = Nod(OXXX, nil, nil)
    498 				*a = n1
    499 				a.Orig = a // completely separate copy
    500 				if !staticassign(a, e.Expr, out) {
    501 					*out = list(*out, Nod(OAS, a, e.Expr))
    502 				}
    503 			}
    504 		}
    505 
    506 		return true
    507 
    508 		// TODO: Table-driven map insert.
    509 	case OMAPLIT:
    510 		break
    511 	}
    512 
    513 	return false
    514 }
    515 
    516 /*
    517  * from here down is the walk analysis
    518  * of composite literals.
    519  * most of the work is to generate
    520  * data statements for the constant
    521  * part of the composite literal.
    522  */
    523 func staticname(t *Type, ctxt int) *Node {
    524 	n := newname(Lookupf("statictmp_%.4d", statuniqgen))
    525 	statuniqgen++
    526 	if ctxt == 0 {
    527 		n.Name.Readonly = true
    528 	}
    529 	addvar(n, t, PEXTERN)
    530 	return n
    531 }
    532 
    533 func isliteral(n *Node) bool {
    534 	if n.Op == OLITERAL {
    535 		if n.Val().Ctype() != CTNIL {
    536 			return true
    537 		}
    538 	}
    539 	return false
    540 }
    541 
    542 func simplename(n *Node) bool {
    543 	if n.Op != ONAME {
    544 		return false
    545 	}
    546 	if !n.Addable {
    547 		return false
    548 	}
    549 	if n.Class&PHEAP != 0 {
    550 		return false
    551 	}
    552 	if n.Class == PPARAMREF {
    553 		return false
    554 	}
    555 	return true
    556 }
    557 
    558 func litas(l *Node, r *Node, init **NodeList) {
    559 	a := Nod(OAS, l, r)
    560 	typecheck(&a, Etop)
    561 	walkexpr(&a, init)
    562 	*init = list(*init, a)
    563 }
    564 
    565 const (
    566 	MODEDYNAM = 1
    567 	MODECONST = 2
    568 )
    569 
    570 func getdyn(n *Node, top int) int {
    571 	mode := 0
    572 	switch n.Op {
    573 	default:
    574 		if isliteral(n) {
    575 			return MODECONST
    576 		}
    577 		return MODEDYNAM
    578 
    579 	case OARRAYLIT:
    580 		if top == 0 && n.Type.Bound < 0 {
    581 			return MODEDYNAM
    582 		}
    583 		fallthrough
    584 
    585 	case OSTRUCTLIT:
    586 		break
    587 	}
    588 
    589 	var value *Node
    590 	for nl := n.List; nl != nil; nl = nl.Next {
    591 		value = nl.N.Right
    592 		mode |= getdyn(value, 0)
    593 		if mode == MODEDYNAM|MODECONST {
    594 			break
    595 		}
    596 	}
    597 
    598 	return mode
    599 }
    600 
    601 func structlit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
    602 	var r *Node
    603 	var a *Node
    604 	var index *Node
    605 	var value *Node
    606 
    607 	for nl := n.List; nl != nil; nl = nl.Next {
    608 		r = nl.N
    609 		if r.Op != OKEY {
    610 			Fatal("structlit: rhs not OKEY: %v", r)
    611 		}
    612 		index = r.Left
    613 		value = r.Right
    614 
    615 		switch value.Op {
    616 		case OARRAYLIT:
    617 			if value.Type.Bound < 0 {
    618 				if pass == 1 && ctxt != 0 {
    619 					a = Nod(ODOT, var_, newname(index.Sym))
    620 					slicelit(ctxt, value, a, init)
    621 				} else if pass == 2 && ctxt == 0 {
    622 					a = Nod(ODOT, var_, newname(index.Sym))
    623 					slicelit(ctxt, value, a, init)
    624 				} else if pass == 3 {
    625 					break
    626 				}
    627 				continue
    628 			}
    629 
    630 			a = Nod(ODOT, var_, newname(index.Sym))
    631 			arraylit(ctxt, pass, value, a, init)
    632 			continue
    633 
    634 		case OSTRUCTLIT:
    635 			a = Nod(ODOT, var_, newname(index.Sym))
    636 			structlit(ctxt, pass, value, a, init)
    637 			continue
    638 		}
    639 
    640 		if isliteral(value) {
    641 			if pass == 2 {
    642 				continue
    643 			}
    644 		} else if pass == 1 {
    645 			continue
    646 		}
    647 
    648 		// build list of var.field = expr
    649 		setlineno(value)
    650 		a = Nod(ODOT, var_, newname(index.Sym))
    651 
    652 		a = Nod(OAS, a, value)
    653 		typecheck(&a, Etop)
    654 		if pass == 1 {
    655 			walkexpr(&a, init) // add any assignments in r to top
    656 			if a.Op != OAS {
    657 				Fatal("structlit: not as")
    658 			}
    659 			a.Dodata = 2
    660 		} else {
    661 			orderstmtinplace(&a)
    662 			walkstmt(&a)
    663 		}
    664 
    665 		*init = list(*init, a)
    666 	}
    667 }
    668 
    669 func arraylit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
    670 	var r *Node
    671 	var a *Node
    672 	var index *Node
    673 	var value *Node
    674 
    675 	for l := n.List; l != nil; l = l.Next {
    676 		r = l.N
    677 		if r.Op != OKEY {
    678 			Fatal("arraylit: rhs not OKEY: %v", r)
    679 		}
    680 		index = r.Left
    681 		value = r.Right
    682 
    683 		switch value.Op {
    684 		case OARRAYLIT:
    685 			if value.Type.Bound < 0 {
    686 				if pass == 1 && ctxt != 0 {
    687 					a = Nod(OINDEX, var_, index)
    688 					slicelit(ctxt, value, a, init)
    689 				} else if pass == 2 && ctxt == 0 {
    690 					a = Nod(OINDEX, var_, index)
    691 					slicelit(ctxt, value, a, init)
    692 				} else if pass == 3 {
    693 					break
    694 				}
    695 				continue
    696 			}
    697 
    698 			a = Nod(OINDEX, var_, index)
    699 			arraylit(ctxt, pass, value, a, init)
    700 			continue
    701 
    702 		case OSTRUCTLIT:
    703 			a = Nod(OINDEX, var_, index)
    704 			structlit(ctxt, pass, value, a, init)
    705 			continue
    706 		}
    707 
    708 		if isliteral(index) && isliteral(value) {
    709 			if pass == 2 {
    710 				continue
    711 			}
    712 		} else if pass == 1 {
    713 			continue
    714 		}
    715 
    716 		// build list of var[index] = value
    717 		setlineno(value)
    718 		a = Nod(OINDEX, var_, index)
    719 
    720 		a = Nod(OAS, a, value)
    721 		typecheck(&a, Etop)
    722 		if pass == 1 {
    723 			walkexpr(&a, init)
    724 			if a.Op != OAS {
    725 				Fatal("arraylit: not as")
    726 			}
    727 			a.Dodata = 2
    728 		} else {
    729 			orderstmtinplace(&a)
    730 			walkstmt(&a)
    731 		}
    732 
    733 		*init = list(*init, a)
    734 	}
    735 }
    736 
    737 func slicelit(ctxt int, n *Node, var_ *Node, init **NodeList) {
    738 	// make an array type
    739 	t := shallow(n.Type)
    740 
    741 	t.Bound = Mpgetfix(n.Right.Val().U.(*Mpint))
    742 	t.Width = 0
    743 	t.Sym = nil
    744 	t.Haspointers = 0
    745 	dowidth(t)
    746 
    747 	if ctxt != 0 {
    748 		// put everything into static array
    749 		vstat := staticname(t, ctxt)
    750 
    751 		arraylit(ctxt, 1, n, vstat, init)
    752 		arraylit(ctxt, 2, n, vstat, init)
    753 
    754 		// copy static to slice
    755 		a := Nod(OSLICE, vstat, Nod(OKEY, nil, nil))
    756 
    757 		a = Nod(OAS, var_, a)
    758 		typecheck(&a, Etop)
    759 		a.Dodata = 2
    760 		*init = list(*init, a)
    761 		return
    762 	}
    763 
    764 	// recipe for var = []t{...}
    765 	// 1. make a static array
    766 	//	var vstat [...]t
    767 	// 2. assign (data statements) the constant part
    768 	//	vstat = constpart{}
    769 	// 3. make an auto pointer to array and allocate heap to it
    770 	//	var vauto *[...]t = new([...]t)
    771 	// 4. copy the static array to the auto array
    772 	//	*vauto = vstat
    773 	// 5. assign slice of allocated heap to var
    774 	//	var = [0:]*auto
    775 	// 6. for each dynamic part assign to the slice
    776 	//	var[i] = dynamic part
    777 	//
    778 	// an optimization is done if there is no constant part
    779 	//	3. var vauto *[...]t = new([...]t)
    780 	//	5. var = [0:]*auto
    781 	//	6. var[i] = dynamic part
    782 
    783 	// if the literal contains constants,
    784 	// make static initialized array (1),(2)
    785 	var vstat *Node
    786 
    787 	mode := getdyn(n, 1)
    788 	if mode&MODECONST != 0 {
    789 		vstat = staticname(t, ctxt)
    790 		arraylit(ctxt, 1, n, vstat, init)
    791 	}
    792 
    793 	// make new auto *array (3 declare)
    794 	vauto := temp(Ptrto(t))
    795 
    796 	// set auto to point at new temp or heap (3 assign)
    797 	var a *Node
    798 	if x := prealloc[n]; x != nil {
    799 		// temp allocated during order.c for dddarg
    800 		x.Type = t
    801 
    802 		if vstat == nil {
    803 			a = Nod(OAS, x, nil)
    804 			typecheck(&a, Etop)
    805 			*init = list(*init, a) // zero new temp
    806 		}
    807 
    808 		a = Nod(OADDR, x, nil)
    809 	} else if n.Esc == EscNone {
    810 		a = temp(t)
    811 		if vstat == nil {
    812 			a = Nod(OAS, temp(t), nil)
    813 			typecheck(&a, Etop)
    814 			*init = list(*init, a) // zero new temp
    815 			a = a.Left
    816 		}
    817 
    818 		a = Nod(OADDR, a, nil)
    819 	} else {
    820 		a = Nod(ONEW, nil, nil)
    821 		a.List = list1(typenod(t))
    822 	}
    823 
    824 	a = Nod(OAS, vauto, a)
    825 	typecheck(&a, Etop)
    826 	walkexpr(&a, init)
    827 	*init = list(*init, a)
    828 
    829 	if vstat != nil {
    830 		// copy static to heap (4)
    831 		a = Nod(OIND, vauto, nil)
    832 
    833 		a = Nod(OAS, a, vstat)
    834 		typecheck(&a, Etop)
    835 		walkexpr(&a, init)
    836 		*init = list(*init, a)
    837 	}
    838 
    839 	// make slice out of heap (5)
    840 	a = Nod(OAS, var_, Nod(OSLICE, vauto, Nod(OKEY, nil, nil)))
    841 
    842 	typecheck(&a, Etop)
    843 	orderstmtinplace(&a)
    844 	walkstmt(&a)
    845 	*init = list(*init, a)
    846 
    847 	// put dynamics into slice (6)
    848 	var value *Node
    849 	var r *Node
    850 	var index *Node
    851 	for l := n.List; l != nil; l = l.Next {
    852 		r = l.N
    853 		if r.Op != OKEY {
    854 			Fatal("slicelit: rhs not OKEY: %v", r)
    855 		}
    856 		index = r.Left
    857 		value = r.Right
    858 		a = Nod(OINDEX, var_, index)
    859 		a.Bounded = true
    860 
    861 		// TODO need to check bounds?
    862 
    863 		switch value.Op {
    864 		case OARRAYLIT:
    865 			if value.Type.Bound < 0 {
    866 				break
    867 			}
    868 			arraylit(ctxt, 2, value, a, init)
    869 			continue
    870 
    871 		case OSTRUCTLIT:
    872 			structlit(ctxt, 2, value, a, init)
    873 			continue
    874 		}
    875 
    876 		if isliteral(index) && isliteral(value) {
    877 			continue
    878 		}
    879 
    880 		// build list of var[c] = expr
    881 		setlineno(value)
    882 		a = Nod(OAS, a, value)
    883 
    884 		typecheck(&a, Etop)
    885 		orderstmtinplace(&a)
    886 		walkstmt(&a)
    887 		*init = list(*init, a)
    888 	}
    889 }
    890 
    891 func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
    892 	var r *Node
    893 	var index *Node
    894 	var value *Node
    895 
    896 	ctxt = 0
    897 
    898 	// make the map var
    899 	nerr := nerrors
    900 
    901 	a := Nod(OMAKE, nil, nil)
    902 	a.List = list1(typenod(n.Type))
    903 	litas(var_, a, init)
    904 
    905 	// count the initializers
    906 	b := int64(0)
    907 
    908 	for l := n.List; l != nil; l = l.Next {
    909 		r = l.N
    910 
    911 		if r.Op != OKEY {
    912 			Fatal("maplit: rhs not OKEY: %v", r)
    913 		}
    914 		index = r.Left
    915 		value = r.Right
    916 
    917 		if isliteral(index) && isliteral(value) {
    918 			b++
    919 		}
    920 	}
    921 
    922 	if b != 0 {
    923 		// build type [count]struct { a Tindex, b Tvalue }
    924 		t := n.Type
    925 
    926 		tk := t.Down
    927 		tv := t.Type
    928 
    929 		symb := Lookup("b")
    930 		t = typ(TFIELD)
    931 		t.Type = tv
    932 		t.Sym = symb
    933 
    934 		syma := Lookup("a")
    935 		t1 := t
    936 		t = typ(TFIELD)
    937 		t.Type = tk
    938 		t.Sym = syma
    939 		t.Down = t1
    940 
    941 		t1 = t
    942 		t = typ(TSTRUCT)
    943 		t.Type = t1
    944 
    945 		t1 = t
    946 		t = typ(TARRAY)
    947 		t.Bound = b
    948 		t.Type = t1
    949 
    950 		dowidth(t)
    951 
    952 		// make and initialize static array
    953 		vstat := staticname(t, ctxt)
    954 
    955 		b := int64(0)
    956 		var index *Node
    957 		var r *Node
    958 		var value *Node
    959 		for l := n.List; l != nil; l = l.Next {
    960 			r = l.N
    961 
    962 			if r.Op != OKEY {
    963 				Fatal("maplit: rhs not OKEY: %v", r)
    964 			}
    965 			index = r.Left
    966 			value = r.Right
    967 
    968 			if isliteral(index) && isliteral(value) {
    969 				// build vstat[b].a = key;
    970 				setlineno(index)
    971 				a = Nodintconst(b)
    972 
    973 				a = Nod(OINDEX, vstat, a)
    974 				a = Nod(ODOT, a, newname(syma))
    975 				a = Nod(OAS, a, index)
    976 				typecheck(&a, Etop)
    977 				walkexpr(&a, init)
    978 				a.Dodata = 2
    979 				*init = list(*init, a)
    980 
    981 				// build vstat[b].b = value;
    982 				setlineno(value)
    983 				a = Nodintconst(b)
    984 
    985 				a = Nod(OINDEX, vstat, a)
    986 				a = Nod(ODOT, a, newname(symb))
    987 				a = Nod(OAS, a, value)
    988 				typecheck(&a, Etop)
    989 				walkexpr(&a, init)
    990 				a.Dodata = 2
    991 				*init = list(*init, a)
    992 
    993 				b++
    994 			}
    995 		}
    996 
    997 		// loop adding structure elements to map
    998 		// for i = 0; i < len(vstat); i++ {
    999 		//	map[vstat[i].a] = vstat[i].b
   1000 		// }
   1001 		index = temp(Types[TINT])
   1002 
   1003 		a = Nod(OINDEX, vstat, index)
   1004 		a.Bounded = true
   1005 		a = Nod(ODOT, a, newname(symb))
   1006 
   1007 		r = Nod(OINDEX, vstat, index)
   1008 		r.Bounded = true
   1009 		r = Nod(ODOT, r, newname(syma))
   1010 		r = Nod(OINDEX, var_, r)
   1011 
   1012 		r = Nod(OAS, r, a)
   1013 
   1014 		a = Nod(OFOR, nil, nil)
   1015 		a.Nbody = list1(r)
   1016 
   1017 		a.Ninit = list1(Nod(OAS, index, Nodintconst(0)))
   1018 		a.Left = Nod(OLT, index, Nodintconst(t.Bound))
   1019 		a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
   1020 
   1021 		typecheck(&a, Etop)
   1022 		walkstmt(&a)
   1023 		*init = list(*init, a)
   1024 	}
   1025 
   1026 	// put in dynamic entries one-at-a-time
   1027 	var key *Node
   1028 
   1029 	var val *Node
   1030 	for l := n.List; l != nil; l = l.Next {
   1031 		r = l.N
   1032 
   1033 		if r.Op != OKEY {
   1034 			Fatal("maplit: rhs not OKEY: %v", r)
   1035 		}
   1036 		index = r.Left
   1037 		value = r.Right
   1038 
   1039 		if isliteral(index) && isliteral(value) {
   1040 			continue
   1041 		}
   1042 
   1043 		// build list of var[c] = expr.
   1044 		// use temporary so that mapassign1 can have addressable key, val.
   1045 		if key == nil {
   1046 			key = temp(var_.Type.Down)
   1047 			val = temp(var_.Type.Type)
   1048 		}
   1049 
   1050 		setlineno(r.Left)
   1051 		a = Nod(OAS, key, r.Left)
   1052 		typecheck(&a, Etop)
   1053 		walkstmt(&a)
   1054 		*init = list(*init, a)
   1055 		setlineno(r.Right)
   1056 		a = Nod(OAS, val, r.Right)
   1057 		typecheck(&a, Etop)
   1058 		walkstmt(&a)
   1059 		*init = list(*init, a)
   1060 
   1061 		setlineno(val)
   1062 		a = Nod(OAS, Nod(OINDEX, var_, key), val)
   1063 		typecheck(&a, Etop)
   1064 		walkstmt(&a)
   1065 		*init = list(*init, a)
   1066 
   1067 		if nerr != nerrors {
   1068 			break
   1069 		}
   1070 	}
   1071 
   1072 	if key != nil {
   1073 		a = Nod(OVARKILL, key, nil)
   1074 		typecheck(&a, Etop)
   1075 		*init = list(*init, a)
   1076 		a = Nod(OVARKILL, val, nil)
   1077 		typecheck(&a, Etop)
   1078 		*init = list(*init, a)
   1079 	}
   1080 }
   1081 
   1082 func anylit(ctxt int, n *Node, var_ *Node, init **NodeList) {
   1083 	t := n.Type
   1084 	switch n.Op {
   1085 	default:
   1086 		Fatal("anylit: not lit")
   1087 
   1088 	case OPTRLIT:
   1089 		if !Isptr[t.Etype] {
   1090 			Fatal("anylit: not ptr")
   1091 		}
   1092 
   1093 		var r *Node
   1094 		if n.Right != nil {
   1095 			r = Nod(OADDR, n.Right, nil)
   1096 			typecheck(&r, Erv)
   1097 		} else {
   1098 			r = Nod(ONEW, nil, nil)
   1099 			r.Typecheck = 1
   1100 			r.Type = t
   1101 			r.Esc = n.Esc
   1102 		}
   1103 
   1104 		walkexpr(&r, init)
   1105 		a := Nod(OAS, var_, r)
   1106 
   1107 		typecheck(&a, Etop)
   1108 		*init = list(*init, a)
   1109 
   1110 		var_ = Nod(OIND, var_, nil)
   1111 		typecheck(&var_, Erv|Easgn)
   1112 		anylit(ctxt, n.Left, var_, init)
   1113 
   1114 	case OSTRUCTLIT:
   1115 		if t.Etype != TSTRUCT {
   1116 			Fatal("anylit: not struct")
   1117 		}
   1118 
   1119 		if simplename(var_) && count(n.List) > 4 {
   1120 			if ctxt == 0 {
   1121 				// lay out static data
   1122 				vstat := staticname(t, ctxt)
   1123 
   1124 				structlit(ctxt, 1, n, vstat, init)
   1125 
   1126 				// copy static to var
   1127 				a := Nod(OAS, var_, vstat)
   1128 
   1129 				typecheck(&a, Etop)
   1130 				walkexpr(&a, init)
   1131 				*init = list(*init, a)
   1132 
   1133 				// add expressions to automatic
   1134 				structlit(ctxt, 2, n, var_, init)
   1135 
   1136 				break
   1137 			}
   1138 
   1139 			structlit(ctxt, 1, n, var_, init)
   1140 			structlit(ctxt, 2, n, var_, init)
   1141 			break
   1142 		}
   1143 
   1144 		// initialize of not completely specified
   1145 		if simplename(var_) || count(n.List) < structcount(t) {
   1146 			a := Nod(OAS, var_, nil)
   1147 			typecheck(&a, Etop)
   1148 			walkexpr(&a, init)
   1149 			*init = list(*init, a)
   1150 		}
   1151 
   1152 		structlit(ctxt, 3, n, var_, init)
   1153 
   1154 	case OARRAYLIT:
   1155 		if t.Etype != TARRAY {
   1156 			Fatal("anylit: not array")
   1157 		}
   1158 		if t.Bound < 0 {
   1159 			slicelit(ctxt, n, var_, init)
   1160 			break
   1161 		}
   1162 
   1163 		if simplename(var_) && count(n.List) > 4 {
   1164 			if ctxt == 0 {
   1165 				// lay out static data
   1166 				vstat := staticname(t, ctxt)
   1167 
   1168 				arraylit(1, 1, n, vstat, init)
   1169 
   1170 				// copy static to automatic
   1171 				a := Nod(OAS, var_, vstat)
   1172 
   1173 				typecheck(&a, Etop)
   1174 				walkexpr(&a, init)
   1175 				*init = list(*init, a)
   1176 
   1177 				// add expressions to automatic
   1178 				arraylit(ctxt, 2, n, var_, init)
   1179 
   1180 				break
   1181 			}
   1182 
   1183 			arraylit(ctxt, 1, n, var_, init)
   1184 			arraylit(ctxt, 2, n, var_, init)
   1185 			break
   1186 		}
   1187 
   1188 		// initialize of not completely specified
   1189 		if simplename(var_) || int64(count(n.List)) < t.Bound {
   1190 			a := Nod(OAS, var_, nil)
   1191 			typecheck(&a, Etop)
   1192 			walkexpr(&a, init)
   1193 			*init = list(*init, a)
   1194 		}
   1195 
   1196 		arraylit(ctxt, 3, n, var_, init)
   1197 
   1198 	case OMAPLIT:
   1199 		if t.Etype != TMAP {
   1200 			Fatal("anylit: not map")
   1201 		}
   1202 		maplit(ctxt, n, var_, init)
   1203 	}
   1204 }
   1205 
   1206 func oaslit(n *Node, init **NodeList) bool {
   1207 	if n.Left == nil || n.Right == nil {
   1208 		// not a special composit literal assignment
   1209 		return false
   1210 	}
   1211 	if n.Left.Type == nil || n.Right.Type == nil {
   1212 		// not a special composit literal assignment
   1213 		return false
   1214 	}
   1215 	if !simplename(n.Left) {
   1216 		// not a special composit literal assignment
   1217 		return false
   1218 	}
   1219 	if !Eqtype(n.Left.Type, n.Right.Type) {
   1220 		// not a special composit literal assignment
   1221 		return false
   1222 	}
   1223 
   1224 	// context is init() function.
   1225 	// implies generated data executed
   1226 	// exactly once and not subject to races.
   1227 	ctxt := 0
   1228 
   1229 	//	if(n->dodata == 1)
   1230 	//		ctxt = 1;
   1231 
   1232 	switch n.Right.Op {
   1233 	default:
   1234 		// not a special composit literal assignment
   1235 		return false
   1236 
   1237 	case OSTRUCTLIT, OARRAYLIT, OMAPLIT:
   1238 		if vmatch1(n.Left, n.Right) {
   1239 			// not a special composit literal assignment
   1240 			return false
   1241 		}
   1242 		anylit(ctxt, n.Right, n.Left, init)
   1243 	}
   1244 
   1245 	n.Op = OEMPTY
   1246 	n.Right = nil
   1247 	return true
   1248 }
   1249 
   1250 func getlit(lit *Node) int {
   1251 	if Smallintconst(lit) {
   1252 		return int(Mpgetfix(lit.Val().U.(*Mpint)))
   1253 	}
   1254 	return -1
   1255 }
   1256 
   1257 func stataddr(nam *Node, n *Node) bool {
   1258 	if n == nil {
   1259 		return false
   1260 	}
   1261 
   1262 	switch n.Op {
   1263 	case ONAME:
   1264 		*nam = *n
   1265 		return n.Addable
   1266 
   1267 	case ODOT:
   1268 		if !stataddr(nam, n.Left) {
   1269 			break
   1270 		}
   1271 		nam.Xoffset += n.Xoffset
   1272 		nam.Type = n.Type
   1273 		return true
   1274 
   1275 	case OINDEX:
   1276 		if n.Left.Type.Bound < 0 {
   1277 			break
   1278 		}
   1279 		if !stataddr(nam, n.Left) {
   1280 			break
   1281 		}
   1282 		l := getlit(n.Right)
   1283 		if l < 0 {
   1284 			break
   1285 		}
   1286 
   1287 		// Check for overflow.
   1288 		if n.Type.Width != 0 && Thearch.MAXWIDTH/n.Type.Width <= int64(l) {
   1289 			break
   1290 		}
   1291 		nam.Xoffset += int64(l) * n.Type.Width
   1292 		nam.Type = n.Type
   1293 		return true
   1294 	}
   1295 
   1296 	return false
   1297 }
   1298 
   1299 func initplan(n *Node) {
   1300 	if initplans[n] != nil {
   1301 		return
   1302 	}
   1303 	p := new(InitPlan)
   1304 	initplans[n] = p
   1305 	switch n.Op {
   1306 	default:
   1307 		Fatal("initplan")
   1308 
   1309 	case OARRAYLIT:
   1310 		var a *Node
   1311 		for l := n.List; l != nil; l = l.Next {
   1312 			a = l.N
   1313 			if a.Op != OKEY || !Smallintconst(a.Left) {
   1314 				Fatal("initplan arraylit")
   1315 			}
   1316 			addvalue(p, n.Type.Type.Width*Mpgetfix(a.Left.Val().U.(*Mpint)), nil, a.Right)
   1317 		}
   1318 
   1319 	case OSTRUCTLIT:
   1320 		var a *Node
   1321 		for l := n.List; l != nil; l = l.Next {
   1322 			a = l.N
   1323 			if a.Op != OKEY || a.Left.Type == nil {
   1324 				Fatal("initplan structlit")
   1325 			}
   1326 			addvalue(p, a.Left.Type.Width, nil, a.Right)
   1327 		}
   1328 
   1329 	case OMAPLIT:
   1330 		var a *Node
   1331 		for l := n.List; l != nil; l = l.Next {
   1332 			a = l.N
   1333 			if a.Op != OKEY {
   1334 				Fatal("initplan maplit")
   1335 			}
   1336 			addvalue(p, -1, a.Left, a.Right)
   1337 		}
   1338 	}
   1339 }
   1340 
   1341 func addvalue(p *InitPlan, xoffset int64, key *Node, n *Node) {
   1342 	// special case: zero can be dropped entirely
   1343 	if iszero(n) {
   1344 		p.Zero += n.Type.Width
   1345 		return
   1346 	}
   1347 
   1348 	// special case: inline struct and array (not slice) literals
   1349 	if isvaluelit(n) {
   1350 		initplan(n)
   1351 		q := initplans[n]
   1352 		var e *InitEntry
   1353 		for i := 0; i < len(q.E); i++ {
   1354 			e = entry(p)
   1355 			*e = q.E[i]
   1356 			e.Xoffset += xoffset
   1357 		}
   1358 
   1359 		return
   1360 	}
   1361 
   1362 	// add to plan
   1363 	if n.Op == OLITERAL {
   1364 		p.Lit += n.Type.Width
   1365 	} else {
   1366 		p.Expr += n.Type.Width
   1367 	}
   1368 
   1369 	e := entry(p)
   1370 	e.Xoffset = xoffset
   1371 	e.Expr = n
   1372 }
   1373 
   1374 func iszero(n *Node) bool {
   1375 	switch n.Op {
   1376 	case OLITERAL:
   1377 		switch n.Val().Ctype() {
   1378 		default:
   1379 			Dump("unexpected literal", n)
   1380 			Fatal("iszero")
   1381 
   1382 		case CTNIL:
   1383 			return true
   1384 
   1385 		case CTSTR:
   1386 			return n.Val().U.(string) == ""
   1387 
   1388 		case CTBOOL:
   1389 			return !n.Val().U.(bool)
   1390 
   1391 		case CTINT, CTRUNE:
   1392 			return mpcmpfixc(n.Val().U.(*Mpint), 0) == 0
   1393 
   1394 		case CTFLT:
   1395 			return mpcmpfltc(n.Val().U.(*Mpflt), 0) == 0
   1396 
   1397 		case CTCPLX:
   1398 			return mpcmpfltc(&n.Val().U.(*Mpcplx).Real, 0) == 0 && mpcmpfltc(&n.Val().U.(*Mpcplx).Imag, 0) == 0
   1399 		}
   1400 
   1401 	case OARRAYLIT:
   1402 		if Isslice(n.Type) {
   1403 			break
   1404 		}
   1405 		fallthrough
   1406 
   1407 		// fall through
   1408 	case OSTRUCTLIT:
   1409 		for l := n.List; l != nil; l = l.Next {
   1410 			if !iszero(l.N.Right) {
   1411 				return false
   1412 			}
   1413 		}
   1414 		return true
   1415 	}
   1416 
   1417 	return false
   1418 }
   1419 
   1420 func isvaluelit(n *Node) bool {
   1421 	return (n.Op == OARRAYLIT && Isfixedarray(n.Type)) || n.Op == OSTRUCTLIT
   1422 }
   1423 
   1424 func entry(p *InitPlan) *InitEntry {
   1425 	p.E = append(p.E, InitEntry{})
   1426 	return &p.E[len(p.E)-1]
   1427 }
   1428 
   1429 func gen_as_init(n *Node) bool {
   1430 	var nr *Node
   1431 	var nl *Node
   1432 	var nam Node
   1433 
   1434 	if n.Dodata == 0 {
   1435 		goto no
   1436 	}
   1437 
   1438 	nr = n.Right
   1439 	nl = n.Left
   1440 	if nr == nil {
   1441 		var nam Node
   1442 		if !stataddr(&nam, nl) {
   1443 			goto no
   1444 		}
   1445 		if nam.Class != PEXTERN {
   1446 			goto no
   1447 		}
   1448 		return true
   1449 	}
   1450 
   1451 	if nr.Type == nil || !Eqtype(nl.Type, nr.Type) {
   1452 		goto no
   1453 	}
   1454 
   1455 	if !stataddr(&nam, nl) {
   1456 		goto no
   1457 	}
   1458 
   1459 	if nam.Class != PEXTERN {
   1460 		goto no
   1461 	}
   1462 
   1463 	switch nr.Op {
   1464 	default:
   1465 		goto no
   1466 
   1467 	case OCONVNOP:
   1468 		nr = nr.Left
   1469 		if nr == nil || nr.Op != OSLICEARR {
   1470 			goto no
   1471 		}
   1472 		fallthrough
   1473 
   1474 		// fall through
   1475 	case OSLICEARR:
   1476 		if nr.Right.Op == OKEY && nr.Right.Left == nil && nr.Right.Right == nil {
   1477 			nr = nr.Left
   1478 			gused(nil) // in case the data is the dest of a goto
   1479 			nl := nr
   1480 			if nr == nil || nr.Op != OADDR {
   1481 				goto no
   1482 			}
   1483 			nr = nr.Left
   1484 			if nr == nil || nr.Op != ONAME {
   1485 				goto no
   1486 			}
   1487 
   1488 			// nr is the array being converted to a slice
   1489 			if nr.Type == nil || nr.Type.Etype != TARRAY || nr.Type.Bound < 0 {
   1490 				goto no
   1491 			}
   1492 
   1493 			nam.Xoffset += int64(Array_array)
   1494 			gdata(&nam, nl, int(Types[Tptr].Width))
   1495 
   1496 			nam.Xoffset += int64(Array_nel) - int64(Array_array)
   1497 			var nod1 Node
   1498 			Nodconst(&nod1, Types[TINT], nr.Type.Bound)
   1499 			gdata(&nam, &nod1, Widthint)
   1500 
   1501 			nam.Xoffset += int64(Array_cap) - int64(Array_nel)
   1502 			gdata(&nam, &nod1, Widthint)
   1503 
   1504 			return true
   1505 		}
   1506 
   1507 		goto no
   1508 
   1509 	case OLITERAL:
   1510 		break
   1511 	}
   1512 
   1513 	switch nr.Type.Etype {
   1514 	default:
   1515 		goto no
   1516 
   1517 	case TBOOL,
   1518 		TINT8,
   1519 		TUINT8,
   1520 		TINT16,
   1521 		TUINT16,
   1522 		TINT32,
   1523 		TUINT32,
   1524 		TINT64,
   1525 		TUINT64,
   1526 		TINT,
   1527 		TUINT,
   1528 		TUINTPTR,
   1529 		TPTR32,
   1530 		TPTR64,
   1531 		TFLOAT32,
   1532 		TFLOAT64:
   1533 		gdata(&nam, nr, int(nr.Type.Width))
   1534 
   1535 	case TCOMPLEX64, TCOMPLEX128:
   1536 		gdatacomplex(&nam, nr.Val().U.(*Mpcplx))
   1537 
   1538 	case TSTRING:
   1539 		gdatastring(&nam, nr.Val().U.(string))
   1540 	}
   1541 
   1542 	return true
   1543 
   1544 no:
   1545 	if n.Dodata == 2 {
   1546 		Dump("\ngen_as_init", n)
   1547 		Fatal("gen_as_init couldnt make data statement")
   1548 	}
   1549 
   1550 	return false
   1551 }
   1552