]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: eliminate switch case kinds
authorJosh Bleecher Snyder <josharian@gmail.com>
Wed, 1 Jun 2016 22:21:56 +0000 (15:21 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 23 Aug 2016 05:26:57 +0000 (05:26 +0000)
We used to have separate kinds for the default
case and the nil type case. Now that those are
gone, we can use a simple bool instead.

Change-Id: I65488e945df68178e893cddd2e091ebb6e32ef4d
Reviewed-on: https://go-review.googlesource.com/26763
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/swt.go
src/cmd/compile/internal/gc/swt_test.go

index 3662758bd4cba2caf2f4b2ebe21ba1e324656354..cf26475f7cfe3a8138bba6a81bc324e91a87593d 100644 (file)
@@ -16,16 +16,6 @@ const (
        switchKindType // switch a.(type) {...}
 )
 
-const (
-       // expression switch
-       caseKindExprConst = iota // case 5:
-       caseKindExprVar          // case x:
-
-       // type switch
-       caseKindTypeConst // case time.Time: (concrete type, has type hash)
-       caseKindTypeVar   // case io.Reader: (interface type)
-)
-
 const binarySearchMin = 4 // minimum number of cases for binary search
 
 // An exprSwitch walks an expression switch.
@@ -46,7 +36,11 @@ type caseClause struct {
        node    *Node  // points at case statement
        ordinal int    // position in switch
        hash    uint32 // hash of a type switch
-       typ     uint8  // type of case
+       // isconst indicates whether this case clause is a constant,
+       // for the purposes of the switch code generation.
+       // For expression switches, that's generally literals (case 5:, not case x:).
+       // For type switches, that's concrete types (case time.Time:), not interfaces (case io.Reader:).
+       isconst bool
 }
 
 // caseClauses are all the case clauses in a switch statement.
@@ -260,7 +254,7 @@ func (s *exprSwitch) walk(sw *Node) {
        // handle the cases in order
        for len(cc) > 0 {
                // deal with expressions one at a time
-               if !okforcmp[t.Etype] || cc[0].typ != caseKindExprConst {
+               if !okforcmp[t.Etype] || !cc[0].isconst {
                        a := s.walkCases(cc[:1])
                        cas = append(cas, a)
                        cc = cc[1:]
@@ -269,7 +263,7 @@ func (s *exprSwitch) walk(sw *Node) {
 
                // do binary search on runs of constants
                var run int
-               for run = 1; run < len(cc) && cc[run].typ == caseKindExprConst; run++ {
+               for run = 1; run < len(cc) && cc[run].isconst; run++ {
                }
 
                // sort and compile constants
@@ -448,20 +442,13 @@ func genCaseClauses(sw *Node, kind int) caseClauses {
                c := caseClause{node: n, ordinal: len(cc.list)}
                if kind == switchKindType {
                        // type switch
-                       switch {
-                       case n.Left.Type.IsInterface():
-                               c.typ = caseKindTypeVar
-                       default:
-                               c.typ = caseKindTypeConst
-                       }
+                       c.isconst = !n.Left.Type.IsInterface()
                        c.hash = typehash(n.Left.Type)
                } else {
                        // expression switch
                        switch consttype(n.Left) {
                        case CTFLT, CTINT, CTRUNE, CTSTR:
-                               c.typ = caseKindExprConst
-                       default:
-                               c.typ = caseKindExprVar
+                               c.isconst = true
                        }
                }
                cc.list = append(cc.list, c)
@@ -619,18 +606,12 @@ func (s *typeSwitch) walk(sw *Node) {
 
        // insert type equality check into each case block
        for _, c := range cc {
-               n := c.node
-               switch c.typ {
-               case caseKindTypeVar, caseKindTypeConst:
-                       n.Right = s.typeone(n)
-               default:
-                       Fatalf("typeSwitch with bad kind: %d", c.typ)
-               }
+               c.node.Right = s.typeone(c.node)
        }
 
        // generate list of if statements, binary search for constant sequences
        for len(cc) > 0 {
-               if cc[0].typ != caseKindTypeConst {
+               if !cc[0].isconst {
                        n := cc[0].node
                        cas = append(cas, n.Right)
                        cc = cc[1:]
@@ -639,7 +620,7 @@ func (s *typeSwitch) walk(sw *Node) {
 
                // identify run of constants
                var run int
-               for run = 1; run < len(cc) && cc[run].typ == caseKindTypeConst; run++ {
+               for run = 1; run < len(cc) && cc[run].isconst; run++ {
                }
 
                // sort by hash
@@ -716,7 +697,7 @@ func (s *typeSwitch) walkCases(cc []caseClause) *Node {
                var cas []*Node
                for _, c := range cc {
                        n := c.node
-                       if c.typ != caseKindTypeConst {
+                       if !c.isconst {
                                Fatalf("typeSwitch walkCases")
                        }
                        a := Nod(OIF, nil, nil)
@@ -754,10 +735,10 @@ func (x caseClauseByExpr) Less(i, j int) bool {
 
 func exprcmp(c1, c2 caseClause) int {
        // sort non-constants last
-       if c1.typ != caseKindExprConst {
+       if !c1.isconst {
                return +1
        }
-       if c2.typ != caseKindExprConst {
+       if !c2.isconst {
                return -1
        }
 
index 4e5dbcae505181f9525294ba9ea1878ad96c369d..332433d31db38943aebcaacd0fb5866ff5ecbd83 100644 (file)
@@ -16,120 +16,120 @@ func TestExprcmp(t *testing.T) {
        }{
                // Non-constants.
                {
-                       caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprVar},
-                       caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nil, nil)},
+                       caseClause{node: Nod(OXXX, nil, nil), isconst: true},
                        +1,
                },
                {
-                       caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprVar},
+                       caseClause{node: Nod(OXXX, nil, nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nil, nil)},
                        -1,
                },
                // Type switches
                {
-                       caseClause{node: Nod(OXXX, Nodintconst(0), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, Nodbool(true), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, Nodintconst(0), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, Nodbool(true), nil), isconst: true},
                        -1,
                },
                {
-                       caseClause{node: Nod(OXXX, Nodbool(true), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, Nodbool(true), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, Nodintconst(1), nil), isconst: true},
                        +1,
                },
                {
-                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 1}}, nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 0}}, nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 1}}, nil), isconst: true},
+                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 0}}, nil), isconst: true},
                        +1,
                },
                {
-                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 1}}, nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 1}}, nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 1}}, nil), isconst: true},
+                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 1}}, nil), isconst: true},
                        -1,
                },
                {
-                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 0}}, nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 1}}, nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 0}}, nil), isconst: true},
+                       caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 1}}, nil), isconst: true},
                        -1,
                },
                // Constant values.
                // CTFLT
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.2)}}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.2)}}), nil), isconst: true},
                        -1,
                },
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), isconst: true},
                        0,
                },
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.2)}}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.2)}}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), isconst: true},
                        +1,
                },
                // CTINT
                {
-                       caseClause{node: Nod(OXXX, Nodintconst(0), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, Nodintconst(0), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, Nodintconst(1), nil), isconst: true},
                        -1,
                },
                {
-                       caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, Nodintconst(1), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, Nodintconst(1), nil), isconst: true},
                        0,
                },
                {
-                       caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, Nodintconst(0), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, Nodintconst(1), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, Nodintconst(0), nil), isconst: true},
                        +1,
                },
                // CTRUNE
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('a'), Rune: true}}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('a'), Rune: true}}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), isconst: true},
                        -1,
                },
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), isconst: true},
                        0,
                },
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('a'), Rune: true}}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('a'), Rune: true}}), nil), isconst: true},
                        +1,
                },
                // CTSTR
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{"ab"}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{"ab"}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true},
                        -1,
                },
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{"xyz"}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{"xyz"}), nil), isconst: true},
                        -1,
                },
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true},
                        0,
                },
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{"ab"}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{"ab"}), nil), isconst: true},
                        +1,
                },
                {
-                       caseClause{node: Nod(OXXX, nodlit(Val{"xyz"}), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodlit(Val{"xyz"}), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), isconst: true},
                        +1,
                },
                // Everything else should compare equal.
                {
-                       caseClause{node: Nod(OXXX, nodnil(), nil), typ: caseKindExprConst},
-                       caseClause{node: Nod(OXXX, nodnil(), nil), typ: caseKindExprConst},
+                       caseClause{node: Nod(OXXX, nodnil(), nil), isconst: true},
+                       caseClause{node: Nod(OXXX, nodnil(), nil), isconst: true},
                        0,
                },
        }
@@ -137,8 +137,8 @@ func TestExprcmp(t *testing.T) {
                got := exprcmp(d.a, d.b)
                if d.want != got {
                        t.Errorf("%d: exprcmp(a, b) = %d; want %d", i, got, d.want)
-                       t.Logf("\ta = caseClause{node: %#v, typ: %#v}", d.a.node, d.a.typ)
-                       t.Logf("\tb = caseClause{node: %#v, typ: %#v}", d.b.node, d.b.typ)
+                       t.Logf("\ta = caseClause{node: %#v, isconst: %v}", d.a.node, d.a.isconst)
+                       t.Logf("\tb = caseClause{node: %#v, isconst: %v}", d.b.node, d.b.isconst)
                }
        }
 }