github.com/zxy12/golang151_with_comment@v0.0.0-20190507085033-721809559d3c/cmd/compile/internal/gc/sinit.go (about)

     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  }