Skip to content

Commit 066453e

Browse files
committed
custom mir: make it clear what the return block is
1 parent e1fadb2 commit 066453e

File tree

19 files changed

+86
-46
lines changed

19 files changed

+86
-46
lines changed

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
6161
@call(mir_drop, args) => {
6262
Ok(TerminatorKind::Drop {
6363
place: self.parse_place(args[0])?,
64-
target: self.parse_block(args[1])?,
64+
target: self.parse_return_to(args[1])?,
6565
unwind: self.parse_unwind_action(args[2])?,
6666
replace: false,
6767
})
@@ -104,6 +104,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
104104
)
105105
}
106106

107+
fn parse_return_to(&self, expr_id: ExprId) -> PResult<BasicBlock> {
108+
parse_by_kind!(self, expr_id, _, "return block",
109+
@call(mir_return_to, args) => {
110+
self.parse_block(args[0])
111+
},
112+
)
113+
}
114+
107115
fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> {
108116
let Some((otherwise, rest)) = arms.split_last() else {
109117
return Err(ParseError {
@@ -146,7 +154,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
146154
ExprKind::Assign { lhs, rhs } => (*lhs, *rhs),
147155
);
148156
let destination = self.parse_place(destination)?;
149-
let target = self.parse_block(args[1])?;
157+
let target = self.parse_return_to(args[1])?;
150158
let unwind = self.parse_unwind_action(args[2])?;
151159

152160
parse_by_kind!(self, call, _, "function call",

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,7 @@ symbols! {
10401040
mir_offset,
10411041
mir_retag,
10421042
mir_return,
1043+
mir_return_to,
10431044
mir_set_discriminant,
10441045
mir_static,
10451046
mir_static_mut,

library/core/src/intrinsics/mir.rs

+40-9
Original file line numberDiff line numberDiff line change
@@ -104,21 +104,22 @@
104104
//! }
105105
//!
106106
//! #[custom_mir(dialect = "runtime", phase = "optimized")]
107+
#![cfg_attr(bootstrap, doc = "#[cfg(any())]")] // disable the following function in doctests when `bootstrap` is set
107108
//! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
108109
//! mir!(
109110
//! let _unused;
110111
//! let popped;
111112
//!
112113
//! {
113-
//! Call(_unused = Vec::push(v, value), pop, UnwindContinue())
114+
//! Call(_unused = Vec::push(v, value), ReturnTo(pop), UnwindContinue())
114115
//! }
115116
//!
116117
//! pop = {
117-
//! Call(popped = Vec::pop(v), drop, UnwindContinue())
118+
//! Call(popped = Vec::pop(v), ReturnTo(drop), UnwindContinue())
118119
//! }
119120
//!
120121
//! drop = {
121-
//! Drop(popped, ret, UnwindContinue())
122+
//! Drop(popped, ReturnTo(ret), UnwindContinue())
122123
//! }
123124
//!
124125
//! ret = {
@@ -242,9 +243,8 @@
242243
//! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block`
243244
//! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the
244245
//! otherwise branch.
245-
//! - [`Call`] has an associated function as well. The third argument of this function is a normal
246-
//! function call expression, for example `my_other_function(a, 5)`.
247-
//!
246+
//! - [`Call`] has an associated function as well, with special syntax:
247+
//! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`.
248248
249249
#![unstable(
250250
feature = "custom_mir",
@@ -295,7 +295,7 @@ define!(
295295
define!(
296296
"mir_unwind_unreachable",
297297
/// An unwind action that triggers undefined behaviour.
298-
fn UnwindUnreachable() -> BasicBlock
298+
fn UnwindUnreachable()
299299
);
300300
define!(
301301
"mir_unwind_terminate",
@@ -310,12 +310,43 @@ define!(
310310
fn UnwindCleanup(goto: BasicBlock)
311311
);
312312

313+
// Return destination for `Call`
314+
define!("mir_return_to", fn ReturnTo(goto: BasicBlock));
315+
313316
// Terminators
314317
define!("mir_return", fn Return() -> BasicBlock);
315318
define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
316319
define!("mir_unreachable", fn Unreachable() -> BasicBlock);
317-
define!("mir_drop", fn Drop<T, U>(place: T, goto: BasicBlock, unwind_action: U));
318-
define!("mir_call", fn Call<U>(call: (), goto: BasicBlock, unwind_action: U));
320+
define!("mir_drop",
321+
/// Drop the contents of a place.
322+
///
323+
/// The first argument must be a place.
324+
///
325+
/// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that
326+
/// will be jumped to after the destructor returns.
327+
///
328+
/// The third argument describes what happens on unwind. It can be one of:
329+
/// - [`UnwindContinue`]
330+
/// - [`UnwindUnreachable`]
331+
/// - [`UnwindTerminate`]
332+
/// - [`UnwindCleanup`]
333+
fn Drop<T>(place: T, goto: (), unwind_action: ())
334+
);
335+
define!("mir_call",
336+
/// Call a function.
337+
///
338+
/// The first argument must be of the form `ret_val = fun(arg1, arg2, ...)`.
339+
///
340+
/// The second argument must be of the form `ReturnTo(bb)`, where `bb` is the basic block that
341+
/// will be jumped to after the function returns.
342+
///
343+
/// The third argument describes what happens on unwind. It can be one of:
344+
/// - [`UnwindContinue`]
345+
/// - [`UnwindUnreachable`]
346+
/// - [`UnwindTerminate`]
347+
/// - [`UnwindCleanup`]
348+
fn Call(call: (), goto: (), unwind_action: ())
349+
);
319350
define!("mir_unwind_resume",
320351
/// A terminator that resumes the unwinding.
321352
fn UnwindResume()

src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs

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

src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
22
--> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
33
|
4-
LL | Call(_res = f(*ptr), retblock, UnwindContinue())
4+
LL | Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue())
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn ident<T>(t: T) -> T {
1313
fn direct_call(x: i32) -> i32 {
1414
mir!(
1515
{
16-
Call(RET = ident(x), retblock, UnwindContinue())
16+
Call(RET = ident(x), ReturnTo(retblock), UnwindContinue())
1717
}
1818

1919
retblock = {
@@ -27,7 +27,7 @@ fn direct_call(x: i32) -> i32 {
2727
fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
2828
mir!(
2929
{
30-
Call(RET = f(x), retblock, UnwindContinue())
30+
Call(RET = f(x), ReturnTo(retblock), UnwindContinue())
3131
}
3232

3333
retblock = {
@@ -49,7 +49,7 @@ impl<'a> Drop for WriteOnDrop<'a> {
4949
fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
5050
mir!(
5151
{
52-
Drop(a, retblock, UnwindContinue())
52+
Drop(a, ReturnTo(retblock), UnwindContinue())
5353
}
5454

5555
retblock = {
@@ -64,7 +64,7 @@ fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
6464
fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
6565
mir!(
6666
{
67-
Drop(b, retblock, UnwindContinue())
67+
Drop(b, ReturnTo(retblock), UnwindContinue())
6868
}
6969

7070
retblock = {

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use core::intrinsics::mir::*;
1111
pub fn a() {
1212
mir!(
1313
{
14-
Call(RET = a(), bb1, UnwindUnreachable())
14+
Call(RET = a(), ReturnTo(bb1), UnwindUnreachable())
1515
}
1616
bb1 = {
1717
Return()
@@ -26,7 +26,7 @@ pub fn a() {
2626
pub fn b() {
2727
mir!(
2828
{
29-
Call(RET = b(), bb1, UnwindContinue())
29+
Call(RET = b(), ReturnTo(bb1), UnwindContinue())
3030
}
3131
bb1 = {
3232
Return()
@@ -41,7 +41,7 @@ pub fn b() {
4141
pub fn c() {
4242
mir!(
4343
{
44-
Call(RET = c(), bb1, UnwindTerminate(ReasonAbi))
44+
Call(RET = c(), ReturnTo(bb1), UnwindTerminate(ReasonAbi))
4545
}
4646
bb1 = {
4747
Return()
@@ -56,7 +56,7 @@ pub fn c() {
5656
pub fn d() {
5757
mir!(
5858
{
59-
Call(RET = d(), bb1, UnwindCleanup(bb2))
59+
Call(RET = d(), ReturnTo(bb1), UnwindCleanup(bb2))
6060
}
6161
bb1 = {
6262
Return()

tests/mir-opt/copy-prop/borrowed_local.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ fn f() -> bool {
2222
let b = a;
2323
// We cannot propagate the place `a`.
2424
let r2 = &b;
25-
Call(RET = cmp_ref(r1, r2), next, UnwindContinue())
25+
Call(RET = cmp_ref(r1, r2), ReturnTo(next), UnwindContinue())
2626
}
2727
next = {
2828
// But we can propagate the value `a`.
29-
Call(RET = opaque(b), ret, UnwindContinue())
29+
Call(RET = opaque(b), ReturnTo(ret), UnwindContinue())
3030
}
3131
ret = {
3232
Return()

tests/mir-opt/copy-prop/calls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn multiple_edges(t: bool) -> u8 {
2626
match t { true => bbt, _ => ret }
2727
}
2828
bbt = {
29-
Call(x = dummy(13), ret, UnwindContinue())
29+
Call(x = dummy(13), ReturnTo(ret), UnwindContinue())
3030
}
3131
ret = {
3232
// `x` is not assigned on the `bb0 -> ret` edge,

tests/mir-opt/copy-prop/custom_move_arg.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ struct NotCopy(bool);
1414
fn f(_1: NotCopy) {
1515
mir!({
1616
let _2 = _1;
17-
Call(RET = opaque(Move(_1)), bb1, UnwindContinue())
17+
Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindContinue())
1818
}
1919
bb1 = {
2020
let _3 = Move(_2);
21-
Call(RET = opaque(_3), bb2, UnwindContinue())
21+
Call(RET = opaque(_3), ReturnTo(bb2), UnwindContinue())
2222
}
2323
bb2 = {
2424
Return()

tests/mir-opt/copy-prop/move_projection.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ fn f(a: Foo) -> bool {
1818
let b = a;
1919
// This is a move out of a copy, so must become a copy of `a.0`.
2020
let c = Move(b.0);
21-
Call(RET = opaque(Move(a)), bb1, UnwindContinue())
21+
Call(RET = opaque(Move(a)), ReturnTo(bb1), UnwindContinue())
2222
}
2323
bb1 = {
24-
Call(RET = opaque(Move(c)), ret, UnwindContinue())
24+
Call(RET = opaque(Move(c)), ReturnTo(ret), UnwindContinue())
2525
}
2626
ret = {
2727
Return()

tests/mir-opt/dead-store-elimination/call_arg_copy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct Packed {
2828
fn move_packed(packed: Packed) {
2929
mir!(
3030
{
31-
Call(RET = use_both(0, packed.y), ret, UnwindContinue())
31+
Call(RET = use_both(0, packed.y), ReturnTo(ret), UnwindContinue())
3232
}
3333
ret = {
3434
Return()

tests/mir-opt/dead-store-elimination/cycle.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) {
2020
mir!(
2121
let condition: bool;
2222
{
23-
Call(condition = cond(), bb1, UnwindContinue())
23+
Call(condition = cond(), ReturnTo(bb1), UnwindContinue())
2424
}
2525
bb1 = {
2626
match condition { true => bb2, _ => ret }
@@ -30,7 +30,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) {
3030
z = y;
3131
y = x;
3232
x = temp;
33-
Call(condition = cond(), bb1, UnwindContinue())
33+
Call(condition = cond(), ReturnTo(bb1), UnwindContinue())
3434
}
3535
ret = {
3636
Return()

tests/mir-opt/gvn.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -529,31 +529,31 @@ fn duplicate_slice() -> (bool, bool) {
529529
// CHECK: [[a:_.*]] = (const "a",);
530530
// CHECK: [[au:_.*]] = ([[a]].0: &str) as u128 (Transmute);
531531
let a = ("a",);
532-
Call(au = transmute::<_, u128>(a.0), bb1, UnwindContinue())
532+
Call(au = transmute::<_, u128>(a.0), ReturnTo(bb1), UnwindContinue())
533533
}
534534
bb1 = {
535535
// CHECK: [[c:_.*]] = identity::<&str>(([[a]].0: &str))
536-
Call(c = identity(a.0), bb2, UnwindContinue())
536+
Call(c = identity(a.0), ReturnTo(bb2), UnwindContinue())
537537
}
538538
bb2 = {
539539
// CHECK: [[cu:_.*]] = [[c]] as u128 (Transmute);
540-
Call(cu = transmute::<_, u128>(c), bb3, UnwindContinue())
540+
Call(cu = transmute::<_, u128>(c), ReturnTo(bb3), UnwindContinue())
541541
}
542542
bb3 = {
543543
// This slice is different from `a.0`. Hence `bu` is not `au`.
544544
// CHECK: [[b:_.*]] = const "a";
545545
// CHECK: [[bu:_.*]] = [[b]] as u128 (Transmute);
546546
let b = "a";
547-
Call(bu = transmute::<_, u128>(b), bb4, UnwindContinue())
547+
Call(bu = transmute::<_, u128>(b), ReturnTo(bb4), UnwindContinue())
548548
}
549549
bb4 = {
550550
// This returns a copy of `b`, which is not `a`.
551551
// CHECK: [[d:_.*]] = identity::<&str>([[b]])
552-
Call(d = identity(b), bb5, UnwindContinue())
552+
Call(d = identity(b), ReturnTo(bb5), UnwindContinue())
553553
}
554554
bb5 = {
555555
// CHECK: [[du:_.*]] = [[d]] as u128 (Transmute);
556-
Call(du = transmute::<_, u128>(d), bb6, UnwindContinue())
556+
Call(du = transmute::<_, u128>(d), ReturnTo(bb6), UnwindContinue())
557557
}
558558
bb6 = {
559559
// `direct` must not fold to `true`, as `indirect` will not.

tests/mir-opt/inline/indirect_destination.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn f(a: *mut u8) {
2525
Goto(bb1)
2626
}
2727
bb1 = {
28-
Call(*a = g(), bb1, UnwindUnreachable())
28+
Call(*a = g(), ReturnTo(bb1), UnwindUnreachable())
2929
}
3030
}
3131
}

tests/mir-opt/reference_prop.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ fn multiple_storage() {
696696
// As there are multiple `StorageLive` statements for `x`, we cannot know if this `z`'s
697697
// pointer address is the address of `x`, so do nothing.
698698
let y = *z;
699-
Call(RET = opaque(y), retblock, UnwindContinue())
699+
Call(RET = opaque(y), ReturnTo(retblock), UnwindContinue())
700700
}
701701

702702
retblock = {
@@ -724,7 +724,7 @@ fn dominate_storage() {
724724
}
725725
bb1 = {
726726
let c = *r;
727-
Call(RET = opaque(c), bb2, UnwindContinue())
727+
Call(RET = opaque(c), ReturnTo(bb2), UnwindContinue())
728728
}
729729
bb2 = {
730730
StorageDead(x);
@@ -760,18 +760,18 @@ fn maybe_dead(m: bool) {
760760
bb1 = {
761761
StorageDead(x);
762762
StorageDead(y);
763-
Call(RET = opaque(u), bb2, UnwindContinue())
763+
Call(RET = opaque(u), ReturnTo(bb2), UnwindContinue())
764764
}
765765
bb2 = {
766766
// As `x` may be `StorageDead`, `a` may be dangling, so we do nothing.
767767
let z = *a;
768-
Call(RET = opaque(z), bb3, UnwindContinue())
768+
Call(RET = opaque(z), ReturnTo(bb3), UnwindContinue())
769769
}
770770
bb3 = {
771771
// As `y` may be `StorageDead`, `b` may be dangling, so we do nothing.
772772
// This implies that we also do not substitute `b` in `bb0`.
773773
let t = *b;
774-
Call(RET = opaque(t), retblock, UnwindContinue())
774+
Call(RET = opaque(t), ReturnTo(retblock), UnwindContinue())
775775
}
776776
retblock = {
777777
Return()

tests/ui/mir/ssa_call_ret.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub fn f() -> u32 {
1313
mir!(
1414
let a: u32;
1515
{
16-
Call(a = g(), bb1, UnwindCleanup(bb2))
16+
Call(a = g(), ReturnTo(bb1), UnwindCleanup(bb2))
1717
}
1818
bb1 = {
1919
RET = a;

0 commit comments

Comments
 (0)