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:
parent
b046786528
commit
b7ac426ee3
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user