Author: rnk Date: Tue Jan 2 13:34:16 2018 New Revision: 321676 URL: http://llvm.org/viewvc/llvm-project?rev=321676&view=rev Log: [WinEH] Allow for multiple terminatepads
Fixes verifier errors with Windows EH and OpenMP, which injects a terminate scope around parallel blocks. Fixes PR35778 Modified: cfe/trunk/lib/CodeGen/CGException.cpp cfe/trunk/lib/CodeGen/CodeGenFunction.cpp cfe/trunk/lib/CodeGen/CodeGenFunction.h cfe/trunk/test/OpenMP/openmp_win_codegen.cpp Modified: cfe/trunk/lib/CodeGen/CGException.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=321676&r1=321675&r2=321676&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGException.cpp (original) +++ cfe/trunk/lib/CodeGen/CGException.cpp Tue Jan 2 13:34:16 2018 @@ -646,7 +646,7 @@ CodeGenFunction::getMSVCDispatchBlock(EH return DispatchBlock; if (EHS.getKind() == EHScope::Terminate) - DispatchBlock = getTerminateHandler(); + DispatchBlock = getTerminateFunclet(); else DispatchBlock = createBasicBlock(); CGBuilderTy Builder(*this, DispatchBlock); @@ -1334,24 +1334,15 @@ llvm::BasicBlock *CodeGenFunction::getTe if (TerminateHandler) return TerminateHandler; - CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); - // Set up the terminate handler. This block is inserted at the very // end of the function by FinishFunction. TerminateHandler = createBasicBlock("terminate.handler"); + CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); Builder.SetInsertPoint(TerminateHandler); + llvm::Value *Exn = nullptr; - SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( - CurrentFuncletPad); - if (EHPersonality::get(*this).usesFuncletPads()) { - llvm::Value *ParentPad = CurrentFuncletPad; - if (!ParentPad) - ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); - CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad); - } else { - if (getLangOpts().CPlusPlus) - Exn = getExceptionFromSlot(); - } + if (getLangOpts().CPlusPlus) + Exn = getExceptionFromSlot(); llvm::CallInst *terminateCall = CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn); terminateCall->setDoesNotReturn(); @@ -1363,6 +1354,42 @@ llvm::BasicBlock *CodeGenFunction::getTe return TerminateHandler; } +llvm::BasicBlock *CodeGenFunction::getTerminateFunclet() { + assert(EHPersonality::get(*this).usesFuncletPads() && + "use getTerminateLandingPad for non-funclet EH"); + + llvm::BasicBlock *&TerminateFunclet = TerminateFunclets[CurrentFuncletPad]; + if (TerminateFunclet) + return TerminateFunclet; + + CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); + + // Set up the terminate handler. This block is inserted at the very + // end of the function by FinishFunction. + TerminateFunclet = createBasicBlock("terminate.handler"); + Builder.SetInsertPoint(TerminateFunclet); + + // Create the cleanuppad using the current parent pad as its token. Use 'none' + // if this is a top-level terminate scope, which is the common case. + SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( + CurrentFuncletPad); + llvm::Value *ParentPad = CurrentFuncletPad; + if (!ParentPad) + ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); + CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad); + + // Emit the __std_terminate call. + llvm::CallInst *terminateCall = + CGM.getCXXABI().emitTerminateForUnexpectedException(*this, nullptr); + terminateCall->setDoesNotReturn(); + Builder.CreateUnreachable(); + + // Restore the saved insertion state. + Builder.restoreIP(SavedIP); + + return TerminateFunclet; +} + llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) { if (EHResumeBlock) return EHResumeBlock; Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=321676&r1=321675&r2=321676&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Jan 2 13:34:16 2018 @@ -419,6 +419,9 @@ void CodeGenFunction::FinishFunction(Sou EmitIfUsed(*this, TerminateHandler); EmitIfUsed(*this, UnreachableBlock); + for (const auto &FuncletAndParent : TerminateFunclets) + EmitIfUsed(*this, FuncletAndParent.second); + if (CGM.getCodeGenOpts().EmitDeclMetadata) EmitDeclMetadata(); Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=321676&r1=321675&r2=321676&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Jan 2 13:34:16 2018 @@ -34,6 +34,7 @@ #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" @@ -1420,6 +1421,9 @@ private: llvm::BasicBlock *TerminateHandler; llvm::BasicBlock *TrapBB; + /// Terminate funclets keyed by parent funclet pad. + llvm::MapVector<llvm::Value *, llvm::BasicBlock *> TerminateFunclets; + /// True if we need emit the life-time markers. const bool ShouldEmitLifetimeMarkers; @@ -1808,6 +1812,10 @@ public: /// getTerminateLandingPad - Return a landing pad that just calls terminate. llvm::BasicBlock *getTerminateLandingPad(); + /// getTerminateLandingPad - Return a cleanup funclet that just calls + /// terminate. + llvm::BasicBlock *getTerminateFunclet(); + /// getTerminateHandler - Return a handler (not a landing pad, just /// a catch handler) that just calls terminate. This is used when /// a terminate scope encloses a try. Modified: cfe/trunk/test/OpenMP/openmp_win_codegen.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/openmp_win_codegen.cpp?rev=321676&r1=321675&r2=321676&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/openmp_win_codegen.cpp (original) +++ cfe/trunk/test/OpenMP/openmp_win_codegen.cpp Tue Jan 2 13:34:16 2018 @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-pc-windows-msvc18.0.0 -std=c++11 -fms-compatibility-version=18 -fms-extensions -emit-llvm %s -fexceptions -fcxx-exceptions -o - -O1 | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-pc-windows-msvc18.0.0 -std=c++11 -fms-compatibility-version=18 -fms-extensions -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s + +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-pc-windows-msvc18.0.0 -std=c++11 -fms-compatibility-version=18 -fms-extensions -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-pc-windows-msvc18.0.0 -std=c++11 -fms-compatibility-version=18 -fms-extensions -emit-llvm %s -fexceptions -fcxx-exceptions -o - -O1 | FileCheck --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} -// REQUIRES: x86-registered-target // expected-no-diagnostics void foo(); @@ -52,13 +52,19 @@ int main() { // CHECK: define internal void [[OUTLINED]]( // CHECK: [[GID:%.+]] = {{.*}}call i32 @__kmpc_global_thread_num(%ident_t* {{.*}}@0) // CHECK: invoke void @{{.+}}foo -// CHECK: catchswitch within -// CHECK: catchpad within +// CHECK: [[CATCHSWITCH:%.+]] = catchswitch within none +// CHECK: [[CATCHPAD:%.+]] = catchpad within [[CATCHSWITCH]] // CHECK: call void @__kmpc_critical(%ident_t* {{.*}}@0, i32 [[GID]], // CHECK: invoke void @{{.+}}bar // CHECK: call void @__kmpc_end_critical(%ident_t* {{.*}}@0, i32 [[GID]], -// CHECK: catchret from -// CHECK: cleanuppad within -// CHECK: call void @__kmpc_end_critical(%ident_t* {{.*}}@0, i32 [[GID]], -// CHECK: cleanupret from - +// CHECK: catchret from [[CATCHPAD]] to +// CHECK: cleanuppad within [[CATCHPAD]] [] +// CHECK-NEXT: call void @__kmpc_end_critical(%ident_t* {{.*}}@0, i32 [[GID]], +// CHECK-NEXT: cleanupret from {{.*}} unwind label %[[CATCHTERM:[^ ]+]] +// CHECK: cleanuppad within none [] +// CHECK-NEXT: call void @"\01?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ] +// CHECK-NEXT: unreachable +// CHECK: [[CATCHTERM]] +// CHECK-NEXT: cleanuppad within [[CATCHPAD]] [] +// CHECK-NEXT: call void @"\01?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ] +// CHECK-NEXT: unreachable _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits