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 @@ -306,6 +306,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/SjLjEHPrepare.cpp b/llvm/lib/CodeGen/SjLjEHPrepare.cpp --- a/llvm/lib/CodeGen/SjLjEHPrepare.cpp +++ b/llvm/lib/CodeGen/SjLjEHPrepare.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" @@ -37,6 +38,7 @@ namespace { class SjLjEHPrepare : public FunctionPass { + IntegerType *DataTy; Type *doubleUnderDataTy; Type *doubleUnderJBufTy; Type *FunctionContextTy; @@ -50,10 +52,11 @@ 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,18 +80,23 @@ 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 @@ -112,8 +120,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 +135,6 @@ for (BasicBlock *B : inverse_depth_first_ext(BB, Visited)) LiveBBs.insert(B); - } /// substituteLPadValues - Substitute the values returned by the landingpad @@ -190,16 +196,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