github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/sinit.go (about)

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