From: Josh Bleecher Snyder Date: Sun, 19 Jun 2016 19:11:47 +0000 (-0700) Subject: cmd/compile: unify arraylit and structlit X-Git-Tag: go1.8beta1~1499 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=cd2d5ee0485fd0fa5a102c9de372c70b7a31d154;p=gostls13.git cmd/compile: unify arraylit and structlit They were almost identical. Merge them and some of their calling code. Passes toolstash -cmp. Change-Id: I9e92a864a6c09c9e18ed52dc247a678467e344ba Reviewed-on: https://go-review.googlesource.com/26754 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: David Crawshaw --- diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index 668e311cbf..fa5d951cab 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -579,117 +579,56 @@ func isStaticCompositeLiteral(n *Node) bool { return false } -func structlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) { - for _, r := range n.List.Slice() { - if r.Op != OKEY { - Fatalf("structlit: rhs not OKEY: %v", r) - } - index := r.Left - value := r.Right - - switch value.Op { - case OSLICELIT: - if pass == 1 && ctxt != 0 { - a := NodSym(ODOT, var_, index.Sym) - slicelit(ctxt, value, a, init) - } else if pass == 2 && ctxt == 0 { - a := NodSym(ODOT, var_, index.Sym) - slicelit(ctxt, value, a, init) - } else if pass == 3 { - break - } - continue - - case OARRAYLIT: - a := NodSym(ODOT, var_, index.Sym) - arraylit(ctxt, pass, value, a, init) - continue - - case OSTRUCTLIT: - a := NodSym(ODOT, var_, index.Sym) - structlit(ctxt, pass, value, a, init) - continue - } - - if isliteral(value) { - if pass == 2 { - continue - } - } else if pass == 1 { - continue - } - - // build list of var.field = expr - setlineno(value) - a := NodSym(ODOT, var_, index.Sym) - - a = Nod(OAS, a, value) - a = typecheck(a, Etop) - if pass == 1 { - a = walkexpr(a, init) // add any assignments in r to top - if a.Op != OAS { - Fatalf("structlit: not as") - } - a.IsStatic = true - } else { - a = orderstmtinplace(a) - a = walkstmt(a) - } - - init.Append(a) +// fixedlit handles struct, array, and slice literals. +// TODO: expand documentation. +func fixedlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) { + var indexnode func(*Node) *Node + switch n.Op { + case OARRAYLIT, OSLICELIT: + indexnode = func(index *Node) *Node { return Nod(OINDEX, var_, index) } + case OSTRUCTLIT: + indexnode = func(index *Node) *Node { return NodSym(ODOT, var_, index.Sym) } + default: + Fatalf("fixedlit bad op: %v", n.Op) } -} -func arraylit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) { for _, r := range n.List.Slice() { if r.Op != OKEY { - Fatalf("arraylit: rhs not OKEY: %v", r) + Fatalf("fixedlit: rhs not OKEY: %v", r) } index := r.Left value := r.Right switch value.Op { case OSLICELIT: - if pass == 1 && ctxt != 0 { - a := Nod(OINDEX, var_, index) + if (pass == 1 && ctxt != 0) || (pass == 2 && ctxt == 0) { + a := indexnode(index) slicelit(ctxt, value, a, init) - } else if pass == 2 && ctxt == 0 { - a := Nod(OINDEX, var_, index) - slicelit(ctxt, value, a, init) - } else if pass == 3 { - break + continue } - continue - - case OARRAYLIT: - a := Nod(OINDEX, var_, index) - arraylit(ctxt, pass, value, a, init) - continue - case OSTRUCTLIT: - a := Nod(OINDEX, var_, index) - structlit(ctxt, pass, value, a, init) + case OARRAYLIT, OSTRUCTLIT: + a := indexnode(index) + fixedlit(ctxt, pass, value, a, init) continue } - if isliteral(index) && isliteral(value) { - if pass == 2 { - continue - } - } else if pass == 1 { + islit := isliteral(value) + if n.Op == OARRAYLIT { + islit = islit && isliteral(index) + } + if (pass == 1 && !islit) || (pass == 2 && islit) { continue } - // build list of var[index] = value + // build list of assignments: var[index] = expr setlineno(value) - a := Nod(OINDEX, var_, index) - - a = Nod(OAS, a, value) + a := Nod(OAS, indexnode(index), value) a = typecheck(a, Etop) if pass == 1 { - a = walkexpr(a, init) + a = walkexpr(a, init) // add any assignments in r to top if a.Op != OAS { - Fatalf("arraylit: not as") + Fatalf("fixedlit: not as") } a.IsStatic = true } else { @@ -710,8 +649,8 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { // put everything into static array vstat := staticname(t, ctxt) - arraylit(ctxt, 1, n, vstat, init) - arraylit(ctxt, 2, n, vstat, init) + fixedlit(ctxt, 1, n, vstat, init) + fixedlit(ctxt, 2, n, vstat, init) // copy static to slice a := Nod(OSLICE, vstat, nil) @@ -749,7 +688,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { mode := getdyn(n, true) if mode&initConst != 0 { vstat = staticname(t, ctxt) - arraylit(ctxt, 1, n, vstat, init) + fixedlit(ctxt, 1, n, vstat, init) } // make new auto *array (3 declare) @@ -814,12 +753,8 @@ func slicelit(ctxt int, n *Node, var_ *Node, init *Nodes) { case OSLICELIT: break - case OARRAYLIT: - arraylit(ctxt, 2, value, a, init) - continue - - case OSTRUCTLIT: - structlit(ctxt, 2, value, a, init) + case OARRAYLIT, OSTRUCTLIT: + fixedlit(ctxt, 2, value, a, init) continue } @@ -1025,9 +960,9 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { var_ = typecheck(var_, Erv|Easgn) anylit(ctxt, n.Left, var_, init) - case OSTRUCTLIT: - if !t.IsStruct() { - Fatalf("anylit: not struct") + case OSTRUCTLIT, OARRAYLIT: + if !t.IsStruct() && !t.IsArray() { + Fatalf("anylit: not struct/array") } if var_.isSimpleName() && n.List.Len() > 4 { @@ -1035,7 +970,11 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { // lay out static data vstat := staticname(t, ctxt) - structlit(ctxt, 1, n, vstat, init) + pass1ctxt := ctxt + if n.Op == OARRAYLIT { + pass1ctxt = 1 + } + fixedlit(pass1ctxt, 1, n, vstat, init) // copy static to var a := Nod(OAS, var_, vstat) @@ -1045,65 +984,35 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { init.Append(a) // add expressions to automatic - structlit(ctxt, 2, n, var_, init) + fixedlit(ctxt, 2, n, var_, init) break } - structlit(ctxt, 1, n, var_, init) - structlit(ctxt, 2, n, var_, init) + fixedlit(ctxt, 1, n, var_, init) + fixedlit(ctxt, 2, n, var_, init) break } - // initialize of not completely specified - if var_.isSimpleName() || n.List.Len() < t.NumFields() { + var components int64 + if n.Op == OARRAYLIT { + components = t.NumElem() + } else { + components = int64(t.NumFields()) + } + // initialization of an array or struct with unspecified components (missing fields or arrays) + if var_.isSimpleName() || int64(n.List.Len()) < components { a := Nod(OAS, var_, nil) a = typecheck(a, Etop) a = walkexpr(a, init) init.Append(a) } - structlit(ctxt, 3, n, var_, init) + fixedlit(ctxt, 3, n, var_, init) case OSLICELIT: slicelit(ctxt, n, var_, init) - case OARRAYLIT: - if var_.isSimpleName() && n.List.Len() > 4 { - if ctxt == 0 { - // lay out static data - vstat := staticname(t, ctxt) - - arraylit(1, 1, n, vstat, init) - - // copy static to automatic - a := Nod(OAS, var_, vstat) - - a = typecheck(a, Etop) - a = walkexpr(a, init) - init.Append(a) - - // add expressions to automatic - arraylit(ctxt, 2, n, var_, init) - - break - } - - arraylit(ctxt, 1, n, var_, init) - arraylit(ctxt, 2, n, var_, init) - break - } - - // initialize of not completely specified - if var_.isSimpleName() || int64(n.List.Len()) < t.NumElem() { - a := Nod(OAS, var_, nil) - a = typecheck(a, Etop) - a = walkexpr(a, init) - init.Append(a) - } - - arraylit(ctxt, 3, n, var_, init) - case OMAPLIT: if !t.IsMap() { Fatalf("anylit: not map") @@ -1219,7 +1128,7 @@ func initplan(n *Node) { case OARRAYLIT, OSLICELIT: for _, a := range n.List.Slice() { if a.Op != OKEY || !Smallintconst(a.Left) { - Fatalf("initplan arraylit") + Fatalf("initplan fixedlit") } addvalue(p, n.Type.Elem().Width*a.Left.Int64(), a.Right) } @@ -1227,7 +1136,7 @@ func initplan(n *Node) { case OSTRUCTLIT: for _, a := range n.List.Slice() { if a.Op != OKEY || a.Left.Type != structkey { - Fatalf("initplan structlit") + Fatalf("initplan fixedlit") } addvalue(p, a.Left.Xoffset, a.Right) } diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 5674dbee89..e528dc2b76 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -1637,11 +1637,7 @@ opswitch: // n can be directly represented in the read-only data section. // Make direct reference to the static data. See issue 12841. vstat := staticname(n.Type, 0) - if n.Op == OSTRUCTLIT { - structlit(0, 1, n, vstat, init) - } else { - arraylit(0, 1, n, vstat, init) - } + fixedlit(0, 1, n, vstat, init) n = vstat n = typecheck(n, Erv) break