1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gc 6 7 import ( 8 "cmd/internal/obj" 9 "fmt" 10 "sort" 11 "strconv" 12 ) 13 14 const ( 15 // expression switch 16 switchKindExpr = iota // switch a {...} or switch 5 {...} 17 switchKindTrue // switch true {...} or switch {...} 18 switchKindFalse // switch false {...} 19 20 // type switch 21 switchKindType // switch a.(type) {...} 22 ) 23 24 const ( 25 caseKindDefault = iota // default: 26 27 // expression switch 28 caseKindExprConst // case 5: 29 caseKindExprVar // case x: 30 31 // type switch 32 caseKindTypeNil // case nil: 33 caseKindTypeConst // case time.Time: (concrete type, has type hash) 34 caseKindTypeVar // case io.Reader: (interface type) 35 ) 36 37 const binarySearchMin = 4 // minimum number of cases for binary search 38 39 // An exprSwitch walks an expression switch. 40 type exprSwitch struct { 41 exprname *Node // node for the expression being switched on 42 kind int // kind of switch statement (switchKind*) 43 } 44 45 // A typeSwitch walks a type switch. 46 type typeSwitch struct { 47 hashname *Node // node for the hash of the type of the variable being switched on 48 facename *Node // node for the concrete type of the variable being switched on 49 okname *Node // boolean node used for comma-ok type assertions 50 } 51 52 // A caseClause is a single case clause in a switch statement. 53 type caseClause struct { 54 node *Node // points at case statement 55 ordinal int // position in switch 56 hash uint32 // hash of a type switch 57 typ uint8 // type of case 58 } 59 60 // typecheckswitch typechecks a switch statement. 61 func typecheckswitch(n *Node) { 62 lno := int(lineno) 63 typechecklist(n.Ninit, Etop) 64 65 var nilonly string 66 var top int 67 var t *Type 68 69 if n.Left != nil && n.Left.Op == OTYPESW { 70 // type switch 71 top = Etype 72 typecheck(&n.Left.Right, Erv) 73 t = n.Left.Right.Type 74 if t != nil && t.Etype != TINTER { 75 Yyerror("cannot type switch on non-interface value %v", Nconv(n.Left.Right, obj.FmtLong)) 76 } 77 } else { 78 // expression switch 79 top = Erv 80 if n.Left != nil { 81 typecheck(&n.Left, Erv) 82 defaultlit(&n.Left, nil) 83 t = n.Left.Type 84 } else { 85 t = Types[TBOOL] 86 } 87 if t != nil { 88 var badtype *Type 89 switch { 90 case !okforeq[t.Etype]: 91 Yyerror("cannot switch on %v", Nconv(n.Left, obj.FmtLong)) 92 case t.Etype == TARRAY && !Isfixedarray(t): 93 nilonly = "slice" 94 case t.Etype == TARRAY && Isfixedarray(t) && algtype1(t, nil) == ANOEQ: 95 Yyerror("cannot switch on %v", Nconv(n.Left, obj.FmtLong)) 96 case t.Etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ: 97 Yyerror("cannot switch on %v (struct containing %v cannot be compared)", Nconv(n.Left, obj.FmtLong), badtype) 98 case t.Etype == TFUNC: 99 nilonly = "func" 100 case t.Etype == TMAP: 101 nilonly = "map" 102 } 103 } 104 } 105 106 n.Type = t 107 108 var def *Node 109 var ll *NodeList 110 for l := n.List; l != nil; l = l.Next { 111 ncase := l.N 112 setlineno(n) 113 if ncase.List == nil { 114 // default 115 if def != nil { 116 Yyerror("multiple defaults in switch (first at %v)", def.Line()) 117 } else { 118 def = ncase 119 } 120 } else { 121 for ll = ncase.List; ll != nil; ll = ll.Next { 122 setlineno(ll.N) 123 typecheck(&ll.N, Erv|Etype) 124 if ll.N.Type == nil || t == nil { 125 continue 126 } 127 setlineno(ncase) 128 switch top { 129 // expression switch 130 case Erv: 131 defaultlit(&ll.N, t) 132 switch { 133 case ll.N.Op == OTYPE: 134 Yyerror("type %v is not an expression", ll.N.Type) 135 case ll.N.Type != nil && assignop(ll.N.Type, t, nil) == 0 && assignop(t, ll.N.Type, nil) == 0: 136 if n.Left != nil { 137 Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ll.N, n.Left, ll.N.Type, t) 138 } else { 139 Yyerror("invalid case %v in switch (mismatched types %v and bool)", ll.N, ll.N.Type) 140 } 141 case nilonly != "" && !Isconst(ll.N, CTNIL): 142 Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ll.N, nilonly, n.Left) 143 } 144 145 // type switch 146 case Etype: 147 var missing, have *Type 148 var ptr int 149 switch { 150 case ll.N.Op == OLITERAL && Istype(ll.N.Type, TNIL): 151 case ll.N.Op != OTYPE && ll.N.Type != nil: // should this be ||? 152 Yyerror("%v is not a type", Nconv(ll.N, obj.FmtLong)) 153 // reset to original type 154 ll.N = n.Left.Right 155 case ll.N.Type.Etype != TINTER && t.Etype == TINTER && !implements(ll.N.Type, t, &missing, &have, &ptr): 156 if have != nil && missing.Broke == 0 && have.Broke == 0 { 157 Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort)) 158 } else if missing.Broke == 0 { 159 Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym) 160 } 161 } 162 } 163 } 164 } 165 166 if top == Etype && n.Type != nil { 167 ll = ncase.List 168 if ncase.Rlist != nil { 169 nvar := ncase.Rlist.N 170 if ll != nil && ll.Next == nil && ll.N.Type != nil && !Istype(ll.N.Type, TNIL) { 171 // single entry type switch 172 nvar.Name.Param.Ntype = typenod(ll.N.Type) 173 } else { 174 // multiple entry type switch or default 175 nvar.Name.Param.Ntype = typenod(n.Type) 176 } 177 178 typecheck(&nvar, Erv|Easgn) 179 ncase.Rlist.N = nvar 180 } 181 } 182 183 typechecklist(ncase.Nbody, Etop) 184 } 185 186 lineno = int32(lno) 187 } 188 189 // walkswitch walks a switch statement. 190 func walkswitch(sw *Node) { 191 // convert switch {...} to switch true {...} 192 if sw.Left == nil { 193 sw.Left = Nodbool(true) 194 typecheck(&sw.Left, Erv) 195 } 196 197 if sw.Left.Op == OTYPESW { 198 var s typeSwitch 199 s.walk(sw) 200 } else { 201 var s exprSwitch 202 s.walk(sw) 203 } 204 } 205 206 // walk generates an AST implementing sw. 207 // sw is an expression switch. 208 // The AST is generally of the form of a linear 209 // search using if..goto, although binary search 210 // is used with long runs of constants. 211 func (s *exprSwitch) walk(sw *Node) { 212 casebody(sw, nil) 213 214 cond := sw.Left 215 sw.Left = nil 216 217 s.kind = switchKindExpr 218 if Isconst(cond, CTBOOL) { 219 s.kind = switchKindTrue 220 if !cond.Val().U.(bool) { 221 s.kind = switchKindFalse 222 } 223 } 224 225 walkexpr(&cond, &sw.Ninit) 226 t := sw.Type 227 if t == nil { 228 return 229 } 230 231 // convert the switch into OIF statements 232 var cas *NodeList 233 if s.kind == switchKindTrue || s.kind == switchKindFalse { 234 s.exprname = Nodbool(s.kind == switchKindTrue) 235 } else if consttype(cond) >= 0 { 236 // leave constants to enable dead code elimination (issue 9608) 237 s.exprname = cond 238 } else { 239 s.exprname = temp(cond.Type) 240 cas = list1(Nod(OAS, s.exprname, cond)) 241 typechecklist(cas, Etop) 242 } 243 244 // enumerate the cases, and lop off the default case 245 cc := caseClauses(sw, s.kind) 246 sw.List = nil 247 var def *Node 248 if len(cc) > 0 && cc[0].typ == caseKindDefault { 249 def = cc[0].node.Right 250 cc = cc[1:] 251 } else { 252 def = Nod(OBREAK, nil, nil) 253 } 254 255 // handle the cases in order 256 for len(cc) > 0 { 257 // deal with expressions one at a time 258 if !okforcmp[t.Etype] || cc[0].typ != caseKindExprConst { 259 a := s.walkCases(cc[:1]) 260 cas = list(cas, a) 261 cc = cc[1:] 262 continue 263 } 264 265 // do binary search on runs of constants 266 var run int 267 for run = 1; run < len(cc) && cc[run].typ == caseKindExprConst; run++ { 268 } 269 270 // sort and compile constants 271 sort.Sort(caseClauseByExpr(cc[:run])) 272 a := s.walkCases(cc[:run]) 273 cas = list(cas, a) 274 cc = cc[run:] 275 } 276 277 // handle default case 278 if nerrors == 0 { 279 cas = list(cas, def) 280 sw.Nbody = concat(cas, sw.Nbody) 281 walkstmtlist(sw.Nbody) 282 } 283 } 284 285 // walkCases generates an AST implementing the cases in cc. 286 func (s *exprSwitch) walkCases(cc []*caseClause) *Node { 287 if len(cc) < binarySearchMin { 288 // linear search 289 var cas *NodeList 290 for _, c := range cc { 291 n := c.node 292 lno := int(setlineno(n)) 293 294 a := Nod(OIF, nil, nil) 295 if (s.kind != switchKindTrue && s.kind != switchKindFalse) || assignop(n.Left.Type, s.exprname.Type, nil) == OCONVIFACE || assignop(s.exprname.Type, n.Left.Type, nil) == OCONVIFACE { 296 a.Left = Nod(OEQ, s.exprname, n.Left) // if name == val 297 typecheck(&a.Left, Erv) 298 } else if s.kind == switchKindTrue { 299 a.Left = n.Left // if val 300 } else { 301 // s.kind == switchKindFalse 302 a.Left = Nod(ONOT, n.Left, nil) // if !val 303 typecheck(&a.Left, Erv) 304 } 305 a.Nbody = list1(n.Right) // goto l 306 307 cas = list(cas, a) 308 lineno = int32(lno) 309 } 310 return liststmt(cas) 311 } 312 313 // find the middle and recur 314 half := len(cc) / 2 315 a := Nod(OIF, nil, nil) 316 mid := cc[half-1].node.Left 317 le := Nod(OLE, s.exprname, mid) 318 if Isconst(mid, CTSTR) { 319 // Search by length and then by value; see exprcmp. 320 lenlt := Nod(OLT, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil)) 321 leneq := Nod(OEQ, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil)) 322 a.Left = Nod(OOROR, lenlt, Nod(OANDAND, leneq, le)) 323 } else { 324 a.Left = le 325 } 326 typecheck(&a.Left, Erv) 327 a.Nbody = list1(s.walkCases(cc[:half])) 328 a.Rlist = list1(s.walkCases(cc[half:])) 329 return a 330 } 331 332 // casebody builds separate lists of statements and cases. 333 // It makes labels between cases and statements 334 // and deals with fallthrough, break, and unreachable statements. 335 func casebody(sw *Node, typeswvar *Node) { 336 if sw.List == nil { 337 return 338 } 339 340 lno := setlineno(sw) 341 342 var cas *NodeList // cases 343 var stat *NodeList // statements 344 var def *Node // defaults 345 br := Nod(OBREAK, nil, nil) 346 347 for l := sw.List; l != nil; l = l.Next { 348 n := l.N 349 setlineno(n) 350 if n.Op != OXCASE { 351 Fatal("casebody %v", Oconv(int(n.Op), 0)) 352 } 353 n.Op = OCASE 354 needvar := count(n.List) != 1 || n.List.N.Op == OLITERAL 355 356 jmp := Nod(OGOTO, newCaseLabel(), nil) 357 if n.List == nil { 358 if def != nil { 359 Yyerror("more than one default case") 360 } 361 // reuse original default case 362 n.Right = jmp 363 def = n 364 } 365 366 if n.List != nil && n.List.Next == nil { 367 // one case -- reuse OCASE node 368 n.Left = n.List.N 369 n.Right = jmp 370 n.List = nil 371 cas = list(cas, n) 372 } else { 373 // expand multi-valued cases 374 for lc := n.List; lc != nil; lc = lc.Next { 375 cas = list(cas, Nod(OCASE, lc.N, jmp)) 376 } 377 } 378 379 stat = list(stat, Nod(OLABEL, jmp.Left, nil)) 380 if typeswvar != nil && needvar && n.Rlist != nil { 381 l := list1(Nod(ODCL, n.Rlist.N, nil)) 382 l = list(l, Nod(OAS, n.Rlist.N, typeswvar)) 383 typechecklist(l, Etop) 384 stat = concat(stat, l) 385 } 386 stat = concat(stat, n.Nbody) 387 388 // botch - shouldn't fall thru declaration 389 last := stat.End.N 390 if last.Xoffset == n.Xoffset && last.Op == OXFALL { 391 if typeswvar != nil { 392 setlineno(last) 393 Yyerror("cannot fallthrough in type switch") 394 } 395 396 if l.Next == nil { 397 setlineno(last) 398 Yyerror("cannot fallthrough final case in switch") 399 } 400 401 last.Op = OFALL 402 } else { 403 stat = list(stat, br) 404 } 405 } 406 407 stat = list(stat, br) 408 if def != nil { 409 cas = list(cas, def) 410 } 411 412 sw.List = cas 413 sw.Nbody = stat 414 lineno = lno 415 } 416 417 // nSwitchLabel is the number of switch labels generated. 418 // This should be per-function, but it is a global counter for now. 419 var nSwitchLabel int 420 421 func newCaseLabel() *Node { 422 label := strconv.Itoa(nSwitchLabel) 423 nSwitchLabel++ 424 return newname(Lookup(label)) 425 } 426 427 // caseClauses generates a slice of caseClauses 428 // corresponding to the clauses in the switch statement sw. 429 // Kind is the kind of switch statement. 430 func caseClauses(sw *Node, kind int) []*caseClause { 431 var cc []*caseClause 432 for l := sw.List; l != nil; l = l.Next { 433 n := l.N 434 c := new(caseClause) 435 cc = append(cc, c) 436 c.ordinal = len(cc) 437 c.node = n 438 439 if n.Left == nil { 440 c.typ = caseKindDefault 441 continue 442 } 443 444 if kind == switchKindType { 445 // type switch 446 switch { 447 case n.Left.Op == OLITERAL: 448 c.typ = caseKindTypeNil 449 case Istype(n.Left.Type, TINTER): 450 c.typ = caseKindTypeVar 451 default: 452 c.typ = caseKindTypeConst 453 c.hash = typehash(n.Left.Type) 454 } 455 } else { 456 // expression switch 457 switch consttype(n.Left) { 458 case CTFLT, CTINT, CTRUNE, CTSTR: 459 c.typ = caseKindExprConst 460 default: 461 c.typ = caseKindExprVar 462 } 463 } 464 } 465 466 if cc == nil { 467 return nil 468 } 469 470 // sort by value and diagnose duplicate cases 471 if kind == switchKindType { 472 // type switch 473 sort.Sort(caseClauseByType(cc)) 474 for i, c1 := range cc { 475 if c1.typ == caseKindTypeNil || c1.typ == caseKindDefault { 476 break 477 } 478 for _, c2 := range cc[i+1:] { 479 if c2.typ == caseKindTypeNil || c2.typ == caseKindDefault || c1.hash != c2.hash { 480 break 481 } 482 if Eqtype(c1.node.Left.Type, c2.node.Left.Type) { 483 yyerrorl(int(c2.node.Lineno), "duplicate case %v in type switch\n\tprevious case at %v", c2.node.Left.Type, c1.node.Line()) 484 } 485 } 486 } 487 } else { 488 // expression switch 489 sort.Sort(caseClauseByExpr(cc)) 490 for i, c1 := range cc { 491 if i+1 == len(cc) { 492 break 493 } 494 c2 := cc[i+1] 495 if exprcmp(c1, c2) != 0 { 496 continue 497 } 498 setlineno(c2.node) 499 Yyerror("duplicate case %v in switch\n\tprevious case at %v", c1.node.Left, c1.node.Line()) 500 } 501 } 502 503 // put list back in processing order 504 sort.Sort(caseClauseByOrd(cc)) 505 return cc 506 } 507 508 // walk generates an AST that implements sw, 509 // where sw is a type switch. 510 // The AST is generally of the form of a linear 511 // search using if..goto, although binary search 512 // is used with long runs of concrete types. 513 func (s *typeSwitch) walk(sw *Node) { 514 cond := sw.Left 515 sw.Left = nil 516 517 if cond == nil { 518 sw.List = nil 519 return 520 } 521 if cond.Right == nil { 522 setlineno(sw) 523 Yyerror("type switch must have an assignment") 524 return 525 } 526 527 walkexpr(&cond.Right, &sw.Ninit) 528 if !Istype(cond.Right.Type, TINTER) { 529 Yyerror("type switch must be on an interface") 530 return 531 } 532 533 var cas *NodeList 534 535 // predeclare temporary variables and the boolean var 536 s.facename = temp(cond.Right.Type) 537 538 a := Nod(OAS, s.facename, cond.Right) 539 typecheck(&a, Etop) 540 cas = list(cas, a) 541 542 s.okname = temp(Types[TBOOL]) 543 typecheck(&s.okname, Erv) 544 545 s.hashname = temp(Types[TUINT32]) 546 typecheck(&s.hashname, Erv) 547 548 // set up labels and jumps 549 casebody(sw, s.facename) 550 551 // calculate type hash 552 t := cond.Right.Type 553 if isnilinter(t) { 554 a = syslook("efacethash", 1) 555 } else { 556 a = syslook("ifacethash", 1) 557 } 558 substArgTypes(a, t) 559 a = Nod(OCALL, a, nil) 560 a.List = list1(s.facename) 561 a = Nod(OAS, s.hashname, a) 562 typecheck(&a, Etop) 563 cas = list(cas, a) 564 565 cc := caseClauses(sw, switchKindType) 566 sw.List = nil 567 var def *Node 568 if len(cc) > 0 && cc[0].typ == caseKindDefault { 569 def = cc[0].node.Right 570 cc = cc[1:] 571 } else { 572 def = Nod(OBREAK, nil, nil) 573 } 574 575 // insert type equality check into each case block 576 for _, c := range cc { 577 n := c.node 578 switch c.typ { 579 case caseKindTypeNil: 580 var v Val 581 v.U = new(NilVal) 582 a = Nod(OIF, nil, nil) 583 a.Left = Nod(OEQ, s.facename, nodlit(v)) 584 typecheck(&a.Left, Erv) 585 a.Nbody = list1(n.Right) // if i==nil { goto l } 586 n.Right = a 587 588 case caseKindTypeVar, caseKindTypeConst: 589 n.Right = s.typeone(n) 590 } 591 } 592 593 // generate list of if statements, binary search for constant sequences 594 for len(cc) > 0 { 595 if cc[0].typ != caseKindTypeConst { 596 n := cc[0].node 597 cas = list(cas, n.Right) 598 cc = cc[1:] 599 continue 600 } 601 602 // identify run of constants 603 var run int 604 for run = 1; run < len(cc) && cc[run].typ == caseKindTypeConst; run++ { 605 } 606 607 // sort by hash 608 sort.Sort(caseClauseByType(cc[:run])) 609 610 // for debugging: linear search 611 if false { 612 for i := 0; i < run; i++ { 613 n := cc[i].node 614 cas = list(cas, n.Right) 615 } 616 continue 617 } 618 619 // combine adjacent cases with the same hash 620 ncase := 0 621 for i := 0; i < run; i++ { 622 ncase++ 623 hash := list1(cc[i].node.Right) 624 for j := i + 1; j < run && cc[i].hash == cc[j].hash; j++ { 625 hash = list(hash, cc[j].node.Right) 626 } 627 cc[i].node.Right = liststmt(hash) 628 } 629 630 // binary search among cases to narrow by hash 631 cas = list(cas, s.walkCases(cc[:ncase])) 632 cc = cc[ncase:] 633 } 634 635 // handle default case 636 if nerrors == 0 { 637 cas = list(cas, def) 638 sw.Nbody = concat(cas, sw.Nbody) 639 sw.List = nil 640 walkstmtlist(sw.Nbody) 641 } 642 } 643 644 // typeone generates an AST that jumps to the 645 // case body if the variable is of type t. 646 func (s *typeSwitch) typeone(t *Node) *Node { 647 var name *Node 648 var init *NodeList 649 if t.Rlist == nil { 650 name = nblank 651 typecheck(&nblank, Erv|Easgn) 652 } else { 653 name = t.Rlist.N 654 init = list1(Nod(ODCL, name, nil)) 655 a := Nod(OAS, name, nil) 656 typecheck(&a, Etop) 657 init = list(init, a) 658 } 659 660 a := Nod(OAS2, nil, nil) 661 a.List = list(list1(name), s.okname) // name, ok = 662 b := Nod(ODOTTYPE, s.facename, nil) 663 b.Type = t.Left.Type // interface.(type) 664 a.Rlist = list1(b) 665 typecheck(&a, Etop) 666 init = list(init, a) 667 668 c := Nod(OIF, nil, nil) 669 c.Left = s.okname 670 c.Nbody = list1(t.Right) // if ok { goto l } 671 672 return liststmt(list(init, c)) 673 } 674 675 // walkCases generates an AST implementing the cases in cc. 676 func (s *typeSwitch) walkCases(cc []*caseClause) *Node { 677 if len(cc) < binarySearchMin { 678 var cas *NodeList 679 for _, c := range cc { 680 n := c.node 681 if c.typ != caseKindTypeConst { 682 Fatal("typeSwitch walkCases") 683 } 684 a := Nod(OIF, nil, nil) 685 a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash))) 686 typecheck(&a.Left, Erv) 687 a.Nbody = list1(n.Right) 688 cas = list(cas, a) 689 } 690 return liststmt(cas) 691 } 692 693 // find the middle and recur 694 half := len(cc) / 2 695 a := Nod(OIF, nil, nil) 696 a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash))) 697 typecheck(&a.Left, Erv) 698 a.Nbody = list1(s.walkCases(cc[:half])) 699 a.Rlist = list1(s.walkCases(cc[half:])) 700 return a 701 } 702 703 type caseClauseByOrd []*caseClause 704 705 func (x caseClauseByOrd) Len() int { return len(x) } 706 func (x caseClauseByOrd) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 707 func (x caseClauseByOrd) Less(i, j int) bool { 708 c1, c2 := x[i], x[j] 709 switch { 710 // sort default first 711 case c1.typ == caseKindDefault: 712 return true 713 case c2.typ == caseKindDefault: 714 return false 715 716 // sort nil second 717 case c1.typ == caseKindTypeNil: 718 return true 719 case c2.typ == caseKindTypeNil: 720 return false 721 } 722 723 // sort by ordinal 724 return c1.ordinal < c2.ordinal 725 } 726 727 type caseClauseByExpr []*caseClause 728 729 func (x caseClauseByExpr) Len() int { return len(x) } 730 func (x caseClauseByExpr) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 731 func (x caseClauseByExpr) Less(i, j int) bool { 732 return exprcmp(x[i], x[j]) < 0 733 } 734 735 func exprcmp(c1, c2 *caseClause) int { 736 // sort non-constants last 737 if c1.typ != caseKindExprConst { 738 return +1 739 } 740 if c2.typ != caseKindExprConst { 741 return -1 742 } 743 744 n1 := c1.node.Left 745 n2 := c2.node.Left 746 747 // sort by type (for switches on interface) 748 ct := int(n1.Val().Ctype()) 749 if ct > int(n2.Val().Ctype()) { 750 return +1 751 } 752 if ct < int(n2.Val().Ctype()) { 753 return -1 754 } 755 if !Eqtype(n1.Type, n2.Type) { 756 if n1.Type.Vargen > n2.Type.Vargen { 757 return +1 758 } else { 759 return -1 760 } 761 } 762 763 // sort by constant value to enable binary search 764 switch ct { 765 case CTFLT: 766 return mpcmpfltflt(n1.Val().U.(*Mpflt), n2.Val().U.(*Mpflt)) 767 case CTINT, CTRUNE: 768 return Mpcmpfixfix(n1.Val().U.(*Mpint), n2.Val().U.(*Mpint)) 769 case CTSTR: 770 // Sort strings by length and then by value. 771 // It is much cheaper to compare lengths than values, 772 // and all we need here is consistency. 773 // We respect this sorting in exprSwitch.walkCases. 774 a := n1.Val().U.(string) 775 b := n2.Val().U.(string) 776 if len(a) < len(b) { 777 return -1 778 } 779 if len(a) > len(b) { 780 return +1 781 } 782 return stringsCompare(a, b) 783 } 784 785 return 0 786 } 787 788 type caseClauseByType []*caseClause 789 790 func (x caseClauseByType) Len() int { return len(x) } 791 func (x caseClauseByType) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 792 func (x caseClauseByType) Less(i, j int) bool { 793 c1, c2 := x[i], x[j] 794 switch { 795 // sort non-constants last 796 case c1.typ != caseKindTypeConst: 797 return false 798 case c2.typ != caseKindTypeConst: 799 return true 800 801 // sort by hash code 802 case c1.hash != c2.hash: 803 return c1.hash < c2.hash 804 } 805 806 // sort by ordinal 807 return c1.ordinal < c2.ordinal 808 } 809 810 func dumpcase(cc []*caseClause) { 811 for _, c := range cc { 812 switch c.typ { 813 case caseKindDefault: 814 fmt.Printf("case-default\n") 815 fmt.Printf("\tord=%d\n", c.ordinal) 816 817 case caseKindExprConst: 818 fmt.Printf("case-exprconst\n") 819 fmt.Printf("\tord=%d\n", c.ordinal) 820 821 case caseKindExprVar: 822 fmt.Printf("case-exprvar\n") 823 fmt.Printf("\tord=%d\n", c.ordinal) 824 fmt.Printf("\top=%v\n", Oconv(int(c.node.Left.Op), 0)) 825 826 case caseKindTypeNil: 827 fmt.Printf("case-typenil\n") 828 fmt.Printf("\tord=%d\n", c.ordinal) 829 830 case caseKindTypeConst: 831 fmt.Printf("case-typeconst\n") 832 fmt.Printf("\tord=%d\n", c.ordinal) 833 fmt.Printf("\thash=%x\n", c.hash) 834 835 case caseKindTypeVar: 836 fmt.Printf("case-typevar\n") 837 fmt.Printf("\tord=%d\n", c.ordinal) 838 839 default: 840 fmt.Printf("case-???\n") 841 fmt.Printf("\tord=%d\n", c.ordinal) 842 fmt.Printf("\top=%v\n", Oconv(int(c.node.Left.Op), 0)) 843 fmt.Printf("\thash=%x\n", c.hash) 844 } 845 } 846 847 fmt.Printf("\n") 848 } 849