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