Custom mir: Add support for some remaining, easy to support constructs

This commit is contained in:
Jakob Degen 2023-01-26 03:29:28 -08:00
parent e187f8871e
commit d7f59e91e0
8 changed files with 68 additions and 6 deletions

View file

@ -18,6 +18,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
@call("mir_storage_dead", args) => {
Ok(StatementKind::StorageDead(self.parse_local(args[0])?))
},
@call("mir_deinit", args) => {
Ok(StatementKind::Deinit(Box::new(self.parse_place(args[0])?)))
},
@call("mir_retag", args) => {
Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?)))
},
@ -141,6 +144,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
parse_by_kind!(self, expr_id, _, "rvalue",
@call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
@call("mir_checked", args) => {
parse_by_kind!(self, args[0], _, "binary op",
ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp(
*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?))
)),
)
},
@call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
ExprKind::Borrow { borrow_kind, arg } => Ok(
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
),
@ -153,6 +164,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
ExprKind::Unary { op, arg } => Ok(
Rvalue::UnaryOp(*op, self.parse_operand(*arg)?)
),
ExprKind::Repeat { value, count } => Ok(
Rvalue::Repeat(self.parse_operand(*value)?, *count)
),
_ => self.parse_operand(expr_id).map(Rvalue::Use),
)
}

View file

@ -211,13 +211,16 @@
//!
//! #### Statements
//! - Assign statements work via normal Rust assignment.
//! - [`Retag`] statements have an associated function.
//! - [`Retag`], [`StorageLive`], [`StorageDead`], [`Deinit`] statements have an associated function.
//!
//! #### Rvalues
//!
//! - Operands implicitly convert to `Use` rvalues.
//! - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
//! - [`Discriminant`] has an associated function.
//! - [`Discriminant`] and [`Len`] have associated functions.
//! - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc.
//! - Checked binary operations are represented by wrapping the associated binop in [`Checked`].
//! - Array repetition syntax (`[foo; 10]`) creates the associated rvalue.
//!
//! #### Terminators
//!
@ -261,6 +264,9 @@ define!("mir_drop_and_replace", fn DropAndReplace<T>(place: T, value: T, goto: B
define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
define!("mir_storage_live", fn StorageLive<T>(local: T));
define!("mir_storage_dead", fn StorageDead<T>(local: T));
define!("mir_deinit", fn Deinit<T>(place: T));
define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool));
define!("mir_len", fn Len<T>(place: T) -> usize);
define!("mir_retag", fn Retag<T>(place: T));
define!("mir_move", fn Move<T>(place: T) -> T);
define!("mir_static", fn Static<T>(s: T) -> &'static T);

View file

@ -0,0 +1,14 @@
// MIR for `arrays` after built
fn arrays() -> usize {
let mut _0: usize; // return place in scope 0 at $DIR/arrays.rs:+0:32: +0:37
let mut _1: [i32; C]; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
let mut _2: usize; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
bb0: {
_1 = [const 5_i32; C]; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
_2 = Len(_1); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
_0 = _2; // scope 0 at $DIR/arrays.rs:+4:9: +4:16
return; // scope 0 at $DIR/arrays.rs:+5:9: +5:17
}
}

View file

@ -0,0 +1,19 @@
#![feature(custom_mir, core_intrinsics, inline_const)]
extern crate core;
use core::intrinsics::mir::*;
// EMIT_MIR arrays.arrays.built.after.mir
#[custom_mir(dialect = "built")]
fn arrays<const C: usize>() -> usize {
mir!({
let x = [5_i32; C];
let c = Len(x);
RET = c;
Return()
})
}
fn main() {
assert_eq!(arrays::<20>(), 20);
}

View file

@ -86,6 +86,7 @@ fn switch_option_repr(option: Bool) -> bool {
#[custom_mir(dialect = "runtime", phase = "initial")]
fn set_discr(option: &mut Option<()>) {
mir!({
Deinit(*option);
SetDiscriminant(*option, 0);
Return()
})

View file

@ -4,7 +4,8 @@ fn set_discr(_1: &mut Option<()>) -> () {
let mut _0: (); // return place in scope 0 at $DIR/enums.rs:+0:39: +0:39
bb0: {
discriminant((*_1)) = 0; // scope 0 at $DIR/enums.rs:+2:9: +2:36
return; // scope 0 at $DIR/enums.rs:+3:9: +3:17
Deinit((*_1)); // scope 0 at $DIR/enums.rs:+2:9: +2:24
discriminant((*_1)) = 0; // scope 0 at $DIR/enums.rs:+3:9: +3:36
return; // scope 0 at $DIR/enums.rs:+4:9: +4:17
}
}

View file

@ -2,6 +2,7 @@
fn f(_1: i32, _2: bool) -> i32 {
let mut _0: i32; // return place in scope 0 at $DIR/operators.rs:+0:30: +0:33
let mut _3: (i32, bool); // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
bb0: {
_1 = Neg(_1); // scope 0 at $DIR/operators.rs:+2:9: +2:15
@ -20,7 +21,10 @@ fn f(_1: i32, _2: bool) -> i32 {
_2 = Le(_1, _1); // scope 0 at $DIR/operators.rs:+15:9: +15:19
_2 = Ge(_1, _1); // scope 0 at $DIR/operators.rs:+16:9: +16:19
_2 = Gt(_1, _1); // scope 0 at $DIR/operators.rs:+17:9: +17:18
_0 = _1; // scope 0 at $DIR/operators.rs:+18:9: +18:16
return; // scope 0 at $DIR/operators.rs:+19:9: +19:17
_3 = CheckedAdd(_1, _1); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
_2 = (_3.1: bool); // scope 0 at $DIR/operators.rs:+19:9: +19:18
_1 = (_3.0: i32); // scope 0 at $DIR/operators.rs:+20:9: +20:18
_0 = _1; // scope 0 at $DIR/operators.rs:+21:9: +21:16
return; // scope 0 at $DIR/operators.rs:+22:9: +22:17
}
}

View file

@ -22,6 +22,9 @@ pub fn f(a: i32, b: bool) -> i32 {
b = a <= a;
b = a >= a;
b = a > a;
let res = Checked(a + a);
b = res.1;
a = res.0;
RET = a;
Return()
})