github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/go/ir/irutil/testdata/switches.go (about) 1 //go:build ignore 2 // +build ignore 3 4 package main 5 6 // This file is the input to TestSwitches in switch_test.go. 7 // Each multiway conditional with constant or type cases (Switch) 8 // discovered by Switches is printed, and compared with the 9 // comments. 10 // 11 // The body of each case is printed as the value of its first 12 // instruction. 13 14 // -------- Value switches -------- 15 16 func four() int { return 4 } 17 18 // A non-constant case makes a switch "impure", but its pure 19 // cases form two separate switches. 20 func SwitchWithNonConstantCase(x int) { 21 // switch t12 { 22 // case t1: Call <()> print t2 23 // case t3: Call <()> print t5 24 // case t4: Call <()> print t5 25 // default: BinOp <bool> {==} t30 t31 26 // } 27 28 // switch t36 { 29 // case t7: Call <()> print t8 30 // case t9: Call <()> print t10 31 // default: Call <()> print t11 32 // } 33 switch x { 34 case 1: 35 print(1) 36 case 2, 3: 37 print(23) 38 case four(): 39 print(3) 40 case 5: 41 print(5) 42 case 6: 43 print(6) 44 } 45 print("done") 46 } 47 48 // Switches may be found even where the source 49 // program doesn't have a switch statement. 50 51 func ImplicitSwitches(x, y int) { 52 // switch t13 { 53 // case t1: Call <()> print t4 54 // case t2: Call <()> print t4 55 // default: BinOp <bool> {<} t28 t3 56 // } 57 if x == 1 || 2 == x || x < 5 { 58 print(12) 59 } 60 61 // switch t25 { 62 // case t5: Call <()> print t7 63 // case t6: Call <()> print t7 64 // default: BinOp <bool> {==} t50 t51 65 // } 66 if x == 3 || 4 == x || x == y { 67 print(34) 68 } 69 70 // Not a switch: no consistent variable. 71 if x == 5 || y == 6 { 72 print(56) 73 } 74 75 // Not a switch: only one constant comparison. 76 if x == 7 || x == y { 77 print(78) 78 } 79 } 80 81 func IfElseBasedSwitch(x int) { 82 // switch t6 { 83 // case t1: Call <()> print t2 84 // case t3: Call <()> print t4 85 // default: Call <()> print t5 86 // } 87 if x == 1 { 88 print(1) 89 } else if x == 2 { 90 print(2) 91 } else { 92 print("else") 93 } 94 } 95 96 func GotoBasedSwitch(x int) { 97 // switch t6 { 98 // case t1: Call <()> print t4 99 // case t2: Call <()> print t5 100 // default: Call <()> print t3 101 // } 102 if x == 1 { 103 goto L1 104 } 105 if x == 2 { 106 goto L2 107 } 108 print("else") 109 L1: 110 print(1) 111 goto end 112 L2: 113 print(2) 114 end: 115 } 116 117 func SwitchInAForLoop(x, y int) { 118 // switch t13 { 119 // case t2: Call <()> print t3 120 // case t4: Call <()> print t5 121 // default: BinOp <bool> {==} t31 t30 122 // } 123 loop: 124 for { 125 print("head") 126 switch x { 127 case 1: 128 print(1) 129 break loop 130 case 2: 131 print(2) 132 break loop 133 case y: 134 print(3) 135 break loop 136 } 137 } 138 } 139 140 // This case is a switch in a for-loop, both constructed using goto. 141 // As before, the default case points back to the block containing the 142 // switch, but that's ok. 143 func SwitchInAForLoopUsingGoto(x int) { 144 // switch t10 { 145 // case t2: Call <()> print t4 146 // case t3: Call <()> print t5 147 // default: BinOp <bool> {==} t10 t2 148 // } 149 loop: 150 print("head") 151 if x == 1 { 152 goto L1 153 } 154 if x == 2 { 155 goto L2 156 } 157 goto loop 158 L1: 159 print(1) 160 goto end 161 L2: 162 print(2) 163 end: 164 } 165 166 func UnstructuredSwitchInAForLoop(x int) { 167 // switch t9 { 168 // case t1: Call <()> print t2 169 // case t3: BinOp <bool> {==} t9 t1 170 // default: Call <()> print t4 171 // } 172 for { 173 if x == 1 { 174 print(1) 175 return 176 } 177 if x == 2 { 178 continue 179 } 180 break 181 } 182 print("end") 183 } 184 185 func CaseWithMultiplePreds(x int) { 186 for { 187 if x == 1 { 188 print(1) 189 return 190 } 191 loop: 192 // This block has multiple predecessors, 193 // so can't be treated as a switch case. 194 if x == 2 { 195 goto loop 196 } 197 break 198 } 199 print("end") 200 } 201 202 func DuplicateConstantsAreNotEliminated(x int) { 203 // switch t7 { 204 // case t1: Call <()> print t2 205 // case t3: Call <()> print t4 206 // case t5: Call <()> print t6 207 // default: Return 208 // } 209 if x == 1 { 210 print(1) 211 } else if x == 1 { // duplicate => unreachable 212 print("1a") 213 } else if x == 2 { 214 print(2) 215 } 216 } 217 218 // Interface values (created by comparisons) are not constants, 219 // so ConstSwitch.X is never of interface type. 220 func MakeInterfaceIsNotAConstant(x interface{}) { 221 if x == "foo" { 222 print("foo") 223 } else if x == 1 { 224 print(1) 225 } 226 } 227 228 func ZeroInitializedVarsAreConstants(x int) { 229 // switch t6 { 230 // case t5: Call <()> print t1 231 // case t2: Call <()> print t3 232 // default: Call <()> print t4 233 // } 234 var zero int // SSA construction replaces zero with 0 235 if x == zero { 236 print(1) 237 } else if x == 2 { 238 print(2) 239 } 240 print("end") 241 } 242 243 // -------- Type switches -------- 244 245 // NB, potentially fragile reliance on register number. 246 func AdHocTypeSwitch(x interface{}) { 247 // switch t2.(type) { 248 // case t4 int: Call <()> println t8 249 // case t13 string: Call <()> println t16 250 // default: Call <()> print t1 251 // } 252 if i, ok := x.(int); ok { 253 println(i) 254 } else if s, ok := x.(string); ok { 255 println(s) 256 } else { 257 print("default") 258 } 259 }