From 0f9baa8a31a4bf4d38ff90e402d43f0cd19662a8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Dec 2023 19:31:52 +0100 Subject: [PATCH 1/2] custom mir: make it clear what the return block is --- .../src/build/custom/parse/instruction.rs | 12 ++++- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/intrinsics/mir.rs | 49 +++++++++++++++---- .../fail/function_calls/arg_inplace_mutate.rs | 2 +- .../arg_inplace_mutate.stack.stderr | 4 +- .../arg_inplace_mutate.tree.stderr | 4 +- .../arg_inplace_observe_after.rs | 2 +- .../arg_inplace_observe_during.none.stderr | 4 +- .../arg_inplace_observe_during.rs | 2 +- .../arg_inplace_observe_during.stack.stderr | 4 +- .../arg_inplace_observe_during.tree.stderr | 4 +- .../return_pointer_aliasing.none.stderr | 4 +- .../function_calls/return_pointer_aliasing.rs | 2 +- .../return_pointer_aliasing.stack.stderr | 4 +- .../return_pointer_aliasing.tree.stderr | 4 +- .../return_pointer_aliasing2.rs | 2 +- .../return_pointer_aliasing2.stack.stderr | 4 +- .../return_pointer_aliasing2.tree.stderr | 4 +- .../return_pointer_on_unwind.rs | 4 +- .../cast_fn_ptr_invalid_caller_arg.rs | 2 +- .../cast_fn_ptr_invalid_caller_arg.stderr | 4 +- .../function_calls/return_place_on_heap.rs | 2 +- tests/mir-opt/building/custom/terminators.rs | 8 +-- .../mir-opt/building/custom/unwind_action.rs | 8 +-- tests/mir-opt/copy-prop/borrowed_local.rs | 4 +- tests/mir-opt/copy-prop/calls.rs | 2 +- tests/mir-opt/copy-prop/custom_move_arg.rs | 4 +- tests/mir-opt/copy-prop/move_projection.rs | 4 +- .../dead-store-elimination/call_arg_copy.rs | 2 +- tests/mir-opt/dead-store-elimination/cycle.rs | 4 +- tests/mir-opt/gvn.rs | 12 ++--- tests/mir-opt/inline/indirect_destination.rs | 2 +- tests/mir-opt/reference_prop.rs | 10 ++-- tests/ui/mir/ssa_call_ret.rs | 2 +- tests/ui/mir/validate/critical-edge.rs | 2 +- tests/ui/mir/validate/noncleanup-cleanup.rs | 2 +- 36 files changed, 115 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 4ce7f831c8711..e3dea2212df0d 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -61,7 +61,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { @call(mir_drop, args) => { Ok(TerminatorKind::Drop { 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])?, replace: false, }) @@ -104,6 +104,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ) } + fn parse_return_to(&self, expr_id: ExprId) -> PResult { + 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 { let Some((otherwise, rest)) = arms.split_last() else { return Err(ParseError { @@ -146,7 +154,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ExprKind::Assign { lhs, rhs } => (*lhs, *rhs), ); 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])?; parse_by_kind!(self, call, _, "function call", diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 95106cc64c129..03314d8bb5d77 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1040,6 +1040,7 @@ symbols! { mir_offset, mir_retag, mir_return, + mir_return_to, mir_set_discriminant, mir_static, mir_static_mut, diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 34a61e76fcf66..cffe462612850 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -104,21 +104,22 @@ //! } //! //! #[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(v: &mut Vec, value: T) { //! mir!( //! let _unused; //! let popped; //! //! { -//! Call(_unused = Vec::push(v, value), pop, UnwindContinue()) +//! Call(_unused = Vec::push(v, value), ReturnTo(pop), UnwindContinue()) //! } //! //! pop = { -//! Call(popped = Vec::pop(v), drop, UnwindContinue()) +//! Call(popped = Vec::pop(v), ReturnTo(drop), UnwindContinue()) //! } //! //! drop = { -//! Drop(popped, ret, UnwindContinue()) +//! Drop(popped, ReturnTo(ret), UnwindContinue()) //! } //! //! ret = { @@ -242,9 +243,8 @@ //! - `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 //! otherwise branch. -//! - [`Call`] has an associated function as well. The third argument of this function is a normal -//! function call expression, for example `my_other_function(a, 5)`. -//! +//! - [`Call`] has an associated function as well, with special syntax: +//! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`. #![unstable( feature = "custom_mir", @@ -295,7 +295,7 @@ define!( define!( "mir_unwind_unreachable", /// An unwind action that triggers undefined behaviour. - fn UnwindUnreachable() -> BasicBlock + fn UnwindUnreachable() ); define!( "mir_unwind_terminate", @@ -310,12 +310,43 @@ define!( fn UnwindCleanup(goto: BasicBlock) ); +// Return destination for `Call` +define!("mir_return_to", fn ReturnTo(goto: BasicBlock)); + // Terminators define!("mir_return", fn Return() -> BasicBlock); define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); define!("mir_unreachable", fn Unreachable() -> BasicBlock); -define!("mir_drop", fn Drop(place: T, goto: BasicBlock, unwind_action: U)); -define!("mir_call", fn Call(call: (), goto: BasicBlock, unwind_action: U)); +define!("mir_drop", + /// 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(place: T, goto: (), unwind_action: ()) +); +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: (), unwind_action: ()) +); define!("mir_unwind_resume", /// A terminator that resumes the unwinding. fn UnwindResume() diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs index e79bd70e915e5..8a5c10913b48a 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs @@ -14,7 +14,7 @@ fn main() { let ptr = std::ptr::addr_of_mut!(non_copy); // Inside `callee`, the first argument and `*ptr` are basically // aliasing places! - Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue()) + Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue()) } after_call = { Return() diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr index 1756123c84ebc..422dc24343612 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr @@ -27,8 +27,8 @@ LL | unsafe { ptr.write(S(0)) }; note: inside `main` --> $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: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr index 76f7ee189e3d4..4fe9b7b4728da 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr @@ -35,8 +35,8 @@ LL | unsafe { ptr.write(S(0)) }; note: inside `main` --> $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: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs index e4c00fdd84561..18daf9497a15b 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs @@ -11,7 +11,7 @@ fn main() { { let non_copy = S(42); // 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 = { // So now we must not be allowed to observe non-copy again. diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr index 723ca75daef89..1c73577f5cd5d 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr @@ -11,8 +11,8 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $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 diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs index 517abd733a9ce..2201bf17bfc78 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs @@ -14,7 +14,7 @@ fn main() { let non_copy = S(42); let ptr = std::ptr::addr_of_mut!(non_copy); // 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 = { Return() diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr index 401e8c6d5a8a6..09c9a777eca46 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr @@ -27,8 +27,8 @@ LL | x.0 = 0; note: inside `main` --> $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: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr index 3529ddd3c53cb..67906f24bbd03 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr @@ -35,8 +35,8 @@ LL | x.0 = 0; note: inside `main` --> $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: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr index 48db898a250fc..eb215a2d2e805 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr @@ -11,8 +11,8 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $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 diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs index 23b1e38b99f72..c8e0782eff2ff 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs @@ -15,7 +15,7 @@ pub fn main() { let ptr = &raw mut x; // We arrange for `myfun` to have a pointer that aliases // 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 = { diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr index 85dcd29ba5513..01357f430fc71 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr @@ -27,8 +27,8 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $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: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr index ea1867b1a7153..6b3f5fbedee9c 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr @@ -35,8 +35,8 @@ LL | unsafe { ptr.read() }; note: inside `main` --> $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: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs index 56706cdb63bad..7db641538ce55 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs @@ -15,7 +15,7 @@ pub fn main() { let ptr = &raw mut _x; // We arrange for `myfun` to have a pointer that aliases // 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 = { diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr index 12a99fbf2931f..04040827b0f97 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr @@ -30,8 +30,8 @@ LL | unsafe { ptr.write(0) }; note: inside `main` --> $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: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr index 926303bb48948..37c98eabbec83 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr @@ -35,8 +35,8 @@ LL | unsafe { ptr.write(0) }; note: inside `main` --> $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: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs index 923c59e74299a..244acd8f2be5e 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs @@ -14,7 +14,7 @@ struct S(i32, [u8; 128]); fn docall(out: &mut S) { mir! { { - Call(*out = callee(), after_call, UnwindContinue()) + Call(*out = callee(), ReturnTo(after_call), UnwindContinue()) } after_call = { @@ -37,7 +37,7 @@ fn callee() -> S { // become visible to the outside. In codegen we can see them // but Miri should detect this as UB! RET.0 = 42; - Call(_unit = startpanic(), after_call, UnwindContinue()) + Call(_unit = startpanic(), ReturnTo(after_call), UnwindContinue()) } after_call = { diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs index 9357b37250508..3a87bb786776e 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs @@ -20,7 +20,7 @@ fn call(f: fn(NonZeroU32)) { let tmp = ptr::addr_of!(c); let ptr = tmp as *const NonZeroU32; // 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 = { Return() diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr index 9e9ea710f0e47..b1a2bd2c79a40 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr @@ -1,8 +1,8 @@ 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 | -LL | Call(_res = f(*ptr), retblock, UnwindContinue()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 +LL | Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs index 89ee689fabe1f..a5cbe2a0d1d9e 100644 --- a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs +++ b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs @@ -11,7 +11,7 @@ pub fn main() { { let x = 0; let ptr = &raw mut x; - Call(*ptr = myfun(), after_call, UnwindContinue()) + Call(*ptr = myfun(), ReturnTo(after_call), UnwindContinue()) } after_call = { diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs index a83a6c07461f4..01c132cf3e77a 100644 --- a/tests/mir-opt/building/custom/terminators.rs +++ b/tests/mir-opt/building/custom/terminators.rs @@ -13,7 +13,7 @@ fn ident(t: T) -> T { fn direct_call(x: i32) -> i32 { mir!( { - Call(RET = ident(x), retblock, UnwindContinue()) + Call(RET = ident(x), ReturnTo(retblock), UnwindContinue()) } retblock = { @@ -27,7 +27,7 @@ fn direct_call(x: i32) -> i32 { fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 { mir!( { - Call(RET = f(x), retblock, UnwindContinue()) + Call(RET = f(x), ReturnTo(retblock), UnwindContinue()) } retblock = { @@ -49,7 +49,7 @@ impl<'a> Drop for WriteOnDrop<'a> { fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { mir!( { - Drop(a, retblock, UnwindContinue()) + Drop(a, ReturnTo(retblock), UnwindContinue()) } 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>) { mir!( { - Drop(b, retblock, UnwindContinue()) + Drop(b, ReturnTo(retblock), UnwindContinue()) } retblock = { diff --git a/tests/mir-opt/building/custom/unwind_action.rs b/tests/mir-opt/building/custom/unwind_action.rs index e3c4ffac358ad..0dfbf780f676a 100644 --- a/tests/mir-opt/building/custom/unwind_action.rs +++ b/tests/mir-opt/building/custom/unwind_action.rs @@ -11,7 +11,7 @@ use core::intrinsics::mir::*; pub fn a() { mir!( { - Call(RET = a(), bb1, UnwindUnreachable()) + Call(RET = a(), ReturnTo(bb1), UnwindUnreachable()) } bb1 = { Return() @@ -26,7 +26,7 @@ pub fn a() { pub fn b() { mir!( { - Call(RET = b(), bb1, UnwindContinue()) + Call(RET = b(), ReturnTo(bb1), UnwindContinue()) } bb1 = { Return() @@ -41,7 +41,7 @@ pub fn b() { pub fn c() { mir!( { - Call(RET = c(), bb1, UnwindTerminate(ReasonAbi)) + Call(RET = c(), ReturnTo(bb1), UnwindTerminate(ReasonAbi)) } bb1 = { Return() @@ -56,7 +56,7 @@ pub fn c() { pub fn d() { mir!( { - Call(RET = d(), bb1, UnwindCleanup(bb2)) + Call(RET = d(), ReturnTo(bb1), UnwindCleanup(bb2)) } bb1 = { Return() diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs index a44e65164af01..af40f5bce8b23 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.rs +++ b/tests/mir-opt/copy-prop/borrowed_local.rs @@ -22,11 +22,11 @@ fn f() -> bool { let b = a; // We cannot propagate the place `a`. let r2 = &b; - Call(RET = cmp_ref(r1, r2), next, UnwindContinue()) + Call(RET = cmp_ref(r1, r2), ReturnTo(next), UnwindContinue()) } next = { // But we can propagate the value `a`. - Call(RET = opaque(b), ret, UnwindContinue()) + Call(RET = opaque(b), ReturnTo(ret), UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/copy-prop/calls.rs b/tests/mir-opt/copy-prop/calls.rs index bc6760707ccca..a6b5d511805c4 100644 --- a/tests/mir-opt/copy-prop/calls.rs +++ b/tests/mir-opt/copy-prop/calls.rs @@ -26,7 +26,7 @@ fn multiple_edges(t: bool) -> u8 { match t { true => bbt, _ => ret } } bbt = { - Call(x = dummy(13), ret, UnwindContinue()) + Call(x = dummy(13), ReturnTo(ret), UnwindContinue()) } ret = { // `x` is not assigned on the `bb0 -> ret` edge, diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs index 8593d9fa9aba2..45913626a8fe5 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.rs +++ b/tests/mir-opt/copy-prop/custom_move_arg.rs @@ -14,11 +14,11 @@ struct NotCopy(bool); fn f(_1: NotCopy) { mir!({ let _2 = _1; - Call(RET = opaque(Move(_1)), bb1, UnwindContinue()) + Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindContinue()) } bb1 = { let _3 = Move(_2); - Call(RET = opaque(_3), bb2, UnwindContinue()) + Call(RET = opaque(_3), ReturnTo(bb2), UnwindContinue()) } bb2 = { Return() diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs index 438a90dddd0cb..f02867814ac0a 100644 --- a/tests/mir-opt/copy-prop/move_projection.rs +++ b/tests/mir-opt/copy-prop/move_projection.rs @@ -18,10 +18,10 @@ fn f(a: Foo) -> bool { let b = a; // This is a move out of a copy, so must become a copy of `a.0`. let c = Move(b.0); - Call(RET = opaque(Move(a)), bb1, UnwindContinue()) + Call(RET = opaque(Move(a)), ReturnTo(bb1), UnwindContinue()) } bb1 = { - Call(RET = opaque(Move(c)), ret, UnwindContinue()) + Call(RET = opaque(Move(c)), ReturnTo(ret), UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index b2eb64756f9ac..490a4aa502c38 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs @@ -28,7 +28,7 @@ struct Packed { fn move_packed(packed: Packed) { mir!( { - Call(RET = use_both(0, packed.y), ret, UnwindContinue()) + Call(RET = use_both(0, packed.y), ReturnTo(ret), UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs index c9ad06a9da266..13e5411275da8 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.rs +++ b/tests/mir-opt/dead-store-elimination/cycle.rs @@ -20,7 +20,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) { mir!( let condition: bool; { - Call(condition = cond(), bb1, UnwindContinue()) + Call(condition = cond(), ReturnTo(bb1), UnwindContinue()) } bb1 = { match condition { true => bb2, _ => ret } @@ -30,7 +30,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) { z = y; y = x; x = temp; - Call(condition = cond(), bb1, UnwindContinue()) + Call(condition = cond(), ReturnTo(bb1), UnwindContinue()) } ret = { Return() diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index db131f7f97d8b..23e33a0fa49ea 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -529,31 +529,31 @@ fn duplicate_slice() -> (bool, bool) { // CHECK: [[a:_.*]] = (const "a",); // CHECK: [[au:_.*]] = ([[a]].0: &str) as u128 (Transmute); let a = ("a",); - Call(au = transmute::<_, u128>(a.0), bb1, UnwindContinue()) + Call(au = transmute::<_, u128>(a.0), ReturnTo(bb1), UnwindContinue()) } bb1 = { // CHECK: [[c:_.*]] = identity::<&str>(([[a]].0: &str)) - Call(c = identity(a.0), bb2, UnwindContinue()) + Call(c = identity(a.0), ReturnTo(bb2), UnwindContinue()) } bb2 = { // CHECK: [[cu:_.*]] = [[c]] as u128 (Transmute); - Call(cu = transmute::<_, u128>(c), bb3, UnwindContinue()) + Call(cu = transmute::<_, u128>(c), ReturnTo(bb3), UnwindContinue()) } bb3 = { // This slice is different from `a.0`. Hence `bu` is not `au`. // CHECK: [[b:_.*]] = const "a"; // CHECK: [[bu:_.*]] = [[b]] as u128 (Transmute); let b = "a"; - Call(bu = transmute::<_, u128>(b), bb4, UnwindContinue()) + Call(bu = transmute::<_, u128>(b), ReturnTo(bb4), UnwindContinue()) } bb4 = { // This returns a copy of `b`, which is not `a`. // CHECK: [[d:_.*]] = identity::<&str>([[b]]) - Call(d = identity(b), bb5, UnwindContinue()) + Call(d = identity(b), ReturnTo(bb5), UnwindContinue()) } bb5 = { // CHECK: [[du:_.*]] = [[d]] as u128 (Transmute); - Call(du = transmute::<_, u128>(d), bb6, UnwindContinue()) + Call(du = transmute::<_, u128>(d), ReturnTo(bb6), UnwindContinue()) } bb6 = { // `direct` must not fold to `true`, as `indirect` will not. diff --git a/tests/mir-opt/inline/indirect_destination.rs b/tests/mir-opt/inline/indirect_destination.rs index 2842e23366e00..82143d85c258a 100644 --- a/tests/mir-opt/inline/indirect_destination.rs +++ b/tests/mir-opt/inline/indirect_destination.rs @@ -25,7 +25,7 @@ pub fn f(a: *mut u8) { Goto(bb1) } bb1 = { - Call(*a = g(), bb1, UnwindUnreachable()) + Call(*a = g(), ReturnTo(bb1), UnwindUnreachable()) } } } diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index 8adfbb4535b9a..b71ad90abb19d 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -696,7 +696,7 @@ fn multiple_storage() { // 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. let y = *z; - Call(RET = opaque(y), retblock, UnwindContinue()) + Call(RET = opaque(y), ReturnTo(retblock), UnwindContinue()) } retblock = { @@ -724,7 +724,7 @@ fn dominate_storage() { } bb1 = { let c = *r; - Call(RET = opaque(c), bb2, UnwindContinue()) + Call(RET = opaque(c), ReturnTo(bb2), UnwindContinue()) } bb2 = { StorageDead(x); @@ -760,18 +760,18 @@ fn maybe_dead(m: bool) { bb1 = { StorageDead(x); StorageDead(y); - Call(RET = opaque(u), bb2, UnwindContinue()) + Call(RET = opaque(u), ReturnTo(bb2), UnwindContinue()) } bb2 = { // As `x` may be `StorageDead`, `a` may be dangling, so we do nothing. let z = *a; - Call(RET = opaque(z), bb3, UnwindContinue()) + Call(RET = opaque(z), ReturnTo(bb3), UnwindContinue()) } bb3 = { // As `y` may be `StorageDead`, `b` may be dangling, so we do nothing. // This implies that we also do not substitute `b` in `bb0`. let t = *b; - Call(RET = opaque(t), retblock, UnwindContinue()) + Call(RET = opaque(t), ReturnTo(retblock), UnwindContinue()) } retblock = { Return() diff --git a/tests/ui/mir/ssa_call_ret.rs b/tests/ui/mir/ssa_call_ret.rs index 6132a6691dea3..f8a83249225c2 100644 --- a/tests/ui/mir/ssa_call_ret.rs +++ b/tests/ui/mir/ssa_call_ret.rs @@ -13,7 +13,7 @@ pub fn f() -> u32 { mir!( let a: u32; { - Call(a = g(), bb1, UnwindCleanup(bb2)) + Call(a = g(), ReturnTo(bb1), UnwindCleanup(bb2)) } bb1 = { RET = a; diff --git a/tests/ui/mir/validate/critical-edge.rs b/tests/ui/mir/validate/critical-edge.rs index 9ef655cd1bb4a..3bb732ad3f776 100644 --- a/tests/ui/mir/validate/critical-edge.rs +++ b/tests/ui/mir/validate/critical-edge.rs @@ -20,7 +20,7 @@ pub fn f(a: u32) -> u32 { } } bb1 = { - Call(RET = f(1), bb2, UnwindTerminate(ReasonAbi)) + Call(RET = f(1), ReturnTo(bb2), UnwindTerminate(ReasonAbi)) } bb2 = { diff --git a/tests/ui/mir/validate/noncleanup-cleanup.rs b/tests/ui/mir/validate/noncleanup-cleanup.rs index 0a1c4528aa6d9..a14ab44257fa1 100644 --- a/tests/ui/mir/validate/noncleanup-cleanup.rs +++ b/tests/ui/mir/validate/noncleanup-cleanup.rs @@ -11,7 +11,7 @@ use core::intrinsics::mir::*; pub fn main() { mir!( { - Call(RET = main(), block, UnwindCleanup(block)) + Call(RET = main(), ReturnTo(block), UnwindCleanup(block)) } block = { Return() From 4bf2794e599c7905d3f83748678be656582ad6c3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Dec 2023 20:13:39 +0100 Subject: [PATCH 2/2] custom mir: better type-checking --- library/core/src/intrinsics/mir.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index cffe462612850..c6401ec1e3333 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -287,31 +287,33 @@ macro_rules! define { } // Unwind actions +pub struct UnwindActionArg; define!( "mir_unwind_continue", /// An unwind action that continues unwinding. - fn UnwindContinue() + fn UnwindContinue() -> UnwindActionArg ); define!( "mir_unwind_unreachable", /// An unwind action that triggers undefined behaviour. - fn UnwindUnreachable() + fn UnwindUnreachable() -> UnwindActionArg ); define!( "mir_unwind_terminate", /// An unwind action that terminates the execution. /// /// `UnwindTerminate` can also be used as a terminator. - fn UnwindTerminate(reason: UnwindTerminateReason) + fn UnwindTerminate(reason: UnwindTerminateReason) -> UnwindActionArg ); define!( "mir_unwind_cleanup", /// An unwind action that continues execution in a given basic blok. - fn UnwindCleanup(goto: BasicBlock) + fn UnwindCleanup(goto: BasicBlock) -> UnwindActionArg ); // Return destination for `Call` -define!("mir_return_to", fn ReturnTo(goto: BasicBlock)); +pub struct ReturnToArg; +define!("mir_return_to", fn ReturnTo(goto: BasicBlock) -> ReturnToArg); // Terminators define!("mir_return", fn Return() -> BasicBlock); @@ -330,7 +332,7 @@ define!("mir_drop", /// - [`UnwindUnreachable`] /// - [`UnwindTerminate`] /// - [`UnwindCleanup`] - fn Drop(place: T, goto: (), unwind_action: ()) + fn Drop(place: T, goto: ReturnToArg, unwind_action: UnwindActionArg) ); define!("mir_call", /// Call a function. @@ -345,7 +347,7 @@ define!("mir_call", /// - [`UnwindUnreachable`] /// - [`UnwindTerminate`] /// - [`UnwindCleanup`] - fn Call(call: (), goto: (), unwind_action: ()) + fn Call(call: (), goto: ReturnToArg, unwind_action: UnwindActionArg) ); define!("mir_unwind_resume", /// A terminator that resumes the unwinding.