Skip to content

Commit 8eee116

Browse files
Add a MIR visitor that allows to mutate the visited data
1 parent bd1ce30 commit 8eee116

File tree

1 file changed

+274
-0
lines changed

1 file changed

+274
-0
lines changed

src/librustc/mir/visit.rs

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,3 +280,277 @@ pub enum LvalueContext {
280280
// Consumed as part of an operand
281281
Consume,
282282
}
283+
284+
pub trait MutVisitor<'tcx> {
285+
// Override these, and call `self.super_xxx` to revert back to the
286+
// default behavior.
287+
288+
fn visit_mir(&mut self, mir: &mut Mir<'tcx>) {
289+
self.super_mir(mir);
290+
}
291+
292+
fn visit_basic_block_data(&mut self,
293+
block: BasicBlock,
294+
data: &mut BasicBlockData<'tcx>) {
295+
self.super_basic_block_data(block, data);
296+
}
297+
298+
fn visit_statement(&mut self,
299+
block: BasicBlock,
300+
statement: &mut Statement<'tcx>) {
301+
self.super_statement(block, statement);
302+
}
303+
304+
fn visit_assign(&mut self,
305+
block: BasicBlock,
306+
lvalue: &mut Lvalue<'tcx>,
307+
rvalue: &mut Rvalue<'tcx>) {
308+
self.super_assign(block, lvalue, rvalue);
309+
}
310+
311+
fn visit_terminator(&mut self,
312+
block: BasicBlock,
313+
terminator: &mut Terminator<'tcx>) {
314+
self.super_terminator(block, terminator);
315+
}
316+
317+
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
318+
self.super_rvalue(rvalue);
319+
}
320+
321+
fn visit_operand(&mut self, operand: &mut Operand<'tcx>) {
322+
self.super_operand(operand);
323+
}
324+
325+
fn visit_lvalue(&mut self,
326+
lvalue: &mut Lvalue<'tcx>,
327+
context: LvalueContext) {
328+
self.super_lvalue(lvalue, context);
329+
}
330+
331+
fn visit_branch(&mut self, source: BasicBlock, target: BasicBlock) {
332+
self.super_branch(source, target);
333+
}
334+
335+
fn visit_constant(&mut self, constant: &mut Constant<'tcx>) {
336+
self.super_constant(constant);
337+
}
338+
339+
fn visit_literal(&mut self, literal: &mut Literal<'tcx>) {
340+
self.super_literal(literal);
341+
}
342+
343+
fn visit_def_id(&mut self, def_id: &mut DefId) {
344+
self.super_def_id(def_id);
345+
}
346+
347+
fn visit_span(&mut self, span: &mut Span) {
348+
self.super_span(span);
349+
}
350+
351+
// The `super_xxx` methods comprise the default behavior and are
352+
// not meant to be overidden.
353+
354+
fn super_mir(&mut self, mir: &mut Mir<'tcx>) {
355+
for block in mir.all_basic_blocks() {
356+
let data = mir.basic_block_data_mut(block);
357+
self.visit_basic_block_data(block, data);
358+
}
359+
}
360+
361+
fn super_basic_block_data(&mut self,
362+
block: BasicBlock,
363+
data: &mut BasicBlockData<'tcx>) {
364+
for statement in &mut data.statements {
365+
self.visit_statement(block, statement);
366+
}
367+
self.visit_terminator(block, &mut data.terminator);
368+
}
369+
370+
fn super_statement(&mut self,
371+
block: BasicBlock,
372+
statement: &mut Statement<'tcx>) {
373+
self.visit_span(&mut statement.span);
374+
375+
match statement.kind {
376+
StatementKind::Assign(ref mut lvalue, ref mut rvalue) => {
377+
self.visit_assign(block, lvalue, rvalue);
378+
}
379+
StatementKind::Drop(_, ref mut lvalue) => {
380+
self.visit_lvalue(lvalue, LvalueContext::Drop);
381+
}
382+
}
383+
}
384+
385+
fn super_assign(&mut self,
386+
_block: BasicBlock,
387+
lvalue: &mut Lvalue<'tcx>,
388+
rvalue: &mut Rvalue<'tcx>) {
389+
self.visit_lvalue(lvalue, LvalueContext::Store);
390+
self.visit_rvalue(rvalue);
391+
}
392+
393+
fn super_terminator(&mut self,
394+
block: BasicBlock,
395+
terminator: &mut Terminator<'tcx>) {
396+
match *terminator {
397+
Terminator::Goto { target } |
398+
Terminator::Panic { target } => {
399+
self.visit_branch(block, target);
400+
}
401+
402+
Terminator::If { ref mut cond, ref mut targets } => {
403+
self.visit_operand(cond);
404+
for &target in targets.as_slice() {
405+
self.visit_branch(block, target);
406+
}
407+
}
408+
409+
Terminator::Switch { ref mut discr, adt_def: _, ref targets } => {
410+
self.visit_lvalue(discr, LvalueContext::Inspect);
411+
for &target in targets {
412+
self.visit_branch(block, target);
413+
}
414+
}
415+
416+
Terminator::SwitchInt { ref mut discr, switch_ty: _, values: _, ref targets } => {
417+
self.visit_lvalue(discr, LvalueContext::Inspect);
418+
for &target in targets {
419+
self.visit_branch(block, target);
420+
}
421+
}
422+
423+
Terminator::Diverge |
424+
Terminator::Return => {
425+
}
426+
427+
Terminator::Call { ref mut data, ref mut targets } => {
428+
self.visit_lvalue(&mut data.destination, LvalueContext::Store);
429+
self.visit_operand(&mut data.func);
430+
for arg in &mut data.args {
431+
self.visit_operand(arg);
432+
}
433+
for &target in targets.as_slice() {
434+
self.visit_branch(block, target);
435+
}
436+
}
437+
}
438+
}
439+
440+
fn super_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
441+
match *rvalue {
442+
Rvalue::Use(ref mut operand) => {
443+
self.visit_operand(operand);
444+
}
445+
446+
Rvalue::Repeat(ref mut value, ref mut len) => {
447+
self.visit_operand(value);
448+
self.visit_constant(len);
449+
}
450+
451+
Rvalue::Ref(r, bk, ref mut path) => {
452+
self.visit_lvalue(path, LvalueContext::Borrow {
453+
region: r,
454+
kind: bk
455+
});
456+
}
457+
458+
Rvalue::Len(ref mut path) => {
459+
self.visit_lvalue(path, LvalueContext::Inspect);
460+
}
461+
462+
Rvalue::Cast(_, ref mut operand, _) => {
463+
self.visit_operand(operand);
464+
}
465+
466+
Rvalue::BinaryOp(_, ref mut lhs, ref mut rhs) => {
467+
self.visit_operand(lhs);
468+
self.visit_operand(rhs);
469+
}
470+
471+
Rvalue::UnaryOp(_, ref mut op) => {
472+
self.visit_operand(op);
473+
}
474+
475+
Rvalue::Box(_) => {
476+
}
477+
478+
Rvalue::Aggregate(ref mut kind, ref mut operands) => {
479+
match *kind {
480+
AggregateKind::Closure(ref mut def_id, _) => {
481+
self.visit_def_id(def_id);
482+
}
483+
_ => { /* nothing to do */ }
484+
}
485+
486+
for operand in &mut operands[..] {
487+
self.visit_operand(operand);
488+
}
489+
}
490+
491+
Rvalue::Slice { ref mut input, from_start, from_end } => {
492+
self.visit_lvalue(input, LvalueContext::Slice {
493+
from_start: from_start,
494+
from_end: from_end,
495+
});
496+
}
497+
498+
Rvalue::InlineAsm(_) => {
499+
}
500+
}
501+
}
502+
503+
fn super_operand(&mut self, operand: &mut Operand<'tcx>) {
504+
match *operand {
505+
Operand::Consume(ref mut lvalue) => {
506+
self.visit_lvalue(lvalue, LvalueContext::Consume);
507+
}
508+
Operand::Constant(ref mut constant) => {
509+
self.visit_constant(constant);
510+
}
511+
}
512+
}
513+
514+
fn super_lvalue(&mut self,
515+
lvalue: &mut Lvalue<'tcx>,
516+
_context: LvalueContext) {
517+
match *lvalue {
518+
Lvalue::Var(_) |
519+
Lvalue::Temp(_) |
520+
Lvalue::Arg(_) |
521+
Lvalue::ReturnPointer => {
522+
}
523+
Lvalue::Static(ref mut def_id) => {
524+
self.visit_def_id(def_id);
525+
}
526+
Lvalue::Projection(ref mut proj) => {
527+
self.visit_lvalue(&mut proj.base, LvalueContext::Projection);
528+
}
529+
}
530+
}
531+
532+
fn super_branch(&mut self, _source: BasicBlock, _target: BasicBlock) {
533+
}
534+
535+
fn super_constant(&mut self, constant: &mut Constant<'tcx>) {
536+
self.visit_span(&mut constant.span);
537+
self.visit_literal(&mut constant.literal);
538+
}
539+
540+
fn super_literal(&mut self, literal: &mut Literal<'tcx>) {
541+
match *literal {
542+
Literal::Item { ref mut def_id, .. } => {
543+
self.visit_def_id(def_id);
544+
},
545+
Literal::Value { .. } => {
546+
// Nothing to do
547+
}
548+
}
549+
}
550+
551+
fn super_def_id(&mut self, _def_id: &mut DefId) {
552+
}
553+
554+
fn super_span(&mut self, _span: &mut Span) {
555+
}
556+
}

0 commit comments

Comments
 (0)