aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2009-08-11 00:09:57 +0000
committerJim Grosbach <grosbach@apple.com>2009-08-11 00:09:57 +0000
commit1b747ad8a0694b86e8d98a8b9a05ddfe74ec0cd3 (patch)
tree55ef4dc73ff823568dc8543cbb1b4cfa77191b0b /lib/CodeGen
parent3a1f0f6785e27eb8ede455a3583ca8c885d3911e (diff)
SjLj based exception handling unwinding support. This patch is nasty, brutish
and short. Well, it's kinda short. Definitely nasty and brutish. The front-end generates the register/unregister calls into the SjLj runtime, call-site indices and landing pad dispatch. The back end fills in the LSDA with the call-site information provided by the front end. Catch blocks are not yet implemented. Built on Darwin and verified no llvm-core "make check" regressions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78625 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.cpp166
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.h1
-rw-r--r--lib/CodeGen/LLVMTargetMachine.cpp13
-rw-r--r--lib/CodeGen/MachineFunction.cpp3
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp1
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp11
6 files changed, 145 insertions, 50 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp
index fec1ad7557..a0cd456d37 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp
@@ -364,6 +364,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
/// try-range address.
void DwarfException::
ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
+ std::map<unsigned,CallSiteEntry*> &CallSiteIndexMap,
const RangeMapType &PadMap,
const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
const SmallVectorImpl<unsigned> &FirstActions) {
@@ -405,10 +406,12 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
"Inconsistent landing pad map!");
+ // For Dwarf exception handling (SjLj handling doesn't use this)
// If some instruction between the previous try-range and this one may
// throw, create a call-site entry with no landing pad for the region
// between the try-ranges.
- if (SawPotentiallyThrowing) {
+ if (SawPotentiallyThrowing &&
+ TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) {
CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0};
CallSites.push_back(Site);
PreviousIsInvoke = false;
@@ -435,6 +438,12 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
// Otherwise, create a new call-site.
CallSites.push_back(Site);
+ // For SjLj handling, map the call site entry to its index
+ if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) {
+ unsigned Index =
+ MF->getLandingPadCallSiteIndex(LandingPad->LandingPadBlock);
+ CallSiteIndexMap[Index] = &CallSites.back();
+ }
PreviousIsInvoke = true;
} else {
// Create a gap.
@@ -446,7 +455,8 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
// If some instruction between the previous try-range and the end of the
// function may throw, create a call-site entry with no landing pad for the
// region following the try-range.
- if (SawPotentiallyThrowing) {
+ if (SawPotentiallyThrowing &&
+ TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) {
CallSiteEntry Site = {LastLabel, 0, 0, 0};
CallSites.push_back(Site);
}
@@ -496,7 +506,7 @@ void DwarfException::EmitExceptionTable() {
// Invokes and nounwind calls have entries in PadMap (due to being bracketed
// by try-range labels when lowered). Ordinary calls do not, so appropriate
- // try-ranges for them need be deduced.
+ // try-ranges for them need be deduced when using Dwarf exception handling.
RangeMapType PadMap;
for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
const LandingPadInfo *LandingPad = LandingPads[i];
@@ -510,7 +520,9 @@ void DwarfException::EmitExceptionTable() {
// Compute the call-site table.
SmallVector<CallSiteEntry, 64> CallSites;
- ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions);
+ std::map<unsigned,CallSiteEntry*> CallSiteIndexMap;
+ ComputeCallSiteTable(CallSites, CallSiteIndexMap, PadMap,
+ LandingPads, FirstActions);
// Final tallies.
@@ -518,12 +530,19 @@ void DwarfException::EmitExceptionTable() {
const unsigned SiteStartSize = sizeof(int32_t); // DW_EH_PE_udata4
const unsigned SiteLengthSize = sizeof(int32_t); // DW_EH_PE_udata4
const unsigned LandingPadSize = sizeof(int32_t); // DW_EH_PE_udata4
- unsigned SizeSites = CallSites.size() * (SiteStartSize +
- SiteLengthSize +
- LandingPadSize);
- for (unsigned i = 0, e = CallSites.size(); i < e; ++i)
+ unsigned SizeSites;
+ if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) {
+ SizeSites = (MF->getMaxCallSiteIndex() - CallSites.size()) *
+ TargetAsmInfo::getULEB128Size(0) * 2;
+ } else
+ SizeSites = CallSites.size() *
+ (SiteStartSize + SiteLengthSize + LandingPadSize);
+ for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
SizeSites += TargetAsmInfo::getULEB128Size(CallSites[i].Action);
-
+ if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj)
+ SizeSites += TargetAsmInfo::getULEB128Size(i);
+ // FIXME: 'i' above should be the landing pad index
+ }
// Type infos.
const unsigned TypeInfoSize = TD->getPointerSize(); // DW_EH_PE_absptr
unsigned SizeTypes = TypeInfos.size() * TypeInfoSize;
@@ -551,6 +570,11 @@ void DwarfException::EmitExceptionTable() {
}
EmitLabel("exception", SubprogramCount);
+ if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) {
+ std::string SjLjName = "_lsda_";
+ SjLjName += MF->getFunction()->getName().str();
+ EmitLabel(SjLjName.c_str(), 0);
+ }
// Emit the header.
Asm->EmitInt8(dwarf::DW_EH_PE_omit);
@@ -600,54 +624,102 @@ void DwarfException::EmitExceptionTable() {
Asm->EOL("TType base offset");
}
#else
- Asm->EmitInt8(dwarf::DW_EH_PE_absptr);
- Asm->EOL("TType format (DW_EH_PE_absptr)");
- Asm->EmitULEB128Bytes(TypeOffset);
- Asm->EOL("TType base offset");
+ // For SjLj exceptions, is there is no TypeInfo, then we just explicitly
+ // say that we're omitting that bit.
+ // FIXME: does this apply to Dwarf also? The above #if 0 implies yes?
+ if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj
+ && (TypeInfos.empty() || FilterIds.empty())) {
+ Asm->EmitInt8(dwarf::DW_EH_PE_omit);
+ Asm->EOL("TType format (DW_EH_PE_omit)");
+ } else {
+ Asm->EmitInt8(dwarf::DW_EH_PE_absptr);
+ Asm->EOL("TType format (DW_EH_PE_absptr)");
+ Asm->EmitULEB128Bytes(TypeOffset);
+ Asm->EOL("TType base offset");
+ }
#endif
- Asm->EmitInt8(dwarf::DW_EH_PE_udata4);
- Asm->EOL("Call site format (DW_EH_PE_udata4)");
- Asm->EmitULEB128Bytes(SizeSites);
- Asm->EOL("Call-site table length");
+ // SjLj Exception handilng
+ if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) {
+ Asm->EmitInt8(dwarf::DW_EH_PE_udata4);
+ Asm->EOL("Call site format (DW_EH_PE_udata4)");
+ Asm->EmitULEB128Bytes(SizeSites);
+ Asm->EOL("Call-site table length");
+
+
+ assert(MF->getCallSiteCount() == CallSites.size());
+
+ // Emit the landing pad site information.
+ // SjLj handling assigned the call site indices in the front end, so
+ // we need to make sure the table here lines up with that. That's pretty
+ // horrible, and should be fixed ASAP to do that stuff in the back end
+ // instead.
+ std::map<unsigned, CallSiteEntry*>::const_iterator I, E;
+ I = CallSiteIndexMap.begin();
+ E = CallSiteIndexMap.end();
+ for (unsigned CurrIdx = 1; I != E; ++I) {
+ // paranoia.
+ assert(CurrIdx <= I->first);
+ // Fill in any gaps in the table
+ while (CurrIdx++ < I->first) {
+ Asm->EmitULEB128Bytes(0);
+ Asm->EOL("Filler landing pad");
+ Asm->EmitULEB128Bytes(0);
+ Asm->EOL("Filler action");
+ }
+ const CallSiteEntry &S = *(I->second);
+ Asm->EmitULEB128Bytes(I->first - 1);
+ Asm->EOL("Landing pad");
+ Asm->EmitULEB128Bytes(S.Action);
+ Asm->EOL("Action");
+ }
+ } else {
+ // DWARF Exception handling
+ assert(TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf);
+
+ Asm->EmitInt8(dwarf::DW_EH_PE_udata4);
+ Asm->EOL("Call site format (DW_EH_PE_udata4)");
+ Asm->EmitULEB128Bytes(SizeSites);
+ Asm->EOL("Call-site table length");
- // Emit the landing pad site information.
- for (SmallVectorImpl<CallSiteEntry>::const_iterator
+ // Emit the landing pad site information.
+ for (SmallVectorImpl<CallSiteEntry>::const_iterator
I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
- const CallSiteEntry &S = *I;
- const char *BeginTag;
- unsigned BeginNumber;
+ const CallSiteEntry &S = *I;
+ const char *BeginTag;
+ unsigned BeginNumber;
- if (!S.BeginLabel) {
- BeginTag = "eh_func_begin";
- BeginNumber = SubprogramCount;
- } else {
- BeginTag = "label";
- BeginNumber = S.BeginLabel;
- }
+ if (!S.BeginLabel) {
+ BeginTag = "eh_func_begin";
+ BeginNumber = SubprogramCount;
+ } else {
+ BeginTag = "label";
+ BeginNumber = S.BeginLabel;
+ }
- EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount,
- true, true);
- Asm->EOL("Region start");
+ EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount,
+ true, true);
+ Asm->EOL("Region start");
- if (!S.EndLabel)
- EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber,
- true);
- else
- EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true);
+ if (!S.EndLabel)
+ EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber,
+ true);
+ else
+ EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true);
- Asm->EOL("Region length");
+ Asm->EOL("Region length");
- if (!S.PadLabel)
- Asm->EmitInt32(0);
- else
- EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount,
- true, true);
+ if (!S.PadLabel)
+ Asm->EmitInt32(0);
+ else
+ EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount,
+ true, true);
- Asm->EOL("Landing pad");
+ Asm->EOL("Landing pad");
- Asm->EmitULEB128Bytes(S.Action);
- Asm->EOL("Action");
+ Asm->EmitULEB128Bytes(S.Action);
+ Asm->EOL("Action");
+ }
}
// Emit the actions.
@@ -690,6 +762,8 @@ void DwarfException::EmitExceptionTable() {
/// EndModule - Emit all exception information that should come after the
/// content.
void DwarfException::EndModule() {
+ if (TAI->getExceptionHandlingType() != ExceptionHandling::Dwarf)
+ return;
if (TimePassesIsEnabled)
ExceptionTimer->startTimer();
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h
index e165df4693..ee390cff01 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.h
+++ b/lib/CodeGen/AsmPrinter/DwarfException.h
@@ -155,6 +155,7 @@ class VISIBILITY_HIDDEN DwarfException : public Dwarf {
/// of any entry - they form gaps in the table. Entries must be ordered by
/// try-range address.
void ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
+ std::map<unsigned,CallSiteEntry*> &CallSiteIndexMap,
const RangeMapType &PadMap,
const SmallVectorImpl<const LandingPadInfo *> &LPs,
const SmallVectorImpl<unsigned> &FirstActions);
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index 8249501dc1..c60f9c7e41 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/LLVMTargetMachine.cpp
@@ -229,10 +229,17 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM,
// Turn exception handling constructs into something the code generators can
// handle.
- if (!getTargetAsmInfo()->doesSupportExceptionHandling())
- PM.add(createLowerInvokePass(getTargetLowering()));
- else
+ switch (getTargetAsmInfo()->getExceptionHandlingType())
+ {
+ // SjLj piggy-backs on dwarf for this bit
+ case ExceptionHandling::SjLj:
+ case ExceptionHandling::Dwarf:
PM.add(createDwarfEHPass(getTargetLowering(), OptLevel==CodeGenOpt::None));
+ break;
+ case ExceptionHandling::None:
+ PM.add(createLowerInvokePass(getTargetLowering()));
+ break;
+ }
PM.add(createGCLoweringPass());
diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp
index 2e9303aeef..ab037c243a 100644
--- a/lib/CodeGen/MachineFunction.cpp
+++ b/lib/CodeGen/MachineFunction.cpp
@@ -93,6 +93,9 @@ MachineFunction::MachineFunction(Function *F,
MachineConstantPool(TM.getTargetData());
Alignment = TM.getTargetLowering()->getFunctionAlignment(F);
+ CallSiteIndex = 0;
+ MaxCallSiteIndex = 0;
+
// Set up jump table.
const TargetData &TD = *TM.getTargetData();
bool IsPic = TM.getRelocationModel() == Reloc::PIC_;
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 712fedad4d..7297d60d34 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5198,6 +5198,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::FRAMEADDR: return "FRAMEADDR";
case ISD::FRAME_TO_ARGS_OFFSET: return "FRAME_TO_ARGS_OFFSET";
case ISD::EXCEPTIONADDR: return "EXCEPTIONADDR";
+ case ISD::LSDAADDR: return "LSDAADDR";
case ISD::EHSELECTION: return "EHSELECTION";
case ISD::EH_RETURN: return "EH_RETURN";
case ISD::ConstantPool: return "ConstantPool";
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
index 0180069623..1d02bffb61 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
@@ -4087,7 +4087,11 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
Offset));
return 0;
}
-
+ case Intrinsic::eh_sjlj_callsite: {
+ MachineFunction &MF = DAG.getMachineFunction();
+ MF.setCallSiteIndex(cast<ConstantSDNode>(getValue(I.getOperand(1)))->getZExtValue());
+ return 0;
+ }
case Intrinsic::convertff:
case Intrinsic::convertfsi:
case Intrinsic::convertfui:
@@ -4451,9 +4455,14 @@ void SelectionDAGLowering::LowerCallTo(CallSite CS, SDValue Callee,
}
if (LandingPad && MMI) {
+ MachineFunction &MF = DAG.getMachineFunction();
// Insert a label before the invoke call to mark the try range. This can be
// used to detect deletion of the invoke via the MachineModuleInfo.
BeginLabel = MMI->NextLabelID();
+
+ // Map this landing pad to the current call site entry
+ MF.setLandingPadCallSiteIndex(LandingPad, MF.getCallSiteIndex());
+
// Both PendingLoads and PendingExports must be flushed here;
// this call might not return.
(void)getRoot();