+
+
+ void %llvm.eh.sjlj.callsite(i32)
+
+
+
For SJLJ based exception handling, the
+ llvm.eh.sjlj.callsite intrinsic identifies the callsite value
+ associated with the following invoke instruction. This is used to ensure
+ that landing pad entries in the LSDA are generated in the matching order.
+
+
+
Asm Table Formats
diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h
index d2bd0f1a881..556ba7f27ef 100644
--- a/include/llvm/CodeGen/MachineModuleInfo.h
+++ b/include/llvm/CodeGen/MachineModuleInfo.h
@@ -113,7 +113,14 @@ class MachineModuleInfo : public ImmutablePass {
// LandingPads - List of LandingPadInfo describing the landing pad information
// in the current function.
std::vector
LandingPads;
-
+
+ // Map of invoke call site index values to associated begin EH_LABEL for
+ // the current function.
+ DenseMap CallSiteMap;
+
+ // The current call site index being processed, if any. 0 if none.
+ unsigned CurCallSite;
+
// TypeInfos - List of C++ TypeInfo used in the current function.
//
std::vector TypeInfos;
@@ -294,7 +301,26 @@ public:
const std::vector &getLandingPads() const {
return LandingPads;
}
-
+
+ /// setCallSiteBeginLabel - Map the begin label for a call site
+ void setCallSiteBeginLabel(unsigned BeginLabel, unsigned Site) {
+ CallSiteMap[BeginLabel] = Site;
+ }
+
+ /// getCallSiteBeginLabel - Get the call site number for a begin label
+ unsigned getCallSiteBeginLabel(unsigned BeginLabel) {
+ assert(CallSiteMap.count(BeginLabel) &&
+ "Missing call site number for EH_LABEL!");
+ return CallSiteMap[BeginLabel];
+ }
+
+ /// setCurrentCallSite - Set the call site currently being processed.
+ void setCurrentCallSite(unsigned Site) { CurCallSite = Site; }
+
+ /// getCurrentCallSite - Get the call site currently being processed, if any.
+ /// return zero if none.
+ unsigned getCurrentCallSite(void) { return CurCallSite; }
+
/// getTypeInfos - Return a reference to the C++ typeinfo for the current
/// function.
const std::vector &getTypeInfos() const {
diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td
index 684f8724cf7..3a0da9cabda 100644
--- a/include/llvm/Intrinsics.td
+++ b/include/llvm/Intrinsics.td
@@ -309,6 +309,7 @@ let Properties = [IntrNoMem] in {
def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>;
def int_eh_sjlj_longjmp : Intrinsic<[llvm_void_ty], [llvm_ptr_ty]>;
def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>;
+ def int_eh_sjlj_callsite: Intrinsic<[llvm_void_ty], [llvm_i32_ty]>;
}
//===---------------- Generic Variable Attribute Intrinsics----------------===//
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp
index d119b3cbd3c..c762b701767 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp
@@ -579,7 +579,16 @@ ComputeCallSiteTable(SmallVectorImpl &CallSites,
}
// Otherwise, create a new call-site.
- CallSites.push_back(Site);
+ if (MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf)
+ CallSites.push_back(Site);
+ else {
+ // SjLj EH must maintain the call sites in the order assigned
+ // to them by the SjLjPrepare pass.
+ unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel);
+ if (CallSites.size() < SiteNo)
+ CallSites.resize(SiteNo);
+ CallSites[SiteNo - 1] = Site;
+ }
PreviousIsInvoke = true;
} else {
// Create a gap.
diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp
index ed5bb5e5410..dc26d9144ff 100644
--- a/lib/CodeGen/MachineModuleInfo.cpp
+++ b/lib/CodeGen/MachineModuleInfo.cpp
@@ -71,6 +71,7 @@ void MachineModuleInfo::EndFunction() {
// Clean up exception info.
LandingPads.clear();
+ CallSiteMap.clear();
TypeInfos.clear();
FilterIds.clear();
FilterEnds.clear();
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 36059a5e85b..23ebc7b17d6 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4327,6 +4327,16 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
DAG.AssignOrdering(Res.getNode(), SDNodeOrder);
return 0;
}
+ case Intrinsic::eh_sjlj_callsite: {
+ MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
+ ConstantInt *CI = dyn_cast(I.getOperand(1));
+ assert(CI && "Non-constant call site value in eh.sjlj.callsite!");
+ assert(MMI->getCurrentCallSite() == 0 && "Overlapping call sites!");
+
+ MMI->setCurrentCallSite(CI->getZExtValue());
+ return 0;
+ }
+
case Intrinsic::convertff:
case Intrinsic::convertfsi:
case Intrinsic::convertfui:
@@ -4784,6 +4794,15 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee,
// used to detect deletion of the invoke via the MachineModuleInfo.
BeginLabel = MMI->NextLabelID();
+ // For SjLj, keep track of which landing pads go with which invokes
+ // so as to maintain the ordering of pads in the LSDA.
+ unsigned CallSiteIndex = MMI->getCurrentCallSite();
+ if (CallSiteIndex) {
+ MMI->setCallSiteBeginLabel(BeginLabel, CallSiteIndex);
+ // Now that the call site is handled, stop tracking it.
+ MMI->setCurrentCallSite(0);
+ }
+
// Both PendingLoads and PendingExports must be flushed here;
// this call might not return.
(void)getRoot();
diff --git a/lib/CodeGen/SjLjEHPrepare.cpp b/lib/CodeGen/SjLjEHPrepare.cpp
index 95589331cf4..8d4d1b21dd8 100644
--- a/lib/CodeGen/SjLjEHPrepare.cpp
+++ b/lib/CodeGen/SjLjEHPrepare.cpp
@@ -51,6 +51,7 @@ namespace {
Value *PersonalityFn;
Constant *SelectorFn;
Constant *ExceptionFn;
+ Constant *CallSiteFn;
Value *CallSite;
public:
@@ -116,6 +117,7 @@ bool SjLjEHPass::doInitialization(Module &M) {
LSDAAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_lsda);
SelectorFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector);
ExceptionFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_exception);
+ CallSiteFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_callsite);
PersonalityFn = 0;
return true;
@@ -143,15 +145,14 @@ void SjLjEHPass::markInvokeCallSite(InvokeInst *II, unsigned InvokeNo,
}
}
- // Insert a store of the invoke num before the invoke and store zero into the
- // location afterward.
+ // Insert a store of the invoke num before the invoke
new StoreInst(CallSiteNoC, CallSite, true, II); // volatile
+ CallInst::Create(CallSiteFn, CallSiteNoC, "", II);
// Add a switch case to our unwind block.
CatchSwitch->addCase(SwitchValC, II->getUnwindDest());
- // We still want this to look like an invoke so we emit the LSDA properly
- // FIXME: ??? Or will this cause strangeness with mis-matched IDs like
- // when it was in the front end?
+ // We still want this to look like an invoke so we emit the LSDA properly,
+ // so we don't transform the invoke into a call here.
}
/// MarkBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until