Skip to content

Commit d956122

Browse files
[WIP] Create a Visitor for the THIR
1 parent 506e75c commit d956122

File tree

2 files changed

+179
-0
lines changed

2 files changed

+179
-0
lines changed

compiler/rustc_mir_build/src/thir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mod arena;
2929
pub use arena::Arena;
3030

3131
mod util;
32+
pub mod visit;
3233

3334
#[derive(Copy, Clone, Debug)]
3435
pub enum LintLevel {
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
use crate::thir::*;
2+
3+
pub trait Visitor<'thir, 'tcx>: Sized {
4+
fn visit_expr(&mut self, expr: &'thir Expr<'thir, 'tcx>) {
5+
walk_expr(self, expr);
6+
}
7+
8+
fn visit_stmt(&mut self, stmt: &'thir Stmt<'thir, 'tcx>) {
9+
walk_stmt(self, stmt);
10+
}
11+
12+
fn visit_block(&mut self, block: &Block<'thir, 'tcx>) {
13+
walk_block(self, block);
14+
}
15+
16+
fn visit_arm(&mut self, arm: &'thir Arm<'thir, 'tcx>) {
17+
walk_arm(self, arm);
18+
}
19+
20+
fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
21+
}
22+
23+
pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
24+
visitor: &mut V,
25+
expr: &'thir Expr<'thir, 'tcx>,
26+
) {
27+
use ExprKind::*;
28+
match expr.kind {
29+
Scope { value, .. } => visitor.visit_expr(value),
30+
Box { value } => visitor.visit_expr(value),
31+
If { cond, then, else_opt } => {
32+
visitor.visit_expr(cond);
33+
visitor.visit_expr(then);
34+
if let Some(else_expr) = else_opt {
35+
visitor.visit_expr(else_expr);
36+
}
37+
}
38+
Call { fun, args, .. } => {
39+
visitor.visit_expr(fun);
40+
for arg in args {
41+
visitor.visit_expr(arg);
42+
}
43+
}
44+
Deref { arg } => visitor.visit_expr(arg),
45+
Binary { lhs, rhs, .. } | LogicalOp { lhs, rhs, .. } => {
46+
visitor.visit_expr(lhs);
47+
visitor.visit_expr(rhs);
48+
}
49+
Unary { arg, .. } => visitor.visit_expr(arg),
50+
Cast { source } => visitor.visit_expr(source),
51+
Use { source } => visitor.visit_expr(source),
52+
NeverToAny { source } => visitor.visit_expr(source),
53+
Pointer { source, .. } => visitor.visit_expr(source),
54+
Loop { body } => visitor.visit_expr(body),
55+
Match { scrutinee, arms } => {
56+
visitor.visit_expr(scrutinee);
57+
for arm in arms {
58+
visitor.visit_arm(arm);
59+
}
60+
}
61+
Block { ref body } => visitor.visit_block(body),
62+
Assign { lhs, rhs } | AssignOp { lhs, rhs, .. } => {
63+
visitor.visit_expr(lhs);
64+
visitor.visit_expr(rhs);
65+
}
66+
Field { lhs, .. } => visitor.visit_expr(lhs),
67+
Index { lhs, index } => {
68+
visitor.visit_expr(lhs);
69+
visitor.visit_expr(index);
70+
}
71+
VarRef { .. } | UpvarRef { .. } => {}
72+
Borrow { arg, .. } => visitor.visit_expr(arg),
73+
AddressOf { arg, .. } => visitor.visit_expr(arg),
74+
Break { value, .. } => {
75+
if let Some(value) = value {
76+
visitor.visit_expr(value)
77+
}
78+
}
79+
Continue { .. } => {}
80+
Return { value } => {
81+
if let Some(value) = value {
82+
visitor.visit_expr(value)
83+
}
84+
}
85+
ConstBlock { value } => visitor.visit_const(value),
86+
Repeat { value, count } => {
87+
visitor.visit_expr(value);
88+
visitor.visit_const(count);
89+
}
90+
Array { fields } | Tuple { fields } => {
91+
for field in fields {
92+
visitor.visit_expr(field);
93+
}
94+
}
95+
Adt { fields, ref base, .. } => {
96+
for field in fields {
97+
visitor.visit_expr(field.expr);
98+
}
99+
if let Some(base) = base {
100+
visitor.visit_expr(base.base);
101+
}
102+
}
103+
PlaceTypeAscription { source, .. } | ValueTypeAscription { source, .. } => {
104+
visitor.visit_expr(source)
105+
}
106+
Closure { .. } => {}
107+
Literal { literal, .. } => visitor.visit_const(literal),
108+
StaticRef { literal, .. } => visitor.visit_const(literal),
109+
InlineAsm { operands, .. } => {
110+
for op in operands {
111+
use InlineAsmOperand::*;
112+
match op {
113+
In { expr, .. }
114+
| Out { expr: Some(expr), .. }
115+
| InOut { expr, .. }
116+
| SymFn { expr } => visitor.visit_expr(expr),
117+
SplitInOut { in_expr, out_expr, .. } => {
118+
visitor.visit_expr(in_expr);
119+
if let Some(out_expr) = out_expr {
120+
visitor.visit_expr(out_expr);
121+
}
122+
}
123+
Out { .. } | Const { .. } | SymStatic { .. } => {}
124+
}
125+
}
126+
}
127+
ThreadLocalRef(_) => {}
128+
LlvmInlineAsm { outputs, inputs, .. } => {
129+
for out_expr in outputs {
130+
visitor.visit_expr(out_expr);
131+
}
132+
for in_expr in inputs {
133+
visitor.visit_expr(in_expr);
134+
}
135+
}
136+
Yield { value } => visitor.visit_expr(value),
137+
}
138+
}
139+
140+
pub fn walk_stmt<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
141+
visitor: &mut V,
142+
stmt: &'thir Stmt<'thir, 'tcx>,
143+
) {
144+
match stmt.kind {
145+
StmtKind::Expr { expr, .. } => visitor.visit_expr(expr),
146+
StmtKind::Let { pattern: _, initializer, .. } => {
147+
if let Some(init) = initializer {
148+
visitor.visit_expr(init);
149+
}
150+
}
151+
}
152+
}
153+
154+
pub fn walk_block<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
155+
visitor: &mut V,
156+
block: &Block<'thir, 'tcx>,
157+
) {
158+
for stmt in block.stmts {
159+
visitor.visit_stmt(stmt);
160+
}
161+
if let Some(expr) = block.expr {
162+
visitor.visit_expr(expr);
163+
}
164+
}
165+
166+
pub fn walk_arm<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
167+
visitor: &mut V,
168+
arm: &'thir Arm<'thir, 'tcx>,
169+
) {
170+
match arm.guard {
171+
Some(Guard::If(expr)) => visitor.visit_expr(expr),
172+
Some(Guard::IfLet(ref _pat, expr)) => {
173+
visitor.visit_expr(expr);
174+
}
175+
None => {}
176+
}
177+
visitor.visit_expr(arm.body);
178+
}

0 commit comments

Comments
 (0)