1 //! Routines for manipulating the control-flow graph. 2 3 use crate::build::CFG; 4 use rustc_middle::mir::*; 5 use rustc_middle::ty::TyCtxt; 6 7 impl<'tcx> CFG<'tcx> { block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx>8 pub(crate) fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> { 9 &self.basic_blocks[blk] 10 } 11 block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx>12 pub(crate) fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> { 13 &mut self.basic_blocks[blk] 14 } 15 16 // llvm.org/PR32488 makes this function use an excess of stack space. Mark 17 // it as #[inline(never)] to keep rustc's stack use in check. 18 #[inline(never)] start_new_block(&mut self) -> BasicBlock19 pub(crate) fn start_new_block(&mut self) -> BasicBlock { 20 self.basic_blocks.push(BasicBlockData::new(None)) 21 } 22 start_new_cleanup_block(&mut self) -> BasicBlock23 pub(crate) fn start_new_cleanup_block(&mut self) -> BasicBlock { 24 let bb = self.start_new_block(); 25 self.block_data_mut(bb).is_cleanup = true; 26 bb 27 } 28 push(&mut self, block: BasicBlock, statement: Statement<'tcx>)29 pub(crate) fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) { 30 debug!("push({:?}, {:?})", block, statement); 31 self.block_data_mut(block).statements.push(statement); 32 } 33 push_assign( &mut self, block: BasicBlock, source_info: SourceInfo, place: Place<'tcx>, rvalue: Rvalue<'tcx>, )34 pub(crate) fn push_assign( 35 &mut self, 36 block: BasicBlock, 37 source_info: SourceInfo, 38 place: Place<'tcx>, 39 rvalue: Rvalue<'tcx>, 40 ) { 41 self.push( 42 block, 43 Statement { source_info, kind: StatementKind::Assign(Box::new((place, rvalue))) }, 44 ); 45 } 46 push_assign_constant( &mut self, block: BasicBlock, source_info: SourceInfo, temp: Place<'tcx>, constant: Constant<'tcx>, )47 pub(crate) fn push_assign_constant( 48 &mut self, 49 block: BasicBlock, 50 source_info: SourceInfo, 51 temp: Place<'tcx>, 52 constant: Constant<'tcx>, 53 ) { 54 self.push_assign( 55 block, 56 source_info, 57 temp, 58 Rvalue::Use(Operand::Constant(Box::new(constant))), 59 ); 60 } 61 push_assign_unit( &mut self, block: BasicBlock, source_info: SourceInfo, place: Place<'tcx>, tcx: TyCtxt<'tcx>, )62 pub(crate) fn push_assign_unit( 63 &mut self, 64 block: BasicBlock, 65 source_info: SourceInfo, 66 place: Place<'tcx>, 67 tcx: TyCtxt<'tcx>, 68 ) { 69 self.push_assign( 70 block, 71 source_info, 72 place, 73 Rvalue::Use(Operand::Constant(Box::new(Constant { 74 span: source_info.span, 75 user_ty: None, 76 literal: ConstantKind::zero_sized(tcx.types.unit), 77 }))), 78 ); 79 } 80 push_fake_read( &mut self, block: BasicBlock, source_info: SourceInfo, cause: FakeReadCause, place: Place<'tcx>, )81 pub(crate) fn push_fake_read( 82 &mut self, 83 block: BasicBlock, 84 source_info: SourceInfo, 85 cause: FakeReadCause, 86 place: Place<'tcx>, 87 ) { 88 let kind = StatementKind::FakeRead(Box::new((cause, place))); 89 let stmt = Statement { source_info, kind }; 90 self.push(block, stmt); 91 } 92 push_place_mention( &mut self, block: BasicBlock, source_info: SourceInfo, place: Place<'tcx>, )93 pub(crate) fn push_place_mention( 94 &mut self, 95 block: BasicBlock, 96 source_info: SourceInfo, 97 place: Place<'tcx>, 98 ) { 99 let kind = StatementKind::PlaceMention(Box::new(place)); 100 let stmt = Statement { source_info, kind }; 101 self.push(block, stmt); 102 } 103 terminate( &mut self, block: BasicBlock, source_info: SourceInfo, kind: TerminatorKind<'tcx>, )104 pub(crate) fn terminate( 105 &mut self, 106 block: BasicBlock, 107 source_info: SourceInfo, 108 kind: TerminatorKind<'tcx>, 109 ) { 110 debug!("terminating block {:?} <- {:?}", block, kind); 111 debug_assert!( 112 self.block_data(block).terminator.is_none(), 113 "terminate: block {:?}={:?} already has a terminator set", 114 block, 115 self.block_data(block) 116 ); 117 self.block_data_mut(block).terminator = Some(Terminator { source_info, kind }); 118 } 119 120 /// In the `origin` block, push a `goto -> target` terminator. goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock)121 pub(crate) fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) { 122 self.terminate(origin, source_info, TerminatorKind::Goto { target }) 123 } 124 } 125