Skip to content

Commit 942cac1

Browse files
committed
Implement a minimal subset of MIR statements and terminators for smir
1 parent 6fe9822 commit 942cac1

File tree

5 files changed

+209
-5
lines changed

5 files changed

+209
-5
lines changed

compiler/rustc_smir/src/rustc_smir/mod.rs

+110-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//! For now, we are developing everything inside `rustc`, thus, we keep this module private.
99
1010
use crate::{
11-
rustc_internal::crate_item,
11+
rustc_internal::{crate_item, item_def_id},
1212
stable_mir::{self},
1313
};
1414
use rustc_middle::ty::{tls::with, TyCtxt};
@@ -47,3 +47,112 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
4747
debug!(?crate_name, ?crate_num, "smir_crate");
4848
stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local }
4949
}
50+
51+
pub fn mir_body(item: &stable_mir::CrateItem) -> stable_mir::mir::Body {
52+
with(|tcx| {
53+
let def_id = item_def_id(item);
54+
let mir = tcx.optimized_mir(def_id);
55+
stable_mir::mir::Body {
56+
blocks: mir
57+
.basic_blocks
58+
.iter()
59+
.map(|block| stable_mir::mir::BasicBlock {
60+
terminator: rustc_terminator_to_terminator(block.terminator()),
61+
statements: block.statements.iter().map(rustc_statement_to_statement).collect(),
62+
})
63+
.collect(),
64+
}
65+
})
66+
}
67+
68+
fn rustc_statement_to_statement(
69+
s: &rustc_middle::mir::Statement<'_>,
70+
) -> stable_mir::mir::Statement {
71+
use rustc_middle::mir::StatementKind::*;
72+
match &s.kind {
73+
Assign(assign) => stable_mir::mir::Statement::Assign(
74+
rustc_place_to_place(&assign.0),
75+
rustc_rvalue_to_rvalue(&assign.1),
76+
),
77+
FakeRead(_) => todo!(),
78+
SetDiscriminant { .. } => todo!(),
79+
Deinit(_) => todo!(),
80+
StorageLive(_) => todo!(),
81+
StorageDead(_) => todo!(),
82+
Retag(_, _) => todo!(),
83+
PlaceMention(_) => todo!(),
84+
AscribeUserType(_, _) => todo!(),
85+
Coverage(_) => todo!(),
86+
Intrinsic(_) => todo!(),
87+
ConstEvalCounter => todo!(),
88+
Nop => stable_mir::mir::Statement::Nop,
89+
}
90+
}
91+
92+
fn rustc_rvalue_to_rvalue(rvalue: &rustc_middle::mir::Rvalue<'_>) -> stable_mir::mir::Operand {
93+
use rustc_middle::mir::Rvalue::*;
94+
match rvalue {
95+
Use(op) => rustc_op_to_op(op),
96+
Repeat(_, _) => todo!(),
97+
Ref(_, _, _) => todo!(),
98+
ThreadLocalRef(_) => todo!(),
99+
AddressOf(_, _) => todo!(),
100+
Len(_) => todo!(),
101+
Cast(_, _, _) => todo!(),
102+
BinaryOp(_, _) => todo!(),
103+
CheckedBinaryOp(_, _) => todo!(),
104+
NullaryOp(_, _) => todo!(),
105+
UnaryOp(_, _) => todo!(),
106+
Discriminant(_) => todo!(),
107+
Aggregate(_, _) => todo!(),
108+
ShallowInitBox(_, _) => todo!(),
109+
CopyForDeref(_) => todo!(),
110+
}
111+
}
112+
113+
fn rustc_op_to_op(op: &rustc_middle::mir::Operand<'_>) -> stable_mir::mir::Operand {
114+
use rustc_middle::mir::Operand::*;
115+
match op {
116+
Copy(place) => stable_mir::mir::Operand::Copy(rustc_place_to_place(place)),
117+
Move(place) => stable_mir::mir::Operand::Move(rustc_place_to_place(place)),
118+
Constant(c) => stable_mir::mir::Operand::Constant(c.to_string()),
119+
}
120+
}
121+
122+
fn rustc_place_to_place(place: &rustc_middle::mir::Place<'_>) -> stable_mir::mir::Place {
123+
assert_eq!(&place.projection[..], &[]);
124+
stable_mir::mir::Place { local: place.local.as_usize() }
125+
}
126+
127+
fn rustc_terminator_to_terminator(
128+
terminator: &rustc_middle::mir::Terminator<'_>,
129+
) -> stable_mir::mir::Terminator {
130+
use rustc_middle::mir::TerminatorKind::*;
131+
use stable_mir::mir::Terminator;
132+
match &terminator.kind {
133+
Goto { target } => Terminator::Goto { target: target.as_usize() },
134+
SwitchInt { discr, targets } => Terminator::SwitchInt {
135+
discr: rustc_op_to_op(discr),
136+
targets: targets
137+
.iter()
138+
.map(|(value, target)| stable_mir::mir::SwitchTarget {
139+
value,
140+
target: target.as_usize(),
141+
})
142+
.collect(),
143+
otherwise: targets.otherwise().as_usize(),
144+
},
145+
Resume => Terminator::Resume,
146+
Abort => Terminator::Abort,
147+
Return => Terminator::Return,
148+
Unreachable => Terminator::Unreachable,
149+
Drop { .. } => todo!(),
150+
Call { .. } => todo!(),
151+
Assert { .. } => todo!(),
152+
Yield { .. } => todo!(),
153+
GeneratorDrop => todo!(),
154+
FalseEdge { .. } => todo!(),
155+
FalseUnwind { .. } => todo!(),
156+
InlineAsm { .. } => todo!(),
157+
}
158+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mod body;
2+
3+
pub use body::*;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
pub struct Body {
2+
pub blocks: Vec<BasicBlock>,
3+
}
4+
5+
pub struct BasicBlock {
6+
pub statements: Vec<Statement>,
7+
pub terminator: Terminator,
8+
}
9+
10+
pub enum Terminator {
11+
Goto {
12+
target: usize,
13+
},
14+
SwitchInt {
15+
discr: Operand,
16+
targets: Vec<SwitchTarget>,
17+
otherwise: usize,
18+
},
19+
Resume,
20+
Abort,
21+
Return,
22+
Unreachable,
23+
Drop {
24+
place: Place,
25+
target: usize,
26+
unwind: Option<usize>,
27+
},
28+
Call {
29+
func: Operand,
30+
args: Vec<Operand>,
31+
destination: Place,
32+
target: Option<usize>,
33+
cleanup: Option<usize>,
34+
},
35+
Assert {
36+
cond: Operand,
37+
expected: bool,
38+
msg: String,
39+
target: usize,
40+
cleanup: Option<usize>,
41+
},
42+
}
43+
44+
pub enum Statement {
45+
Assign(Place, Operand),
46+
Nop,
47+
}
48+
49+
pub enum Operand {
50+
Copy(Place),
51+
Move(Place),
52+
Constant(String),
53+
}
54+
55+
pub struct Place {
56+
pub local: usize,
57+
}
58+
59+
pub struct SwitchTarget {
60+
pub value: u128,
61+
pub target: usize,
62+
}

compiler/rustc_smir/src/stable_mir/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
//! There shouldn't be any direct references to internal compiler constructs in this module.
1212
//! If you need an internal construct, consider using `rustc_internal` or `rustc_smir`.
1313
14+
pub mod mir;
15+
1416
/// Use String for now but we should replace it.
1517
pub type Symbol = String;
1618

@@ -37,6 +39,12 @@ pub struct Crate {
3739
#[derive(Clone, PartialEq, Eq, Debug)]
3840
pub struct CrateItem(pub(crate) DefId);
3941

42+
impl CrateItem {
43+
pub fn body(&self) -> mir::Body {
44+
crate::rustc_smir::mir_body(self)
45+
}
46+
}
47+
4048
/// Access to the local crate.
4149
pub fn local_crate() -> Crate {
4250
crate::rustc_smir::local_crate()

tests/ui-fulldeps/stable-mir/crate-info.rs

+26-4
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,34 @@ fn test_stable_mir(tcx: TyCtxt<'_>) {
3030

3131
// Find items in the local crate.
3232
let items = stable_mir::all_local_items();
33-
assert!(has_item(tcx, &items, (DefKind::Fn, "foo_bar")));
34-
assert!(has_item(tcx, &items, (DefKind::Fn, "foo::bar")));
33+
assert!(get_item(tcx, &items, (DefKind::Fn, "foo_bar")).is_some());
34+
assert!(get_item(tcx, &items, (DefKind::Fn, "foo::bar")).is_some());
3535

3636
// Find the `std` crate.
3737
assert!(stable_mir::find_crate("std").is_some());
38+
39+
let bar = get_item(tcx, &items, (DefKind::Fn, "bar")).unwrap();
40+
let body = bar.body();
41+
assert_eq!(body.blocks.len(), 1);
42+
let block = &body.blocks[0];
43+
assert_eq!(block.statements.len(), 1);
44+
match &block.statements[0] {
45+
stable_mir::mir::Statement::Assign(..) => {}
46+
_ => panic!(),
47+
}
48+
match &block.terminator {
49+
stable_mir::mir::Terminator::Return => {}
50+
_ => panic!(),
51+
}
3852
}
3953

4054
// Use internal API to find a function in a crate.
41-
fn has_item(tcx: TyCtxt, items: &stable_mir::CrateItems, item: (DefKind, &str)) -> bool {
42-
items.iter().any(|crate_item| {
55+
fn get_item<'a>(
56+
tcx: TyCtxt,
57+
items: &'a stable_mir::CrateItems,
58+
item: (DefKind, &str),
59+
) -> Option<&'a stable_mir::CrateItem> {
60+
items.iter().find(|crate_item| {
4361
let def_id = rustc_internal::item_def_id(crate_item);
4462
tcx.def_kind(def_id) == item.0 && tcx.def_path_str(def_id) == item.1
4563
})
@@ -94,6 +112,10 @@ fn generate_input(path: &str) -> std::io::Result<()> {
94112
}}
95113
}}
96114
115+
pub fn bar(x: i32) -> i32 {{
116+
x
117+
}}
118+
97119
pub fn foo_bar(x: i32, y: i32) -> i64 {{
98120
let x_64 = foo::bar(x);
99121
let y_64 = foo::bar(y);

0 commit comments

Comments
 (0)