]>
Commit | Line | Data |
---|---|---|
dfeec247 XL |
1 | //! Routines for manipulating the control-flow graph. |
2 | ||
3 | use crate::build::CFG; | |
ba9703b0 | 4 | use rustc_middle::mir::*; |
5e7ed085 | 5 | use rustc_middle::ty::TyCtxt; |
dfeec247 XL |
6 | |
7 | impl<'tcx> CFG<'tcx> { | |
923072b8 | 8 | pub(crate) fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> { |
dfeec247 XL |
9 | &self.basic_blocks[blk] |
10 | } | |
11 | ||
923072b8 | 12 | pub(crate) fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> { |
dfeec247 XL |
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)] | |
923072b8 | 19 | pub(crate) fn start_new_block(&mut self) -> BasicBlock { |
dfeec247 XL |
20 | self.basic_blocks.push(BasicBlockData::new(None)) |
21 | } | |
22 | ||
923072b8 | 23 | pub(crate) fn start_new_cleanup_block(&mut self) -> BasicBlock { |
dfeec247 XL |
24 | let bb = self.start_new_block(); |
25 | self.block_data_mut(bb).is_cleanup = true; | |
26 | bb | |
27 | } | |
28 | ||
923072b8 | 29 | pub(crate) fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) { |
dfeec247 XL |
30 | debug!("push({:?}, {:?})", block, statement); |
31 | self.block_data_mut(block).statements.push(statement); | |
32 | } | |
33 | ||
923072b8 | 34 | pub(crate) fn push_assign( |
dfeec247 XL |
35 | &mut self, |
36 | block: BasicBlock, | |
37 | source_info: SourceInfo, | |
ba9703b0 | 38 | place: Place<'tcx>, |
dfeec247 XL |
39 | rvalue: Rvalue<'tcx>, |
40 | ) { | |
41 | self.push( | |
42 | block, | |
94222f64 | 43 | Statement { source_info, kind: StatementKind::Assign(Box::new((place, rvalue))) }, |
dfeec247 XL |
44 | ); |
45 | } | |
46 | ||
923072b8 | 47 | pub(crate) fn push_assign_constant( |
dfeec247 XL |
48 | &mut self, |
49 | block: BasicBlock, | |
50 | source_info: SourceInfo, | |
ba9703b0 | 51 | temp: Place<'tcx>, |
dfeec247 XL |
52 | constant: Constant<'tcx>, |
53 | ) { | |
94222f64 XL |
54 | self.push_assign( |
55 | block, | |
56 | source_info, | |
57 | temp, | |
58 | Rvalue::Use(Operand::Constant(Box::new(constant))), | |
59 | ); | |
dfeec247 XL |
60 | } |
61 | ||
923072b8 | 62 | pub(crate) fn push_assign_unit( |
dfeec247 XL |
63 | &mut self, |
64 | block: BasicBlock, | |
65 | source_info: SourceInfo, | |
ba9703b0 XL |
66 | place: Place<'tcx>, |
67 | tcx: TyCtxt<'tcx>, | |
dfeec247 XL |
68 | ) { |
69 | self.push_assign( | |
70 | block, | |
71 | source_info, | |
72 | place, | |
94222f64 | 73 | Rvalue::Use(Operand::Constant(Box::new(Constant { |
ba9703b0 XL |
74 | span: source_info.span, |
75 | user_ty: None, | |
04454e1e | 76 | literal: ConstantKind::zero_sized(tcx.types.unit), |
94222f64 | 77 | }))), |
dfeec247 XL |
78 | ); |
79 | } | |
80 | ||
923072b8 | 81 | pub(crate) fn push_fake_read( |
dfeec247 XL |
82 | &mut self, |
83 | block: BasicBlock, | |
84 | source_info: SourceInfo, | |
85 | cause: FakeReadCause, | |
86 | place: Place<'tcx>, | |
87 | ) { | |
94222f64 | 88 | let kind = StatementKind::FakeRead(Box::new((cause, place))); |
dfeec247 XL |
89 | let stmt = Statement { source_info, kind }; |
90 | self.push(block, stmt); | |
91 | } | |
92 | ||
353b0b11 FG |
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 | ||
923072b8 | 104 | pub(crate) fn terminate( |
dfeec247 XL |
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. | |
923072b8 | 121 | pub(crate) fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) { |
dfeec247 XL |
122 | self.terminate(origin, source_info, TerminatorKind::Goto { target }) |
123 | } | |
124 | } |