@@ -250,51 +250,58 @@ pub enum Terminator<'tcx> {
250250 func : Operand < ' tcx > ,
251251 /// Arguments the function is called with
252252 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 > ,
256255 } ,
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- }
267256}
268257
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+ }
276278}
277279
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 ( ) ,
284287 }
285288 }
286289
287- pub fn as_slice ( & self ) -> & [ BasicBlock ] {
290+ pub fn successors_mut ( & mut self ) -> & mut [ BasicBlock ] {
288291 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 ( ) ,
291296 }
292297 }
293298
294- pub fn as_mut_slice ( & mut self ) -> & mut [ BasicBlock ] {
299+ pub fn destination ( & self ) -> Option < Lvalue < ' tcx > > {
295300 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
298305 }
299306 }
300307}
@@ -309,12 +316,7 @@ impl<'tcx> Terminator<'tcx> {
309316 SwitchInt { targets : ref b, .. } => b,
310317 Resume => & [ ] ,
311318 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 ( ) ,
318320 }
319321 }
320322
@@ -327,12 +329,7 @@ impl<'tcx> Terminator<'tcx> {
327329 SwitchInt { targets : ref mut b, .. } => b,
328330 Resume => & mut [ ] ,
329331 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 ( ) ,
336333 }
337334 }
338335}
@@ -399,13 +396,18 @@ impl<'tcx> Terminator<'tcx> {
399396 SwitchInt { discr : ref lv, .. } => write ! ( fmt, "switchInt({:?})" , lv) ,
400397 Return => write ! ( fmt, "return" ) ,
401398 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, ")" )
409411 }
410412 }
411413 }
@@ -417,8 +419,6 @@ impl<'tcx> Terminator<'tcx> {
417419 Return | Resume => vec ! [ ] ,
418420 Goto { .. } => vec ! [ "" . into_cow( ) ] ,
419421 If { .. } => vec ! [ "true" . into_cow( ) , "false" . into_cow( ) ] ,
420- Call { .. } => vec ! [ "return" . into_cow( ) , "unwind" . into_cow( ) ] ,
421- DivergingCall { .. } => vec ! [ "unwind" . into_cow( ) ] ,
422422 Switch { ref adt_def, .. } => {
423423 adt_def. variants
424424 . iter ( )
@@ -435,6 +435,16 @@ impl<'tcx> Terminator<'tcx> {
435435 . chain ( iter:: once ( String :: from ( "otherwise" ) . into_cow ( ) ) )
436436 . collect ( )
437437 }
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+ } ,
438448 }
439449 }
440450}
0 commit comments