Skip to content

Commit 2423483

Browse files
committedOct 7, 2022
Fix MIR inlining of asm_unwind
1 parent 01af504 commit 2423483

File tree

3 files changed

+85
-25
lines changed

3 files changed

+85
-25
lines changed
 

‎compiler/rustc_mir_transform/src/inline.rs

+19-25
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,21 @@ impl Integrator<'_, '_> {
977977
trace!("mapping block `{:?}` to `{:?}`", block, new);
978978
new
979979
}
980+
981+
fn map_unwind(&self, unwind: Option<BasicBlock>) -> Option<BasicBlock> {
982+
if self.in_cleanup_block {
983+
if unwind.is_some() {
984+
bug!("cleanup on cleanup block");
985+
}
986+
return unwind;
987+
}
988+
989+
match unwind {
990+
Some(target) => Some(self.map_block(target)),
991+
// Add an unwind edge to the original call's cleanup block
992+
None => self.cleanup_block,
993+
}
994+
}
980995
}
981996

982997
impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
@@ -1085,35 +1100,17 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
10851100
TerminatorKind::Drop { ref mut target, ref mut unwind, .. }
10861101
| TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => {
10871102
*target = self.map_block(*target);
1088-
if let Some(tgt) = *unwind {
1089-
*unwind = Some(self.map_block(tgt));
1090-
} else if !self.in_cleanup_block {
1091-
// Unless this drop is in a cleanup block, add an unwind edge to
1092-
// the original call's cleanup block
1093-
*unwind = self.cleanup_block;
1094-
}
1103+
*unwind = self.map_unwind(*unwind);
10951104
}
10961105
TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => {
10971106
if let Some(ref mut tgt) = *target {
10981107
*tgt = self.map_block(*tgt);
10991108
}
1100-
if let Some(tgt) = *cleanup {
1101-
*cleanup = Some(self.map_block(tgt));
1102-
} else if !self.in_cleanup_block {
1103-
// Unless this call is in a cleanup block, add an unwind edge to
1104-
// the original call's cleanup block
1105-
*cleanup = self.cleanup_block;
1106-
}
1109+
*cleanup = self.map_unwind(*cleanup);
11071110
}
11081111
TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => {
11091112
*target = self.map_block(*target);
1110-
if let Some(tgt) = *cleanup {
1111-
*cleanup = Some(self.map_block(tgt));
1112-
} else if !self.in_cleanup_block {
1113-
// Unless this assert is in a cleanup block, add an unwind edge to
1114-
// the original call's cleanup block
1115-
*cleanup = self.cleanup_block;
1116-
}
1113+
*cleanup = self.map_unwind(*cleanup);
11171114
}
11181115
TerminatorKind::Return => {
11191116
terminator.kind = if let Some(tgt) = self.callsite.target {
@@ -1141,11 +1138,8 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
11411138
TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => {
11421139
if let Some(ref mut tgt) = *destination {
11431140
*tgt = self.map_block(*tgt);
1144-
} else if !self.in_cleanup_block {
1145-
// Unless this inline asm is in a cleanup block, add an unwind edge to
1146-
// the original call's cleanup block
1147-
*cleanup = self.cleanup_block;
11481141
}
1142+
*cleanup = self.map_unwind(*cleanup);
11491143
}
11501144
}
11511145
}

‎src/test/mir-opt/inline/asm-unwind.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Tests inlining of `may_unwind` inline assembly.
2+
//
3+
// ignore-wasm32-bare compiled with panic=abort by default
4+
#![feature(asm_unwind)]
5+
6+
struct D;
7+
8+
impl Drop for D {
9+
fn drop(&mut self) {}
10+
}
11+
12+
#[inline(always)]
13+
fn foo() {
14+
let _d = D;
15+
unsafe { std::arch::asm!("", options(may_unwind)) };
16+
}
17+
18+
// EMIT_MIR asm_unwind.main.Inline.diff
19+
pub fn main() {
20+
foo();
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
- // MIR for `main` before Inline
2+
+ // MIR for `main` after Inline
3+
4+
fn main() -> () {
5+
let mut _0: (); // return place in scope 0 at $DIR/asm-unwind.rs:+0:15: +0:15
6+
let _1: (); // in scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10
7+
+ scope 1 (inlined foo) { // at $DIR/asm-unwind.rs:20:5: 20:10
8+
+ let _2: D; // in scope 1 at $DIR/asm-unwind.rs:14:9: 14:11
9+
+ scope 2 {
10+
+ debug _d => _2; // in scope 2 at $DIR/asm-unwind.rs:14:9: 14:11
11+
+ scope 3 {
12+
+ }
13+
+ }
14+
+ }
15+
16+
bb0: {
17+
StorageLive(_1); // scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10
18+
- _1 = foo() -> bb1; // scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10
19+
- // mir::Constant
20+
- // + span: $DIR/asm-unwind.rs:20:5: 20:8
21+
- // + literal: Const { ty: fn() {foo}, val: Value(<ZST>) }
22+
+ StorageLive(_2); // scope 1 at $DIR/asm-unwind.rs:14:9: 14:11
23+
+ asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb3]; // scope 3 at $DIR/asm-unwind.rs:15:14: 15:54
24+
}
25+
26+
bb1: {
27+
+ drop(_2) -> bb2; // scope 1 at $DIR/asm-unwind.rs:16:1: 16:2
28+
+ }
29+
+
30+
+ bb2: {
31+
+ StorageDead(_2); // scope 1 at $DIR/asm-unwind.rs:16:1: 16:2
32+
StorageDead(_1); // scope 0 at $DIR/asm-unwind.rs:+1:10: +1:11
33+
_0 = const (); // scope 0 at $DIR/asm-unwind.rs:+0:15: +2:2
34+
return; // scope 0 at $DIR/asm-unwind.rs:+2:2: +2:2
35+
+ }
36+
+
37+
+ bb3 (cleanup): {
38+
+ drop(_2) -> bb4; // scope 1 at $DIR/asm-unwind.rs:16:1: 16:2
39+
+ }
40+
+
41+
+ bb4 (cleanup): {
42+
+ resume; // scope 1 at $DIR/asm-unwind.rs:13:1: 16:2
43+
}
44+
}
45+

0 commit comments

Comments
 (0)