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