Fix MIR inlining of asm_unwind
This commit is contained in:
parent
01af5040fd
commit
242348343b
@ -977,6 +977,21 @@ fn map_block(&self, block: BasicBlock) -> BasicBlock {
|
|||||||
trace!("mapping block `{:?}` to `{:?}`", block, new);
|
trace!("mapping block `{:?}` to `{:?}`", block, new);
|
||||||
new
|
new
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn map_unwind(&self, unwind: Option<BasicBlock>) -> Option<BasicBlock> {
|
||||||
|
if self.in_cleanup_block {
|
||||||
|
if unwind.is_some() {
|
||||||
|
bug!("cleanup on cleanup block");
|
||||||
|
}
|
||||||
|
return unwind;
|
||||||
|
}
|
||||||
|
|
||||||
|
match unwind {
|
||||||
|
Some(target) => Some(self.map_block(target)),
|
||||||
|
// Add an unwind edge to the original call's cleanup block
|
||||||
|
None => self.cleanup_block,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
|
impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
|
||||||
@ -1085,35 +1100,17 @@ fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, loc: Location)
|
|||||||
TerminatorKind::Drop { ref mut target, ref mut unwind, .. }
|
TerminatorKind::Drop { ref mut target, ref mut unwind, .. }
|
||||||
| TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => {
|
| TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => {
|
||||||
*target = self.map_block(*target);
|
*target = self.map_block(*target);
|
||||||
if let Some(tgt) = *unwind {
|
*unwind = self.map_unwind(*unwind);
|
||||||
*unwind = Some(self.map_block(tgt));
|
|
||||||
} else if !self.in_cleanup_block {
|
|
||||||
// Unless this drop is in a cleanup block, add an unwind edge to
|
|
||||||
// the original call's cleanup block
|
|
||||||
*unwind = self.cleanup_block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => {
|
TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => {
|
||||||
if let Some(ref mut tgt) = *target {
|
if let Some(ref mut tgt) = *target {
|
||||||
*tgt = self.map_block(*tgt);
|
*tgt = self.map_block(*tgt);
|
||||||
}
|
}
|
||||||
if let Some(tgt) = *cleanup {
|
*cleanup = self.map_unwind(*cleanup);
|
||||||
*cleanup = Some(self.map_block(tgt));
|
|
||||||
} else if !self.in_cleanup_block {
|
|
||||||
// Unless this call is in a cleanup block, add an unwind edge to
|
|
||||||
// the original call's cleanup block
|
|
||||||
*cleanup = self.cleanup_block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => {
|
TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => {
|
||||||
*target = self.map_block(*target);
|
*target = self.map_block(*target);
|
||||||
if let Some(tgt) = *cleanup {
|
*cleanup = self.map_unwind(*cleanup);
|
||||||
*cleanup = Some(self.map_block(tgt));
|
|
||||||
} else if !self.in_cleanup_block {
|
|
||||||
// Unless this assert is in a cleanup block, add an unwind edge to
|
|
||||||
// the original call's cleanup block
|
|
||||||
*cleanup = self.cleanup_block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TerminatorKind::Return => {
|
TerminatorKind::Return => {
|
||||||
terminator.kind = if let Some(tgt) = self.callsite.target {
|
terminator.kind = if let Some(tgt) = self.callsite.target {
|
||||||
@ -1141,11 +1138,8 @@ fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, loc: Location)
|
|||||||
TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => {
|
TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => {
|
||||||
if let Some(ref mut tgt) = *destination {
|
if let Some(ref mut tgt) = *destination {
|
||||||
*tgt = self.map_block(*tgt);
|
*tgt = self.map_block(*tgt);
|
||||||
} else if !self.in_cleanup_block {
|
|
||||||
// Unless this inline asm is in a cleanup block, add an unwind edge to
|
|
||||||
// the original call's cleanup block
|
|
||||||
*cleanup = self.cleanup_block;
|
|
||||||
}
|
}
|
||||||
|
*cleanup = self.map_unwind(*cleanup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
src/test/mir-opt/inline/asm-unwind.rs
Normal file
21
src/test/mir-opt/inline/asm-unwind.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Tests inlining of `may_unwind` inline assembly.
|
||||||
|
//
|
||||||
|
// ignore-wasm32-bare compiled with panic=abort by default
|
||||||
|
#![feature(asm_unwind)]
|
||||||
|
|
||||||
|
struct D;
|
||||||
|
|
||||||
|
impl Drop for D {
|
||||||
|
fn drop(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn foo() {
|
||||||
|
let _d = D;
|
||||||
|
unsafe { std::arch::asm!("", options(may_unwind)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR asm_unwind.main.Inline.diff
|
||||||
|
pub fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
45
src/test/mir-opt/inline/asm_unwind.main.Inline.diff
Normal file
45
src/test/mir-opt/inline/asm_unwind.main.Inline.diff
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
- // MIR for `main` before Inline
|
||||||
|
+ // MIR for `main` after Inline
|
||||||
|
|
||||||
|
fn main() -> () {
|
||||||
|
let mut _0: (); // return place in scope 0 at $DIR/asm-unwind.rs:+0:15: +0:15
|
||||||
|
let _1: (); // in scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10
|
||||||
|
+ scope 1 (inlined foo) { // at $DIR/asm-unwind.rs:20:5: 20:10
|
||||||
|
+ let _2: D; // in scope 1 at $DIR/asm-unwind.rs:14:9: 14:11
|
||||||
|
+ scope 2 {
|
||||||
|
+ debug _d => _2; // in scope 2 at $DIR/asm-unwind.rs:14:9: 14:11
|
||||||
|
+ scope 3 {
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1); // scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10
|
||||||
|
- _1 = foo() -> bb1; // scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10
|
||||||
|
- // mir::Constant
|
||||||
|
- // + span: $DIR/asm-unwind.rs:20:5: 20:8
|
||||||
|
- // + literal: Const { ty: fn() {foo}, val: Value(<ZST>) }
|
||||||
|
+ StorageLive(_2); // scope 1 at $DIR/asm-unwind.rs:14:9: 14:11
|
||||||
|
+ asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb3]; // scope 3 at $DIR/asm-unwind.rs:15:14: 15:54
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
+ drop(_2) -> bb2; // scope 1 at $DIR/asm-unwind.rs:16:1: 16:2
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb2: {
|
||||||
|
+ StorageDead(_2); // scope 1 at $DIR/asm-unwind.rs:16:1: 16:2
|
||||||
|
StorageDead(_1); // scope 0 at $DIR/asm-unwind.rs:+1:10: +1:11
|
||||||
|
_0 = const (); // scope 0 at $DIR/asm-unwind.rs:+0:15: +2:2
|
||||||
|
return; // scope 0 at $DIR/asm-unwind.rs:+2:2: +2:2
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb3 (cleanup): {
|
||||||
|
+ drop(_2) -> bb4; // scope 1 at $DIR/asm-unwind.rs:16:1: 16:2
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb4 (cleanup): {
|
||||||
|
+ resume; // scope 1 at $DIR/asm-unwind.rs:13:1: 16:2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user