diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 8f463e2d3f9..9196816b351 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -45,6 +45,9 @@ namespace llvm { bool EnableFastISel; } +static cl::opt DisableOldSjLjEH("disable-old-sjlj-eh", cl::Hidden, + cl::desc("Disable the old SjLj EH preparation pass")); + static cl::opt DisablePostRA("disable-post-ra", cl::Hidden, cl::desc("Disable Post Regalloc")); static cl::opt DisableBranchFold("disable-branch-fold", cl::Hidden, @@ -322,7 +325,8 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, // 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. - PM.add(createSjLjEHPass(getTargetLowering())); + if (!DisableOldSjLjEH) + PM.add(createSjLjEHPass(getTargetLowering())); // FALLTHROUGH case ExceptionHandling::DwarfCFI: case ExceptionHandling::ARM: diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h index 5556dc5a4dd..2e5b65cb78b 100644 --- a/lib/Target/ARM/ARM.h +++ b/lib/Target/ARM/ARM.h @@ -41,6 +41,7 @@ FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false); FunctionPass *createARMExpandPseudoPass(); FunctionPass *createARMGlobalMergePass(const TargetLowering* tli); FunctionPass *createARMConstantIslandPass(); +FunctionPass *createARMSjLjLoweringPass(); FunctionPass *createNEONMoveFixPass(); FunctionPass *createMLxExpansionPass(); FunctionPass *createThumb2ITBlockPass(); diff --git a/lib/Target/ARM/ARMSjLjLoweringPass.cpp b/lib/Target/ARM/ARMSjLjLoweringPass.cpp new file mode 100644 index 00000000000..a7dce3be4b8 --- /dev/null +++ b/lib/Target/ARM/ARMSjLjLoweringPass.cpp @@ -0,0 +1,118 @@ +//===-- ARMSjLjLoweringPass.cpp - ARM SjLj Lowering Pass ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that lowers the SjLj exception handling into +// machine instructions. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "arm-sjlj-lowering" +#include "ARM.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +// Hidden options for the new EH stuff. +static cl::opt +EnableNewSjLjEHPrepare("enable-new-sjlj-eh", cl::Hidden, + cl::desc("Use the new SjLj EH preparation pass")); + +namespace { + +class ARMSjLjLowering : public MachineFunctionPass { + Type *FunctionCtxTy; + LLVMContext *Context; + + MachineFunction *MF; + const Function *Fn; + const TargetLowering *TLI; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + + /// createFunctionContext - Create the function context on the stack. This + /// returns the nonnegative identifier representing it in the FrameInfo. + int createFunctionContext(); + +public: + static char ID; + ARMSjLjLowering() : MachineFunctionPass(ID) {} + + virtual bool runOnMachineFunction(MachineFunction &mf); + + virtual const char *getPassName() const { + return "ARM setjmp/longjmp exception handling lowering pass"; + } +}; + +char ARMSjLjLowering::ID = 0; + +} // end anonymous namespace + +FunctionPass *llvm::createARMSjLjLoweringPass() { + return new ARMSjLjLowering(); +} + +bool ARMSjLjLowering::runOnMachineFunction(MachineFunction &mf) { + if (!EnableNewSjLjEHPrepare) return false; + + MF = &mf; + Fn = MF->getFunction(); + Context = &Fn->getContext(); + TLI = MF->getTarget().getTargetLowering(); + TII = MF->getTarget().getInstrInfo(); + TRI = MF->getTarget().getRegisterInfo(); + + int FrameIdx = createFunctionContext(); (void)FrameIdx; + + return true; +} + +/// createFunctionContext - Create the function context on the stack. +int ARMSjLjLowering::createFunctionContext() { + // struct _Unwind_FunctionContext { + // // next function in stack of handlers. + // struct _Unwind_FunctionContext *prev; + // + // // set by calling function before registering to be the landing pad. + // uintptr_t resumeLocation; + // + // // set by personality handler to be parameters passed to landing pad + // // function. + // uintptr_t resumeParameters[4]; + // + // // set by calling function before registering + // __personality_routine personality; // arm offset=24 + // + // uintptr_t lsda // arm offset=28 + // + // // variable length array, contains registers to restore + // // 0 = r7, 1 = pc, 2 = sp + // void *jbuf[]; // 5 for GCC compatibility. + // }; + Type *VoidPtrTy = Type::getInt8PtrTy(*Context); + Type *Int32Ty = Type::getInt32Ty(*Context); + FunctionCtxTy = + StructType::get(VoidPtrTy, // prev + Int32Ty, // resumeLocation + ArrayType::get(Int32Ty, 4), // resumeParameters + VoidPtrTy, // personality + VoidPtrTy, // lsda + ArrayType::get(VoidPtrTy, 5), // jbuf + NULL); + + uint64_t TySize = TLI->getTargetData()->getTypeAllocSize(FunctionCtxTy); + unsigned Align = TLI->getTargetData()->getPrefTypeAlignment(FunctionCtxTy); + + return MF->getFrameInfo()->CreateStackObject(TySize, Align, false, false); +} diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index 78a6a4381a8..a75ce264cd3 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -15,6 +15,7 @@ #include "ARM.h" #include "llvm/PassManager.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/TargetRegistry.h" @@ -107,7 +108,8 @@ bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM, PM.add(createARMLoadStoreOptimizationPass(true)); if (OptLevel != CodeGenOpt::None && Subtarget.isCortexA9()) PM.add(createMLxExpansionPass()); - + if (getMCAsmInfo()->getExceptionHandlingType() == ExceptionHandling::SjLj) + createARMSjLjLoweringPass(); return true; }