Commit b0467865 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile: eliminate switch case kinds

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: 's avatarMatthew Dempsky <mdempsky@google.com>
parent 4739dcf7
......@@ -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
}
......
......@@ -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)
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment