]> git.lizzy.rs Git - rust.git/blob - src/librustc_passes/mir_stats.rs
Auto merge of #47804 - retep007:recursive-requirements, r=pnkfelix
[rust.git] / src / librustc_passes / mir_stats.rs
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};
16 use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
17 use rustc::mir::{Constant, Literal, Location, Local, LocalDecl};
18 use rustc::mir::{Place, PlaceElem, PlaceProjection};
19 use rustc::mir::{Mir, Operand, ProjectionElem};
20 use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
21 use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData};
22 use rustc::mir::visit as mir_visit;
23 use rustc::ty::{self, ClosureSubsts, TyCtxt};
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
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     }
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",
88             StatementKind::EndRegion(..) => "StatementKind::EndRegion",
89             StatementKind::Validate(..) => "StatementKind::Validate",
90             StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
91             StatementKind::StorageLive(..) => "StatementKind::StorageLive",
92             StatementKind::StorageDead(..) => "StatementKind::StorageDead",
93             StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
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",
114             TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
115             TerminatorKind::Resume => "TerminatorKind::Resume",
116             TerminatorKind::Abort => "TerminatorKind::Abort",
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",
123             TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
124             TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
125             TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
126             TerminatorKind::FalseUnwind { .. } => "TerminatorKind::FalseUnwind",
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",
138             AssertMessage::GeneratorResumedAfterReturn => {
139                 "AssertMessage::GeneratorResumedAfterReturn"
140             }
141             AssertMessage::GeneratorResumedAfterPanic => {
142                 "AssertMessage::GeneratorResumedAfterPanic"
143             }
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",
161             Rvalue::Discriminant(..) => "Rvalue::Discriminant",
162             Rvalue::NullaryOp(..) => "Rvalue::NullaryOp",
163             Rvalue::Aggregate(ref kind, ref _operands) => {
164                 // AggregateKind is not distinguished by visit API, so
165                 // record it. (`super_rvalue` handles `_operands`.)
166                 self.record(match **kind {
167                     AggregateKind::Array(_) => "AggregateKind::Array",
168                     AggregateKind::Tuple => "AggregateKind::Tuple",
169                     AggregateKind::Adt(..) => "AggregateKind::Adt",
170                     AggregateKind::Closure(..) => "AggregateKind::Closure",
171                     AggregateKind::Generator(..) => "AggregateKind::Generator",
172                 }, kind);
173
174                 "Rvalue::Aggregate"
175             }
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 {
186             Operand::Copy(..) => "Operand::Copy",
187             Operand::Move(..) => "Operand::Move",
188             Operand::Constant(..) => "Operand::Constant",
189         }, operand);
190         self.super_operand(operand, location);
191     }
192
193     fn visit_place(&mut self,
194                     place: &Place<'tcx>,
195                     context: mir_visit::PlaceContext<'tcx>,
196                     location: Location) {
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);
204     }
205
206     fn visit_projection(&mut self,
207                         place: &PlaceProjection<'tcx>,
208                         context: mir_visit::PlaceContext<'tcx>,
209                         location: Location) {
210         self.record("PlaceProjection", place);
211         self.super_projection(place, context, location);
212     }
213
214     fn visit_projection_elem(&mut self,
215                              place: &PlaceElem<'tcx>,
216                              context: mir_visit::PlaceContext<'tcx>,
217                              location: Location) {
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);
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 {
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,
255                             substs: &ClosureSubsts<'tcx>,
256                             _: Location) {
257         self.record("ClosureSubsts", substs);
258         self.super_closure_substs(substs);
259     }
260
261     fn visit_const(&mut self,
262                    constant: &&'tcx ty::Const<'tcx>,
263                    _: Location) {
264         self.record("Const", constant);
265         self.super_const(constant);
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
275     fn visit_local_decl(&mut self,
276                         local: Local,
277                         local_decl: &LocalDecl<'tcx>) {
278         self.record("LocalDecl", local_decl);
279         self.super_local_decl(local, local_decl);
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 }