88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11+ use graphviz:: IntoCow ;
1112use middle:: const_eval:: ConstVal ;
1213use middle:: def_id:: DefId ;
1314use middle:: subst:: Substs ;
1415use middle:: ty:: { self , AdtDef , ClosureSubsts , FnOutput , Region , Ty } ;
1516use rustc_back:: slice;
16- use rustc_data_structures:: tuple_slice:: TupleSlice ;
1717use rustc_front:: hir:: InlineAsm ;
18- use syntax:: ast:: { self , Name } ;
19- use syntax:: codemap:: Span ;
20- use graphviz:: IntoCow ;
2118use std:: ascii;
22- use std:: borrow:: Cow ;
19+ use std:: borrow:: { Cow } ;
2320use std:: fmt:: { self , Debug , Formatter , Write } ;
2421use std:: { iter, u32} ;
2522use std:: ops:: { Index , IndexMut } ;
23+ use syntax:: ast:: { self , Name } ;
24+ use syntax:: codemap:: Span ;
2625
2726/// Lowered representation of a single function.
2827#[ derive( Clone , RustcEncodable , RustcDecodable ) ]
@@ -263,101 +262,63 @@ pub enum Terminator<'tcx> {
263262 /// `END_BLOCK`.
264263 Return ,
265264
265+ /// Drop the Lvalue
266+ Drop {
267+ value : Lvalue < ' tcx > ,
268+ target : BasicBlock ,
269+ unwind : Option < BasicBlock >
270+ } ,
271+
266272 /// Block ends with a call of a converging function
267273 Call {
268274 /// The function that’s being called
269275 func : Operand < ' tcx > ,
270276 /// Arguments the function is called with
271277 args : Vec < Operand < ' tcx > > ,
272- /// The kind of call with associated information
273- kind : CallKind < ' tcx > ,
278+ /// Destination for the return value. If some, the call is converging.
279+ destination : Option < ( Lvalue < ' tcx > , BasicBlock ) > ,
280+ /// Cleanups to be done if the call unwinds.
281+ cleanup : Option < BasicBlock >
274282 } ,
275283}
276284
277- #[ derive( Clone , RustcEncodable , RustcDecodable ) ]
278- pub enum CallKind < ' tcx > {
279- /// Diverging function without associated cleanup
280- Diverging ,
281- /// Diverging function with associated cleanup
282- DivergingCleanup ( BasicBlock ) ,
283- /// Converging function without associated cleanup
284- Converging {
285- /// Destination where the call result is written
286- destination : Lvalue < ' tcx > ,
287- /// Block to branch into on successful return
288- target : BasicBlock ,
289- } ,
290- ConvergingCleanup {
291- /// Destination where the call result is written
292- destination : Lvalue < ' tcx > ,
293- /// First target is branched to on successful return.
294- /// Second block contains the cleanups to do on unwind.
295- targets : ( BasicBlock , BasicBlock )
296- }
297- }
298-
299- impl < ' tcx > CallKind < ' tcx > {
300- pub fn successors ( & self ) -> & [ BasicBlock ] {
301- match * self {
302- CallKind :: Diverging => & [ ] ,
303- CallKind :: DivergingCleanup ( ref b) |
304- CallKind :: Converging { target : ref b, .. } => slice:: ref_slice ( b) ,
305- CallKind :: ConvergingCleanup { ref targets, .. } => targets. as_slice ( ) ,
306- }
307- }
308-
309- pub fn successors_mut ( & mut self ) -> & mut [ BasicBlock ] {
310- match * self {
311- CallKind :: Diverging => & mut [ ] ,
312- CallKind :: DivergingCleanup ( ref mut b) |
313- CallKind :: Converging { target : ref mut b, .. } => slice:: mut_ref_slice ( b) ,
314- CallKind :: ConvergingCleanup { ref mut targets, .. } => targets. as_mut_slice ( ) ,
315- }
316- }
317-
318- pub fn destination ( & self ) -> Option < & Lvalue < ' tcx > > {
319- match * self {
320- CallKind :: Converging { ref destination, .. } |
321- CallKind :: ConvergingCleanup { ref destination, .. } => Some ( destination) ,
322- CallKind :: Diverging |
323- CallKind :: DivergingCleanup ( _) => None
324- }
325- }
326-
327- pub fn destination_mut ( & mut self ) -> Option < & mut Lvalue < ' tcx > > {
328- match * self {
329- CallKind :: Converging { ref mut destination, .. } |
330- CallKind :: ConvergingCleanup { ref mut destination, .. } => Some ( destination) ,
331- CallKind :: Diverging |
332- CallKind :: DivergingCleanup ( _) => None
333- }
334- }
335- }
336-
337285impl < ' tcx > Terminator < ' tcx > {
338- pub fn successors ( & self ) -> & [ BasicBlock ] {
286+ pub fn successors ( & self ) -> Cow < [ BasicBlock ] > {
339287 use self :: Terminator :: * ;
340288 match * self {
341- Goto { target : ref b } => slice:: ref_slice ( b) ,
342- If { targets : ref b, .. } => b. as_slice ( ) ,
343- Switch { targets : ref b, .. } => b,
344- SwitchInt { targets : ref b, .. } => b,
345- Resume => & [ ] ,
346- Return => & [ ] ,
347- Call { ref kind, .. } => kind. successors ( ) ,
289+ Goto { target : ref b } => slice:: ref_slice ( b) . into_cow ( ) ,
290+ If { targets : ( b1, b2) , .. } => vec ! [ b1, b2] . into_cow ( ) ,
291+ Switch { targets : ref b, .. } => b[ ..] . into_cow ( ) ,
292+ SwitchInt { targets : ref b, .. } => b[ ..] . into_cow ( ) ,
293+ Resume => ( & [ ] ) . into_cow ( ) ,
294+ Return => ( & [ ] ) . into_cow ( ) ,
295+ Call { destination : Some ( ( _, t) ) , cleanup : Some ( c) , .. } => vec ! [ t, c] . into_cow ( ) ,
296+ Call { destination : Some ( ( _, ref t) ) , cleanup : None , .. } =>
297+ slice:: ref_slice ( t) . into_cow ( ) ,
298+ Call { destination : None , cleanup : Some ( ref c) , .. } => slice:: ref_slice ( c) . into_cow ( ) ,
299+ Call { destination : None , cleanup : None , .. } => ( & [ ] ) . into_cow ( ) ,
300+ Drop { target, unwind : Some ( unwind) , .. } => vec ! [ target, unwind] . into_cow ( ) ,
301+ Drop { ref target, .. } => slice:: ref_slice ( target) . into_cow ( ) ,
348302 }
349303 }
350304
351- pub fn successors_mut ( & mut self ) -> & mut [ BasicBlock ] {
305+ // FIXME: no mootable cow. I’m honestly not sure what a “cow” between `&mut [BasicBlock]` and
306+ // `Vec<&mut BasicBlock>` would look like in the first place.
307+ pub fn successors_mut ( & mut self ) -> Vec < & mut BasicBlock > {
352308 use self :: Terminator :: * ;
353309 match * self {
354- Goto { target : ref mut b } => slice:: mut_ref_slice ( b) ,
355- If { targets : ref mut b, .. } => b. as_mut_slice ( ) ,
356- Switch { targets : ref mut b, .. } => b,
357- SwitchInt { targets : ref mut b, .. } => b,
358- Resume => & mut [ ] ,
359- Return => & mut [ ] ,
360- Call { ref mut kind, .. } => kind. successors_mut ( ) ,
310+ Goto { target : ref mut b } => vec ! [ b] ,
311+ If { targets : ( ref mut b1, ref mut b2) , .. } => vec ! [ b1, b2] ,
312+ Switch { targets : ref mut b, .. } => b. iter_mut ( ) . collect ( ) ,
313+ SwitchInt { targets : ref mut b, .. } => b. iter_mut ( ) . collect ( ) ,
314+ Resume => Vec :: new ( ) ,
315+ Return => Vec :: new ( ) ,
316+ Call { destination : Some ( ( _, ref mut t) ) , cleanup : Some ( ref mut c) , .. } => vec ! [ t, c] ,
317+ Call { destination : Some ( ( _, ref mut t) ) , cleanup : None , .. } => vec ! [ t] ,
318+ Call { destination : None , cleanup : Some ( ref mut c) , .. } => vec ! [ c] ,
319+ Call { destination : None , cleanup : None , .. } => vec ! [ ] ,
320+ Drop { ref mut target, unwind : Some ( ref mut unwind) , .. } => vec ! [ target, unwind] ,
321+ Drop { ref mut target, .. } => vec ! [ target]
361322 }
362323 }
363324}
@@ -424,8 +385,9 @@ impl<'tcx> Terminator<'tcx> {
424385 SwitchInt { discr : ref lv, .. } => write ! ( fmt, "switchInt({:?})" , lv) ,
425386 Return => write ! ( fmt, "return" ) ,
426387 Resume => write ! ( fmt, "resume" ) ,
427- Call { ref kind, ref func, ref args } => {
428- if let Some ( destination) = kind. destination ( ) {
388+ Drop { ref value, .. } => write ! ( fmt, "drop({:?})" , value) ,
389+ Call { ref func, ref args, ref destination, .. } => {
390+ if let Some ( ( ref destination, _) ) = * destination {
429391 try!( write ! ( fmt, "{:?} = " , destination) ) ;
430392 }
431393 try!( write ! ( fmt, "{:?}(" , func) ) ;
@@ -445,34 +407,31 @@ impl<'tcx> Terminator<'tcx> {
445407 use self :: Terminator :: * ;
446408 match * self {
447409 Return | Resume => vec ! [ ] ,
448- Goto { .. } => vec ! [ "" . into_cow ( ) ] ,
449- If { .. } => vec ! [ "true" . into_cow ( ) , "false" . into_cow ( ) ] ,
410+ Goto { .. } => vec ! [ "" . into ( ) ] ,
411+ If { .. } => vec ! [ "true" . into ( ) , "false" . into ( ) ] ,
450412 Switch { ref adt_def, .. } => {
451413 adt_def. variants
452414 . iter ( )
453- . map ( |variant| variant. name . to_string ( ) . into_cow ( ) )
415+ . map ( |variant| variant. name . to_string ( ) . into ( ) )
454416 . collect ( )
455417 }
456418 SwitchInt { ref values, .. } => {
457419 values. iter ( )
458420 . map ( |const_val| {
459421 let mut buf = String :: new ( ) ;
460422 fmt_const_val ( & mut buf, const_val) . unwrap ( ) ;
461- buf. into_cow ( )
423+ buf. into ( )
462424 } )
463- . chain ( iter:: once ( String :: from ( "otherwise" ) . into_cow ( ) ) )
425+ . chain ( iter:: once ( String :: from ( "otherwise" ) . into ( ) ) )
464426 . collect ( )
465427 }
466- Call { ref kind, .. } => match * kind {
467- CallKind :: Diverging =>
468- vec ! [ ] ,
469- CallKind :: DivergingCleanup ( ..) =>
470- vec ! [ "unwind" . into_cow( ) ] ,
471- CallKind :: Converging { .. } =>
472- vec ! [ "return" . into_cow( ) ] ,
473- CallKind :: ConvergingCleanup { .. } =>
474- vec ! [ "return" . into_cow( ) , "unwind" . into_cow( ) ] ,
475- } ,
428+ Call { destination : Some ( _) , cleanup : Some ( _) , .. } =>
429+ vec ! [ "return" . into_cow( ) , "unwind" . into_cow( ) ] ,
430+ Call { destination : Some ( _) , cleanup : None , .. } => vec ! [ "return" . into_cow( ) ] ,
431+ Call { destination : None , cleanup : Some ( _) , .. } => vec ! [ "unwind" . into_cow( ) ] ,
432+ Call { destination : None , cleanup : None , .. } => vec ! [ ] ,
433+ Drop { unwind : None , .. } => vec ! [ "return" . into_cow( ) ] ,
434+ Drop { .. } => vec ! [ "return" . into_cow( ) , "unwind" . into_cow( ) ] ,
476435 }
477436 }
478437}
@@ -490,23 +449,13 @@ pub struct Statement<'tcx> {
490449#[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
491450pub enum StatementKind < ' tcx > {
492451 Assign ( Lvalue < ' tcx > , Rvalue < ' tcx > ) ,
493- Drop ( DropKind , Lvalue < ' tcx > ) ,
494- }
495-
496- #[ derive( Copy , Clone , Debug , PartialEq , Eq , RustcEncodable , RustcDecodable ) ]
497- pub enum DropKind {
498- /// free a partially constructed box, should go away eventually
499- Free ,
500- Deep
501452}
502453
503454impl < ' tcx > Debug for Statement < ' tcx > {
504455 fn fmt ( & self , fmt : & mut Formatter ) -> fmt:: Result {
505456 use self :: StatementKind :: * ;
506457 match self . kind {
507- Assign ( ref lv, ref rv) => write ! ( fmt, "{:?} = {:?}" , lv, rv) ,
508- Drop ( DropKind :: Free , ref lv) => write ! ( fmt, "free {:?}" , lv) ,
509- Drop ( DropKind :: Deep , ref lv) => write ! ( fmt, "drop {:?}" , lv) ,
458+ Assign ( ref lv, ref rv) => write ! ( fmt, "{:?} = {:?}" , lv, rv)
510459 }
511460 }
512461}
0 commit comments