Skip to content

Commit f183e30

Browse files
authored
Rollup merge of #107322 - JakobDegen:custom-mir, r=tmiasko
Custom mir: Add support for some remaining, easy to support constructs Some documentation for previous changes and support for `Deinit`, checked binops, len, and array repetition r? `@oli-obk` or `@tmiasko`
2 parents 9c2336a + d7f59e9 commit f183e30

File tree

8 files changed

+68
-6
lines changed

8 files changed

+68
-6
lines changed

compiler/rustc_mir_build/src/build/custom/parse/instruction.rs

+14
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
1818
@call("mir_storage_dead", args) => {
1919
Ok(StatementKind::StorageDead(self.parse_local(args[0])?))
2020
},
21+
@call("mir_deinit", args) => {
22+
Ok(StatementKind::Deinit(Box::new(self.parse_place(args[0])?)))
23+
},
2124
@call("mir_retag", args) => {
2225
Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?)))
2326
},
@@ -141,6 +144,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
141144
fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
142145
parse_by_kind!(self, expr_id, _, "rvalue",
143146
@call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
147+
@call("mir_checked", args) => {
148+
parse_by_kind!(self, args[0], _, "binary op",
149+
ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp(
150+
*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?))
151+
)),
152+
)
153+
},
154+
@call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
144155
ExprKind::Borrow { borrow_kind, arg } => Ok(
145156
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
146157
),
@@ -153,6 +164,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
153164
ExprKind::Unary { op, arg } => Ok(
154165
Rvalue::UnaryOp(*op, self.parse_operand(*arg)?)
155166
),
167+
ExprKind::Repeat { value, count } => Ok(
168+
Rvalue::Repeat(self.parse_operand(*value)?, *count)
169+
),
156170
_ => self.parse_operand(expr_id).map(Rvalue::Use),
157171
)
158172
}

library/core/src/intrinsics/mir.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -211,13 +211,16 @@
211211
//!
212212
//! #### Statements
213213
//! - Assign statements work via normal Rust assignment.
214-
//! - [`Retag`] statements have an associated function.
214+
//! - [`Retag`], [`StorageLive`], [`StorageDead`], [`Deinit`] statements have an associated function.
215215
//!
216216
//! #### Rvalues
217217
//!
218218
//! - Operands implicitly convert to `Use` rvalues.
219219
//! - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
220-
//! - [`Discriminant`] has an associated function.
220+
//! - [`Discriminant`] and [`Len`] have associated functions.
221+
//! - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc.
222+
//! - Checked binary operations are represented by wrapping the associated binop in [`Checked`].
223+
//! - Array repetition syntax (`[foo; 10]`) creates the associated rvalue.
221224
//!
222225
//! #### Terminators
223226
//!
@@ -261,6 +264,9 @@ define!("mir_drop_and_replace", fn DropAndReplace<T>(place: T, value: T, goto: B
261264
define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
262265
define!("mir_storage_live", fn StorageLive<T>(local: T));
263266
define!("mir_storage_dead", fn StorageDead<T>(local: T));
267+
define!("mir_deinit", fn Deinit<T>(place: T));
268+
define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool));
269+
define!("mir_len", fn Len<T>(place: T) -> usize);
264270
define!("mir_retag", fn Retag<T>(place: T));
265271
define!("mir_move", fn Move<T>(place: T) -> T);
266272
define!("mir_static", fn Static<T>(s: T) -> &'static T);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// MIR for `arrays` after built
2+
3+
fn arrays() -> usize {
4+
let mut _0: usize; // return place in scope 0 at $DIR/arrays.rs:+0:32: +0:37
5+
let mut _1: [i32; C]; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
6+
let mut _2: usize; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
7+
8+
bb0: {
9+
_1 = [const 5_i32; C]; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
10+
_2 = Len(_1); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
11+
_0 = _2; // scope 0 at $DIR/arrays.rs:+4:9: +4:16
12+
return; // scope 0 at $DIR/arrays.rs:+5:9: +5:17
13+
}
14+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![feature(custom_mir, core_intrinsics, inline_const)]
2+
3+
extern crate core;
4+
use core::intrinsics::mir::*;
5+
6+
// EMIT_MIR arrays.arrays.built.after.mir
7+
#[custom_mir(dialect = "built")]
8+
fn arrays<const C: usize>() -> usize {
9+
mir!({
10+
let x = [5_i32; C];
11+
let c = Len(x);
12+
RET = c;
13+
Return()
14+
})
15+
}
16+
17+
fn main() {
18+
assert_eq!(arrays::<20>(), 20);
19+
}

tests/mir-opt/building/custom/enums.rs

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ fn switch_option_repr(option: Bool) -> bool {
8686
#[custom_mir(dialect = "runtime", phase = "initial")]
8787
fn set_discr(option: &mut Option<()>) {
8888
mir!({
89+
Deinit(*option);
8990
SetDiscriminant(*option, 0);
9091
Return()
9192
})

tests/mir-opt/building/custom/enums.set_discr.built.after.mir

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ fn set_discr(_1: &mut Option<()>) -> () {
44
let mut _0: (); // return place in scope 0 at $DIR/enums.rs:+0:39: +0:39
55

66
bb0: {
7-
discriminant((*_1)) = 0; // scope 0 at $DIR/enums.rs:+2:9: +2:36
8-
return; // scope 0 at $DIR/enums.rs:+3:9: +3:17
7+
Deinit((*_1)); // scope 0 at $DIR/enums.rs:+2:9: +2:24
8+
discriminant((*_1)) = 0; // scope 0 at $DIR/enums.rs:+3:9: +3:36
9+
return; // scope 0 at $DIR/enums.rs:+4:9: +4:17
910
}
1011
}

tests/mir-opt/building/custom/operators.f.built.after.mir

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
fn f(_1: i32, _2: bool) -> i32 {
44
let mut _0: i32; // return place in scope 0 at $DIR/operators.rs:+0:30: +0:33
5+
let mut _3: (i32, bool); // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
56

67
bb0: {
78
_1 = Neg(_1); // scope 0 at $DIR/operators.rs:+2:9: +2:15
@@ -20,7 +21,10 @@ fn f(_1: i32, _2: bool) -> i32 {
2021
_2 = Le(_1, _1); // scope 0 at $DIR/operators.rs:+15:9: +15:19
2122
_2 = Ge(_1, _1); // scope 0 at $DIR/operators.rs:+16:9: +16:19
2223
_2 = Gt(_1, _1); // scope 0 at $DIR/operators.rs:+17:9: +17:18
23-
_0 = _1; // scope 0 at $DIR/operators.rs:+18:9: +18:16
24-
return; // scope 0 at $DIR/operators.rs:+19:9: +19:17
24+
_3 = CheckedAdd(_1, _1); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
25+
_2 = (_3.1: bool); // scope 0 at $DIR/operators.rs:+19:9: +19:18
26+
_1 = (_3.0: i32); // scope 0 at $DIR/operators.rs:+20:9: +20:18
27+
_0 = _1; // scope 0 at $DIR/operators.rs:+21:9: +21:16
28+
return; // scope 0 at $DIR/operators.rs:+22:9: +22:17
2529
}
2630
}

tests/mir-opt/building/custom/operators.rs

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ pub fn f(a: i32, b: bool) -> i32 {
2222
b = a <= a;
2323
b = a >= a;
2424
b = a > a;
25+
let res = Checked(a + a);
26+
b = res.1;
27+
a = res.0;
2528
RET = a;
2629
Return()
2730
})

0 commit comments

Comments
 (0)