Custom MIR: Support cleanup blocks

Cleanup blocks are declared with `bb (cleanup) = { ... }`.

`Call` and `Drop` terminators take an additional argument describing the
unwind action, which is one of the following:

* `UnwindContinue()`
* `UnwindUnreachable()`
* `UnwindTerminate(reason)`, where reason is `ReasonAbi` or `ReasonInCleanup`
* `UnwindCleanup(block)`

Also support unwind resume and unwind terminate terminators:

* `UnwindResume()`
* `UnwindTerminate(reason)`
This commit is contained in:
Tomasz Miąsko 2023-11-09 00:00:00 +00:00
parent 287ae4db75
commit 78da577650
38 changed files with 428 additions and 107 deletions

View file

@ -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)
Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue())
}
after_call = {
Return()

View file

@ -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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_unit = callee(Move(*ptr), ptr), 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

View file

@ -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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_unit = callee(Move(*ptr), ptr), 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

View file

@ -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)
Call(_unit = change_arg(Move(non_copy)), after_call, UnwindContinue())
}
after_call = {
// 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`
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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 ptr = std::ptr::addr_of_mut!(non_copy);
// This could change `non_copy` in-place
Call(_unit = change_arg(Move(*ptr), ptr), after_call)
Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue())
}
after_call = {
Return()

View file

@ -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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_unit = change_arg(Move(*ptr), ptr), 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

View file

@ -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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_unit = change_arg(Move(*ptr), ptr), 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

View file

@ -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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(*ptr = myfun(ptr), after_call, UnwindContinue())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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;
// 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)
Call(*ptr = myfun(ptr), after_call, UnwindContinue())
}
after_call = {

View file

@ -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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(*ptr = myfun(ptr), 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

View file

@ -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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(*ptr = myfun(ptr), 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

View file

@ -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)
Call(_x = myfun(ptr), after_call, UnwindContinue())
}
after_call = {

View file

@ -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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_x = myfun(ptr), 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

View file

@ -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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Call(_x = myfun(ptr), 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

View file

@ -14,7 +14,7 @@ struct S(i32, [u8; 128]);
fn docall(out: &mut S) {
mir! {
{
Call(*out = callee(), after_call)
Call(*out = callee(), 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)
Call(_unit = startpanic(), after_call, UnwindContinue())
}
after_call = {

View file

@ -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) //~ERROR: expected something greater or equal to 1
Call(_res = f(*ptr), retblock, UnwindContinue()) //~ERROR: expected something greater or equal to 1
}
retblock = {
Return()

View file

@ -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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
LL | Call(_res = f(*ptr), 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

View file

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