]>
Commit | Line | Data |
---|---|---|
476ff2be SL |
1 | // Copyright 2016 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | // The visitors in this module collect sizes and counts of the most important | |
12 | // pieces of MIR. The resulting numbers are good approximations but not | |
13 | // completely accurate (some things might be counted twice, others missed). | |
14 | ||
15 | use rustc_const_math::{ConstUsize}; | |
476ff2be | 16 | use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData}; |
abe05a73 | 17 | use rustc::mir::{Constant, Literal, Location, Local, LocalDecl}; |
ff7c6d11 | 18 | use rustc::mir::{Place, PlaceElem, PlaceProjection}; |
476ff2be SL |
19 | use rustc::mir::{Mir, Operand, ProjectionElem}; |
20 | use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind}; | |
8bb4bdeb | 21 | use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData}; |
476ff2be | 22 | use rustc::mir::visit as mir_visit; |
ea8adc8c | 23 | use rustc::ty::{self, ClosureSubsts, TyCtxt}; |
476ff2be SL |
24 | use rustc::util::nodemap::{FxHashMap}; |
25 | ||
26 | struct NodeData { | |
27 | count: usize, | |
28 | size: usize, | |
29 | } | |
30 | ||
31 | struct StatCollector<'a, 'tcx: 'a> { | |
32 | _tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
33 | data: FxHashMap<&'static str, NodeData>, | |
34 | } | |
35 | ||
476ff2be SL |
36 | impl<'a, 'tcx> StatCollector<'a, 'tcx> { |
37 | ||
38 | fn record_with_size(&mut self, label: &'static str, node_size: usize) { | |
39 | let entry = self.data.entry(label).or_insert(NodeData { | |
40 | count: 0, | |
41 | size: 0, | |
42 | }); | |
43 | ||
44 | entry.count += 1; | |
45 | entry.size = node_size; | |
46 | } | |
47 | ||
48 | fn record<T>(&mut self, label: &'static str, node: &T) { | |
49 | self.record_with_size(label, ::std::mem::size_of_val(node)); | |
50 | } | |
476ff2be SL |
51 | } |
52 | ||
53 | impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { | |
54 | fn visit_mir(&mut self, mir: &Mir<'tcx>) { | |
55 | self.record("Mir", mir); | |
56 | ||
57 | // since the `super_mir` method does not traverse the MIR of | |
58 | // promoted rvalues, (but we still want to gather statistics | |
59 | // on the structures represented there) we manually traverse | |
60 | // the promoted rvalues here. | |
61 | for promoted_mir in &mir.promoted { | |
62 | self.visit_mir(promoted_mir); | |
63 | } | |
64 | ||
65 | self.super_mir(mir); | |
66 | } | |
67 | ||
68 | fn visit_basic_block_data(&mut self, | |
69 | block: BasicBlock, | |
70 | data: &BasicBlockData<'tcx>) { | |
71 | self.record("BasicBlockData", data); | |
72 | self.super_basic_block_data(block, data); | |
73 | } | |
74 | ||
75 | fn visit_visibility_scope_data(&mut self, | |
76 | scope_data: &VisibilityScopeData) { | |
77 | self.record("VisibilityScopeData", scope_data); | |
78 | self.super_visibility_scope_data(scope_data); | |
79 | } | |
80 | ||
81 | fn visit_statement(&mut self, | |
82 | block: BasicBlock, | |
83 | statement: &Statement<'tcx>, | |
84 | location: Location) { | |
85 | self.record("Statement", statement); | |
86 | self.record(match statement.kind { | |
87 | StatementKind::Assign(..) => "StatementKind::Assign", | |
041b39d2 | 88 | StatementKind::EndRegion(..) => "StatementKind::EndRegion", |
3b2f2976 | 89 | StatementKind::Validate(..) => "StatementKind::Validate", |
476ff2be SL |
90 | StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant", |
91 | StatementKind::StorageLive(..) => "StatementKind::StorageLive", | |
92 | StatementKind::StorageDead(..) => "StatementKind::StorageDead", | |
8bb4bdeb | 93 | StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm", |
476ff2be SL |
94 | StatementKind::Nop => "StatementKind::Nop", |
95 | }, &statement.kind); | |
96 | self.super_statement(block, statement, location); | |
97 | } | |
98 | ||
99 | fn visit_terminator(&mut self, | |
100 | block: BasicBlock, | |
101 | terminator: &Terminator<'tcx>, | |
102 | location: Location) { | |
103 | self.record("Terminator", terminator); | |
104 | self.super_terminator(block, terminator, location); | |
105 | } | |
106 | ||
107 | fn visit_terminator_kind(&mut self, | |
108 | block: BasicBlock, | |
109 | kind: &TerminatorKind<'tcx>, | |
110 | location: Location) { | |
111 | self.record("TerminatorKind", kind); | |
112 | self.record(match *kind { | |
113 | TerminatorKind::Goto { .. } => "TerminatorKind::Goto", | |
476ff2be SL |
114 | TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt", |
115 | TerminatorKind::Resume => "TerminatorKind::Resume", | |
ff7c6d11 | 116 | TerminatorKind::Abort => "TerminatorKind::Abort", |
476ff2be SL |
117 | TerminatorKind::Return => "TerminatorKind::Return", |
118 | TerminatorKind::Unreachable => "TerminatorKind::Unreachable", | |
119 | TerminatorKind::Drop { .. } => "TerminatorKind::Drop", | |
120 | TerminatorKind::DropAndReplace { .. } => "TerminatorKind::DropAndReplace", | |
121 | TerminatorKind::Call { .. } => "TerminatorKind::Call", | |
122 | TerminatorKind::Assert { .. } => "TerminatorKind::Assert", | |
ea8adc8c XL |
123 | TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop", |
124 | TerminatorKind::Yield { .. } => "TerminatorKind::Yield", | |
abe05a73 | 125 | TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges", |
2c00a5a8 | 126 | TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind", |
476ff2be SL |
127 | }, kind); |
128 | self.super_terminator_kind(block, kind, location); | |
129 | } | |
130 | ||
131 | fn visit_assert_message(&mut self, | |
132 | msg: &AssertMessage<'tcx>, | |
133 | location: Location) { | |
134 | self.record("AssertMessage", msg); | |
135 | self.record(match *msg { | |
136 | AssertMessage::BoundsCheck { .. } => "AssertMessage::BoundsCheck", | |
137 | AssertMessage::Math(..) => "AssertMessage::Math", | |
ea8adc8c XL |
138 | AssertMessage::GeneratorResumedAfterReturn => { |
139 | "AssertMessage::GeneratorResumedAfterReturn" | |
140 | } | |
141 | AssertMessage::GeneratorResumedAfterPanic => { | |
142 | "AssertMessage::GeneratorResumedAfterPanic" | |
143 | } | |
476ff2be SL |
144 | }, msg); |
145 | self.super_assert_message(msg, location); | |
146 | } | |
147 | ||
148 | fn visit_rvalue(&mut self, | |
149 | rvalue: &Rvalue<'tcx>, | |
150 | location: Location) { | |
151 | self.record("Rvalue", rvalue); | |
152 | let rvalue_kind = match *rvalue { | |
153 | Rvalue::Use(..) => "Rvalue::Use", | |
154 | Rvalue::Repeat(..) => "Rvalue::Repeat", | |
155 | Rvalue::Ref(..) => "Rvalue::Ref", | |
156 | Rvalue::Len(..) => "Rvalue::Len", | |
157 | Rvalue::Cast(..) => "Rvalue::Cast", | |
158 | Rvalue::BinaryOp(..) => "Rvalue::BinaryOp", | |
159 | Rvalue::CheckedBinaryOp(..) => "Rvalue::CheckedBinaryOp", | |
160 | Rvalue::UnaryOp(..) => "Rvalue::UnaryOp", | |
8bb4bdeb | 161 | Rvalue::Discriminant(..) => "Rvalue::Discriminant", |
7cac9316 | 162 | Rvalue::NullaryOp(..) => "Rvalue::NullaryOp", |
476ff2be SL |
163 | Rvalue::Aggregate(ref kind, ref _operands) => { |
164 | // AggregateKind is not distinguished by visit API, so | |
165 | // record it. (`super_rvalue` handles `_operands`.) | |
cc61c64b | 166 | self.record(match **kind { |
8bb4bdeb | 167 | AggregateKind::Array(_) => "AggregateKind::Array", |
476ff2be SL |
168 | AggregateKind::Tuple => "AggregateKind::Tuple", |
169 | AggregateKind::Adt(..) => "AggregateKind::Adt", | |
170 | AggregateKind::Closure(..) => "AggregateKind::Closure", | |
ea8adc8c | 171 | AggregateKind::Generator(..) => "AggregateKind::Generator", |
476ff2be SL |
172 | }, kind); |
173 | ||
174 | "Rvalue::Aggregate" | |
175 | } | |
476ff2be SL |
176 | }; |
177 | self.record(rvalue_kind, rvalue); | |
178 | self.super_rvalue(rvalue, location); | |
179 | } | |
180 | ||
181 | fn visit_operand(&mut self, | |
182 | operand: &Operand<'tcx>, | |
183 | location: Location) { | |
184 | self.record("Operand", operand); | |
185 | self.record(match *operand { | |
ff7c6d11 XL |
186 | Operand::Copy(..) => "Operand::Copy", |
187 | Operand::Move(..) => "Operand::Move", | |
476ff2be SL |
188 | Operand::Constant(..) => "Operand::Constant", |
189 | }, operand); | |
190 | self.super_operand(operand, location); | |
191 | } | |
192 | ||
ff7c6d11 XL |
193 | fn visit_place(&mut self, |
194 | place: &Place<'tcx>, | |
195 | context: mir_visit::PlaceContext<'tcx>, | |
476ff2be | 196 | location: Location) { |
ff7c6d11 XL |
197 | self.record("Place", place); |
198 | self.record(match *place { | |
199 | Place::Local(..) => "Place::Local", | |
200 | Place::Static(..) => "Place::Static", | |
201 | Place::Projection(..) => "Place::Projection", | |
202 | }, place); | |
203 | self.super_place(place, context, location); | |
476ff2be SL |
204 | } |
205 | ||
206 | fn visit_projection(&mut self, | |
ff7c6d11 XL |
207 | place: &PlaceProjection<'tcx>, |
208 | context: mir_visit::PlaceContext<'tcx>, | |
476ff2be | 209 | location: Location) { |
ff7c6d11 XL |
210 | self.record("PlaceProjection", place); |
211 | self.super_projection(place, context, location); | |
476ff2be SL |
212 | } |
213 | ||
214 | fn visit_projection_elem(&mut self, | |
ff7c6d11 XL |
215 | place: &PlaceElem<'tcx>, |
216 | context: mir_visit::PlaceContext<'tcx>, | |
476ff2be | 217 | location: Location) { |
ff7c6d11 XL |
218 | self.record("PlaceElem", place); |
219 | self.record(match *place { | |
220 | ProjectionElem::Deref => "PlaceElem::Deref", | |
221 | ProjectionElem::Subslice { .. } => "PlaceElem::Subslice", | |
222 | ProjectionElem::Field(..) => "PlaceElem::Field", | |
223 | ProjectionElem::Index(..) => "PlaceElem::Index", | |
224 | ProjectionElem::ConstantIndex { .. } => "PlaceElem::ConstantIndex", | |
225 | ProjectionElem::Downcast(..) => "PlaceElem::Downcast", | |
226 | }, place); | |
227 | self.super_projection_elem(place, context, location); | |
476ff2be SL |
228 | } |
229 | ||
230 | fn visit_constant(&mut self, | |
231 | constant: &Constant<'tcx>, | |
232 | location: Location) { | |
233 | self.record("Constant", constant); | |
234 | self.super_constant(constant, location); | |
235 | } | |
236 | ||
237 | fn visit_literal(&mut self, | |
238 | literal: &Literal<'tcx>, | |
239 | location: Location) { | |
240 | self.record("Literal", literal); | |
241 | self.record(match *literal { | |
476ff2be SL |
242 | Literal::Value { .. } => "Literal::Value", |
243 | Literal::Promoted { .. } => "Literal::Promoted", | |
244 | }, literal); | |
245 | self.super_literal(literal, location); | |
246 | } | |
247 | ||
248 | fn visit_source_info(&mut self, | |
249 | source_info: &SourceInfo) { | |
250 | self.record("SourceInfo", source_info); | |
251 | self.super_source_info(source_info); | |
252 | } | |
253 | ||
254 | fn visit_closure_substs(&mut self, | |
3b2f2976 XL |
255 | substs: &ClosureSubsts<'tcx>, |
256 | _: Location) { | |
476ff2be SL |
257 | self.record("ClosureSubsts", substs); |
258 | self.super_closure_substs(substs); | |
259 | } | |
260 | ||
ea8adc8c XL |
261 | fn visit_const(&mut self, |
262 | constant: &&'tcx ty::Const<'tcx>, | |
263 | _: Location) { | |
264 | self.record("Const", constant); | |
265 | self.super_const(constant); | |
476ff2be SL |
266 | } |
267 | ||
268 | fn visit_const_usize(&mut self, | |
269 | const_usize: &ConstUsize, | |
270 | _: Location) { | |
271 | self.record("ConstUsize", const_usize); | |
272 | self.super_const_usize(const_usize); | |
273 | } | |
274 | ||
476ff2be | 275 | fn visit_local_decl(&mut self, |
abe05a73 | 276 | local: Local, |
476ff2be SL |
277 | local_decl: &LocalDecl<'tcx>) { |
278 | self.record("LocalDecl", local_decl); | |
abe05a73 | 279 | self.super_local_decl(local, local_decl); |
476ff2be SL |
280 | } |
281 | ||
282 | fn visit_visibility_scope(&mut self, | |
283 | scope: &VisibilityScope) { | |
284 | self.record("VisiblityScope", scope); | |
285 | self.super_visibility_scope(scope); | |
286 | } | |
287 | } |