aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/LLVMTargetMachine.cpp6
-rw-r--r--lib/Target/ARM/ARM.h1
-rw-r--r--lib/Target/ARM/ARMSjLjLoweringPass.cpp118
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp4
4 files changed, 127 insertions, 2 deletions
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index 8f463e2d3f..9196816b35 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/LLVMTargetMachine.cpp
@@ -45,6 +45,9 @@ namespace llvm {
bool EnableFastISel;
}
+static cl::opt<bool> DisableOldSjLjEH("disable-old-sjlj-eh", cl::Hidden,
+ cl::desc("Disable the old SjLj EH preparation pass"));
+
static cl::opt<bool> DisablePostRA("disable-post-ra", cl::Hidden,
cl::desc("Disable Post Regalloc"));
static cl::opt<bool> 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 5556dc5a4d..2e5b65cb78 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 0000000000..a7dce3be4b
--- /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<bool>
+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 78a6a4381a..a75ce264cd 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;
}