@@ -40,12 +40,9 @@ impl<'tcx> GotocCtx<'tcx> {
40
40
TerminatorKind :: Goto { target } => {
41
41
Stmt :: goto ( self . current_fn ( ) . find_label ( target) , loc)
42
42
}
43
- TerminatorKind :: SwitchInt { discr, switch_ty, targets } => match targets {
44
- SwitchTargets { values, .. } => {
45
- let all_targets = targets. all_targets ( ) ;
46
- self . codegen_switch_int ( discr, switch_ty, values, all_targets)
47
- }
48
- } ,
43
+ TerminatorKind :: SwitchInt { discr, switch_ty, targets } => {
44
+ self . codegen_switch_int ( discr, switch_ty, targets)
45
+ }
49
46
TerminatorKind :: Resume => Stmt :: assert_false ( "resume instruction" , loc) ,
50
47
TerminatorKind :: Abort => Stmt :: assert_false ( "abort instruction" , loc) ,
51
48
TerminatorKind :: Return => {
@@ -206,62 +203,48 @@ impl<'tcx> GotocCtx<'tcx> {
206
203
& mut self ,
207
204
discr : & Operand < ' tcx > ,
208
205
switch_ty : Ty < ' tcx > ,
209
- values : & SmallVec < [ u128 ; 1 ] > ,
210
- targets : & [ BasicBlock ] ,
206
+ targets : & SwitchTargets ,
211
207
) -> Stmt {
212
- assert_eq ! ( targets. len( ) , values. len( ) + 1 ) ;
213
-
214
208
let v = self . codegen_operand ( discr) ;
215
209
let switch_ty = self . monomorphize ( switch_ty) ;
216
- match switch_ty. kind ( ) {
217
- //TODO, can replace with guarded goto
218
- ty:: Bool => {
219
- let jmp: usize = values[ 0 ] . try_into ( ) . unwrap ( ) ;
220
- let jmp2 = if jmp == 0 { 1 } else { 0 } ;
221
- Stmt :: block (
222
- vec ! [
223
- v. cast_to( Type :: bool ( ) ) . if_then_else(
210
+ if targets. all_targets ( ) . len ( ) == 1 {
211
+ // Translate to a guarded goto
212
+ let first_target = targets. iter ( ) . next ( ) . unwrap ( ) ;
213
+ Stmt :: block (
214
+ vec ! [
215
+ v. eq( Expr :: int_constant( first_target. 0 , self . codegen_ty( switch_ty) ) )
216
+ . if_then_else(
224
217
Stmt :: goto(
225
- self . current_fn( ) . labels( ) [ targets [ jmp2 ] . index( ) ] . clone( ) ,
218
+ self . current_fn( ) . labels( ) [ first_target . 1 . index( ) ] . clone( ) ,
226
219
Location :: none( ) ,
227
220
) ,
228
221
None ,
229
222
Location :: none( ) ,
230
223
) ,
231
- Stmt :: goto(
232
- self . current_fn( ) . labels( ) [ targets[ jmp] . index( ) ] . clone( ) ,
233
- Location :: none( ) ,
234
- ) ,
235
- ] ,
236
- Location :: none ( ) ,
237
- )
238
- }
239
- ty:: Char | ty:: Int ( _) | ty:: Uint ( _) => {
240
- let cases = values
241
- . iter ( )
242
- . enumerate ( )
243
- . map ( |( i, idx) | {
244
- let bb = & targets[ i] ;
245
- Expr :: int_constant ( * idx, self . codegen_ty ( switch_ty) ) . switch_case (
246
- Stmt :: goto (
247
- self . current_fn ( ) . labels ( ) [ bb. index ( ) ] . clone ( ) ,
248
- Location :: none ( ) ,
249
- ) ,
250
- )
251
- } )
252
- . collect ( ) ;
253
- let default = Stmt :: goto (
254
- self . current_fn ( ) . labels ( ) [ targets[ values. len ( ) ] . index ( ) ] . clone ( ) ,
255
- Location :: none ( ) ,
256
- ) ;
257
- v. switch ( cases, Some ( default) , Location :: none ( ) )
258
- }
259
- x => {
260
- unreachable ! (
261
- "Unexpected switch_ty {:?}\n {:?}\n {:?}\n {:?}\n {:?}\n {:?}" ,
262
- discr, switch_ty, values, targets, v, x
263
- )
264
- }
224
+ Stmt :: goto(
225
+ self . current_fn( ) . labels( ) [ targets. otherwise( ) . index( ) ] . clone( ) ,
226
+ Location :: none( ) ,
227
+ ) ,
228
+ ] ,
229
+ Location :: none ( ) ,
230
+ )
231
+ } else {
232
+ // Switches with empty targets should've been eliminated already.
233
+ assert ! ( targets. all_targets( ) . len( ) > 1 ) ;
234
+ let cases = targets
235
+ . iter ( )
236
+ . map ( |( c, bb) | {
237
+ Expr :: int_constant ( c, self . codegen_ty ( switch_ty) ) . switch_case ( Stmt :: goto (
238
+ self . current_fn ( ) . labels ( ) [ bb. index ( ) ] . clone ( ) ,
239
+ Location :: none ( ) ,
240
+ ) )
241
+ } )
242
+ . collect ( ) ;
243
+ let default = Stmt :: goto (
244
+ self . current_fn ( ) . labels ( ) [ targets. otherwise ( ) . index ( ) ] . clone ( ) ,
245
+ Location :: none ( ) ,
246
+ ) ;
247
+ v. switch ( cases, Some ( default) , Location :: none ( ) )
265
248
}
266
249
}
267
250
0 commit comments