From: David Majnemer Date: Tue, 23 Feb 2016 07:18:15 +0000 (+0000) Subject: [WinEH] Visit 'unwind to caller' catchswitches nested in catchswitches X-Git-Tag: llvmorg-3.9.0-rc1~13483 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=17525aba8af3b218f52ccda0f01e066853d4a1e9;p=platform%2Fupstream%2Fllvm.git [WinEH] Visit 'unwind to caller' catchswitches nested in catchswitches We had the right logic for the nested cleanuppad case but omitted it for catchswitches. llvm-svn: 261615 --- diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 3e16a25..8157857 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -254,9 +254,11 @@ static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo, FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow; for (const User *U : CatchPad->users()) { const auto *UserI = cast(U); - if (auto *InnerCatchSwitch = dyn_cast(UserI)) - if (InnerCatchSwitch->getUnwindDest() == CatchSwitch->getUnwindDest()) + if (auto *InnerCatchSwitch = dyn_cast(UserI)) { + BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest(); + if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest()) calculateCXXStateNumbers(FuncInfo, UserI, CatchLow); + } if (auto *InnerCleanupPad = dyn_cast(UserI)) { BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad); // If a nested cleanup pad reports a null unwind destination and the @@ -361,9 +363,11 @@ static void calculateSEHStateNumbers(WinEHFuncInfo &FuncInfo, // outside the __try. for (const User *U : CatchPad->users()) { const auto *UserI = cast(U); - if (auto *InnerCatchSwitch = dyn_cast(UserI)) - if (InnerCatchSwitch->getUnwindDest() == CatchSwitch->getUnwindDest()) + if (auto *InnerCatchSwitch = dyn_cast(UserI)) { + BasicBlock *UnwindDest = InnerCatchSwitch->getUnwindDest(); + if (!UnwindDest || UnwindDest == CatchSwitch->getUnwindDest()) calculateSEHStateNumbers(FuncInfo, UserI, ParentState); + } if (auto *InnerCleanupPad = dyn_cast(UserI)) { BasicBlock *UnwindDest = getCleanupRetUnwindDest(InnerCleanupPad); // If a nested cleanup pad reports a null unwind destination and the diff --git a/llvm/test/CodeGen/WinEH/wineh-nested-unwind.ll b/llvm/test/CodeGen/WinEH/wineh-nested-unwind.ll new file mode 100644 index 0000000..b568be5 --- /dev/null +++ b/llvm/test/CodeGen/WinEH/wineh-nested-unwind.ll @@ -0,0 +1,55 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc18.0.0" + +; Function Attrs: uwtable +define void @f() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { +entry: + invoke void @g() + to label %try.cont unwind label %catch.dispatch + +catch.dispatch: ; preds = %entry + %0 = catchswitch within none [label %catch] unwind label %ehcleanup + +catch: ; preds = %catch.dispatch + %1 = catchpad within %0 [i8* null, i32 64, i8* null] + invoke void @g() [ "funclet"(token %1) ] + to label %dtor.exit unwind label %catch.dispatch.i + +catch.dispatch.i: ; preds = %catch + %2 = catchswitch within %1 [label %catch.i] unwind to caller + +catch.i: ; preds = %catch.dispatch.i + %3 = catchpad within %2 [i8* null, i32 64, i8* null] + catchret from %3 to label %dtor.exit + +dtor.exit: + catchret from %1 to label %try.cont + +try.cont: + ret void + +ehcleanup: ; preds = %catch.dispatch + %4 = cleanuppad within none [] + call void @dtor() #1 [ "funclet"(token %4) ] + cleanupret from %4 unwind to caller +} + +declare void @g() + +declare i32 @__CxxFrameHandler3(...) + +; Function Attrs: nounwind +declare void @dtor() #1 + +attributes #0 = { uwtable } +attributes #1 = { nounwind } + +; CHECK-LABEL: $ip2state$f: +; CHECK: -1 +; CHECK: 1 +; CHECK: -1 +; CHECK: 4 +; CHECK: 2 +; CHECK: 3 +; CHECK: 2