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.
12 // static initialization
21 initplans map[*Node]*InitPlan
22 inittemps = make(map[*Node]*Node)
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) {
33 for l := n.List; l != nil; l = l.Next {
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)
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.
57 if n.Initorder == InitDone {
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.
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.
74 for i := len(initlist) - 1; i >= 0; i-- {
84 // The loop involves only functions, ok.
88 // reached a new unvisited node.
89 n.Initorder = InitPending
90 initlist = append(initlist, n)
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 {
98 Fatalf("init1: bad defn")
101 init2list(defn.Nbody, out)
106 Fatalf("init1: bad defn")
108 if isblank(defn.Left) && candiscard(defn.Right) {
115 init2(defn.Right, out)
117 fmt.Printf("%v\n", n.Sym)
119 if isblank(n) || !staticinit(n, out) {
121 Dump("nonstatic", defn)
123 *out = list(*out, defn)
126 case OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV:
127 if defn.Initorder == InitDone {
130 defn.Initorder = InitPending
131 for l := defn.Rlist; l != nil; l = l.Next {
135 Dump("nonstatic", defn)
137 *out = list(*out, defn)
138 defn.Initorder = InitDone
142 last := len(initlist) - 1
143 if initlist[last] != n {
144 Fatalf("bad initlist %v", initlist)
146 initlist[last] = nil // allow GC
147 initlist = initlist[:last]
149 n.Initorder = InitDone
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
164 // Find the index of node and visited in the initlist.
165 var nodeindex, visitedindex int
166 for ; initlist[nodeindex] != node; nodeindex++ {
168 for ; initlist[visitedindex] != visited; visitedindex++ {
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())
175 // Print visited -> ... -> n1 -> node.
176 for _, n := range initlist[visitedindex:] {
177 fmt.Printf("\t%v %v refers to\n", n.Line(), n.Sym)
180 // Print node -> ... -> visited.
181 for _, n := range initlist[nodeindex:visitedindex] {
182 fmt.Printf("\t%v %v refers to\n", n.Line(), n.Sym)
185 fmt.Printf("\t%v %v\n", visited.Line(), visited.Sym)
189 // recurse over n, doing init1 everywhere.
190 func init2(n *Node, out **NodeList) {
191 if n == nil || n.Initorder == InitDone {
195 if n.Op == ONAME && n.Ninit != nil {
196 Fatalf("name %v with ninit: %v\n", n.Sym, Nconv(n, obj.FmtSign))
202 init2list(n.Ninit, out)
203 init2list(n.List, out)
204 init2list(n.Rlist, out)
205 init2list(n.Nbody, out)
207 if n.Op == OCLOSURE {
208 init2list(n.Func.Closure.Nbody, out)
210 if n.Op == ODOTMETH || n.Op == OCALLPART {
211 init2(n.Type.Nname, out)
215 func init2list(l *NodeList, out **NodeList) {
216 for ; l != nil; l = l.Next {
221 func initreorder(l *NodeList, out **NodeList) {
224 for ; l != nil; l = l.Next {
227 case ODCLFUNC, ODCLCONST, ODCLTYPE:
231 initreorder(n.Ninit, out)
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 {
242 initplans = make(map[*Node]*InitPlan)
244 initreorder(l, &lout)
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 {
258 l := n.Name.Defn.Left
259 r := n.Name.Defn.Right
260 return staticassign(l, r, out)
263 // like staticassign but we are copying an already
264 // initialized value r.
265 func staticcopy(l *Node, r *Node, out **NodeList) bool {
269 if r.Class == PFUNC {
270 gdata(l, r, Widthptr)
273 if r.Class != PEXTERN || r.Sym.Pkg != localpkg {
276 if r.Name.Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value
279 if r.Name.Defn.Op != OAS {
283 r = r.Name.Defn.Right
285 for r.Op == OCONVNOP {
291 if staticcopy(l, r, out) {
294 *out = list(*out, Nod(OAS, l, r))
301 gdata(l, r, int(l.Type.Width))
307 gdata(l, r, int(l.Type.Width))
313 //dump("not static addr", r);
318 case OARRAYLIT, OSTRUCTLIT, OMAPLIT:
319 gdata(l, Nod(OADDR, inittemps[r], nil), int(l.Type.Width))
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)
347 n.Xoffset = l.Xoffset + e.Xoffset
349 if e.Expr.Op == OLITERAL {
350 gdata(&n, e.Expr, int(n.Type.Width))
352 ll := Nod(OXXX, nil, nil)
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)
361 rr.Orig = rr // completely separate copy
363 rr.Xoffset += e.Xoffset
365 *out = list(*out, Nod(OAS, ll, rr))
376 func staticassign(l *Node, r *Node, out **NodeList) bool {
377 for r.Op == OCONVNOP {
383 return staticcopy(l, r, out)
389 gdata(l, r, int(l.Type.Width))
394 if stataddr(&nam, r.Left) {
397 gdata(l, &n, int(l.Type.Width))
404 case OARRAYLIT, OMAPLIT, OSTRUCTLIT:
406 a := staticname(r.Left.Type, 1)
409 gdata(l, Nod(OADDR, a, nil), int(l.Type.Width))
411 // Init underlying literal.
412 if !staticassign(a, r.Left, out) {
413 *out = list(*out, Nod(OAS, a, r.Left))
417 //dump("not static ptrlit", r);
420 if l.Class == PEXTERN && r.Left.Op == OLITERAL {
421 sval := r.Left.Val().U.(string)
422 slicebytes(l, sval, len(sval))
432 ta.Type = r.Type.Type
433 ta.Bound = Mpgetfix(r.Right.Val().U.(*Mpint))
434 a := staticname(ta, 1)
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)
444 // Fall through to init underlying array.
456 n.Xoffset = l.Xoffset + e.Xoffset
458 if e.Expr.Op == OLITERAL {
459 gdata(&n, e.Expr, int(n.Type.Width))
462 a := Nod(OXXX, nil, nil)
464 a.Orig = a // completely separate copy
465 if !staticassign(a, e.Expr, out) {
466 *out = list(*out, Nod(OAS, a, e.Expr))
474 // TODO: Table-driven map insert.
478 if len(r.Func.Cvars.Slice()) == 0 {
479 // Closures with no captured variables are globals,
480 // so the assignment can be done at link time.
482 gdata(&n, r.Func.Closure.Func.Nname, Widthptr)
487 //dump("not static", r);
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))
500 n.Name.Readonly = true
502 addvar(n, t, PEXTERN)
506 func isliteral(n *Node) bool {
507 if n.Op == OLITERAL {
508 if n.Val().Ctype() != CTNIL {
515 func simplename(n *Node) bool {
522 if n.Class&PHEAP != 0 {
525 if n.Class == PPARAMREF {
531 func litas(l *Node, r *Node, init **NodeList) {
535 *init = list(*init, a)
543 func getdyn(n *Node, top int) int {
553 if top == 0 && n.Type.Bound < 0 {
562 for nl := n.List; nl != nil; nl = nl.Next {
564 mode |= getdyn(value, 0)
565 if mode == MODEDYNAM|MODECONST {
573 func structlit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
574 for nl := n.List; nl != nil; nl = nl.Next {
577 Fatalf("structlit: rhs not OKEY: %v", r)
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 {
599 a = Nod(ODOT, var_, newname(index.Sym))
600 arraylit(ctxt, pass, value, a, init)
604 a = Nod(ODOT, var_, newname(index.Sym))
605 structlit(ctxt, pass, value, a, init)
609 if isliteral(value) {
613 } else if pass == 1 {
617 // build list of var.field = expr
619 a = Nod(ODOT, var_, newname(index.Sym))
621 a = Nod(OAS, a, value)
624 walkexpr(&a, init) // add any assignments in r to top
626 Fatalf("structlit: not as")
634 *init = list(*init, a)
638 func arraylit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
639 for l := n.List; l != nil; l = l.Next {
642 Fatalf("arraylit: rhs not OKEY: %v", r)
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 {
664 a = Nod(OINDEX, var_, index)
665 arraylit(ctxt, pass, value, a, init)
669 a = Nod(OINDEX, var_, index)
670 structlit(ctxt, pass, value, a, init)
674 if isliteral(index) && isliteral(value) {
678 } else if pass == 1 {
682 // build list of var[index] = value
684 a = Nod(OINDEX, var_, index)
686 a = Nod(OAS, a, value)
691 Fatalf("arraylit: not as")
699 *init = list(*init, a)
703 func slicelit(ctxt int, n *Node, var_ *Node, init **NodeList) {
704 // make an array type
707 t.Bound = Mpgetfix(n.Right.Val().U.(*Mpint))
714 // put everything into static array
715 vstat := staticname(t, ctxt)
717 arraylit(ctxt, 1, n, vstat, init)
718 arraylit(ctxt, 2, n, vstat, init)
720 // copy static to slice
721 a := Nod(OSLICE, vstat, Nod(OKEY, nil, nil))
723 a = Nod(OAS, var_, a)
726 *init = list(*init, a)
730 // recipe for var = []t{...}
731 // 1. make a static array
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
739 // 5. assign slice of allocated heap to var
741 // 6. for each dynamic part assign to the slice
742 // var[i] = dynamic part
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
749 // if the literal contains constants,
750 // make static initialized array (1),(2)
754 if mode&MODECONST != 0 {
755 vstat = staticname(t, ctxt)
756 arraylit(ctxt, 1, n, vstat, init)
759 // make new auto *array (3 declare)
760 vauto := temp(Ptrto(t))
762 // set auto to point at new temp or heap (3 assign)
764 if x := prealloc[n]; x != nil {
765 // temp allocated during order.go for dddarg
771 *init = list(*init, a) // zero new temp
774 a = Nod(OADDR, x, nil)
775 } else if n.Esc == EscNone {
778 a = Nod(OAS, temp(t), nil)
780 *init = list(*init, a) // zero new temp
784 a = Nod(OADDR, a, nil)
786 a = Nod(ONEW, nil, nil)
787 a.List = list1(typenod(t))
790 a = Nod(OAS, vauto, a)
793 *init = list(*init, a)
796 // copy static to heap (4)
797 a = Nod(OIND, vauto, nil)
799 a = Nod(OAS, a, vstat)
802 *init = list(*init, a)
805 // make slice out of heap (5)
806 a = Nod(OAS, var_, Nod(OSLICE, vauto, Nod(OKEY, nil, nil)))
811 *init = list(*init, a)
813 // put dynamics into slice (6)
814 for l := n.List; l != nil; l = l.Next {
817 Fatalf("slicelit: rhs not OKEY: %v", r)
821 a := Nod(OINDEX, var_, index)
824 // TODO need to check bounds?
828 if value.Type.Bound < 0 {
831 arraylit(ctxt, 2, value, a, init)
835 structlit(ctxt, 2, value, a, init)
839 if isliteral(index) && isliteral(value) {
843 // build list of var[c] = expr
845 a = Nod(OAS, a, value)
850 *init = list(*init, a)
854 func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
860 a := Nod(OMAKE, nil, nil)
861 a.List = list1(typenod(n.Type))
864 // count the initializers
867 for l := n.List; l != nil; l = l.Next {
870 Fatalf("maplit: rhs not OKEY: %v", r)
875 if isliteral(index) && isliteral(value) {
881 // build type [count]struct { a Tindex, b Tvalue }
910 // make and initialize static array
911 vstat := staticname(t, ctxt)
914 for l := n.List; l != nil; l = l.Next {
918 Fatalf("maplit: rhs not OKEY: %v", r)
923 if isliteral(index) && isliteral(value) {
924 // build vstat[b].a = key;
928 a = Nod(OINDEX, vstat, a)
929 a = Nod(ODOT, a, newname(syma))
930 a = Nod(OAS, a, index)
934 *init = list(*init, a)
936 // build vstat[b].b = value;
940 a = Nod(OINDEX, vstat, a)
941 a = Nod(ODOT, a, newname(symb))
942 a = Nod(OAS, a, value)
946 *init = list(*init, a)
952 // loop adding structure elements to map
953 // for i = 0; i < len(vstat); i++ {
954 // map[vstat[i].a] = vstat[i].b
956 index := temp(Types[TINT])
958 a = Nod(OINDEX, vstat, index)
960 a = Nod(ODOT, a, newname(symb))
962 r := Nod(OINDEX, vstat, index)
964 r = Nod(ODOT, r, newname(syma))
965 r = Nod(OINDEX, var_, r)
969 a = Nod(OFOR, nil, nil)
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)))
978 *init = list(*init, a)
981 // put in dynamic entries one-at-a-time
985 for l := n.List; l != nil; l = l.Next {
989 Fatalf("maplit: rhs not OKEY: %v", r)
994 if isliteral(index) && isliteral(value) {
998 // build list of var[c] = expr.
999 // use temporary so that mapassign1 can have addressable key, val.
1001 key = temp(var_.Type.Down)
1002 val = temp(var_.Type.Type)
1006 a = Nod(OAS, key, r.Left)
1009 *init = list(*init, a)
1011 a = Nod(OAS, val, r.Right)
1014 *init = list(*init, a)
1017 a = Nod(OAS, Nod(OINDEX, var_, key), val)
1020 *init = list(*init, a)
1022 if nerr != nerrors {
1028 a = Nod(OVARKILL, key, nil)
1030 *init = list(*init, a)
1031 a = Nod(OVARKILL, val, nil)
1033 *init = list(*init, a)
1037 func anylit(ctxt int, n *Node, var_ *Node, init **NodeList) {
1041 Fatalf("anylit: not lit")
1044 if !Isptr[t.Etype] {
1045 Fatalf("anylit: not ptr")
1050 r = Nod(OADDR, n.Right, nil)
1053 r = Nod(ONEW, nil, nil)
1060 a := Nod(OAS, var_, r)
1063 *init = list(*init, a)
1065 var_ = Nod(OIND, var_, nil)
1066 typecheck(&var_, Erv|Easgn)
1067 anylit(ctxt, n.Left, var_, init)
1070 if t.Etype != TSTRUCT {
1071 Fatalf("anylit: not struct")
1074 if simplename(var_) && count(n.List) > 4 {
1076 // lay out static data
1077 vstat := staticname(t, ctxt)
1079 structlit(ctxt, 1, n, vstat, init)
1081 // copy static to var
1082 a := Nod(OAS, var_, vstat)
1086 *init = list(*init, a)
1088 // add expressions to automatic
1089 structlit(ctxt, 2, n, var_, init)
1094 structlit(ctxt, 1, n, var_, init)
1095 structlit(ctxt, 2, n, var_, init)
1099 // initialize of not completely specified
1100 if simplename(var_) || count(n.List) < structcount(t) {
1101 a := Nod(OAS, var_, nil)
1104 *init = list(*init, a)
1107 structlit(ctxt, 3, n, var_, init)
1110 if t.Etype != TARRAY {
1111 Fatalf("anylit: not array")
1114 slicelit(ctxt, n, var_, init)
1118 if simplename(var_) && count(n.List) > 4 {
1120 // lay out static data
1121 vstat := staticname(t, ctxt)
1123 arraylit(1, 1, n, vstat, init)
1125 // copy static to automatic
1126 a := Nod(OAS, var_, vstat)
1130 *init = list(*init, a)
1132 // add expressions to automatic
1133 arraylit(ctxt, 2, n, var_, init)
1138 arraylit(ctxt, 1, n, var_, init)
1139 arraylit(ctxt, 2, n, var_, init)
1143 // initialize of not completely specified
1144 if simplename(var_) || int64(count(n.List)) < t.Bound {
1145 a := Nod(OAS, var_, nil)
1148 *init = list(*init, a)
1151 arraylit(ctxt, 3, n, var_, init)
1154 if t.Etype != TMAP {
1155 Fatalf("anylit: not map")
1157 maplit(ctxt, n, var_, init)
1161 func oaslit(n *Node, init **NodeList) bool {
1162 if n.Left == nil || n.Right == nil {
1163 // not a special composit literal assignment
1166 if n.Left.Type == nil || n.Right.Type == nil {
1167 // not a special composit literal assignment
1170 if !simplename(n.Left) {
1171 // not a special composit literal assignment
1174 if !Eqtype(n.Left.Type, n.Right.Type) {
1175 // not a special composit literal assignment
1179 // context is init() function.
1180 // implies generated data executed
1181 // exactly once and not subject to races.
1184 // if(n->dodata == 1)
1189 // not a special composit literal assignment
1192 case OSTRUCTLIT, OARRAYLIT, OMAPLIT:
1193 if vmatch1(n.Left, n.Right) {
1194 // not a special composit literal assignment
1197 anylit(ctxt, n.Right, n.Left, init)
1205 func getlit(lit *Node) int {
1206 if Smallintconst(lit) {
1207 return int(Mpgetfix(lit.Val().U.(*Mpint)))
1212 // stataddr sets nam to the static address of n and reports whether it succeeeded.
1213 func stataddr(nam *Node, n *Node) bool {
1224 if !stataddr(nam, n.Left) {
1227 nam.Xoffset += n.Xoffset
1232 if n.Left.Type.Bound < 0 {
1235 if !stataddr(nam, n.Left) {
1238 l := getlit(n.Right)
1243 // Check for overflow.
1244 if n.Type.Width != 0 && Thearch.MAXWIDTH/n.Type.Width <= int64(l) {
1247 nam.Xoffset += int64(l) * n.Type.Width
1255 func initplan(n *Node) {
1256 if initplans[n] != nil {
1266 for l := n.List; l != nil; l = l.Next {
1268 if a.Op != OKEY || !Smallintconst(a.Left) {
1269 Fatalf("initplan arraylit")
1271 addvalue(p, n.Type.Type.Width*Mpgetfix(a.Left.Val().U.(*Mpint)), nil, a.Right)
1275 for l := n.List; l != nil; l = l.Next {
1277 if a.Op != OKEY || a.Left.Type == nil {
1278 Fatalf("initplan structlit")
1280 addvalue(p, a.Left.Type.Width, nil, a.Right)
1284 for l := n.List; l != nil; l = l.Next {
1287 Fatalf("initplan maplit")
1289 addvalue(p, -1, a.Left, a.Right)
1294 func addvalue(p *InitPlan, xoffset int64, key *Node, n *Node) {
1295 // special case: zero can be dropped entirely
1297 p.Zero += n.Type.Width
1301 // special case: inline struct and array (not slice) literals
1305 for _, qe := range q.E {
1308 e.Xoffset += xoffset
1314 if n.Op == OLITERAL {
1315 p.Lit += n.Type.Width
1317 p.Expr += n.Type.Width
1325 func iszero(n *Node) bool {
1328 switch n.Val().Ctype() {
1330 Dump("unexpected literal", n)
1337 return n.Val().U.(string) == ""
1340 return !n.Val().U.(bool)
1343 return mpcmpfixc(n.Val().U.(*Mpint), 0) == 0
1346 return mpcmpfltc(n.Val().U.(*Mpflt), 0) == 0
1349 return mpcmpfltc(&n.Val().U.(*Mpcplx).Real, 0) == 0 && mpcmpfltc(&n.Val().U.(*Mpcplx).Imag, 0) == 0
1353 if Isslice(n.Type) {
1360 for l := n.List; l != nil; l = l.Next {
1361 if !iszero(l.N.Right) {
1371 func isvaluelit(n *Node) bool {
1372 return (n.Op == OARRAYLIT && Isfixedarray(n.Type)) || n.Op == OSTRUCTLIT
1375 func entry(p *InitPlan) *InitEntry {
1376 p.E = append(p.E, InitEntry{})
1377 return &p.E[len(p.E)-1]
1380 // gen_as_init attempts to emit static data for n and reports whether it succeeded.
1381 // If reportOnly is true, it does not emit static data and does not modify the AST.
1382 func gen_as_init(n *Node, reportOnly bool) bool {
1395 if !stataddr(&nam, nl) {
1398 if nam.Class != PEXTERN {
1404 if nr.Type == nil || !Eqtype(nl.Type, nr.Type) {
1408 if !stataddr(&nam, nl) {
1412 if nam.Class != PEXTERN {
1422 if nr == nil || nr.Op != OSLICEARR {
1429 if nr.Right.Op == OKEY && nr.Right.Left == nil && nr.Right.Right == nil {
1432 if nr == nil || nr.Op != OADDR {
1436 if nr == nil || nr.Op != ONAME {
1440 // nr is the array being converted to a slice
1441 if nr.Type == nil || nr.Type.Etype != TARRAY || nr.Type.Bound < 0 {
1446 nam.Xoffset += int64(Array_array)
1447 gdata(&nam, nl, int(Types[Tptr].Width))
1449 nam.Xoffset += int64(Array_nel) - int64(Array_array)
1451 Nodconst(&nod1, Types[TINT], nr.Type.Bound)
1452 gdata(&nam, &nod1, Widthint)
1454 nam.Xoffset += int64(Array_cap) - int64(Array_nel)
1455 gdata(&nam, &nod1, Widthint)
1467 switch nr.Type.Etype {
1488 gdata(&nam, nr, int(nr.Type.Width))
1491 case TCOMPLEX64, TCOMPLEX128:
1493 gdatacomplex(&nam, nr.Val().U.(*Mpcplx))
1498 gdatastring(&nam, nr.Val().U.(string))
1506 Dump("\ngen_as_init", n)
1507 Fatalf("gen_as_init couldnt make data statement")