Add a pre-dispatch SjLj EH hook on the unwind edge for targets to do any
setup they require. Use this for ARM/Darwin to rematerialize the base
pointer from the frame pointer when required. rdar://8564268

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116879 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SjLjEHPrepare.cpp b/lib/CodeGen/SjLjEHPrepare.cpp
index b637980..1f6a5c4 100644
--- a/lib/CodeGen/SjLjEHPrepare.cpp
+++ b/lib/CodeGen/SjLjEHPrepare.cpp
@@ -53,6 +53,7 @@
     Constant *SelectorFn;
     Constant *ExceptionFn;
     Constant *CallSiteFn;
+    Constant *DispatchSetupFn;
 
     Value *CallSite;
   public:
@@ -116,6 +117,8 @@
   SelectorFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector);
   ExceptionFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_exception);
   CallSiteFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_callsite);
+  DispatchSetupFn
+    = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_dispatch_setup);
   PersonalityFn = 0;
 
   return true;
@@ -438,9 +441,17 @@
     BasicBlock *DispatchBlock =
             BasicBlock::Create(F.getContext(), "eh.sjlj.setjmp.catch", &F);
 
-    // Insert a load in the Catch block, and a switch on its value.  By default,
-    // we go to a block that just does an unwind (which is the correct action
-    // for a standard call).
+    // Add a call to dispatch_setup at the start of the dispatch block. This
+    // is expanded to any target-specific setup that needs to be done.
+    Value *SetupArg =
+      CastInst::Create(Instruction::BitCast, FunctionContext,
+                       Type::getInt8PtrTy(F.getContext()), "",
+                       DispatchBlock);
+    CallInst::Create(DispatchSetupFn, SetupArg, "", DispatchBlock);
+
+    // Insert a load of the callsite in the dispatch block, and a switch on
+    // its value.  By default, we go to a block that just does an unwind
+    // (which is the correct action for a standard call).
     BasicBlock *UnwindBlock =
       BasicBlock::Create(F.getContext(), "unwindbb", &F);
     Unwinds.push_back(new UnwindInst(F.getContext(), UnwindBlock));