1
0
mirror of https://github.com/golang/go synced 2024-11-12 03:10:22 -07:00

cmd/compile: split genCaseClauses by switch type

The implementations are going to start diverging more.
Instead of more if clauses and empty parameters,
specialize.

Change-Id: I44584450592e8c9f72a10d8ada859c07e9d9aa19
Reviewed-on: https://go-review.googlesource.com/26764
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Josh Bleecher Snyder 2016-06-03 12:05:32 -07:00
parent b046786528
commit b7ac426ee3

View File

@ -247,7 +247,7 @@ func (s *exprSwitch) walk(sw *Node) {
} }
// Enumerate the cases and prepare the default case. // Enumerate the cases and prepare the default case.
clauses := genCaseClauses(sw, s.kind) clauses := s.genCaseClauses(sw.List.Slice())
sw.List.Set(nil) sw.List.Set(nil)
cc := clauses.list cc := clauses.list
@ -414,12 +414,10 @@ func casebody(sw *Node, typeswvar *Node) {
lineno = lno lineno = lno
} }
// genCaseClauses generates the caseClauses value // genCaseClauses generates the caseClauses value for clauses.
// corresponding to the clauses in the switch statement sw. func (s *exprSwitch) genCaseClauses(clauses []*Node) caseClauses {
// Kind is the kind of switch statement.
func genCaseClauses(sw *Node, kind int) caseClauses {
var cc caseClauses var cc caseClauses
for _, n := range sw.List.Slice() { for _, n := range clauses {
if n.Left == nil { if n.Left == nil {
// default case // default case
if cc.defjmp != nil { if cc.defjmp != nil {
@ -428,8 +426,36 @@ func genCaseClauses(sw *Node, kind int) caseClauses {
cc.defjmp = n.Right cc.defjmp = n.Right
continue continue
} }
c := caseClause{node: n, ordinal: len(cc.list)}
switch consttype(n.Left) {
case CTFLT, CTINT, CTRUNE, CTSTR:
c.isconst = true
}
cc.list = append(cc.list, c)
}
if kind == switchKindType && n.Left.Op == OLITERAL { if cc.defjmp == nil {
cc.defjmp = Nod(OBREAK, nil, nil)
}
// diagnose duplicate cases
s.checkDupCases(cc.list)
return cc
}
// genCaseClauses generates the caseClauses value for clauses.
func (s *typeSwitch) genCaseClauses(clauses []*Node) caseClauses {
var cc caseClauses
for _, n := range clauses {
switch {
case n.Left == nil:
// default case
if cc.defjmp != nil {
Fatalf("duplicate default case not detected during typechecking")
}
cc.defjmp = n.Right
continue
case n.Left.Op == OLITERAL:
// nil case in type switch // nil case in type switch
if cc.niljmp != nil { if cc.niljmp != nil {
Fatalf("duplicate nil case not detected during typechecking") Fatalf("duplicate nil case not detected during typechecking")
@ -439,17 +465,11 @@ func genCaseClauses(sw *Node, kind int) caseClauses {
} }
// general case // general case
c := caseClause{node: n, ordinal: len(cc.list)} c := caseClause{
if kind == switchKindType { node: n,
// type switch ordinal: len(cc.list),
c.isconst = !n.Left.Type.IsInterface() isconst: !n.Left.Type.IsInterface(),
c.hash = typehash(n.Left.Type) hash: typehash(n.Left.Type),
} else {
// expression switch
switch consttype(n.Left) {
case CTFLT, CTINT, CTRUNE, CTSTR:
c.isconst = true
}
} }
cc.list = append(cc.list, c) cc.list = append(cc.list, c)
} }
@ -458,21 +478,15 @@ func genCaseClauses(sw *Node, kind int) caseClauses {
cc.defjmp = Nod(OBREAK, nil, nil) cc.defjmp = Nod(OBREAK, nil, nil)
} }
if cc.list == nil { // diagnose duplicate cases
return cc s.checkDupCases(cc.list)
}
// sort by value and diagnose duplicate cases
if kind == switchKindType {
checkDupTypeCases(cc.list)
} else {
checkDupExprCases(cc.list)
}
return cc return cc
} }
func checkDupTypeCases(cc []caseClause) { func (s *typeSwitch) checkDupCases(cc []caseClause) {
if len(cc) < 2 {
return
}
// We store seen types in a map keyed by type hash. // We store seen types in a map keyed by type hash.
// It is possible, but very unlikely, for multiple distinct types to have the same hash. // It is possible, but very unlikely, for multiple distinct types to have the same hash.
seen := make(map[uint32][]*Node) seen := make(map[uint32][]*Node)
@ -499,7 +513,10 @@ Outer:
} }
} }
func checkDupExprCases(cc []caseClause) { func (s *exprSwitch) checkDupCases(cc []caseClause) {
if len(cc) < 2 {
return
}
sort.Sort(caseClauseByExpr(cc)) sort.Sort(caseClauseByExpr(cc))
for i, c1 := range cc[:len(cc)-1] { for i, c1 := range cc[:len(cc)-1] {
c2 := cc[i+1] c2 := cc[i+1]
@ -556,7 +573,7 @@ func (s *typeSwitch) walk(sw *Node) {
// set up labels and jumps // set up labels and jumps
casebody(sw, s.facename) casebody(sw, s.facename)
clauses := genCaseClauses(sw, switchKindType) clauses := s.genCaseClauses(sw.List.Slice())
sw.List.Set(nil) sw.List.Set(nil)
def := clauses.defjmp def := clauses.defjmp