@@ -250,51 +250,58 @@ pub enum Terminator<'tcx> {
250
250
func : Operand < ' tcx > ,
251
251
/// Arguments the function is called with
252
252
args : Vec < Operand < ' tcx > > ,
253
- /// Location to write the return value into
254
- destination : Lvalue < ' tcx > ,
255
- targets : CallTargets ,
253
+ /// The kind of call with associated information
254
+ kind : CallKind < ' tcx > ,
256
255
} ,
257
-
258
- /// Block ends with a call of a diverging function.
259
- DivergingCall {
260
- /// The function that’s being called
261
- func : Operand < ' tcx > ,
262
- /// Arguments the function is called with
263
- args : Vec < Operand < ' tcx > > ,
264
- /// Some, if there’s any cleanup to be done when function unwinds
265
- cleanup : Option < BasicBlock > ,
266
- }
267
256
}
268
257
269
- #[ derive( Clone , Copy , RustcEncodable , RustcDecodable ) ]
270
- pub enum CallTargets {
271
- /// The only target that should be entered when function returns normally.
272
- Return ( BasicBlock ) ,
273
- /// In addition to the normal-return block, function has associated cleanup that should be done
274
- /// when function unwinds.
275
- WithCleanup ( ( BasicBlock , BasicBlock ) )
258
+ #[ derive( Clone , RustcEncodable , RustcDecodable ) ]
259
+ pub enum CallKind < ' tcx > {
260
+ /// Diverging function without associated cleanup
261
+ Diverging ,
262
+ /// Diverging function with associated cleanup
263
+ DivergingCleanup ( BasicBlock ) ,
264
+ /// Converging function without associated cleanup
265
+ Converging {
266
+ /// Destination where the call result is written
267
+ destination : Lvalue < ' tcx > ,
268
+ /// Block to branch into on successful return
269
+ target : BasicBlock ,
270
+ } ,
271
+ ConvergingCleanup {
272
+ /// Destination where the call result is written
273
+ destination : Lvalue < ' tcx > ,
274
+ /// First target is branched to on successful return.
275
+ /// Second block contains the cleanups to do on unwind.
276
+ targets : ( BasicBlock , BasicBlock )
277
+ }
276
278
}
277
279
278
- impl CallTargets {
279
- pub fn new ( ret : BasicBlock , cleanup : Option < BasicBlock > ) -> CallTargets {
280
- if let Some ( c) = cleanup {
281
- CallTargets :: WithCleanup ( ( ret, c) )
282
- } else {
283
- CallTargets :: Return ( ret)
280
+ impl < ' tcx > CallKind < ' tcx > {
281
+ pub fn successors ( & self ) -> & [ BasicBlock ] {
282
+ match * self {
283
+ CallKind :: Diverging => & [ ] ,
284
+ CallKind :: DivergingCleanup ( ref b) |
285
+ CallKind :: Converging { target : ref b, .. } => slice:: ref_slice ( b) ,
286
+ CallKind :: ConvergingCleanup { ref targets, .. } => targets. as_slice ( ) ,
284
287
}
285
288
}
286
289
287
- pub fn as_slice ( & self ) -> & [ BasicBlock ] {
290
+ pub fn successors_mut ( & mut self ) -> & mut [ BasicBlock ] {
288
291
match * self {
289
- CallTargets :: Return ( ref b) => slice:: ref_slice ( b) ,
290
- CallTargets :: WithCleanup ( ref bs) => bs. as_slice ( )
292
+ CallKind :: Diverging => & mut [ ] ,
293
+ CallKind :: DivergingCleanup ( ref mut b) |
294
+ CallKind :: Converging { target : ref mut b, .. } => slice:: mut_ref_slice ( b) ,
295
+ CallKind :: ConvergingCleanup { ref mut targets, .. } => targets. as_mut_slice ( ) ,
291
296
}
292
297
}
293
298
294
- pub fn as_mut_slice ( & mut self ) -> & mut [ BasicBlock ] {
299
+ pub fn destination ( & self ) -> Option < Lvalue < ' tcx > > {
295
300
match * self {
296
- CallTargets :: Return ( ref mut b) => slice:: mut_ref_slice ( b) ,
297
- CallTargets :: WithCleanup ( ref mut bs) => bs. as_mut_slice ( )
301
+ CallKind :: Converging { ref destination, .. } |
302
+ CallKind :: ConvergingCleanup { ref destination, .. } => Some ( destination. clone ( ) ) ,
303
+ CallKind :: Diverging |
304
+ CallKind :: DivergingCleanup ( _) => None
298
305
}
299
306
}
300
307
}
@@ -309,12 +316,7 @@ impl<'tcx> Terminator<'tcx> {
309
316
SwitchInt { targets : ref b, .. } => b,
310
317
Resume => & [ ] ,
311
318
Return => & [ ] ,
312
- Call { targets : ref b, .. } => b. as_slice ( ) ,
313
- DivergingCall { cleanup : ref b, .. } => if let Some ( b) = b. as_ref ( ) {
314
- slice:: ref_slice ( b)
315
- } else {
316
- & mut [ ]
317
- } ,
319
+ Call { ref kind, .. } => kind. successors ( ) ,
318
320
}
319
321
}
320
322
@@ -327,12 +329,7 @@ impl<'tcx> Terminator<'tcx> {
327
329
SwitchInt { targets : ref mut b, .. } => b,
328
330
Resume => & mut [ ] ,
329
331
Return => & mut [ ] ,
330
- Call { targets : ref mut b, .. } => b. as_mut_slice ( ) ,
331
- DivergingCall { cleanup : ref mut b, .. } => if let Some ( b) = b. as_mut ( ) {
332
- slice:: mut_ref_slice ( b)
333
- } else {
334
- & mut [ ]
335
- } ,
332
+ Call { ref mut kind, .. } => kind. successors_mut ( ) ,
336
333
}
337
334
}
338
335
}
@@ -399,13 +396,18 @@ impl<'tcx> Terminator<'tcx> {
399
396
SwitchInt { discr : ref lv, .. } => write ! ( fmt, "switchInt({:?})" , lv) ,
400
397
Return => write ! ( fmt, "return" ) ,
401
398
Resume => write ! ( fmt, "resume" ) ,
402
- Call { .. } => {
403
- // the author didn’t bother rebasing this
404
- unimplemented ! ( )
405
- } ,
406
- DivergingCall { .. } => {
407
- // the author didn’t bother rebasing this
408
- unimplemented ! ( )
399
+ Call { ref kind, ref func, ref args } => {
400
+ if let Some ( destination) = kind. destination ( ) {
401
+ try!( write ! ( fmt, "{:?} = " , destination) ) ;
402
+ }
403
+ try!( write ! ( fmt, "{:?}(" , func) ) ;
404
+ for ( index, arg) in args. iter ( ) . enumerate ( ) {
405
+ if index > 0 {
406
+ try!( write ! ( fmt, ", " ) ) ;
407
+ }
408
+ try!( write ! ( fmt, "{:?}" , arg) ) ;
409
+ }
410
+ write ! ( fmt, ")" )
409
411
}
410
412
}
411
413
}
@@ -417,8 +419,6 @@ impl<'tcx> Terminator<'tcx> {
417
419
Return | Resume => vec ! [ ] ,
418
420
Goto { .. } => vec ! [ "" . into_cow( ) ] ,
419
421
If { .. } => vec ! [ "true" . into_cow( ) , "false" . into_cow( ) ] ,
420
- Call { .. } => vec ! [ "return" . into_cow( ) , "unwind" . into_cow( ) ] ,
421
- DivergingCall { .. } => vec ! [ "unwind" . into_cow( ) ] ,
422
422
Switch { ref adt_def, .. } => {
423
423
adt_def. variants
424
424
. iter ( )
@@ -435,6 +435,16 @@ impl<'tcx> Terminator<'tcx> {
435
435
. chain ( iter:: once ( String :: from ( "otherwise" ) . into_cow ( ) ) )
436
436
. collect ( )
437
437
}
438
+ Call { ref kind, .. } => match * kind {
439
+ CallKind :: Diverging =>
440
+ vec ! [ ] ,
441
+ CallKind :: DivergingCleanup ( ..) =>
442
+ vec ! [ "unwind" . into_cow( ) ] ,
443
+ CallKind :: Converging { .. } =>
444
+ vec ! [ "return" . into_cow( ) ] ,
445
+ CallKind :: ConvergingCleanup { .. } =>
446
+ vec ! [ "return" . into_cow( ) , "unwind" . into_cow( ) ] ,
447
+ } ,
438
448
}
439
449
}
440
450
}
0 commit comments