visit.rs 14.0 KB
Newer Older
N
Niko Matsakis 已提交
1 2 3 4 5 6 7 8 9 10
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
use middle::def_id::DefId;
12 13
use middle::ty::Region;
use mir::repr::*;
14
use rustc_data_structures::tuple_slice::TupleSlice;
15
use syntax::codemap::Span;
N
Niko Matsakis 已提交
16

17 18 19 20 21
macro_rules! make_mir_visitor {
    ($visitor_trait_name:ident, $($mutability:ident)*) => {
        pub trait $visitor_trait_name<'tcx> {
            // Override these, and call `self.super_xxx` to revert back to the
            // default behavior.
N
Niko Matsakis 已提交
22

23 24
            fn visit_mir(&mut self, mir: & $($mutability)* Mir<'tcx>) {
                self.super_mir(mir);
N
Niko Matsakis 已提交
25 26
            }

27 28 29 30
            fn visit_basic_block_data(&mut self,
                                      block: BasicBlock,
                                      data: & $($mutability)* BasicBlockData<'tcx>) {
                self.super_basic_block_data(block, data);
N
Niko Matsakis 已提交
31 32
            }

33 34 35 36
            fn visit_statement(&mut self,
                               block: BasicBlock,
                               statement: & $($mutability)* Statement<'tcx>) {
                self.super_statement(block, statement);
N
Niko Matsakis 已提交
37 38
            }

39 40 41 42 43
            fn visit_assign(&mut self,
                            block: BasicBlock,
                            lvalue: & $($mutability)* Lvalue<'tcx>,
                            rvalue: & $($mutability)* Rvalue<'tcx>) {
                self.super_assign(block, lvalue, rvalue);
N
Niko Matsakis 已提交
44 45
            }

46 47 48 49
            fn visit_terminator(&mut self,
                                block: BasicBlock,
                                terminator: & $($mutability)* Terminator<'tcx>) {
                self.super_terminator(block, terminator);
50 51
            }

52 53 54
            fn visit_rvalue(&mut self,
                            rvalue: & $($mutability)* Rvalue<'tcx>) {
                self.super_rvalue(rvalue);
N
Niko Matsakis 已提交
55 56
            }

57 58 59
            fn visit_operand(&mut self,
                             operand: & $($mutability)* Operand<'tcx>) {
                self.super_operand(operand);
60
            }
N
Niko Matsakis 已提交
61

62 63 64 65
            fn visit_lvalue(&mut self,
                            lvalue: & $($mutability)* Lvalue<'tcx>,
                            context: LvalueContext) {
                self.super_lvalue(lvalue, context);
N
Niko Matsakis 已提交
66 67
            }

68 69 70 71
            fn visit_branch(&mut self,
                            source: BasicBlock,
                            target: BasicBlock) {
                self.super_branch(source, target);
N
Niko Matsakis 已提交
72 73
            }

74 75 76
            fn visit_constant(&mut self,
                              constant: & $($mutability)* Constant<'tcx>) {
                self.super_constant(constant);
N
Niko Matsakis 已提交
77 78
            }

79 80 81
            fn visit_literal(&mut self,
                             literal: & $($mutability)* Literal<'tcx>) {
                self.super_literal(literal);
N
Niko Matsakis 已提交
82 83
            }

84 85 86
            fn visit_def_id(&mut self,
                            def_id: & $($mutability)* DefId) {
                self.super_def_id(def_id);
N
Niko Matsakis 已提交
87 88
            }

89 90 91
            fn visit_span(&mut self,
                          span: & $($mutability)* Span) {
                self.super_span(span);
N
Niko Matsakis 已提交
92 93
            }

94
            // The `super_xxx` methods comprise the default behavior and are
C
Carlos E. Garcia 已提交
95
            // not meant to be overridden.
N
Niko Matsakis 已提交
96

97 98 99 100 101 102
            fn super_mir(&mut self,
                         mir: & $($mutability)* Mir<'tcx>) {
                for block in mir.all_basic_blocks() {
                    let data = & $($mutability)* mir[block];
                    self.visit_basic_block_data(block, data);
                }
N
Niko Matsakis 已提交
103 104
            }

105 106 107 108 109
            fn super_basic_block_data(&mut self,
                                      block: BasicBlock,
                                      data: & $($mutability)* BasicBlockData<'tcx>) {
                for statement in & $($mutability)* data.statements {
                    self.visit_statement(block, statement);
N
Niko Matsakis 已提交
110 111
                }

112 113 114
                if let Some(ref $($mutability)* terminator) = data.terminator {
                    self.visit_terminator(block, terminator);
                }
N
Niko Matsakis 已提交
115 116
            }

117 118 119 120
            fn super_statement(&mut self,
                               block: BasicBlock,
                               statement: & $($mutability)* Statement<'tcx>) {
                self.visit_span(& $($mutability)* statement.span);
N
Niko Matsakis 已提交
121

122 123 124 125 126 127
                match statement.kind {
                    StatementKind::Assign(ref $($mutability)* lvalue,
                                          ref $($mutability)* rvalue) => {
                        self.visit_assign(block, lvalue, rvalue);
                    }
                }
N
Niko Matsakis 已提交
128
            }
129

130 131 132 133 134 135
            fn super_assign(&mut self,
                            _block: BasicBlock,
                            lvalue: &$($mutability)* Lvalue<'tcx>,
                            rvalue: &$($mutability)* Rvalue<'tcx>) {
                self.visit_lvalue(lvalue, LvalueContext::Store);
                self.visit_rvalue(rvalue);
136
            }
137

138 139 140
            fn super_terminator(&mut self,
                                block: BasicBlock,
                                terminator: &$($mutability)* Terminator<'tcx>) {
141 142
                match terminator.kind {
                    TerminatorKind::Goto { target } => {
143 144
                        self.visit_branch(block, target);
                    }
145

146 147
                    TerminatorKind::If { ref $($mutability)* cond,
                                         ref $($mutability)* targets } => {
148 149 150 151 152
                        self.visit_operand(cond);
                        for &target in targets.as_slice() {
                            self.visit_branch(block, target);
                        }
                    }
153

154 155 156
                    TerminatorKind::Switch { ref $($mutability)* discr,
                                             adt_def: _,
                                             ref targets } => {
157 158 159 160 161
                        self.visit_lvalue(discr, LvalueContext::Inspect);
                        for &target in targets {
                            self.visit_branch(block, target);
                        }
                    }
162

163 164 165 166
                    TerminatorKind::SwitchInt { ref $($mutability)* discr,
                                                switch_ty: _,
                                                values: _,
                                                ref targets } => {
167 168 169 170 171
                        self.visit_lvalue(discr, LvalueContext::Inspect);
                        for &target in targets {
                            self.visit_branch(block, target);
                        }
                    }
172

173 174
                    TerminatorKind::Resume |
                    TerminatorKind::Return => {
175
                    }
176

177 178 179
                    TerminatorKind::Drop { ref $($mutability)* value,
                                           target,
                                           unwind } => {
180 181 182 183 184
                        self.visit_lvalue(value, LvalueContext::Drop);
                        self.visit_branch(block, target);
                        unwind.map(|t| self.visit_branch(block, t));
                    }

185 186 187 188
                    TerminatorKind::Call { ref $($mutability)* func,
                                           ref $($mutability)* args,
                                           ref $($mutability)* destination,
                                           cleanup } => {
189 190 191 192
                        self.visit_operand(func);
                        for arg in args {
                            self.visit_operand(arg);
                        }
S
Simonas Kazlauskas 已提交
193 194
                        if let Some((ref $($mutability)* destination, target)) = *destination {
                            self.visit_lvalue(destination, LvalueContext::Store);
195 196
                            self.visit_branch(block, target);
                        }
S
Simonas Kazlauskas 已提交
197
                        cleanup.map(|t| self.visit_branch(block, t));
198 199 200
                    }
                }
            }
201

202 203 204 205 206 207
            fn super_rvalue(&mut self,
                            rvalue: & $($mutability)* Rvalue<'tcx>) {
                match *rvalue {
                    Rvalue::Use(ref $($mutability)* operand) => {
                        self.visit_operand(operand);
                    }
208

209
                    Rvalue::Repeat(ref $($mutability)* value,
210
                                   _) => {
211 212
                        self.visit_operand(value);
                    }
213

214 215 216 217 218 219
                    Rvalue::Ref(r, bk, ref $($mutability)* path) => {
                        self.visit_lvalue(path, LvalueContext::Borrow {
                            region: r,
                            kind: bk
                        });
                    }
220

221 222 223
                    Rvalue::Len(ref $($mutability)* path) => {
                        self.visit_lvalue(path, LvalueContext::Inspect);
                    }
224

225 226 227
                    Rvalue::Cast(_, ref $($mutability)* operand, _) => {
                        self.visit_operand(operand);
                    }
228

229 230 231 232 233 234
                    Rvalue::BinaryOp(_,
                                     ref $($mutability)* lhs,
                                     ref $($mutability)* rhs) => {
                        self.visit_operand(lhs);
                        self.visit_operand(rhs);
                    }
235

236 237 238
                    Rvalue::UnaryOp(_, ref $($mutability)* op) => {
                        self.visit_operand(op);
                    }
239

240 241
                    Rvalue::Box(_) => {
                    }
242

243 244 245 246 247 248 249 250 251 252 253 254 255
                    Rvalue::Aggregate(ref $($mutability)* kind,
                                      ref $($mutability)* operands) => {
                        match *kind {
                            AggregateKind::Closure(ref $($mutability)* def_id, _) => {
                                self.visit_def_id(def_id);
                            }
                            _ => { /* nothing to do */ }
                        }

                        for operand in & $($mutability)* operands[..] {
                            self.visit_operand(operand);
                        }
                    }
256

257 258 259 260 261 262 263 264
                    Rvalue::Slice { ref $($mutability)* input,
                                    from_start,
                                    from_end } => {
                        self.visit_lvalue(input, LvalueContext::Slice {
                            from_start: from_start,
                            from_end: from_end,
                        });
                    }
265

266 267 268 269 270 271 272 273
                    Rvalue::InlineAsm { ref $($mutability)* outputs,
                                        ref $($mutability)* inputs, .. } => {
                        for output in & $($mutability)* outputs[..] {
                            self.visit_lvalue(output, LvalueContext::Store);
                        }
                        for input in & $($mutability)* inputs[..] {
                            self.visit_operand(input);
                        }
274
                    }
275 276 277
                }
            }

278 279 280 281 282 283 284 285 286
            fn super_operand(&mut self,
                             operand: & $($mutability)* Operand<'tcx>) {
                match *operand {
                    Operand::Consume(ref $($mutability)* lvalue) => {
                        self.visit_lvalue(lvalue, LvalueContext::Consume);
                    }
                    Operand::Constant(ref $($mutability)* constant) => {
                        self.visit_constant(constant);
                    }
287 288 289
                }
            }

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
            fn super_lvalue(&mut self,
                            lvalue: & $($mutability)* Lvalue<'tcx>,
                            _context: LvalueContext) {
                match *lvalue {
                    Lvalue::Var(_) |
                    Lvalue::Temp(_) |
                    Lvalue::Arg(_) |
                    Lvalue::ReturnPointer => {
                    }
                    Lvalue::Static(ref $($mutability)* def_id) => {
                        self.visit_def_id(def_id);
                    }
                    Lvalue::Projection(ref $($mutability)* proj) => {
                        self.visit_lvalue(& $($mutability)* proj.base,
                                          LvalueContext::Projection);
                    }
306 307
                }
            }
308

309 310 311
            fn super_branch(&mut self,
                            _source: BasicBlock,
                            _target: BasicBlock) {
312 313
            }

314 315 316 317
            fn super_constant(&mut self,
                              constant: & $($mutability)* Constant<'tcx>) {
                self.visit_span(& $($mutability)* constant.span);
                self.visit_literal(& $($mutability)* constant.literal);
318 319
            }

320 321 322 323
            fn super_literal(&mut self,
                             literal: & $($mutability)* Literal<'tcx>) {
                match *literal {
                    Literal::Item { ref $($mutability)* def_id, .. } => {
324
                        self.visit_def_id(def_id);
325 326 327
                    },
                    Literal::Value { .. } => {
                        // 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 342
make_mir_visitor!(Visitor,);
make_mir_visitor!(MutVisitor,mut);
343

344 345 346 347
#[derive(Copy, Clone, Debug)]
pub enum LvalueContext {
    // Appears as LHS of an assignment or as dest of a call
    Store,
348

349 350
    // Being dropped
    Drop,
351

352 353
    // Being inspected in some way, like loading a len
    Inspect,
354

355 356
    // Being borrowed
    Borrow { region: Region, kind: BorrowKind },
357

358 359
    // Being sliced -- this should be same as being borrowed, probably
    Slice { from_start: usize, from_end: usize },
360

361 362 363 364 365
    // Used as base for another lvalue, e.g. `x` in `x.y`
    Projection,

    // Consumed as part of an operand
    Consume,
366
}