diff options
author | Jim Grosbach <grosbach@apple.com> | 2009-08-11 00:09:57 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2009-08-11 00:09:57 +0000 |
commit | 1b747ad8a0694b86e8d98a8b9a05ddfe74ec0cd3 (patch) | |
tree | 55ef4dc73ff823568dc8543cbb1b4cfa77191b0b /lib/CodeGen | |
parent | 3a1f0f6785e27eb8ede455a3583ca8c885d3911e (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.cpp | 166 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfException.h | 1 | ||||
-rw-r--r-- | lib/CodeGen/LLVMTargetMachine.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/MachineFunction.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp | 11 |
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(); |