From 481dc721c37a3da0b3cc88191d01fe5b523625ee Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Wed, 19 Dec 2007 07:36:31 +0000 Subject: [PATCH] The C++ exception handling personality function wants to know about calls that cannot throw ('nounwind'): if such a call does throw for some reason then the personality will terminate the program. The distinction between an ordinary call and a nounwind call is that an ordinary call gets an entry in the exception table but a nounwind call does not. This patch sets up the exception table appropriately. One oddity is that I've chosen to bracket nounwind calls with labels (like invokes) - the other choice would have been to bracket ordinary calls with labels. While bracketing ordinary calls is more natural (because bracketing by labels would then correspond exactly to getting an entry in the exception table), I didn't do it because introducing labels impedes some optimizations and I'm guessing that ordinary calls occur more often than nounwind calls. This fixes the gcc filter2 eh test, at least at -O0 (the inliner needs some tweaking at higher optimization levels). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45197 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/DwarfWriter.cpp | 77 +++++++++++++------ lib/CodeGen/MachineModuleInfo.cpp | 3 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 8 +- 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/lib/CodeGen/DwarfWriter.cpp b/lib/CodeGen/DwarfWriter.cpp index d1f195d5567..1445a039227 100644 --- a/lib/CodeGen/DwarfWriter.cpp +++ b/lib/CodeGen/DwarfWriter.cpp @@ -3013,8 +3013,10 @@ private: /// CallSiteEntry - Structure describing an entry in the call-site table. struct CallSiteEntry { + // The 'try-range' is BeginLabel .. EndLabel. unsigned BeginLabel; // zero indicates the start of the function. unsigned EndLabel; // zero indicates the end of the function. + // The landing pad starts at PadLabel. unsigned PadLabel; // zero indicates that there is no landing pad. unsigned Action; }; @@ -3113,13 +3115,21 @@ private: SizeActions += SizeSiteActions; } - // Compute the call-site table. Entries must be ordered by address. + // Compute the call-site table. The entry for an invoke has a try-range + // containing the call, a non-zero landing pad and an appropriate action. + // The entry for an ordinary call has a try-range containing the call and + // zero for the landing pad and the action. Calls marked 'nounwind' have + // no entry and must not be contained in the try-range of any entry - they + // form gaps in the table. Entries must be ordered by try-range address. SmallVector CallSites; RangeMapType PadMap; + // 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. for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { const LandingPadInfo *LandingPad = LandingPads[i]; - for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) { + for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { unsigned BeginLabel = LandingPad->BeginLabels[j]; assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); PadRange P = { i, j }; @@ -3127,27 +3137,39 @@ private: } } - bool MayThrow = false; + // The end label of the previous invoke or nounwind try-range. unsigned LastLabel = 0; + + // Whether there is a potentially throwing instruction (currently this means + // an ordinary call) between the end of the previous try-range and now. + bool SawPotentiallyThrowing = false; + + // Whether the last callsite entry was for an invoke. + bool PreviousIsInvoke = false; + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + // Visit all instructions in order of address. for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); MI != E; ++MI) { if (MI->getOpcode() != TargetInstrInfo::LABEL) { - MayThrow |= TII->isCall(MI->getOpcode()); + SawPotentiallyThrowing |= TII->isCall(MI->getOpcode()); continue; } unsigned BeginLabel = MI->getOperand(0).getImmedValue(); assert(BeginLabel && "Invalid label!"); + // End of the previous try-range? if (BeginLabel == LastLabel) - MayThrow = false; + SawPotentiallyThrowing = false; + // Beginning of a new try-range? RangeMapType::iterator L = PadMap.find(BeginLabel); - if (L == PadMap.end()) + // Nope, it was just some random label. continue; PadRange P = L->second; @@ -3159,36 +3181,43 @@ private: // 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 (MayThrow) { + if (SawPotentiallyThrowing) { CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; CallSites.push_back(Site); + PreviousIsInvoke = false; } LastLabel = LandingPad->EndLabels[P.RangeIndex]; - CallSiteEntry Site = {BeginLabel, LastLabel, - LandingPad->LandingPadLabel, FirstActions[P.PadIndex]}; - - assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel && - "Invalid landing pad!"); - - // Try to merge with the previous call-site. - if (CallSites.size()) { - CallSiteEntry &Prev = CallSites[CallSites.size()-1]; - if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { - // Extend the range of the previous entry. - Prev.EndLabel = Site.EndLabel; - continue; + assert(BeginLabel && LastLabel && "Invalid landing pad!"); + + if (LandingPad->LandingPadLabel) { + // This try-range is for an invoke. + CallSiteEntry Site = {BeginLabel, LastLabel, + LandingPad->LandingPadLabel, FirstActions[P.PadIndex]}; + + // Try to merge with the previous call-site. + if (PreviousIsInvoke) { + CallSiteEntry &Prev = CallSites[CallSites.size()-1]; + if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { + // Extend the range of the previous entry. + Prev.EndLabel = Site.EndLabel; + continue; + } } - } - // Otherwise, create a new call-site. - CallSites.push_back(Site); + // Otherwise, create a new call-site. + CallSites.push_back(Site); + PreviousIsInvoke = true; + } else { + // Create a gap. + PreviousIsInvoke = false; + } } } // 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 (MayThrow) { + if (SawPotentiallyThrowing) { CallSiteEntry Site = {LastLabel, 0, 0, 0}; CallSites.push_back(Site); } diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index 14253f41117..59c335e7fb0 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -1747,7 +1747,7 @@ void MachineModuleInfo::TidyLandingPads() { LandingPad.LandingPadLabel = MappedLabel(LandingPad.LandingPadLabel); // Special case: we *should* emit LPs with null LP MBB. This indicates - // "rethrow" case. + // "nounwind" case. if (!LandingPad.LandingPadLabel && LandingPad.LandingPadBlock) { LandingPads.erase(LandingPads.begin() + i); continue; @@ -1757,7 +1757,6 @@ void MachineModuleInfo::TidyLandingPads() { unsigned BeginLabel = MappedLabel(LandingPad.BeginLabels[j]); unsigned EndLabel = MappedLabel(LandingPad.EndLabels[j]); - if (!BeginLabel || !EndLabel) { LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j); LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index bc336d20697..05a7a954d7f 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2952,7 +2952,11 @@ void SelectionDAGLowering::LowerCallTo(Instruction &I, Args.push_back(Entry); } - if (ExceptionHandling && MMI && LandingPad) { + bool MarkTryRange = LandingPad || + // C++ requires special handling of 'nounwind' calls. + (Attrs && Attrs->paramHasAttr(0, ParamAttr::NoUnwind)); + + if (MarkTryRange && ExceptionHandling && MMI) { // 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(); @@ -2969,7 +2973,7 @@ void SelectionDAGLowering::LowerCallTo(Instruction &I, setValue(&I, Result.first); DAG.setRoot(Result.second); - if (ExceptionHandling && MMI && LandingPad) { + if (MarkTryRange && ExceptionHandling && MMI) { // Insert a label at the end of the invoke call to mark the try range. This // can be used to detect deletion of the invoke via the MachineModuleInfo. EndLabel = MMI->NextLabelID(); -- 2.34.1