diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -342,7 +342,7 @@ /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// - FunctionPass *createSjLjEHPreparePass(); + FunctionPass *createSjLjEHPreparePass(const TargetMachine *TM); /// createWasmEHPass - This pass adapts exception handling code to use /// WebAssembly's exception handling scheme. diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -309,6 +309,10 @@ void getNameWithPrefix(SmallVectorImpl &Name, const GlobalValue *GV, Mangler &Mang, bool MayAlwaysUsePrivate = false) const; MCSymbol *getSymbol(const GlobalValue *GV) const; + + /// The integer bit size to use for SjLj based exception handling. + static constexpr unsigned DefaultSjLjDataSize = 32; + virtual unsigned getSjLjDataSize() const { return DefaultSjLjDataSize; } }; /// This class describes a target machine that is implemented with the LLVM diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -97,6 +97,7 @@ initializeSafeStackLegacyPassPass(Registry); initializeScalarizeMaskedMemIntrinPass(Registry); initializeShrinkWrapPass(Registry); + initializeSjLjEHPreparePass(Registry); initializeSlotIndexesPass(Registry); initializeStackColoringPass(Registry); initializeStackMapLivenessPass(Registry); diff --git a/llvm/lib/CodeGen/SjLjEHPrepare.cpp b/llvm/lib/CodeGen/SjLjEHPrepare.cpp --- a/llvm/lib/CodeGen/SjLjEHPrepare.cpp +++ b/llvm/lib/CodeGen/SjLjEHPrepare.cpp @@ -27,6 +27,7 @@ #include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Utils/Local.h" using namespace llvm; @@ -37,6 +38,7 @@ namespace { class SjLjEHPrepare : public FunctionPass { + IntegerType *DataTy; Type *doubleUnderDataTy; Type *doubleUnderJBufTy; Type *FunctionContextTy; @@ -50,10 +52,12 @@ Function *CallSiteFn; Function *FuncCtxFn; AllocaInst *FuncCtx; + const TargetMachine *TM; public: static char ID; // Pass identification, replacement for typeid - explicit SjLjEHPrepare() : FunctionPass(ID) {} + explicit SjLjEHPrepare(const TargetMachine *TM = nullptr) + : FunctionPass(ID), TM(TM) {} bool doInitialization(Module &M) override; bool runOnFunction(Function &F) override; @@ -77,23 +81,28 @@ false, false) // Public Interface To the SjLjEHPrepare pass. -FunctionPass *llvm::createSjLjEHPreparePass() { return new SjLjEHPrepare(); } +FunctionPass *llvm::createSjLjEHPreparePass(const TargetMachine *TM) { + return new SjLjEHPrepare(TM); +} + // doInitialization - Set up decalarations and types needed to process // exceptions. bool SjLjEHPrepare::doInitialization(Module &M) { // Build the function context structure. // builtin_setjmp uses a five word jbuf Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext()); - Type *Int32Ty = Type::getInt32Ty(M.getContext()); - doubleUnderDataTy = ArrayType::get(Int32Ty, 4); + unsigned DataBits = + TM ? TM->getSjLjDataSize() : TargetMachine::DefaultSjLjDataSize; + DataTy = Type::getIntNTy(M.getContext(), DataBits); + doubleUnderDataTy = ArrayType::get(DataTy, 4); doubleUnderJBufTy = ArrayType::get(VoidPtrTy, 5); FunctionContextTy = StructType::get(VoidPtrTy, // __prev - Int32Ty, // call_site + DataTy, // call_site doubleUnderDataTy, // __data VoidPtrTy, // __personality VoidPtrTy, // __lsda doubleUnderJBufTy // __jbuf - ); + ); return true; } @@ -112,8 +121,7 @@ Builder.CreateGEP(FunctionContextTy, FuncCtx, Idxs, "call_site"); // Insert a store of the call-site number - ConstantInt *CallSiteNoC = - ConstantInt::get(Type::getInt32Ty(I->getContext()), Number); + ConstantInt *CallSiteNoC = ConstantInt::get(DataTy, Number); Builder.CreateStore(CallSiteNoC, CallSite, true /*volatile*/); } @@ -128,7 +136,6 @@ for (BasicBlock *B : inverse_depth_first_ext(BB, Visited)) LiveBBs.insert(B); - } /// substituteLPadValues - Substitute the values returned by the landingpad @@ -190,16 +197,18 @@ Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 2, "__data"); // The exception values come back in context->__data[0]. - Type *Int32Ty = Type::getInt32Ty(F.getContext()); Value *ExceptionAddr = Builder.CreateConstGEP2_32(doubleUnderDataTy, FCData, 0, 0, "exception_gep"); - Value *ExnVal = Builder.CreateLoad(Int32Ty, ExceptionAddr, true, "exn_val"); + Value *ExnVal = Builder.CreateLoad(DataTy, ExceptionAddr, true, "exn_val"); ExnVal = Builder.CreateIntToPtr(ExnVal, Builder.getInt8PtrTy()); Value *SelectorAddr = Builder.CreateConstGEP2_32(doubleUnderDataTy, FCData, 0, 1, "exn_selector_gep"); Value *SelVal = - Builder.CreateLoad(Int32Ty, SelectorAddr, true, "exn_selector_val"); + Builder.CreateLoad(DataTy, SelectorAddr, true, "exn_selector_val"); + + // SelVal must be Int32Ty, so trunc it + SelVal = Builder.CreateTrunc(SelVal, Type::getInt32Ty(F.getContext())); substituteLPadValues(LPI, ExnVal, SelVal); } diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -695,7 +695,7 @@ // removed from the parent invoke(s). This could happen when a landing // pad is shared by multiple invokes and is also a target of a normal // edge from elsewhere. - addPass(createSjLjEHPreparePass()); + addPass(createSjLjEHPreparePass(TM)); LLVM_FALLTHROUGH; case ExceptionHandling::DwarfCFI: case ExceptionHandling::ARM: diff --git a/llvm/lib/Target/VE/VETargetMachine.h b/llvm/lib/Target/VE/VETargetMachine.h --- a/llvm/lib/Target/VE/VETargetMachine.h +++ b/llvm/lib/Target/VE/VETargetMachine.h @@ -50,6 +50,8 @@ bool isMachineVerifierClean() const override { return false; } TargetTransformInfo getTargetTransformInfo(const Function &F) override; + + unsigned getSjLjDataSize() const override { return 64; } }; } // namespace llvm diff --git a/llvm/test/CodeGen/VE/sjlj_except.ll b/llvm/test/CodeGen/VE/sjlj_except.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/VE/sjlj_except.ll @@ -0,0 +1,32 @@ +; RUN: llc -mtriple=x86_64-unknown-unknown --exception-model=sjlj --print-after=sjljehprepare < %s |& FileCheck --check-prefix=CHECK-X86 %s +; RUN: (llc -mtriple=ve-unknown-unknown --exception-model=sjlj --print-after=sjljehprepare < %s || true) |& FileCheck --check-prefix=CHECK-VE %s + +@SomeGlobal = external dso_local global i8 + +define dso_local i32 @foo(i32 %arg) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) { +; CHECK-VE: *** IR Dump After SJLJ Exception Handling preparation *** +; CHECK-VE-NEXT: define dso_local i32 @foo(i32 %arg) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) { +; CHECK-VE-NEXT: entry: +; CHECK-VE-NEXT: %fn_context = alloca { i8*, i64, [4 x i64], i8*, i8*, [5 x i8*] }, align 8 +; CHECK-VE-NEXT: %arg.tmp = select i1 true, i32 %arg, i32 undef +; CHECK-VE-NEXT: %pers_fn_gep = getelementptr { i8*, i64, [4 x i64], i8*, i8*, [5 x i8*] }, { i8*, i64, [4 x i64], i8*, i8*, [5 x i8*] }* %fn_context, i32 0, i32 3 +; CHECK-X86: *** IR Dump After SJLJ Exception Handling preparation *** +; CHECK-X86-NEXT: define dso_local i32 @foo(i32 %arg) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) { +; CHECK-X86-NEXT: entry: +; CHECK-X86-NEXT: %fn_context = alloca { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }, align 8 +; CHECK-X86-NEXT: %arg.tmp = select i1 true, i32 %arg, i32 undef +; CHECK-X86-NEXT: %pers_fn_gep = getelementptr { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }, { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }* %fn_context, i32 0, i32 3 +entry: + invoke void @errorbar() to label %exit unwind label %handle + +handle: + %error = landingpad { i8*, i32 } catch i8* @SomeGlobal + ret i32 1 + +exit: + ret i32 0 +} + +declare dso_local void @errorbar() local_unnamed_addr + +declare dso_local i32 @__gxx_personality_sj0(...)