summaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/ARM/ARM.h1
-rw-r--r--lib/Target/ARM/ARMSjLjLoweringPass.cpp118
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp4
3 files changed, 122 insertions, 1 deletions
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;
}