Skip to content

Commit 77004ea

Browse files
authored
Rollup merge of rust-lang#110610 - spastorino:smir-terminator, r=oli-obk
Add Terminator conversion from MIR to SMIR, part #1 This adds internal MIR TerminatorKind to SMIR Terminator conversion. r? ```@oli-obk```
2 parents bcc9aa0 + 698acc6 commit 77004ea

File tree

5 files changed

+209
-13
lines changed

5 files changed

+209
-13
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4093,6 +4093,7 @@ dependencies = [
40934093
name = "rustc_smir"
40944094
version = "0.0.0"
40954095
dependencies = [
4096+
"rustc_hir",
40964097
"rustc_middle",
40974098
"rustc_span",
40984099
"tracing",

compiler/rustc_smir/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ version = "0.0.0"
44
edition = "2021"
55

66
[dependencies]
7+
rustc_hir = { path = "../rustc_hir" }
78
rustc_middle = { path = "../rustc_middle", optional = true }
89
rustc_span = { path = "../rustc_span", optional = true }
910
tracing = "0.1"

compiler/rustc_smir/src/rustc_smir/mod.rs

+117-9
Original file line numberDiff line numberDiff line change
@@ -93,20 +93,26 @@ fn rustc_statement_to_statement(
9393
}
9494
}
9595

96-
fn rustc_rvalue_to_rvalue(rvalue: &rustc_middle::mir::Rvalue<'_>) -> stable_mir::mir::Operand {
96+
fn rustc_rvalue_to_rvalue(rvalue: &rustc_middle::mir::Rvalue<'_>) -> stable_mir::mir::Rvalue {
9797
use rustc_middle::mir::Rvalue::*;
9898
match rvalue {
99-
Use(op) => rustc_op_to_op(op),
99+
Use(op) => stable_mir::mir::Rvalue::Use(rustc_op_to_op(op)),
100100
Repeat(_, _) => todo!(),
101101
Ref(_, _, _) => todo!(),
102102
ThreadLocalRef(_) => todo!(),
103103
AddressOf(_, _) => todo!(),
104104
Len(_) => todo!(),
105105
Cast(_, _, _) => todo!(),
106106
BinaryOp(_, _) => todo!(),
107-
CheckedBinaryOp(_, _) => todo!(),
107+
CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp(
108+
rustc_bin_op_to_bin_op(bin_op),
109+
rustc_op_to_op(&ops.0),
110+
rustc_op_to_op(&ops.1),
111+
),
108112
NullaryOp(_, _) => todo!(),
109-
UnaryOp(_, _) => todo!(),
113+
UnaryOp(un_op, op) => {
114+
stable_mir::mir::Rvalue::UnaryOp(rustc_un_op_to_un_op(un_op), rustc_op_to_op(op))
115+
}
110116
Discriminant(_) => todo!(),
111117
Aggregate(_, _) => todo!(),
112118
ShallowInitBox(_, _) => todo!(),
@@ -124,8 +130,10 @@ fn rustc_op_to_op(op: &rustc_middle::mir::Operand<'_>) -> stable_mir::mir::Opera
124130
}
125131

126132
fn rustc_place_to_place(place: &rustc_middle::mir::Place<'_>) -> stable_mir::mir::Place {
127-
assert_eq!(&place.projection[..], &[]);
128-
stable_mir::mir::Place { local: place.local.as_usize() }
133+
stable_mir::mir::Place {
134+
local: place.local.as_usize(),
135+
projection: format!("{:?}", place.projection),
136+
}
129137
}
130138

131139
fn rustc_unwind_to_unwind(
@@ -140,6 +148,96 @@ fn rustc_unwind_to_unwind(
140148
}
141149
}
142150

151+
fn rustc_assert_msg_to_msg<'tcx>(
152+
assert_message: &rustc_middle::mir::AssertMessage<'tcx>,
153+
) -> stable_mir::mir::AssertMessage {
154+
use rustc_middle::mir::AssertKind;
155+
match assert_message {
156+
AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck {
157+
len: rustc_op_to_op(len),
158+
index: rustc_op_to_op(index),
159+
},
160+
AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow(
161+
rustc_bin_op_to_bin_op(bin_op),
162+
rustc_op_to_op(op1),
163+
rustc_op_to_op(op2),
164+
),
165+
AssertKind::OverflowNeg(op) => {
166+
stable_mir::mir::AssertMessage::OverflowNeg(rustc_op_to_op(op))
167+
}
168+
AssertKind::DivisionByZero(op) => {
169+
stable_mir::mir::AssertMessage::DivisionByZero(rustc_op_to_op(op))
170+
}
171+
AssertKind::RemainderByZero(op) => {
172+
stable_mir::mir::AssertMessage::RemainderByZero(rustc_op_to_op(op))
173+
}
174+
AssertKind::ResumedAfterReturn(generator) => {
175+
stable_mir::mir::AssertMessage::ResumedAfterReturn(rustc_generator_to_generator(
176+
generator,
177+
))
178+
}
179+
AssertKind::ResumedAfterPanic(generator) => {
180+
stable_mir::mir::AssertMessage::ResumedAfterPanic(rustc_generator_to_generator(
181+
generator,
182+
))
183+
}
184+
AssertKind::MisalignedPointerDereference { required, found } => {
185+
stable_mir::mir::AssertMessage::MisalignedPointerDereference {
186+
required: rustc_op_to_op(required),
187+
found: rustc_op_to_op(found),
188+
}
189+
}
190+
}
191+
}
192+
193+
fn rustc_bin_op_to_bin_op(bin_op: &rustc_middle::mir::BinOp) -> stable_mir::mir::BinOp {
194+
use rustc_middle::mir::BinOp;
195+
match bin_op {
196+
BinOp::Add => stable_mir::mir::BinOp::Add,
197+
BinOp::Sub => stable_mir::mir::BinOp::Sub,
198+
BinOp::Mul => stable_mir::mir::BinOp::Mul,
199+
BinOp::Div => stable_mir::mir::BinOp::Div,
200+
BinOp::Rem => stable_mir::mir::BinOp::Rem,
201+
BinOp::BitXor => stable_mir::mir::BinOp::BitXor,
202+
BinOp::BitAnd => stable_mir::mir::BinOp::BitAnd,
203+
BinOp::BitOr => stable_mir::mir::BinOp::BitOr,
204+
BinOp::Shl => stable_mir::mir::BinOp::Shl,
205+
BinOp::Shr => stable_mir::mir::BinOp::Shr,
206+
BinOp::Eq => stable_mir::mir::BinOp::Eq,
207+
BinOp::Lt => stable_mir::mir::BinOp::Lt,
208+
BinOp::Le => stable_mir::mir::BinOp::Le,
209+
BinOp::Ne => stable_mir::mir::BinOp::Ne,
210+
BinOp::Ge => stable_mir::mir::BinOp::Ge,
211+
BinOp::Gt => stable_mir::mir::BinOp::Gt,
212+
BinOp::Offset => stable_mir::mir::BinOp::Offset,
213+
}
214+
}
215+
216+
fn rustc_un_op_to_un_op(unary_op: &rustc_middle::mir::UnOp) -> stable_mir::mir::UnOp {
217+
use rustc_middle::mir::UnOp;
218+
match unary_op {
219+
UnOp::Not => stable_mir::mir::UnOp::Not,
220+
UnOp::Neg => stable_mir::mir::UnOp::Neg,
221+
}
222+
}
223+
224+
fn rustc_generator_to_generator(
225+
generator: &rustc_hir::GeneratorKind,
226+
) -> stable_mir::mir::GeneratorKind {
227+
use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
228+
match generator {
229+
GeneratorKind::Async(async_gen) => {
230+
let async_gen = match async_gen {
231+
AsyncGeneratorKind::Block => stable_mir::mir::AsyncGeneratorKind::Block,
232+
AsyncGeneratorKind::Closure => stable_mir::mir::AsyncGeneratorKind::Closure,
233+
AsyncGeneratorKind::Fn => stable_mir::mir::AsyncGeneratorKind::Fn,
234+
};
235+
stable_mir::mir::GeneratorKind::Async(async_gen)
236+
}
237+
GeneratorKind::Gen => stable_mir::mir::GeneratorKind::Gen,
238+
}
239+
}
240+
143241
fn rustc_terminator_to_terminator(
144242
terminator: &rustc_middle::mir::Terminator<'_>,
145243
) -> stable_mir::mir::Terminator {
@@ -162,7 +260,11 @@ fn rustc_terminator_to_terminator(
162260
Terminate => Terminator::Abort,
163261
Return => Terminator::Return,
164262
Unreachable => Terminator::Unreachable,
165-
Drop { .. } => todo!(),
263+
Drop { place, target, unwind } => Terminator::Drop {
264+
place: rustc_place_to_place(place),
265+
target: target.as_usize(),
266+
unwind: rustc_unwind_to_unwind(unwind),
267+
},
166268
Call { func, args, destination, target, unwind, from_hir_call: _, fn_span: _ } => {
167269
Terminator::Call {
168270
func: rustc_op_to_op(func),
@@ -172,9 +274,15 @@ fn rustc_terminator_to_terminator(
172274
unwind: rustc_unwind_to_unwind(unwind),
173275
}
174276
}
175-
Assert { .. } => todo!(),
277+
Assert { cond, expected, msg, target, unwind } => Terminator::Assert {
278+
cond: rustc_op_to_op(cond),
279+
expected: *expected,
280+
msg: rustc_assert_msg_to_msg(msg),
281+
target: target.as_usize(),
282+
unwind: rustc_unwind_to_unwind(unwind),
283+
},
176284
Yield { .. } => todo!(),
177-
GeneratorDrop => todo!(),
285+
GeneratorDrop => Terminator::GeneratorDrop,
178286
FalseEdge { .. } => todo!(),
179287
FalseUnwind { .. } => todo!(),
180288
InlineAsm { .. } => todo!(),

compiler/rustc_smir/src/stable_mir/mir/body.rs

+66-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub enum Terminator {
2626
Drop {
2727
place: Place,
2828
target: usize,
29-
unwind: Option<usize>,
29+
unwind: UnwindAction,
3030
},
3131
Call {
3232
func: Operand,
@@ -38,10 +38,11 @@ pub enum Terminator {
3838
Assert {
3939
cond: Operand,
4040
expected: bool,
41-
msg: String,
41+
msg: AssertMessage,
4242
target: usize,
43-
cleanup: Option<usize>,
43+
unwind: UnwindAction,
4444
},
45+
GeneratorDrop,
4546
}
4647

4748
#[derive(Clone, Debug)]
@@ -52,12 +53,72 @@ pub enum UnwindAction {
5253
Cleanup(usize),
5354
}
5455

56+
#[derive(Clone, Debug)]
57+
pub enum AssertMessage {
58+
BoundsCheck { len: Operand, index: Operand },
59+
Overflow(BinOp, Operand, Operand),
60+
OverflowNeg(Operand),
61+
DivisionByZero(Operand),
62+
RemainderByZero(Operand),
63+
ResumedAfterReturn(GeneratorKind),
64+
ResumedAfterPanic(GeneratorKind),
65+
MisalignedPointerDereference { required: Operand, found: Operand },
66+
}
67+
68+
#[derive(Clone, Debug)]
69+
pub enum BinOp {
70+
Add,
71+
Sub,
72+
Mul,
73+
Div,
74+
Rem,
75+
BitXor,
76+
BitAnd,
77+
BitOr,
78+
Shl,
79+
Shr,
80+
Eq,
81+
Lt,
82+
Le,
83+
Ne,
84+
Ge,
85+
Gt,
86+
Offset,
87+
}
88+
89+
#[derive(Clone, Debug)]
90+
pub enum UnOp {
91+
Not,
92+
Neg,
93+
}
94+
95+
#[derive(Clone, Debug)]
96+
pub enum GeneratorKind {
97+
Async(AsyncGeneratorKind),
98+
Gen,
99+
}
100+
101+
#[derive(Clone, Debug)]
102+
pub enum AsyncGeneratorKind {
103+
Block,
104+
Closure,
105+
Fn,
106+
}
107+
55108
#[derive(Clone, Debug)]
56109
pub enum Statement {
57-
Assign(Place, Operand),
110+
Assign(Place, Rvalue),
58111
Nop,
59112
}
60113

114+
// FIXME this is incomplete
115+
#[derive(Clone, Debug)]
116+
pub enum Rvalue {
117+
Use(Operand),
118+
CheckedBinaryOp(BinOp, Operand, Operand),
119+
UnaryOp(UnOp, Operand),
120+
}
121+
61122
#[derive(Clone, Debug)]
62123
pub enum Operand {
63124
Copy(Place),
@@ -68,6 +129,7 @@ pub enum Operand {
68129
#[derive(Clone, Debug)]
69130
pub struct Place {
70131
pub local: usize,
132+
pub projection: String,
71133
}
72134

73135
#[derive(Clone, Debug)]

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

+24
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,24 @@ fn test_stable_mir(tcx: TyCtxt<'_>) {
6060
stable_mir::mir::Terminator::Call { .. } => {}
6161
other => panic!("{other:?}"),
6262
}
63+
64+
let drop = get_item(tcx, &items, (DefKind::Fn, "drop")).unwrap();
65+
let body = drop.body();
66+
assert_eq!(body.blocks.len(), 2);
67+
let block = &body.blocks[0];
68+
match &block.terminator {
69+
stable_mir::mir::Terminator::Drop { .. } => {}
70+
other => panic!("{other:?}"),
71+
}
72+
73+
let assert = get_item(tcx, &items, (DefKind::Fn, "assert")).unwrap();
74+
let body = assert.body();
75+
assert_eq!(body.blocks.len(), 2);
76+
let block = &body.blocks[0];
77+
match &block.terminator {
78+
stable_mir::mir::Terminator::Assert { .. } => {}
79+
other => panic!("{other:?}"),
80+
}
6381
}
6482

6583
// Use internal API to find a function in a crate.
@@ -131,6 +149,12 @@ fn generate_input(path: &str) -> std::io::Result<()> {
131149
let x_64 = foo::bar(x);
132150
let y_64 = foo::bar(y);
133151
x_64.wrapping_add(y_64)
152+
}}
153+
154+
pub fn drop(_: String) {{}}
155+
156+
pub fn assert(x: i32) -> i32 {{
157+
x + 1
134158
}}"#
135159
)?;
136160
Ok(())

0 commit comments

Comments
 (0)