for (auto &MBB : reverse(MF)) {
bool SeenThrowableInstInBB = false;
for (auto &MI : reverse(MBB)) {
- if (MI.getOpcode() == WebAssembly::TRY)
- EHPadStack.pop_back();
- else if (WebAssembly::isCatch(MI.getOpcode()))
- EHPadStack.push_back(MI.getParent());
bool MayThrow = WebAssembly::mayThrow(MI);
// If MBB has an EH pad successor and this is the last instruction that
// may throw, this instruction unwinds to the EH pad and not to the
// caller.
- if (MBB.hasEHPadSuccessor() && MayThrow && !SeenThrowableInstInBB) {
+ if (MBB.hasEHPadSuccessor() && MayThrow && !SeenThrowableInstInBB)
SeenThrowableInstInBB = true;
- continue;
- }
// We wrap up the current range when we see a marker even if we haven't
// finished a BB.
- if (RangeEnd && WebAssembly::isMarker(MI.getOpcode())) {
+ else if (RangeEnd && WebAssembly::isMarker(MI.getOpcode()))
RecordCallerMismatchRange(EHPadStack.back());
- continue;
- }
// If EHPadStack is empty, that means it correctly unwinds to the caller
// if it throws, so we're good. If MI does not throw, we're good too.
- if (EHPadStack.empty() || !MayThrow)
- continue;
+ else if (EHPadStack.empty() || !MayThrow) {
+ }
// We found an instruction that unwinds to the caller but currently has an
// incorrect unwind destination. Create a new range or increment the
// currently existing range.
- if (!RangeEnd)
- RangeBegin = RangeEnd = &MI;
- else
- RangeBegin = &MI;
+ else {
+ if (!RangeEnd)
+ RangeBegin = RangeEnd = &MI;
+ else
+ RangeBegin = &MI;
+ }
+
+ // Update EHPadStack.
+ if (MI.getOpcode() == WebAssembly::TRY)
+ EHPadStack.pop_back();
+ else if (WebAssembly::isCatch(MI.getOpcode()))
+ EHPadStack.push_back(MI.getParent());
}
if (RangeEnd)
cleanupret from %0 unwind to caller
}
+; This crashed when updating EHPadStack within fixCallUniwindMismatch had a bug.
+; This should not crash and try-delegate has to be created around 'call @baz',
+; because the initial TRY placement for 'call @quux' was done before 'call @baz'
+; because 'call @baz''s return value is stackified.
+
+; CHECK-LABEL: test19
+; CHECK: try
+; CHECK: try
+; CHECK: call $[[RET:[0-9]+]]=, baz
+; CHECK: delegate 1
+; CHECK: call quux, $[[RET]]
+; CHECK: catch_all
+; CHECK: end_try
+define void @test19() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
+entry:
+ %call = call i32 @baz()
+ invoke void @quux(i32 %call)
+ to label %invoke.cont unwind label %ehcleanup
+
+ehcleanup: ; preds = %entry
+ %0 = cleanuppad within none []
+ cleanupret from %0 unwind to caller
+
+invoke.cont: ; preds = %entry
+ unreachable
+}
+
; Check if the unwind destination mismatch stats are correct
-; NOSORT: 18 wasm-cfg-stackify - Number of call unwind mismatches found
+; NOSORT: 19 wasm-cfg-stackify - Number of call unwind mismatches found
; NOSORT: 3 wasm-cfg-stackify - Number of catch unwind mismatches found
declare void @foo()