Missed a couple of places where new instructions are added due to spill / restore.
[oota-llvm.git] / lib / CodeGen / DwarfWriter.cpp
index 6214e1b3b835f408e2cf0180a4b77fee5e73f471..f86c4d5d76a76f4a7f9bc1ec3449fee06227bbc9 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "llvm/CodeGen/DwarfWriter.h"
 
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/UniqueVector.h"
@@ -31,6 +32,7 @@
 #include "llvm/Target/MRegisterInfo.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
 #include <ostream>
@@ -1110,6 +1112,16 @@ private:
   ///
   bool shouldEmit;
 
+  struct FunctionDebugFrameInfo {
+    unsigned Number;
+    std::vector<MachineMove> Moves;
+
+    FunctionDebugFrameInfo(unsigned Num, const std::vector<MachineMove> &M):
+      Number(Num), Moves(M) { };
+  };
+
+  std::vector<FunctionDebugFrameInfo> DebugFrames;
+  
 public:
   
   /// ShouldEmitDwarf - Returns true if Dwarf declarations should be made.
@@ -1957,7 +1969,7 @@ private:
     // Dwarf sections base addresses.
     if (TAI->doesDwarfRequireFrameSection()) {
       Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
-      EmitLabel("section_frame", 0);
+      EmitLabel("section_debug_frame", 0);
     }
     Asm->SwitchToDataSection(TAI->getDwarfInfoSection());
     EmitLabel("section_info", 0);
@@ -1982,9 +1994,6 @@ private:
     EmitLabel("text_begin", 0);
     Asm->SwitchToDataSection(TAI->getDataSection());
     EmitLabel("data_begin", 0);
-
-    // Emit common frame information.
-    EmitInitialDebugFrame();
   }
 
   /// EmitDIE - Recusively Emits a debug information entry.
@@ -2321,9 +2330,9 @@ private:
     Asm->EOL();
   }
     
-  /// EmitInitialDebugFrame - Emit common frame info into a debug frame section.
+  /// EmitCommonDebugFrame - Emit common frame info into a debug frame section.
   ///
-  void EmitInitialDebugFrame() {
+  void EmitCommonDebugFrame() {
     if (!TAI->doesDwarfRequireFrameSection())
       return;
 
@@ -2335,12 +2344,12 @@ private:
     // Start the dwarf frame section.
     Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
 
-    EmitLabel("frame_common", 0);
-    EmitDifference("frame_common_end", 0,
-                   "frame_common_begin", 0, true);
+    EmitLabel("debug_frame_common", 0);
+    EmitDifference("debug_frame_common_end", 0,
+                   "debug_frame_common_begin", 0, true);
     Asm->EOL("Length of Common Information Entry");
 
-    EmitLabel("frame_common_begin", 0);
+    EmitLabel("debug_frame_common_begin", 0);
     Asm->EmitInt32((int)DW_CIE_ID);
     Asm->EOL("CIE Identifier Tag");
     Asm->EmitInt8(DW_CIE_VERSION);
@@ -2360,41 +2369,40 @@ private:
     EmitFrameMoves(NULL, 0, Moves);
 
     Asm->EmitAlignment(2);
-    EmitLabel("frame_common_end", 0);
+    EmitLabel("debug_frame_common_end", 0);
     
     Asm->EOL();
   }
 
   /// EmitFunctionDebugFrame - Emit per function frame info into a debug frame
   /// section.
-  void EmitFunctionDebugFrame() {
+  void EmitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) {
     if (!TAI->doesDwarfRequireFrameSection())
       return;
        
     // Start the dwarf frame section.
     Asm->SwitchToDataSection(TAI->getDwarfFrameSection());
     
-    EmitDifference("frame_end", SubprogramCount,
-                   "frame_begin", SubprogramCount, true);
+    EmitDifference("debug_frame_end", DebugFrameInfo.Number,
+                   "debug_frame_begin", DebugFrameInfo.Number, true);
     Asm->EOL("Length of Frame Information Entry");
     
-    EmitLabel("frame_begin", SubprogramCount);
+    EmitLabel("debug_frame_begin", DebugFrameInfo.Number);
 
-    EmitSectionOffset("frame_common", "section_frame", 0, 0, true, false);
+    EmitSectionOffset("debug_frame_common", "section_debug_frame",
+                      0, 0, true, false);
     Asm->EOL("FDE CIE offset");
 
-    EmitReference("func_begin", SubprogramCount);
+    EmitReference("func_begin", DebugFrameInfo.Number);
     Asm->EOL("FDE initial location");
-    EmitDifference("func_end", SubprogramCount,
-                   "func_begin", SubprogramCount);
+    EmitDifference("func_end", DebugFrameInfo.Number,
+                   "func_begin", DebugFrameInfo.Number);
     Asm->EOL("FDE address range");
     
-    std::vector<MachineMove> &Moves = MMI->getFrameMoves();
-    
-    EmitFrameMoves("func_begin", SubprogramCount, Moves);
+    EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves);
     
     Asm->EmitAlignment(2);
-    EmitLabel("frame_end", SubprogramCount);
+    EmitLabel("debug_frame_end", DebugFrameInfo.Number);
 
     Asm->EOL();
   }
@@ -2636,7 +2644,15 @@ public:
       Asm->SwitchToTextSection(SectionMap[i].c_str());
       EmitLabel("section_end", i);
     }
-    
+
+    // Emit common frame information.
+    EmitCommonDebugFrame();
+
+    // Emit function debug frame information
+    for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
+           E = DebugFrames.end(); I != E; ++I)
+      EmitFunctionDebugFrame(*I);
+
     // Compute DIE offsets and sizes.
     SizeAndOffsets();
     
@@ -2705,9 +2721,9 @@ public:
     
     // Construct scopes for subprogram.
     ConstructRootScope(MMI->getRootScope());
-    
-    // Emit function frame information.
-    EmitFunctionDebugFrame();
+
+    DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
+                                                 MMI->getFrameMoves()));
   }
 };
 
@@ -2836,7 +2852,7 @@ private:
       
       EmitLabel("eh_frame_begin", EHFrameInfo.Number);
 
-      EmitSectionOffset("eh_frame_begin", "section_eh_frame",
+      EmitSectionOffset("eh_frame_begin", "eh_frame_common",
                         EHFrameInfo.Number, EHFrameInfo.PersonalityIndex,
                         true, true);
       Asm->EOL("FDE CIE offset");
@@ -2877,7 +2893,7 @@ private:
     if (const char *UsedDirective = TAI->getUsedDirective())
       O << UsedDirective << EHFrameInfo.FnName << ".eh\n\n";
   }
-  
+
   /// EmitExceptionTable - Emit landpads and actions.
   ///
   /// The general organization of the table is complex, but the basic concepts
@@ -2897,23 +2913,97 @@ private:
   ///     found the the frame is unwound and handling continues.
   ///  3. Type id table contains references to all the C++ typeinfo for all
   ///     catches in the function.  This tables is reversed indexed base 1.
+
+  /// SharedTypeIds - How many leading type ids two landing pads have in common.
+  static unsigned SharedTypeIds(const LandingPadInfo *L,
+                                const LandingPadInfo *R) {
+    const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
+    unsigned LSize = LIds.size(), RSize = RIds.size();
+    unsigned MinSize = LSize < RSize ? LSize : RSize;
+    unsigned Count = 0;
+
+    for (; Count != MinSize; ++Count)
+      if (LIds[Count] != RIds[Count])
+        return Count;
+
+    return Count;
+  }
+
+  /// PadLT - Order landing pads lexicographically by type id.
+  static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R) {
+    const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
+    unsigned LSize = LIds.size(), RSize = RIds.size();
+    unsigned MinSize = LSize < RSize ? LSize : RSize;
+
+    for (unsigned i = 0; i != MinSize; ++i)
+      if (LIds[i] != RIds[i])
+        return LIds[i] < RIds[i];
+
+    return LSize < RSize;
+  }
+
+  struct KeyInfo {
+    static inline unsigned getEmptyKey() { return -1U; }
+    static inline unsigned getTombstoneKey() { return -2U; }
+    static unsigned getHashValue(const unsigned &Key) { return Key; }
+    static bool isPod() { return true; }
+  };
+
+  struct PadSite {
+    unsigned PadIndex;
+    unsigned SiteIndex;
+  };
+
+  typedef DenseMap<unsigned, PadSite, KeyInfo> PadMapType;
+
+  struct ActionEntry {
+    int ValueForTypeID; // The value to write - may not be equal to the type id.
+    int NextAction;
+    struct ActionEntry *Previous;
+  };
+
   void EmitExceptionTable() {
     // Map all labels and get rid of any dead landing pads.
     MMI->TidyLandingPads();
-    
+
     const std::vector<GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
-    const std::vector<LandingPadInfo> &LandingPads = MMI->getLandingPads();
-    if (LandingPads.empty()) return;
-    
-    // FIXME - Should fold actions for multiple landing pads.
-    
+    const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
+    const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
+    if (PadInfos.empty()) return;
+
+    // Sort the landing pads in order of their type ids.  This is used to fold
+    // duplicate actions.
+    SmallVector<const LandingPadInfo *, 64> LandingPads;
+    LandingPads.reserve(PadInfos.size());
+    for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
+      LandingPads.push_back(&PadInfos[i]);
+    std::sort(LandingPads.begin(), LandingPads.end(), PadLT);
+
     // Gather first action index for each landing pad site.
-    SmallVector<unsigned, 8> Actions;
-    
-    // FIXME - Assume there is only one filter typeinfo list per function
-    // time being.  I.E., Each call to eh_filter will have the same list.
-    // This can change if a function is inlined. 
-    const LandingPadInfo *Filter = 0;
+    SmallVector<unsigned, 64> FirstActions;
+    FirstActions.reserve(PadInfos.size());
+
+    // The actions table.
+    SmallVector<ActionEntry, 32> Actions;
+
+    // Negative type ids index into FilterIds, positive type ids index into
+    // TypeInfos.  The value written for a positive type id is just the type
+    // id itself.  For a negative type id, however, the value written is the
+    // (negative) byte offset of the corresponding FilterIds entry.  The byte
+    // offset is usually equal to the type id, because the FilterIds entries
+    // are written using a variable width encoding which outputs one byte per
+    // entry as long as the value written is not too large, but can differ.
+    // This kind of complication does not occur for positive type ids because
+    // type infos are output using a fixed width encoding.
+    // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i].
+    SmallVector<int, 16> FilterOffsets;
+    FilterOffsets.reserve(FilterIds.size());
+    int Offset = -1;
+    for(std::vector<unsigned>::const_iterator I = FilterIds.begin(),
+        E = FilterIds.end(); I != E; ++I) {
+      FilterOffsets.push_back(Offset);
+      Offset -= Asm->SizeSLEB128(*I);
+    }
 
     // Compute sizes for exception table.
     unsigned SizeSites = 0;
@@ -2921,47 +3011,61 @@ private:
 
     // Look at each landing pad site to compute size.  We need the size of each
     // landing pad site info and the size of the landing pad's actions.
+    int FirstAction = 0;
+
     for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
-      const LandingPadInfo &LandingPad = LandingPads[i];
-      bool IsFilter = LandingPad.IsFilter;
+      const LandingPadInfo *LP = LandingPads[i];
+      const std::vector<int> &TypeIds = LP->TypeIds;
+      const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0;
       unsigned SizeSiteActions = 0;
-      const std::vector<unsigned> &TypeIds = LandingPad.TypeIds;
-      unsigned SizeAction = 0;
-      signed FirstAction;
-
-      if (IsFilter) {
-        // FIXME - Assume there is only one filter typeinfo list per function
-        // time being.  I.E., Each call to eh_filter will have the same list.
-        // This can change if a function is inlined. 
-        Filter = &LandingPad;
-        SizeAction =  Asm->SizeSLEB128(-1) + Asm->SizeSLEB128(0);
-        SizeSiteActions += SizeAction;
-        // Record the first action of the landing pad site.
-        FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
-      } else if (TypeIds.empty()) {
-        FirstAction = 0;
-      } else {
-        // Gather the action sizes
-        for (unsigned j = 0, M = TypeIds.size(); j != M; ++j) {
-          unsigned TypeID = TypeIds[j];
-          unsigned SizeTypeID = Asm->SizeSLEB128(TypeID);
-          signed Action = j ? -(SizeAction + SizeTypeID) : 0;
-          SizeAction = SizeTypeID + Asm->SizeSLEB128(Action);
+
+      if (NumShared < TypeIds.size()) {
+        unsigned SizeAction = 0;
+        ActionEntry *PrevAction = 0;
+
+        if (NumShared) {
+          const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size();
+          assert(Actions.size());
+          PrevAction = &Actions.back();
+          SizeAction = Asm->SizeSLEB128(PrevAction->NextAction) +
+            Asm->SizeSLEB128(PrevAction->ValueForTypeID);
+          for (unsigned j = NumShared; j != SizePrevIds; ++j) {
+            SizeAction -= Asm->SizeSLEB128(PrevAction->ValueForTypeID);
+            SizeAction += -PrevAction->NextAction;
+            PrevAction = PrevAction->Previous;
+          }
+        }
+
+        // Compute the actions.
+        for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) {
+          int TypeID = TypeIds[I];
+          assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!");
+          int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID;
+          unsigned SizeTypeID = Asm->SizeSLEB128(ValueForTypeID);
+
+          int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
+          SizeAction = SizeTypeID + Asm->SizeSLEB128(NextAction);
           SizeSiteActions += SizeAction;
+
+          ActionEntry Action = {ValueForTypeID, NextAction, PrevAction};
+          Actions.push_back(Action);
+
+          PrevAction = &Actions.back();
         }
-        
+
         // Record the first action of the landing pad site.
         FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
-      }
-      Actions.push_back(FirstAction);
-        
+      } // else identical - re-use previous FirstAction
+
+      FirstActions.push_back(FirstAction);
+
       // Compute this sites contribution to size.
       SizeActions += SizeSiteActions;
-      unsigned M = LandingPad.BeginLabels.size();
+      unsigned M = LP->BeginLabels.size();
       SizeSites += M*(sizeof(int32_t) +               // Site start.
                       sizeof(int32_t) +               // Site length.
                       sizeof(int32_t) +               // Landing pad.
-                      Asm->SizeSLEB128(FirstAction)); // Action.
+                      Asm->SizeULEB128(FirstAction)); // Action.
     }
     
     // Final tallies.
@@ -2999,59 +3103,72 @@ private:
     Asm->EOL("Call site format (DW_EH_PE_udata4)");
     Asm->EmitULEB128Bytes(SizeSites);
     Asm->EOL("Call-site table length");
-    
-    // Emit the landing pad site information.
+
+    // Emit the landing pad site information in order of address.
+    PadMapType PadMap;
+
     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) {
-        EmitSectionOffset("label", "eh_func_begin",
-                          LandingPad.BeginLabels[j], SubprogramCount,
+      const LandingPadInfo *LandingPad = LandingPads[i];
+      for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
+        unsigned BeginLabel = LandingPad->BeginLabels[j];
+        assert(!PadMap.count(BeginLabel) && "duplicate landing pad labels!");
+        PadSite P = { i, j };
+        PadMap[BeginLabel] = P;
+      }
+    }
+
+    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)
+          continue;
+
+        unsigned BeginLabel = MI->getOperand(0).getImmedValue();
+        PadMapType::iterator L = PadMap.find(BeginLabel);
+
+        if (L == PadMap.end())
+          continue;
+
+        PadSite P = L->second;
+        const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
+
+        assert(BeginLabel == LandingPad->BeginLabels[P.SiteIndex] &&
+               "Inconsistent landing pad map!");
+
+        EmitSectionOffset("label", "eh_func_begin", BeginLabel, SubprogramCount,
                           false, true);
         Asm->EOL("Region start");
-      
-        EmitDifference("label", LandingPad.EndLabels[j],
-                       "label", LandingPad.BeginLabels[j]);
+
+        EmitDifference("label", LandingPad->EndLabels[P.SiteIndex],
+                       "label", BeginLabel);
         Asm->EOL("Region length");
-      
-        if (LandingPad.TypeIds.empty()) {
+
+        if (LandingPad->TypeIds.empty()) {
           if (TAI->getAddressSize() == sizeof(int32_t))
             Asm->EmitInt32(0);
           else
             Asm->EmitInt64(0);
         } else {
-          EmitSectionOffset("label", "eh_func_begin", LandingPad.LandingPadLabel,
-                            SubprogramCount, false, true);
+          EmitSectionOffset("label", "eh_func_begin",
+                            LandingPad->LandingPadLabel, SubprogramCount,
+                            false, true);
         }
         Asm->EOL("Landing pad");
 
-        Asm->EmitULEB128Bytes(Actions[i]);
+        Asm->EmitULEB128Bytes(FirstActions[P.PadIndex]);
         Asm->EOL("Action");
       }
     }
-    
+
     // Emit the actions.
-    for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
-      const LandingPadInfo &LandingPad = LandingPads[i];
-      const std::vector<unsigned> &TypeIds = LandingPad.TypeIds;
-      unsigned SizeAction = 0;
-      
-      if (LandingPad.IsFilter) {
-        Asm->EmitSLEB128Bytes(-1);
-        Asm->EOL("TypeInfo index");
-        Asm->EmitSLEB128Bytes(0);
-        Asm->EOL("Next action");
-      } else {
-        for (unsigned j = 0, M = TypeIds.size(); j < M; ++j) {
-          unsigned TypeID = TypeIds[j];
-          unsigned SizeTypeID = Asm->SizeSLEB128(TypeID);
-          Asm->EmitSLEB128Bytes(TypeID);
-          Asm->EOL("TypeInfo index");
-          signed Action = j ? -(SizeAction + SizeTypeID) : 0;
-          SizeAction = SizeTypeID + Asm->SizeSLEB128(Action);
-          Asm->EmitSLEB128Bytes(Action);
-          Asm->EOL("Next action");
-        }
-      }
+    for (unsigned I = 0, N = Actions.size(); I != N; ++I) {
+      ActionEntry &Action = Actions[I];
+
+      Asm->EmitSLEB128Bytes(Action.ValueForTypeID);
+      Asm->EOL("TypeInfo index");
+      Asm->EmitSLEB128Bytes(Action.NextAction);
+      Asm->EOL("Next action");
     }
 
     // Emit the type ids.
@@ -3071,16 +3188,11 @@ private:
       Asm->EOL("TypeInfo");
     }
 
-    // Emit the filter typeinfo.
-    if (Filter) {
-      const std::vector<unsigned> &TypeIds = Filter->TypeIds;
-      for (unsigned j = 0, M = TypeIds.size(); j < M; ++j) {
-        unsigned TypeID = TypeIds[j];
-        Asm->EmitSLEB128Bytes(TypeID);
-        Asm->EOL("TypeInfo index");
-      }
-      Asm->EmitSLEB128Bytes(0);
-      Asm->EOL("End of filter typeinfo");
+    // Emit the filter typeids.
+    for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) {
+      unsigned TypeID = FilterIds[j];
+      Asm->EmitSLEB128Bytes(TypeID);
+      Asm->EOL("Filter TypeInfo index");
     }
     
     Asm->EmitAlignment(2);