]>
Commit | Line | Data |
---|---|---|
f035d41b XL |
1 | //! A less precise version of `MaybeInitializedPlaces` whose domain is entire locals. |
2 | //! | |
3 | //! A local will be maybe initialized if *any* projections of that local might be initialized. | |
4 | ||
c295e0f8 | 5 | use crate::GenKill; |
f035d41b XL |
6 | |
7 | use rustc_index::bit_set::BitSet; | |
8 | use rustc_middle::mir::visit::{PlaceContext, Visitor}; | |
9 | use rustc_middle::mir::{self, BasicBlock, Local, Location}; | |
10 | ||
11 | pub struct MaybeInitializedLocals; | |
12 | ||
c295e0f8 | 13 | impl crate::AnalysisDomain<'tcx> for MaybeInitializedLocals { |
1b1a35ee | 14 | type Domain = BitSet<Local>; |
f035d41b XL |
15 | |
16 | const NAME: &'static str = "maybe_init_locals"; | |
17 | ||
1b1a35ee XL |
18 | fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { |
19 | // bottom = uninit | |
20 | BitSet::new_empty(body.local_decls.len()) | |
f035d41b XL |
21 | } |
22 | ||
1b1a35ee | 23 | fn initialize_start_block(&self, body: &mir::Body<'tcx>, entry_set: &mut Self::Domain) { |
f035d41b XL |
24 | // Function arguments are initialized to begin with. |
25 | for arg in body.args_iter() { | |
26 | entry_set.insert(arg); | |
27 | } | |
28 | } | |
29 | } | |
30 | ||
c295e0f8 | 31 | impl crate::GenKillAnalysis<'tcx> for MaybeInitializedLocals { |
1b1a35ee XL |
32 | type Idx = Local; |
33 | ||
f035d41b XL |
34 | fn statement_effect( |
35 | &self, | |
36 | trans: &mut impl GenKill<Self::Idx>, | |
37 | statement: &mir::Statement<'tcx>, | |
38 | loc: Location, | |
39 | ) { | |
40 | TransferFunction { trans }.visit_statement(statement, loc) | |
41 | } | |
42 | ||
43 | fn terminator_effect( | |
44 | &self, | |
45 | trans: &mut impl GenKill<Self::Idx>, | |
46 | terminator: &mir::Terminator<'tcx>, | |
47 | loc: Location, | |
48 | ) { | |
49 | TransferFunction { trans }.visit_terminator(terminator, loc) | |
50 | } | |
51 | ||
52 | fn call_return_effect( | |
53 | &self, | |
54 | trans: &mut impl GenKill<Self::Idx>, | |
55 | _block: BasicBlock, | |
56 | _func: &mir::Operand<'tcx>, | |
57 | _args: &[mir::Operand<'tcx>], | |
58 | return_place: mir::Place<'tcx>, | |
59 | ) { | |
60 | trans.gen(return_place.local) | |
61 | } | |
62 | ||
63 | /// See `Analysis::apply_yield_resume_effect`. | |
64 | fn yield_resume_effect( | |
65 | &self, | |
66 | trans: &mut impl GenKill<Self::Idx>, | |
67 | _resume_block: BasicBlock, | |
68 | resume_place: mir::Place<'tcx>, | |
69 | ) { | |
70 | trans.gen(resume_place.local) | |
71 | } | |
72 | } | |
73 | ||
74 | struct TransferFunction<'a, T> { | |
75 | trans: &'a mut T, | |
76 | } | |
77 | ||
78 | impl<T> Visitor<'tcx> for TransferFunction<'a, T> | |
79 | where | |
80 | T: GenKill<Local>, | |
81 | { | |
82 | fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) { | |
83 | use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, NonUseContext}; | |
84 | match context { | |
85 | // These are handled specially in `call_return_effect` and `yield_resume_effect`. | |
86 | PlaceContext::MutatingUse(MutatingUseContext::Call | MutatingUseContext::Yield) => {} | |
87 | ||
88 | // Otherwise, when a place is mutated, we must consider it possibly initialized. | |
89 | PlaceContext::MutatingUse(_) => self.trans.gen(local), | |
90 | ||
91 | // If the local is moved out of, or if it gets marked `StorageDead`, consider it no | |
92 | // longer initialized. | |
93 | PlaceContext::NonUse(NonUseContext::StorageDead) | |
94 | | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => self.trans.kill(local), | |
95 | ||
96 | // All other uses do not affect this analysis. | |
97 | PlaceContext::NonUse( | |
98 | NonUseContext::StorageLive | |
99 | | NonUseContext::AscribeUserTy | |
100 | | NonUseContext::VarDebugInfo, | |
101 | ) | |
102 | | PlaceContext::NonMutatingUse( | |
103 | NonMutatingUseContext::Inspect | |
104 | | NonMutatingUseContext::Copy | |
105 | | NonMutatingUseContext::SharedBorrow | |
106 | | NonMutatingUseContext::ShallowBorrow | |
107 | | NonMutatingUseContext::UniqueBorrow | |
108 | | NonMutatingUseContext::AddressOf | |
109 | | NonMutatingUseContext::Projection, | |
110 | ) => {} | |
111 | } | |
112 | } | |
113 | } |