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