]> git.lizzy.rs Git - rust.git/blob - src/librustc/mir/visit.rs
Rollup merge of #30959 - bluss:bench-resolution, r=Gankro
[rust.git] / src / librustc / mir / visit.rs
1 // Copyright 2012-2014 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 use middle::def_id::DefId;
12 use middle::ty::Region;
13 use mir::repr::*;
14 use rustc_data_structures::tuple_slice::TupleSlice;
15 use syntax::codemap::Span;
16
17 macro_rules! make_mir_visitor {
18     ($visitor_trait_name:ident, $($mutability:ident)*) => {
19         pub trait $visitor_trait_name<'tcx> {
20             // Override these, and call `self.super_xxx` to revert back to the
21             // default behavior.
22
23             fn visit_mir(&mut self, mir: & $($mutability)* Mir<'tcx>) {
24                 self.super_mir(mir);
25             }
26
27             fn visit_basic_block_data(&mut self,
28                                       block: BasicBlock,
29                                       data: & $($mutability)* BasicBlockData<'tcx>) {
30                 self.super_basic_block_data(block, data);
31             }
32
33             fn visit_statement(&mut self,
34                                block: BasicBlock,
35                                statement: & $($mutability)* Statement<'tcx>) {
36                 self.super_statement(block, statement);
37             }
38
39             fn visit_assign(&mut self,
40                             block: BasicBlock,
41                             lvalue: & $($mutability)* Lvalue<'tcx>,
42                             rvalue: & $($mutability)* Rvalue<'tcx>) {
43                 self.super_assign(block, lvalue, rvalue);
44             }
45
46             fn visit_terminator(&mut self,
47                                 block: BasicBlock,
48                                 terminator: & $($mutability)* Terminator<'tcx>) {
49                 self.super_terminator(block, terminator);
50             }
51
52             fn visit_rvalue(&mut self,
53                             rvalue: & $($mutability)* Rvalue<'tcx>) {
54                 self.super_rvalue(rvalue);
55             }
56
57             fn visit_operand(&mut self,
58                              operand: & $($mutability)* Operand<'tcx>) {
59                 self.super_operand(operand);
60             }
61
62             fn visit_lvalue(&mut self,
63                             lvalue: & $($mutability)* Lvalue<'tcx>,
64                             context: LvalueContext) {
65                 self.super_lvalue(lvalue, context);
66             }
67
68             fn visit_branch(&mut self,
69                             source: BasicBlock,
70                             target: BasicBlock) {
71                 self.super_branch(source, target);
72             }
73
74             fn visit_constant(&mut self,
75                               constant: & $($mutability)* Constant<'tcx>) {
76                 self.super_constant(constant);
77             }
78
79             fn visit_literal(&mut self,
80                              literal: & $($mutability)* Literal<'tcx>) {
81                 self.super_literal(literal);
82             }
83
84             fn visit_def_id(&mut self,
85                             def_id: & $($mutability)* DefId) {
86                 self.super_def_id(def_id);
87             }
88
89             fn visit_span(&mut self,
90                           span: & $($mutability)* Span) {
91                 self.super_span(span);
92             }
93
94             // The `super_xxx` methods comprise the default behavior and are
95             // not meant to be overidden.
96
97             fn super_mir(&mut self,
98                          mir: & $($mutability)* Mir<'tcx>) {
99                 for block in mir.all_basic_blocks() {
100                     let data = & $($mutability)* mir[block];
101                     self.visit_basic_block_data(block, data);
102                 }
103             }
104
105             fn super_basic_block_data(&mut self,
106                                       block: BasicBlock,
107                                       data: & $($mutability)* BasicBlockData<'tcx>) {
108                 for statement in & $($mutability)* data.statements {
109                     self.visit_statement(block, statement);
110                 }
111
112                 if let Some(ref $($mutability)* terminator) = data.terminator {
113                     self.visit_terminator(block, terminator);
114                 }
115             }
116
117             fn super_statement(&mut self,
118                                block: BasicBlock,
119                                statement: & $($mutability)* Statement<'tcx>) {
120                 self.visit_span(& $($mutability)* statement.span);
121
122                 match statement.kind {
123                     StatementKind::Assign(ref $($mutability)* lvalue,
124                                           ref $($mutability)* rvalue) => {
125                         self.visit_assign(block, lvalue, rvalue);
126                     }
127                     StatementKind::Drop(_, ref $($mutability)* lvalue) => {
128                         self.visit_lvalue(lvalue, LvalueContext::Drop);
129                     }
130                 }
131             }
132
133             fn super_assign(&mut self,
134                             _block: BasicBlock,
135                             lvalue: &$($mutability)* Lvalue<'tcx>,
136                             rvalue: &$($mutability)* Rvalue<'tcx>) {
137                 self.visit_lvalue(lvalue, LvalueContext::Store);
138                 self.visit_rvalue(rvalue);
139             }
140
141             fn super_terminator(&mut self,
142                                 block: BasicBlock,
143                                 terminator: &$($mutability)* Terminator<'tcx>) {
144                 match *terminator {
145                     Terminator::Goto { target } => {
146                         self.visit_branch(block, target);
147                     }
148
149                     Terminator::If { ref $($mutability)* cond,
150                                      ref $($mutability)* targets } => {
151                         self.visit_operand(cond);
152                         for &target in targets.as_slice() {
153                             self.visit_branch(block, target);
154                         }
155                     }
156
157                     Terminator::Switch { ref $($mutability)* discr,
158                                          adt_def: _,
159                                          ref targets } => {
160                         self.visit_lvalue(discr, LvalueContext::Inspect);
161                         for &target in targets {
162                             self.visit_branch(block, target);
163                         }
164                     }
165
166                     Terminator::SwitchInt { ref $($mutability)* discr,
167                                             switch_ty: _,
168                                             values: _,
169                                             ref targets } => {
170                         self.visit_lvalue(discr, LvalueContext::Inspect);
171                         for &target in targets {
172                             self.visit_branch(block, target);
173                         }
174                     }
175
176                     Terminator::Resume |
177                     Terminator::Return => {
178                     }
179
180                     Terminator::Call { ref $($mutability)* func,
181                                        ref $($mutability)* args,
182                                        ref $($mutability)* kind } => {
183                         self.visit_operand(func);
184                         for arg in args {
185                             self.visit_operand(arg);
186                         }
187                         match *kind {
188                             CallKind::Converging {
189                                 ref $($mutability)* destination,
190                                 ..
191                             }        |
192                             CallKind::ConvergingCleanup {
193                                 ref $($mutability)* destination,
194                                 ..
195                             } => {
196                                 self.visit_lvalue(destination, LvalueContext::Store);
197                             }
198                             CallKind::Diverging           |
199                             CallKind::DivergingCleanup(_) => {}
200                         }
201                         for &target in kind.successors() {
202                             self.visit_branch(block, target);
203                         }
204                     }
205                 }
206             }
207
208             fn super_rvalue(&mut self,
209                             rvalue: & $($mutability)* Rvalue<'tcx>) {
210                 match *rvalue {
211                     Rvalue::Use(ref $($mutability)* operand) => {
212                         self.visit_operand(operand);
213                     }
214
215                     Rvalue::Repeat(ref $($mutability)* value,
216                                    ref $($mutability)* len) => {
217                         self.visit_operand(value);
218                         self.visit_constant(len);
219                     }
220
221                     Rvalue::Ref(r, bk, ref $($mutability)* path) => {
222                         self.visit_lvalue(path, LvalueContext::Borrow {
223                             region: r,
224                             kind: bk
225                         });
226                     }
227
228                     Rvalue::Len(ref $($mutability)* path) => {
229                         self.visit_lvalue(path, LvalueContext::Inspect);
230                     }
231
232                     Rvalue::Cast(_, ref $($mutability)* operand, _) => {
233                         self.visit_operand(operand);
234                     }
235
236                     Rvalue::BinaryOp(_,
237                                      ref $($mutability)* lhs,
238                                      ref $($mutability)* rhs) => {
239                         self.visit_operand(lhs);
240                         self.visit_operand(rhs);
241                     }
242
243                     Rvalue::UnaryOp(_, ref $($mutability)* op) => {
244                         self.visit_operand(op);
245                     }
246
247                     Rvalue::Box(_) => {
248                     }
249
250                     Rvalue::Aggregate(ref $($mutability)* kind,
251                                       ref $($mutability)* operands) => {
252                         match *kind {
253                             AggregateKind::Closure(ref $($mutability)* def_id, _) => {
254                                 self.visit_def_id(def_id);
255                             }
256                             _ => { /* nothing to do */ }
257                         }
258
259                         for operand in & $($mutability)* operands[..] {
260                             self.visit_operand(operand);
261                         }
262                     }
263
264                     Rvalue::Slice { ref $($mutability)* input,
265                                     from_start,
266                                     from_end } => {
267                         self.visit_lvalue(input, LvalueContext::Slice {
268                             from_start: from_start,
269                             from_end: from_end,
270                         });
271                     }
272
273                     Rvalue::InlineAsm(_) => {
274                     }
275                 }
276             }
277
278             fn super_operand(&mut self,
279                              operand: & $($mutability)* Operand<'tcx>) {
280                 match *operand {
281                     Operand::Consume(ref $($mutability)* lvalue) => {
282                         self.visit_lvalue(lvalue, LvalueContext::Consume);
283                     }
284                     Operand::Constant(ref $($mutability)* constant) => {
285                         self.visit_constant(constant);
286                     }
287                 }
288             }
289
290             fn super_lvalue(&mut self,
291                             lvalue: & $($mutability)* Lvalue<'tcx>,
292                             _context: LvalueContext) {
293                 match *lvalue {
294                     Lvalue::Var(_) |
295                     Lvalue::Temp(_) |
296                     Lvalue::Arg(_) |
297                     Lvalue::ReturnPointer => {
298                     }
299                     Lvalue::Static(ref $($mutability)* def_id) => {
300                         self.visit_def_id(def_id);
301                     }
302                     Lvalue::Projection(ref $($mutability)* proj) => {
303                         self.visit_lvalue(& $($mutability)* proj.base,
304                                           LvalueContext::Projection);
305                     }
306                 }
307             }
308
309             fn super_branch(&mut self,
310                             _source: BasicBlock,
311                             _target: BasicBlock) {
312             }
313
314             fn super_constant(&mut self,
315                               constant: & $($mutability)* Constant<'tcx>) {
316                 self.visit_span(& $($mutability)* constant.span);
317                 self.visit_literal(& $($mutability)* constant.literal);
318             }
319
320             fn super_literal(&mut self,
321                              literal: & $($mutability)* Literal<'tcx>) {
322                 match *literal {
323                     Literal::Item { ref $($mutability)* def_id, .. } => {
324                         self.visit_def_id(def_id);
325                     },
326                     Literal::Value { .. } => {
327                         // Nothing to do
328                     }
329                 }
330             }
331
332             fn super_def_id(&mut self, _def_id: & $($mutability)* DefId) {
333             }
334
335             fn super_span(&mut self, _span: & $($mutability)* Span) {
336             }
337         }
338     }
339 }
340
341 make_mir_visitor!(Visitor,);
342 make_mir_visitor!(MutVisitor,mut);
343
344 #[derive(Copy, Clone, Debug)]
345 pub enum LvalueContext {
346     // Appears as LHS of an assignment or as dest of a call
347     Store,
348
349     // Being dropped
350     Drop,
351
352     // Being inspected in some way, like loading a len
353     Inspect,
354
355     // Being borrowed
356     Borrow { region: Region, kind: BorrowKind },
357
358     // Being sliced -- this should be same as being borrowed, probably
359     Slice { from_start: usize, from_end: usize },
360
361     // Used as base for another lvalue, e.g. `x` in `x.y`
362     Projection,
363
364     // Consumed as part of an operand
365     Consume,
366 }