1
Fork 0

Rollup merge of #119325 - RalfJung:custom-mir, r=compiler-errors

custom mir: make it clear what the return block is

Custom MIR recently got support for specifying the "unwind action", so now there's two things coming after the actual call part of `Call` terminators. That's not very self-explaining so I propose we change the syntax to imitate keyword arguments:
```
Call(popped = Vec::pop(v), ReturnTo(drop), UnwindContinue())
```

Also fix some outdated docs and add some docs to `Call` and `Drop`.
This commit is contained in:
Matthias Krüger 2024-01-04 15:33:58 +01:00 committed by GitHub
commit a919d97aaa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 120 additions and 78 deletions

View file

@ -61,7 +61,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
@call(mir_drop, args) => { @call(mir_drop, args) => {
Ok(TerminatorKind::Drop { Ok(TerminatorKind::Drop {
place: self.parse_place(args[0])?, place: self.parse_place(args[0])?,
target: self.parse_block(args[1])?, target: self.parse_return_to(args[1])?,
unwind: self.parse_unwind_action(args[2])?, unwind: self.parse_unwind_action(args[2])?,
replace: false, replace: false,
}) })
@ -104,6 +104,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
) )
} }
fn parse_return_to(&self, expr_id: ExprId) -> PResult<BasicBlock> {
parse_by_kind!(self, expr_id, _, "return block",
@call(mir_return_to, args) => {
self.parse_block(args[0])
},
)
}
fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> { fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> {
let Some((otherwise, rest)) = arms.split_last() else { let Some((otherwise, rest)) = arms.split_last() else {
return Err(ParseError { return Err(ParseError {
@ -146,7 +154,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
ExprKind::Assign { lhs, rhs } => (*lhs, *rhs), ExprKind::Assign { lhs, rhs } => (*lhs, *rhs),
); );
let destination = self.parse_place(destination)?; let destination = self.parse_place(destination)?;
let target = self.parse_block(args[1])?; let target = self.parse_return_to(args[1])?;
let unwind = self.parse_unwind_action(args[2])?; let unwind = self.parse_unwind_action(args[2])?;
parse_by_kind!(self, call, _, "function call", parse_by_kind!(self, call, _, "function call",

View file

@ -1041,6 +1041,7 @@ symbols! {
mir_offset, mir_offset,
mir_retag, mir_retag,
mir_return, mir_return,
mir_return_to,
mir_set_discriminant, mir_set_discriminant,
mir_static, mir_static,
mir_static_mut, mir_static_mut,

View file

@ -104,21 +104,22 @@
//! } //! }
//! //!
//! #[custom_mir(dialect = "runtime", phase = "optimized")] //! #[custom_mir(dialect = "runtime", phase = "optimized")]
#![cfg_attr(bootstrap, doc = "#[cfg(any())]")] // disable the following function in doctests when `bootstrap` is set
//! fn push_and_pop<T>(v: &mut Vec<T>, value: T) { //! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
//! mir!( //! mir!(
//! let _unused; //! let _unused;
//! let popped; //! let popped;
//! //!
//! { //! {
//! Call(_unused = Vec::push(v, value), pop, UnwindContinue()) //! Call(_unused = Vec::push(v, value), ReturnTo(pop), UnwindContinue())
//! } //! }
//! //!
//! pop = { //! pop = {
//! Call(popped = Vec::pop(v), drop, UnwindContinue()) //! Call(popped = Vec::pop(v), ReturnTo(drop), UnwindContinue())
//! } //! }
//! //!
//! drop = { //! drop = {
//! Drop(popped, ret, UnwindContinue()) //! Drop(popped, ReturnTo(ret), UnwindContinue())
//! } //! }
//! //!
//! ret = { //! ret = {
@ -242,9 +243,8 @@
//! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block` //! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block`
//! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the //! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the
//! otherwise branch. //! otherwise branch.
//! - [`Call`] has an associated function as well. The third argument of this function is a normal //! - [`Call`] has an associated function as well, with special syntax:
//! function call expression, for example `my_other_function(a, 5)`. //! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`.
//!
#![unstable( #![unstable(
feature = "custom_mir", feature = "custom_mir",
@ -287,35 +287,68 @@ macro_rules! define {
} }
// Unwind actions // Unwind actions
pub struct UnwindActionArg;
define!( define!(
"mir_unwind_continue", "mir_unwind_continue",
/// An unwind action that continues unwinding. /// An unwind action that continues unwinding.
fn UnwindContinue() fn UnwindContinue() -> UnwindActionArg
); );
define!( define!(
"mir_unwind_unreachable", "mir_unwind_unreachable",
/// An unwind action that triggers undefined behaviour. /// An unwind action that triggers undefined behaviour.
fn UnwindUnreachable() -> BasicBlock fn UnwindUnreachable() -> UnwindActionArg
); );
define!( define!(
"mir_unwind_terminate", "mir_unwind_terminate",
/// An unwind action that terminates the execution. /// An unwind action that terminates the execution.
/// ///
/// `UnwindTerminate` can also be used as a terminator. /// `UnwindTerminate` can also be used as a terminator.
fn UnwindTerminate(reason: UnwindTerminateReason) fn UnwindTerminate(reason: UnwindTerminateReason) -> UnwindActionArg
); );
define!( define!(
"mir_unwind_cleanup", "mir_unwind_cleanup",
/// An unwind action that continues execution in a given basic blok. /// An unwind action that continues execution in a given basic blok.
fn UnwindCleanup(goto: BasicBlock) fn UnwindCleanup(goto: BasicBlock) -> UnwindActionArg
); );
// Return destination for `Call`
pub struct ReturnToArg;
define!("mir_return_to", fn ReturnTo(goto: BasicBlock) -> ReturnToArg);
// Terminators // Terminators
define!("mir_return", fn Return() -> BasicBlock); define!("mir_return", fn Return() -> BasicBlock);
define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
define!("mir_unreachable", fn Unreachable() -> BasicBlock); define!("mir_unreachable", fn Unreachable() -> BasicBlock);
define!("mir_drop", fn Drop<T, U>(place: T, goto: BasicBlock, unwind_action: U)); define!("mir_drop",
define!("mir_call", fn Call<U>(call: (), goto: BasicBlock, unwind_action: U)); /// Drop the contents of a place.
///
/// The first argument must be a place.
///
/// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that
/// will be jumped to after the destructor returns.
///
/// The third argument describes what happens on unwind. It can be one of:
/// - [`UnwindContinue`]
/// - [`UnwindUnreachable`]
/// - [`UnwindTerminate`]
/// - [`UnwindCleanup`]
fn Drop<T>(place: T, goto: ReturnToArg, unwind_action: UnwindActionArg)
);
define!("mir_call",
/// Call a function.
///
/// The first argument must be of the form `ret_val = fun(arg1, arg2, ...)`.
///
/// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that
/// will be jumped to after the function returns.
///
/// The third argument describes what happens on unwind. It can be one of:
/// - [`UnwindContinue`]
/// - [`UnwindUnreachable`]
/// - [`UnwindTerminate`]
/// - [`UnwindCleanup`]
fn Call(call: (), goto: ReturnToArg, unwind_action: UnwindActionArg)
);
define!("mir_unwind_resume", define!("mir_unwind_resume",
/// A terminator that resumes the unwinding. /// A terminator that resumes the unwinding.
fn UnwindResume() fn UnwindResume()

View file

@ -14,7 +14,7 @@ fn main() {
let ptr = std::ptr::addr_of_mut!(non_copy); let ptr = std::ptr::addr_of_mut!(non_copy);
// Inside `callee`, the first argument and `*ptr` are basically // Inside `callee`, the first argument and `*ptr` are basically
// aliasing places! // aliasing places!
Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue()) Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
} }
after_call = { after_call = {
Return() Return()

View file

@ -27,8 +27,8 @@ LL | unsafe { ptr.write(S(0)) };
note: inside `main` note: inside `main`
--> $DIR/arg_inplace_mutate.rs:LL:CC --> $DIR/arg_inplace_mutate.rs:LL:CC
| |
LL | Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue()) LL | Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -35,8 +35,8 @@ LL | unsafe { ptr.write(S(0)) };
note: inside `main` note: inside `main`
--> $DIR/arg_inplace_mutate.rs:LL:CC --> $DIR/arg_inplace_mutate.rs:LL:CC
| |
LL | Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue()) LL | Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -11,7 +11,7 @@ fn main() {
{ {
let non_copy = S(42); let non_copy = S(42);
// This could change `non_copy` in-place // This could change `non_copy` in-place
Call(_unit = change_arg(Move(non_copy)), after_call, UnwindContinue()) Call(_unit = change_arg(Move(non_copy)), ReturnTo(after_call), UnwindContinue())
} }
after_call = { after_call = {
// So now we must not be allowed to observe non-copy again. // So now we must not be allowed to observe non-copy again.

View file

@ -11,8 +11,8 @@ LL | unsafe { ptr.read() };
note: inside `main` note: inside `main`
--> $DIR/arg_inplace_observe_during.rs:LL:CC --> $DIR/arg_inplace_observe_during.rs:LL:CC
| |
LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) LL | Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -14,7 +14,7 @@ fn main() {
let non_copy = S(42); let non_copy = S(42);
let ptr = std::ptr::addr_of_mut!(non_copy); let ptr = std::ptr::addr_of_mut!(non_copy);
// This could change `non_copy` in-place // This could change `non_copy` in-place
Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
} }
after_call = { after_call = {
Return() Return()

View file

@ -27,8 +27,8 @@ LL | x.0 = 0;
note: inside `main` note: inside `main`
--> $DIR/arg_inplace_observe_during.rs:LL:CC --> $DIR/arg_inplace_observe_during.rs:LL:CC
| |
LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) LL | Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -35,8 +35,8 @@ LL | x.0 = 0;
note: inside `main` note: inside `main`
--> $DIR/arg_inplace_observe_during.rs:LL:CC --> $DIR/arg_inplace_observe_during.rs:LL:CC
| |
LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue()) LL | Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -11,8 +11,8 @@ LL | unsafe { ptr.read() };
note: inside `main` note: inside `main`
--> $DIR/return_pointer_aliasing.rs:LL:CC --> $DIR/return_pointer_aliasing.rs:LL:CC
| |
LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue()) LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -15,7 +15,7 @@ pub fn main() {
let ptr = &raw mut x; let ptr = &raw mut x;
// We arrange for `myfun` to have a pointer that aliases // We arrange for `myfun` to have a pointer that aliases
// its return place. Even just reading from that pointer is UB. // its return place. Even just reading from that pointer is UB.
Call(*ptr = myfun(ptr), after_call, UnwindContinue()) Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
} }
after_call = { after_call = {

View file

@ -27,8 +27,8 @@ LL | unsafe { ptr.read() };
note: inside `main` note: inside `main`
--> $DIR/return_pointer_aliasing.rs:LL:CC --> $DIR/return_pointer_aliasing.rs:LL:CC
| |
LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue()) LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -35,8 +35,8 @@ LL | unsafe { ptr.read() };
note: inside `main` note: inside `main`
--> $DIR/return_pointer_aliasing.rs:LL:CC --> $DIR/return_pointer_aliasing.rs:LL:CC
| |
LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue()) LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -15,7 +15,7 @@ pub fn main() {
let ptr = &raw mut _x; let ptr = &raw mut _x;
// We arrange for `myfun` to have a pointer that aliases // We arrange for `myfun` to have a pointer that aliases
// its return place. Even just reading from that pointer is UB. // its return place. Even just reading from that pointer is UB.
Call(_x = myfun(ptr), after_call, UnwindContinue()) Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
} }
after_call = { after_call = {

View file

@ -30,8 +30,8 @@ LL | unsafe { ptr.write(0) };
note: inside `main` note: inside `main`
--> $DIR/return_pointer_aliasing2.rs:LL:CC --> $DIR/return_pointer_aliasing2.rs:LL:CC
| |
LL | Call(_x = myfun(ptr), after_call, UnwindContinue()) LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -35,8 +35,8 @@ LL | unsafe { ptr.write(0) };
note: inside `main` note: inside `main`
--> $DIR/return_pointer_aliasing2.rs:LL:CC --> $DIR/return_pointer_aliasing2.rs:LL:CC
| |
LL | Call(_x = myfun(ptr), after_call, UnwindContinue()) LL | Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -14,7 +14,7 @@ struct S(i32, [u8; 128]);
fn docall(out: &mut S) { fn docall(out: &mut S) {
mir! { mir! {
{ {
Call(*out = callee(), after_call, UnwindContinue()) Call(*out = callee(), ReturnTo(after_call), UnwindContinue())
} }
after_call = { after_call = {
@ -37,7 +37,7 @@ fn callee() -> S {
// become visible to the outside. In codegen we can see them // become visible to the outside. In codegen we can see them
// but Miri should detect this as UB! // but Miri should detect this as UB!
RET.0 = 42; RET.0 = 42;
Call(_unit = startpanic(), after_call, UnwindContinue()) Call(_unit = startpanic(), ReturnTo(after_call), UnwindContinue())
} }
after_call = { after_call = {

View file

@ -20,7 +20,7 @@ fn call(f: fn(NonZeroU32)) {
let tmp = ptr::addr_of!(c); let tmp = ptr::addr_of!(c);
let ptr = tmp as *const NonZeroU32; let ptr = tmp as *const NonZeroU32;
// The call site now is a NonZeroU32-to-u32 transmute. // The call site now is a NonZeroU32-to-u32 transmute.
Call(_res = f(*ptr), retblock, UnwindContinue()) //~ERROR: expected something greater or equal to 1 Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue()) //~ERROR: expected something greater or equal to 1
} }
retblock = { retblock = {
Return() Return()

View file

@ -1,8 +1,8 @@
error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1 error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
--> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC --> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
| |
LL | Call(_res = f(*ptr), retblock, UnwindContinue()) LL | Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
| |
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View file

@ -11,7 +11,7 @@ pub fn main() {
{ {
let x = 0; let x = 0;
let ptr = &raw mut x; let ptr = &raw mut x;
Call(*ptr = myfun(), after_call, UnwindContinue()) Call(*ptr = myfun(), ReturnTo(after_call), UnwindContinue())
} }
after_call = { after_call = {

View file

@ -13,7 +13,7 @@ fn ident<T>(t: T) -> T {
fn direct_call(x: i32) -> i32 { fn direct_call(x: i32) -> i32 {
mir!( mir!(
{ {
Call(RET = ident(x), retblock, UnwindContinue()) Call(RET = ident(x), ReturnTo(retblock), UnwindContinue())
} }
retblock = { retblock = {
@ -27,7 +27,7 @@ fn direct_call(x: i32) -> i32 {
fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 { fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
mir!( mir!(
{ {
Call(RET = f(x), retblock, UnwindContinue()) Call(RET = f(x), ReturnTo(retblock), UnwindContinue())
} }
retblock = { retblock = {
@ -49,7 +49,7 @@ impl<'a> Drop for WriteOnDrop<'a> {
fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
mir!( mir!(
{ {
Drop(a, retblock, UnwindContinue()) Drop(a, ReturnTo(retblock), UnwindContinue())
} }
retblock = { retblock = {
@ -64,7 +64,7 @@ fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
mir!( mir!(
{ {
Drop(b, retblock, UnwindContinue()) Drop(b, ReturnTo(retblock), UnwindContinue())
} }
retblock = { retblock = {

View file

@ -11,7 +11,7 @@ use core::intrinsics::mir::*;
pub fn a() { pub fn a() {
mir!( mir!(
{ {
Call(RET = a(), bb1, UnwindUnreachable()) Call(RET = a(), ReturnTo(bb1), UnwindUnreachable())
} }
bb1 = { bb1 = {
Return() Return()
@ -26,7 +26,7 @@ pub fn a() {
pub fn b() { pub fn b() {
mir!( mir!(
{ {
Call(RET = b(), bb1, UnwindContinue()) Call(RET = b(), ReturnTo(bb1), UnwindContinue())
} }
bb1 = { bb1 = {
Return() Return()
@ -41,7 +41,7 @@ pub fn b() {
pub fn c() { pub fn c() {
mir!( mir!(
{ {
Call(RET = c(), bb1, UnwindTerminate(ReasonAbi)) Call(RET = c(), ReturnTo(bb1), UnwindTerminate(ReasonAbi))
} }
bb1 = { bb1 = {
Return() Return()
@ -56,7 +56,7 @@ pub fn c() {
pub fn d() { pub fn d() {
mir!( mir!(
{ {
Call(RET = d(), bb1, UnwindCleanup(bb2)) Call(RET = d(), ReturnTo(bb1), UnwindCleanup(bb2))
} }
bb1 = { bb1 = {
Return() Return()

View file

@ -22,11 +22,11 @@ fn f() -> bool {
let b = a; let b = a;
// We cannot propagate the place `a`. // We cannot propagate the place `a`.
let r2 = &b; let r2 = &b;
Call(RET = cmp_ref(r1, r2), next, UnwindContinue()) Call(RET = cmp_ref(r1, r2), ReturnTo(next), UnwindContinue())
} }
next = { next = {
// But we can propagate the value `a`. // But we can propagate the value `a`.
Call(RET = opaque(b), ret, UnwindContinue()) Call(RET = opaque(b), ReturnTo(ret), UnwindContinue())
} }
ret = { ret = {
Return() Return()

View file

@ -26,7 +26,7 @@ fn multiple_edges(t: bool) -> u8 {
match t { true => bbt, _ => ret } match t { true => bbt, _ => ret }
} }
bbt = { bbt = {
Call(x = dummy(13), ret, UnwindContinue()) Call(x = dummy(13), ReturnTo(ret), UnwindContinue())
} }
ret = { ret = {
// `x` is not assigned on the `bb0 -> ret` edge, // `x` is not assigned on the `bb0 -> ret` edge,

View file

@ -14,11 +14,11 @@ struct NotCopy(bool);
fn f(_1: NotCopy) { fn f(_1: NotCopy) {
mir!({ mir!({
let _2 = _1; let _2 = _1;
Call(RET = opaque(Move(_1)), bb1, UnwindContinue()) Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindContinue())
} }
bb1 = { bb1 = {
let _3 = Move(_2); let _3 = Move(_2);
Call(RET = opaque(_3), bb2, UnwindContinue()) Call(RET = opaque(_3), ReturnTo(bb2), UnwindContinue())
} }
bb2 = { bb2 = {
Return() Return()

View file

@ -18,10 +18,10 @@ fn f(a: Foo) -> bool {
let b = a; let b = a;
// This is a move out of a copy, so must become a copy of `a.0`. // This is a move out of a copy, so must become a copy of `a.0`.
let c = Move(b.0); let c = Move(b.0);
Call(RET = opaque(Move(a)), bb1, UnwindContinue()) Call(RET = opaque(Move(a)), ReturnTo(bb1), UnwindContinue())
} }
bb1 = { bb1 = {
Call(RET = opaque(Move(c)), ret, UnwindContinue()) Call(RET = opaque(Move(c)), ReturnTo(ret), UnwindContinue())
} }
ret = { ret = {
Return() Return()

View file

@ -28,7 +28,7 @@ struct Packed {
fn move_packed(packed: Packed) { fn move_packed(packed: Packed) {
mir!( mir!(
{ {
Call(RET = use_both(0, packed.y), ret, UnwindContinue()) Call(RET = use_both(0, packed.y), ReturnTo(ret), UnwindContinue())
} }
ret = { ret = {
Return() Return()

View file

@ -20,7 +20,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) {
mir!( mir!(
let condition: bool; let condition: bool;
{ {
Call(condition = cond(), bb1, UnwindContinue()) Call(condition = cond(), ReturnTo(bb1), UnwindContinue())
} }
bb1 = { bb1 = {
match condition { true => bb2, _ => ret } match condition { true => bb2, _ => ret }
@ -30,7 +30,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) {
z = y; z = y;
y = x; y = x;
x = temp; x = temp;
Call(condition = cond(), bb1, UnwindContinue()) Call(condition = cond(), ReturnTo(bb1), UnwindContinue())
} }
ret = { ret = {
Return() Return()

View file

@ -529,31 +529,31 @@ fn duplicate_slice() -> (bool, bool) {
// CHECK: [[a:_.*]] = (const "a",); // CHECK: [[a:_.*]] = (const "a",);
// CHECK: [[au:_.*]] = ([[a]].0: &str) as u128 (Transmute); // CHECK: [[au:_.*]] = ([[a]].0: &str) as u128 (Transmute);
let a = ("a",); let a = ("a",);
Call(au = transmute::<_, u128>(a.0), bb1, UnwindContinue()) Call(au = transmute::<_, u128>(a.0), ReturnTo(bb1), UnwindContinue())
} }
bb1 = { bb1 = {
// CHECK: [[c:_.*]] = identity::<&str>(([[a]].0: &str)) // CHECK: [[c:_.*]] = identity::<&str>(([[a]].0: &str))
Call(c = identity(a.0), bb2, UnwindContinue()) Call(c = identity(a.0), ReturnTo(bb2), UnwindContinue())
} }
bb2 = { bb2 = {
// CHECK: [[cu:_.*]] = [[c]] as u128 (Transmute); // CHECK: [[cu:_.*]] = [[c]] as u128 (Transmute);
Call(cu = transmute::<_, u128>(c), bb3, UnwindContinue()) Call(cu = transmute::<_, u128>(c), ReturnTo(bb3), UnwindContinue())
} }
bb3 = { bb3 = {
// This slice is different from `a.0`. Hence `bu` is not `au`. // This slice is different from `a.0`. Hence `bu` is not `au`.
// CHECK: [[b:_.*]] = const "a"; // CHECK: [[b:_.*]] = const "a";
// CHECK: [[bu:_.*]] = [[b]] as u128 (Transmute); // CHECK: [[bu:_.*]] = [[b]] as u128 (Transmute);
let b = "a"; let b = "a";
Call(bu = transmute::<_, u128>(b), bb4, UnwindContinue()) Call(bu = transmute::<_, u128>(b), ReturnTo(bb4), UnwindContinue())
} }
bb4 = { bb4 = {
// This returns a copy of `b`, which is not `a`. // This returns a copy of `b`, which is not `a`.
// CHECK: [[d:_.*]] = identity::<&str>([[b]]) // CHECK: [[d:_.*]] = identity::<&str>([[b]])
Call(d = identity(b), bb5, UnwindContinue()) Call(d = identity(b), ReturnTo(bb5), UnwindContinue())
} }
bb5 = { bb5 = {
// CHECK: [[du:_.*]] = [[d]] as u128 (Transmute); // CHECK: [[du:_.*]] = [[d]] as u128 (Transmute);
Call(du = transmute::<_, u128>(d), bb6, UnwindContinue()) Call(du = transmute::<_, u128>(d), ReturnTo(bb6), UnwindContinue())
} }
bb6 = { bb6 = {
// `direct` must not fold to `true`, as `indirect` will not. // `direct` must not fold to `true`, as `indirect` will not.

View file

@ -25,7 +25,7 @@ pub fn f(a: *mut u8) {
Goto(bb1) Goto(bb1)
} }
bb1 = { bb1 = {
Call(*a = g(), bb1, UnwindUnreachable()) Call(*a = g(), ReturnTo(bb1), UnwindUnreachable())
} }
} }
} }

View file

@ -696,7 +696,7 @@ fn multiple_storage() {
// As there are multiple `StorageLive` statements for `x`, we cannot know if this `z`'s // As there are multiple `StorageLive` statements for `x`, we cannot know if this `z`'s
// pointer address is the address of `x`, so do nothing. // pointer address is the address of `x`, so do nothing.
let y = *z; let y = *z;
Call(RET = opaque(y), retblock, UnwindContinue()) Call(RET = opaque(y), ReturnTo(retblock), UnwindContinue())
} }
retblock = { retblock = {
@ -724,7 +724,7 @@ fn dominate_storage() {
} }
bb1 = { bb1 = {
let c = *r; let c = *r;
Call(RET = opaque(c), bb2, UnwindContinue()) Call(RET = opaque(c), ReturnTo(bb2), UnwindContinue())
} }
bb2 = { bb2 = {
StorageDead(x); StorageDead(x);
@ -760,18 +760,18 @@ fn maybe_dead(m: bool) {
bb1 = { bb1 = {
StorageDead(x); StorageDead(x);
StorageDead(y); StorageDead(y);
Call(RET = opaque(u), bb2, UnwindContinue()) Call(RET = opaque(u), ReturnTo(bb2), UnwindContinue())
} }
bb2 = { bb2 = {
// As `x` may be `StorageDead`, `a` may be dangling, so we do nothing. // As `x` may be `StorageDead`, `a` may be dangling, so we do nothing.
let z = *a; let z = *a;
Call(RET = opaque(z), bb3, UnwindContinue()) Call(RET = opaque(z), ReturnTo(bb3), UnwindContinue())
} }
bb3 = { bb3 = {
// As `y` may be `StorageDead`, `b` may be dangling, so we do nothing. // As `y` may be `StorageDead`, `b` may be dangling, so we do nothing.
// This implies that we also do not substitute `b` in `bb0`. // This implies that we also do not substitute `b` in `bb0`.
let t = *b; let t = *b;
Call(RET = opaque(t), retblock, UnwindContinue()) Call(RET = opaque(t), ReturnTo(retblock), UnwindContinue())
} }
retblock = { retblock = {
Return() Return()

View file

@ -13,7 +13,7 @@ pub fn f() -> u32 {
mir!( mir!(
let a: u32; let a: u32;
{ {
Call(a = g(), bb1, UnwindCleanup(bb2)) Call(a = g(), ReturnTo(bb1), UnwindCleanup(bb2))
} }
bb1 = { bb1 = {
RET = a; RET = a;

View file

@ -20,7 +20,7 @@ pub fn f(a: u32) -> u32 {
} }
} }
bb1 = { bb1 = {
Call(RET = f(1), bb2, UnwindTerminate(ReasonAbi)) Call(RET = f(1), ReturnTo(bb2), UnwindTerminate(ReasonAbi))
} }
bb2 = { bb2 = {

View file

@ -11,7 +11,7 @@ use core::intrinsics::mir::*;
pub fn main() { pub fn main() {
mir!( mir!(
{ {
Call(RET = main(), block, UnwindCleanup(block)) Call(RET = main(), ReturnTo(block), UnwindCleanup(block))
} }
block = { block = {
Return() Return()