]>
Commit | Line | Data |
---|---|---|
dfeec247 XL |
1 | //! Routines for manipulating the control-flow graph. |
2 | ||
3 | use crate::build::CFG; | |
ba9703b0 XL |
4 | use rustc_middle::mir::*; |
5 | use rustc_middle::ty::{self, TyCtxt}; | |
dfeec247 XL |
6 | |
7 | impl<'tcx> CFG<'tcx> { | |
8 | crate fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> { | |
9 | &self.basic_blocks[blk] | |
10 | } | |
11 | ||
12 | 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)] | |
19 | crate fn start_new_block(&mut self) -> BasicBlock { | |
20 | self.basic_blocks.push(BasicBlockData::new(None)) | |
21 | } | |
22 | ||
23 | 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 | ||
29 | 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 | ||
34 | crate fn push_assign( | |
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, | |
ba9703b0 | 43 | Statement { source_info, kind: StatementKind::Assign(box (place, rvalue)) }, |
dfeec247 XL |
44 | ); |
45 | } | |
46 | ||
47 | crate fn push_assign_constant( | |
48 | &mut self, | |
49 | block: BasicBlock, | |
50 | source_info: SourceInfo, | |
ba9703b0 | 51 | temp: Place<'tcx>, |
dfeec247 XL |
52 | constant: Constant<'tcx>, |
53 | ) { | |
54 | self.push_assign(block, source_info, temp, Rvalue::Use(Operand::Constant(box constant))); | |
55 | } | |
56 | ||
57 | crate fn push_assign_unit( | |
58 | &mut self, | |
59 | block: BasicBlock, | |
60 | source_info: SourceInfo, | |
ba9703b0 XL |
61 | place: Place<'tcx>, |
62 | tcx: TyCtxt<'tcx>, | |
dfeec247 XL |
63 | ) { |
64 | self.push_assign( | |
65 | block, | |
66 | source_info, | |
67 | place, | |
ba9703b0 XL |
68 | Rvalue::Use(Operand::Constant(box Constant { |
69 | span: source_info.span, | |
70 | user_ty: None, | |
6a06907d | 71 | literal: ty::Const::zero_sized(tcx, tcx.types.unit).into(), |
ba9703b0 | 72 | })), |
dfeec247 XL |
73 | ); |
74 | } | |
75 | ||
76 | crate fn push_fake_read( | |
77 | &mut self, | |
78 | block: BasicBlock, | |
79 | source_info: SourceInfo, | |
80 | cause: FakeReadCause, | |
81 | place: Place<'tcx>, | |
82 | ) { | |
83 | let kind = StatementKind::FakeRead(cause, box place); | |
84 | let stmt = Statement { source_info, kind }; | |
85 | self.push(block, stmt); | |
86 | } | |
87 | ||
88 | crate fn terminate( | |
89 | &mut self, | |
90 | block: BasicBlock, | |
91 | source_info: SourceInfo, | |
92 | kind: TerminatorKind<'tcx>, | |
93 | ) { | |
94 | debug!("terminating block {:?} <- {:?}", block, kind); | |
95 | debug_assert!( | |
96 | self.block_data(block).terminator.is_none(), | |
97 | "terminate: block {:?}={:?} already has a terminator set", | |
98 | block, | |
99 | self.block_data(block) | |
100 | ); | |
101 | self.block_data_mut(block).terminator = Some(Terminator { source_info, kind }); | |
102 | } | |
103 | ||
104 | /// In the `origin` block, push a `goto -> target` terminator. | |
105 | crate fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) { | |
106 | self.terminate(origin, source_info, TerminatorKind::Goto { target }) | |
107 | } | |
108 | } |