The C++ exception handling personality function wants
authorDuncan Sands <baldrick@free.fr>
Wed, 19 Dec 2007 07:36:31 +0000 (07:36 +0000)
committerDuncan Sands <baldrick@free.fr>
Wed, 19 Dec 2007 07:36:31 +0000 (07:36 +0000)
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
lib/CodeGen/MachineModuleInfo.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

index d1f195d55672aea08c5dd8b0aa5c6ee699a628d2..1445a0392276c9def73bc71a368d64b331aeffb0 100644 (file)
@@ -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<CallSiteEntry, 64> 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);
     }
index 14253f41117be5e248163336bc7b18cf4dd2c608..59c335e7fb053c5af2262c95a6311fc18cd90a02 100644 (file)
@@ -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);
index bc336d2069758d6a67b19223af25ebf115c0444d..05a7a954d7fa4cf78b39e1550b0fd9d3d0e80a1c 100644 (file)
@@ -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();