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  }