]> git.lizzy.rs Git - rust.git/blob - src/librustc/mir/visit.rs
hir, mir: Separate HIR expressions / MIR operands from InlineAsm.
[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 overridden.
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                 }
128             }
129
130             fn super_assign(&mut self,
131                             _block: BasicBlock,
132                             lvalue: &$($mutability)* Lvalue<'tcx>,
133                             rvalue: &$($mutability)* Rvalue<'tcx>) {
134                 self.visit_lvalue(lvalue, LvalueContext::Store);
135                 self.visit_rvalue(rvalue);
136             }
137
138             fn super_terminator(&mut self,
139                                 block: BasicBlock,
140                                 terminator: &$($mutability)* Terminator<'tcx>) {
141                 match *terminator {
142                     Terminator::Goto { target } => {
143                         self.visit_branch(block, target);
144                     }
145
146                     Terminator::If { ref $($mutability)* cond,
147                                      ref $($mutability)* targets } => {
148                         self.visit_operand(cond);
149                         for &target in targets.as_slice() {
150                             self.visit_branch(block, target);
151                         }
152                     }
153
154                     Terminator::Switch { ref $($mutability)* discr,
155                                          adt_def: _,
156                                          ref targets } => {
157                         self.visit_lvalue(discr, LvalueContext::Inspect);
158                         for &target in targets {
159                             self.visit_branch(block, target);
160                         }
161                     }
162
163                     Terminator::SwitchInt { ref $($mutability)* discr,
164                                             switch_ty: _,
165                                             values: _,
166                                             ref targets } => {
167                         self.visit_lvalue(discr, LvalueContext::Inspect);
168                         for &target in targets {
169                             self.visit_branch(block, target);
170                         }
171                     }
172
173                     Terminator::Resume |
174                     Terminator::Return => {
175                     }
176
177                     Terminator::Drop { ref $($mutability)* value, target, unwind } => {
178                         self.visit_lvalue(value, LvalueContext::Drop);
179                         self.visit_branch(block, target);
180                         unwind.map(|t| self.visit_branch(block, t));
181                     }
182
183                     Terminator::Call { ref $($mutability)* func,
184                                        ref $($mutability)* args,
185                                        ref $($mutability)* destination,
186                                        cleanup } => {
187                         self.visit_operand(func);
188                         for arg in args {
189                             self.visit_operand(arg);
190                         }
191                         if let Some((ref $($mutability)* destination, target)) = *destination {
192                             self.visit_lvalue(destination, LvalueContext::Store);
193                             self.visit_branch(block, target);
194                         }
195                         cleanup.map(|t| self.visit_branch(block, t));
196                     }
197                 }
198             }
199
200             fn super_rvalue(&mut self,
201                             rvalue: & $($mutability)* Rvalue<'tcx>) {
202                 match *rvalue {
203                     Rvalue::Use(ref $($mutability)* operand) => {
204                         self.visit_operand(operand);
205                     }
206
207                     Rvalue::Repeat(ref $($mutability)* value,
208                                    _) => {
209                         self.visit_operand(value);
210                     }
211
212                     Rvalue::Ref(r, bk, ref $($mutability)* path) => {
213                         self.visit_lvalue(path, LvalueContext::Borrow {
214                             region: r,
215                             kind: bk
216                         });
217                     }
218
219                     Rvalue::Len(ref $($mutability)* path) => {
220                         self.visit_lvalue(path, LvalueContext::Inspect);
221                     }
222
223                     Rvalue::Cast(_, ref $($mutability)* operand, _) => {
224                         self.visit_operand(operand);
225                     }
226
227                     Rvalue::BinaryOp(_,
228                                      ref $($mutability)* lhs,
229                                      ref $($mutability)* rhs) => {
230                         self.visit_operand(lhs);
231                         self.visit_operand(rhs);
232                     }
233
234                     Rvalue::UnaryOp(_, ref $($mutability)* op) => {
235                         self.visit_operand(op);
236                     }
237
238                     Rvalue::Box(_) => {
239                     }
240
241                     Rvalue::Aggregate(ref $($mutability)* kind,
242                                       ref $($mutability)* operands) => {
243                         match *kind {
244                             AggregateKind::Closure(ref $($mutability)* def_id, _) => {
245                                 self.visit_def_id(def_id);
246                             }
247                             _ => { /* nothing to do */ }
248                         }
249
250                         for operand in & $($mutability)* operands[..] {
251                             self.visit_operand(operand);
252                         }
253                     }
254
255                     Rvalue::Slice { ref $($mutability)* input,
256                                     from_start,
257                                     from_end } => {
258                         self.visit_lvalue(input, LvalueContext::Slice {
259                             from_start: from_start,
260                             from_end: from_end,
261                         });
262                     }
263
264                     Rvalue::InlineAsm { ref $($mutability)* outputs,
265                                         ref $($mutability)* inputs, .. } => {
266                         for output in & $($mutability)* outputs[..] {
267                             self.visit_lvalue(output, LvalueContext::Store);
268                         }
269                         for input in & $($mutability)* inputs[..] {
270                             self.visit_operand(input);
271                         }
272                     }
273                 }
274             }
275
276             fn super_operand(&mut self,
277                              operand: & $($mutability)* Operand<'tcx>) {
278                 match *operand {
279                     Operand::Consume(ref $($mutability)* lvalue) => {
280                         self.visit_lvalue(lvalue, LvalueContext::Consume);
281                     }
282                     Operand::Constant(ref $($mutability)* constant) => {
283                         self.visit_constant(constant);
284                     }
285                 }
286             }
287
288             fn super_lvalue(&mut self,
289                             lvalue: & $($mutability)* Lvalue<'tcx>,
290                             _context: LvalueContext) {
291                 match *lvalue {
292                     Lvalue::Var(_) |
293                     Lvalue::Temp(_) |
294                     Lvalue::Arg(_) |
295                     Lvalue::ReturnPointer => {
296                     }
297                     Lvalue::Static(ref $($mutability)* def_id) => {
298                         self.visit_def_id(def_id);
299                     }
300                     Lvalue::Projection(ref $($mutability)* proj) => {
301                         self.visit_lvalue(& $($mutability)* proj.base,
302                                           LvalueContext::Projection);
303                     }
304                 }
305             }
306
307             fn super_branch(&mut self,
308                             _source: BasicBlock,
309                             _target: BasicBlock) {
310             }
311
312             fn super_constant(&mut self,
313                               constant: & $($mutability)* Constant<'tcx>) {
314                 self.visit_span(& $($mutability)* constant.span);
315                 self.visit_literal(& $($mutability)* constant.literal);
316             }
317
318             fn super_literal(&mut self,
319                              literal: & $($mutability)* Literal<'tcx>) {
320                 match *literal {
321                     Literal::Item { ref $($mutability)* def_id, .. } => {
322                         self.visit_def_id(def_id);
323                     },
324                     Literal::Value { .. } => {
325                         // Nothing to do
326                     }
327                 }
328             }
329
330             fn super_def_id(&mut self, _def_id: & $($mutability)* DefId) {
331             }
332
333             fn super_span(&mut self, _span: & $($mutability)* Span) {
334             }
335         }
336     }
337 }
338
339 make_mir_visitor!(Visitor,);
340 make_mir_visitor!(MutVisitor,mut);
341
342 #[derive(Copy, Clone, Debug)]
343 pub enum LvalueContext {
344     // Appears as LHS of an assignment or as dest of a call
345     Store,
346
347     // Being dropped
348     Drop,
349
350     // Being inspected in some way, like loading a len
351     Inspect,
352
353     // Being borrowed
354     Borrow { region: Region, kind: BorrowKind },
355
356     // Being sliced -- this should be same as being borrowed, probably
357     Slice { from_start: usize, from_end: usize },
358
359     // Used as base for another lvalue, e.g. `x` in `x.y`
360     Projection,
361
362     // Consumed as part of an operand
363     Consume,
364 }