Fix the source line debug information for the Windows platform.
[oota-llvm.git] / lib / CodeGen / DwarfWriter.cpp
index 5ef48cc340114c05570799edf01b3747a073c96c..784bf930b584db7690734a66ba13d83a43c8323b 100644 (file)
@@ -30,7 +30,7 @@
 #include "llvm/Support/Mangler.h"
 #include "llvm/System/Path.h"
 #include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/MRegisterInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetFrameInfo.h"
 #include "llvm/Target/TargetInstrInfo.h"
@@ -296,6 +296,7 @@ public:
     isString,
     isLabel,
     isAsIsLabel,
+    isSectionOffset,
     isDelta,
     isEntry,
     isBlock
@@ -504,6 +505,56 @@ public:
 #endif
 };
 
+//===----------------------------------------------------------------------===//
+/// DIESectionOffset - A section offset DIE.
+//
+class DIESectionOffset : public DIEValue {
+public:
+  const DWLabel Label;
+  const DWLabel Section;
+  bool IsEH : 1;
+  bool UseSet : 1;
+  
+  DIESectionOffset(const DWLabel &Lab, const DWLabel &Sec,
+                   bool isEH = false, bool useSet = true)
+  : DIEValue(isSectionOffset), Label(Lab), Section(Sec),
+                               IsEH(isEH), UseSet(useSet) {}
+
+  // Implement isa/cast/dyncast.
+  static bool classof(const DIESectionOffset *)  { return true; }
+  static bool classof(const DIEValue *D) { return D->Type == isSectionOffset; }
+  
+  /// EmitValue - Emit section offset.
+  ///
+  virtual void EmitValue(DwarfDebug &DD, unsigned Form);
+  
+  /// SizeOf - Determine size of section offset value in bytes.
+  ///
+  virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const;
+  
+  /// Profile - Used to gather unique data for the value folding set.
+  ///
+  static void Profile(FoldingSetNodeID &ID, const DWLabel &Label,
+                                            const DWLabel &Section) {
+    ID.AddInteger(isSectionOffset);
+    Label.Profile(ID);
+    Section.Profile(ID);
+    // IsEH and UseSet are specific to the Label/Section that we will emit
+    // the offset for; so Label/Section are enough for uniqueness.
+  }
+  virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, Label, Section); }
+
+#ifndef NDEBUG
+  virtual void print(std::ostream &O) {
+    O << "Off: ";
+    Label.print(O);
+    O << "-";
+    Section.print(O);
+    O << "-" << IsEH << "-" << UseSet;
+  }
+#endif
+};
+
 //===----------------------------------------------------------------------===//
 /// DIEDelta - A simple label difference DIE.
 /// 
@@ -782,7 +833,7 @@ protected:
   const TargetData *TD;
   
   /// RI - Register Information.
-  const MRegisterInfo *RI;
+  const TargetRegisterInfo *RI;
   
   /// M - Current module.
   ///
@@ -925,19 +976,20 @@ public:
 
   void EmitSectionOffset(const char* Label, const char* Section,
                          unsigned LabelNumber, unsigned SectionNumber,
-                         bool IsSmall = false, bool isEH = false) {
+                         bool IsSmall = false, bool isEH = false,
+                         bool useSet = true) {
     bool printAbsolute = false;
-    if (TAI->needsSet()) {
+    if (isEH)
+      printAbsolute = TAI->isAbsoluteEHSectionOffsets();
+    else
+      printAbsolute = TAI->isAbsoluteDebugSectionOffsets();
+
+    if (TAI->needsSet() && useSet) {
       O << "\t.set\t";
       PrintLabelName("set", SetCounter, Flavor);
       O << ",";
       PrintLabelName(Label, LabelNumber);
 
-      if (isEH)
-        printAbsolute = TAI->isAbsoluteEHSectionOffsets();
-      else
-        printAbsolute = TAI->isAbsoluteDebugSectionOffsets();
-      
       if (!printAbsolute) {
         O << "-";
         PrintLabelName(Section, SectionNumber);
@@ -953,11 +1005,6 @@ public:
         
       PrintLabelName(Label, LabelNumber);
 
-      if (isEH)
-        printAbsolute = TAI->isAbsoluteEHSectionOffsets();
-      else
-        printAbsolute = TAI->isAbsoluteDebugSectionOffsets();
-
       if (!printAbsolute) {
         O << "-";
         PrintLabelName(Section, SectionNumber);
@@ -1279,6 +1326,24 @@ public:
     Die->AddValue(Attribute, Form, Value);
   }
       
+  /// AddSectionOffset - Add a section offset label attribute data and value.
+  ///
+  void AddSectionOffset(DIE *Die, unsigned Attribute, unsigned Form,
+                        const DWLabel &Label, const DWLabel &Section,
+                        bool isEH = false, bool useSet = true) {
+    FoldingSetNodeID ID;
+    DIESectionOffset::Profile(ID, Label, Section);
+    void *Where;
+    DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where);
+    if (!Value) {
+      Value = new DIESectionOffset(Label, Section, isEH, useSet);
+      ValuesSet.InsertNode(Value, Where);
+      Values.push_back(Value);
+    }
+  
+    Die->AddValue(Attribute, Form, Value);
+  }
+      
   /// AddDelta - Add a label delta attribute data and value.
   ///
   void AddDelta(DIE *Die, unsigned Attribute, unsigned Form,
@@ -1718,11 +1783,8 @@ private:
   CompileUnit *NewCompileUnit(CompileUnitDesc *UnitDesc, unsigned ID) {
     // Construct debug information entry.
     DIE *Die = new DIE(DW_TAG_compile_unit);
-    if (TAI->isAbsoluteDebugSectionOffsets())
-      AddLabel(Die, DW_AT_stmt_list, DW_FORM_data4, DWLabel("section_line", 0));
-    else
-      AddDelta(Die, DW_AT_stmt_list, DW_FORM_data4, DWLabel("section_line", 0),
-               DWLabel("section_line", 0));      
+    AddSectionOffset(Die, DW_AT_stmt_list, DW_FORM_data4,
+              DWLabel("section_line", 0), DWLabel("section_line", 0), false);
     AddString(Die, DW_AT_producer,  DW_FORM_string, UnitDesc->getProducer());
     AddUInt  (Die, DW_AT_language,  DW_FORM_data1,  UnitDesc->getLanguage());
     AddString(Die, DW_AT_name,      DW_FORM_string, UnitDesc->getFileName());
@@ -1875,7 +1937,8 @@ private:
     
     // Add variable address.
     MachineLocation Location;
-    RI->getLocation(*MF, DV->getFrameIndex(), Location);
+    Location.set(RI->getFrameRegister(*MF),
+                 RI->getFrameIndexOffset(*MF, DV->getFrameIndex()));
     AddAddress(VariableDie, DW_AT_location, Location);
 
     return VariableDie;
@@ -2378,7 +2441,7 @@ private:
 
     EmitFrameMoves(NULL, 0, Moves, false);
 
-    Asm->EmitAlignment(2);
+    Asm->EmitAlignment(2, 0, 0, false);
     EmitLabel("debug_frame_common_end", 0);
     
     Asm->EOL();
@@ -2411,7 +2474,7 @@ private:
     
     EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves, false);
     
-    Asm->EmitAlignment(2);
+    Asm->EmitAlignment(2, 0, 0, false);
     EmitLabel("debug_frame_end", DebugFrameInfo.Number);
 
     Asm->EOL();
@@ -2720,6 +2783,14 @@ public:
     
     // Assumes in correct section after the entry point.
     EmitLabel("func_begin", ++SubprogramCount);
+
+    // Emit label for the implicitly defined dbg.stoppoint at the start of
+    // the function.
+    const std::vector<SourceLineInfo> &LineInfos = MMI->getSourceLines();
+    if (!LineInfos.empty()) {
+      const SourceLineInfo &LineInfo = LineInfos[0];
+      Asm->printLabel(LineInfo.getLabelID());
+    }
   }
   
   /// EndFunction - Gather and emit post-function debug information.
@@ -2764,23 +2835,34 @@ private:
     bool hasCalls;
     bool hasLandingPads;
     std::vector<MachineMove> Moves;
-    Function::LinkageTypes linkage;
+    const Function * function;
 
     FunctionEHFrameInfo(const std::string &FN, unsigned Num, unsigned P,
                         bool hC, bool hL,
                         const std::vector<MachineMove> &M,
-                        Function::LinkageTypes l):
+                        const Function *f):
       FnName(FN), Number(Num), PersonalityIndex(P),
-      hasCalls(hC), hasLandingPads(hL), Moves(M),
-      linkage(l) { }
+      hasCalls(hC), hasLandingPads(hL), Moves(M), function (f) { }
   };
 
   std::vector<FunctionEHFrameInfo> EHFrames;
-    
-  /// shouldEmit - Flag to indicate if debug information should be emitted.
-  ///
-  bool shouldEmit;
-  
+
+  /// shouldEmitTable - Per-function flag to indicate if EH tables should
+  /// be emitted.
+  bool shouldEmitTable;
+
+  /// shouldEmitMoves - Per-function flag to indicate if frame moves info
+  /// should be emitted.
+  bool shouldEmitMoves;
+
+  /// shouldEmitTableModule - Per-module flag to indicate if EH tables
+  /// should be emitted.
+  bool shouldEmitTableModule;
+
+  /// shouldEmitFrameModule - Per-module flag to indicate if frame moves 
+  /// should be emitted.
+  bool shouldEmitMovesModule;
+
   /// EmitCommonEHFrame - Emit the common eh unwind frame.
   ///
   void EmitCommonEHFrame(const Function *Personality, unsigned Index) {
@@ -2797,7 +2879,7 @@ private:
 
     // Define base labels.
     EmitLabel("eh_frame_common", Index);
-    
+
     // Define the eh frame length.
     EmitDifference("eh_frame_common_end", Index,
                    "eh_frame_common_begin", Index, true);
@@ -2809,48 +2891,50 @@ private:
     Asm->EOL("CIE Identifier Tag");
     Asm->EmitInt8(DW_CIE_VERSION);
     Asm->EOL("CIE Version");
-    
+
     // The personality presence indicates that language specific information
     // will show up in the eh frame.
     Asm->EmitString(Personality ? "zPLR" : "zR");
     Asm->EOL("CIE Augmentation");
-    
+
     // Round out reader.
     Asm->EmitULEB128Bytes(1);
     Asm->EOL("CIE Code Alignment Factor");
     Asm->EmitSLEB128Bytes(stackGrowth);
-    Asm->EOL("CIE Data Alignment Factor");   
+    Asm->EOL("CIE Data Alignment Factor");
     Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true));
-    Asm->EOL("CIE RA Column");
-    
+    Asm->EOL("CIE Return Address Column");
+
     // If there is a personality, we need to indicate the functions location.
     if (Personality) {
       Asm->EmitULEB128Bytes(7);
       Asm->EOL("Augmentation Size");
 
-      if (TAI->getNeedsIndirectEncoding())
+      if (TAI->getNeedsIndirectEncoding()) {
         Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect);
-      else
+        Asm->EOL("Personality (pcrel sdata4 indirect)");
+      } else {
         Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4);
+        Asm->EOL("Personality (pcrel sdata4)");
+      }
 
-      Asm->EOL("Personality (pcrel sdata4 indirect)");
-      
-      PrintRelDirective();
+      PrintRelDirective(true);
       O << TAI->getPersonalityPrefix();
       Asm->EmitExternalGlobal((const GlobalVariable *)(Personality));
       O << TAI->getPersonalitySuffix();
-      O << "-" << TAI->getPCSymbol();
+      if (strcmp(TAI->getPersonalitySuffix(), "+4@GOTPCREL"))
+        O << "-" << TAI->getPCSymbol();
       Asm->EOL("Personality");
 
-      Asm->EmitULEB128Bytes(DW_EH_PE_pcrel);
-      Asm->EOL("LSDA Encoding (pcrel)");
-      Asm->EmitULEB128Bytes(DW_EH_PE_pcrel);
-      Asm->EOL("FDE Encoding (pcrel)");
+      Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4);
+      Asm->EOL("LSDA Encoding (pcrel sdata4)");
+      Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4);
+      Asm->EOL("FDE Encoding (pcrel sdata4)");
    } else {
       Asm->EmitULEB128Bytes(1);
       Asm->EOL("Augmentation Size");
-      Asm->EmitULEB128Bytes(DW_EH_PE_pcrel);
-      Asm->EOL("FDE Encoding (pcrel)");
+      Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_sdata4);
+      Asm->EOL("FDE Encoding (pcrel sdata4)");
     }
 
     // Indicate locations of general callee saved registers in frame.
@@ -2858,37 +2942,58 @@ private:
     RI->getInitialFrameState(Moves);
     EmitFrameMoves(NULL, 0, Moves, true);
 
-    Asm->EmitAlignment(2);
+    // On Darwin the linker honors the alignment of eh_frame, which means it
+    // must be 8-byte on 64-bit targets to match what gcc does.  Otherwise
+    // you get holes which confuse readers of eh_frame.
+    Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, 
+                       0, 0, false);
     EmitLabel("eh_frame_common_end", Index);
-    
+
     Asm->EOL();
   }
-  
+
   /// EmitEHFrame - Emit function exception frame information.
   ///
   void EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) {
+    Function::LinkageTypes linkage = EHFrameInfo.function->getLinkage();
+
     Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection());
 
     // Externally visible entry into the functions eh frame info.
     // If the corresponding function is static, this should not be
     // externally visible.
-    if (EHFrameInfo.linkage != Function::InternalLinkage) {
+    if (linkage != Function::InternalLinkage) {
       if (const char *GlobalEHDirective = TAI->getGlobalEHDirective())
         O << GlobalEHDirective << EHFrameInfo.FnName << "\n";
     }
 
-    // If there are no calls then you can't unwind.
-    if (!EHFrameInfo.hasCalls) { 
+    // If corresponding function is weak definition, this should be too.
+    if ((linkage == Function::WeakLinkage || 
+         linkage == Function::LinkOnceLinkage) &&
+        TAI->getWeakDefDirective())
+      O << TAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n";
+
+    // If there are no calls then you can't unwind.  This may mean we can
+    // omit the EH Frame, but some environments do not handle weak absolute
+    // symbols.  
+    // If UnwindTablesMandatory is set we cannot do this optimization; the
+    // unwind info is to be available for non-EH uses.
+    if (!EHFrameInfo.hasCalls &&
+        !UnwindTablesMandatory &&
+        ((linkage != Function::WeakLinkage && 
+          linkage != Function::LinkOnceLinkage) ||
+         !TAI->getWeakDefDirective() ||
+         TAI->getSupportsWeakOmittedEHFrame()))
+    { 
       O << EHFrameInfo.FnName << " = 0\n";
+      // This name has no connection to the function, so it might get 
+      // dead-stripped when the function is not, erroneously.  Prohibit 
+      // dead-stripping unconditionally.
+      if (const char *UsedDirective = TAI->getUsedDirective())
+        O << UsedDirective << EHFrameInfo.FnName << "\n\n";
     } else {
       O << EHFrameInfo.FnName << ":\n";
 
-      // If corresponding function is weak definition, this should be too.
-      if ((EHFrameInfo.linkage == Function::WeakLinkage || 
-           EHFrameInfo.linkage == Function::LinkOnceLinkage) &&
-          TAI->getWeakDefDirective())
-        O << TAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n";
-
       // EH frame header.
       EmitDifference("eh_frame_end", EHFrameInfo.Number,
                      "eh_frame_begin", EHFrameInfo.Number, true);
@@ -2898,44 +3003,51 @@ private:
 
       EmitSectionOffset("eh_frame_begin", "eh_frame_common",
                         EHFrameInfo.Number, EHFrameInfo.PersonalityIndex,
-                        true, true);
+                        true, true, false);
       Asm->EOL("FDE CIE offset");
 
-      EmitReference("eh_func_begin", EHFrameInfo.Number, true);
+      EmitReference("eh_func_begin", EHFrameInfo.Number, true, true);
       Asm->EOL("FDE initial location");
       EmitDifference("eh_func_end", EHFrameInfo.Number,
-                     "eh_func_begin", EHFrameInfo.Number);
+                     "eh_func_begin", EHFrameInfo.Number, true);
       Asm->EOL("FDE address range");
-      
+
       // If there is a personality and landing pads then point to the language
       // specific data area in the exception table.
       if (EHFrameInfo.PersonalityIndex) {
         Asm->EmitULEB128Bytes(4);
         Asm->EOL("Augmentation size");
-        
-        if (EHFrameInfo.hasLandingPads) {
-          EmitReference("exception", EHFrameInfo.Number, true);
-        } else if (TD->getPointerSize() == 8) {
-          Asm->EmitInt64((int)0);
-        } else {
+
+        if (EHFrameInfo.hasLandingPads)
+          EmitReference("exception", EHFrameInfo.Number, true, true);
+        else
           Asm->EmitInt32((int)0);
-        }
         Asm->EOL("Language Specific Data Area");
       } else {
         Asm->EmitULEB128Bytes(0);
         Asm->EOL("Augmentation size");
       }
-      
+
       // Indicate locations of function specific  callee saved registers in
       // frame.
       EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, true);
       
-      Asm->EmitAlignment(2);
+      // On Darwin the linker honors the alignment of eh_frame, which means it
+      // must be 8-byte on 64-bit targets to match what gcc does.  Otherwise
+      // you get holes which confuse readers of eh_frame.
+      Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, 
+                         0, 0, false);
       EmitLabel("eh_frame_end", EHFrameInfo.Number);
-    }
     
-    if (const char *UsedDirective = TAI->getUsedDirective())
-      O << UsedDirective << EHFrameInfo.FnName << "\n\n";
+      // If the function is marked used, this table should be also.  We cannot 
+      // make the mark unconditional in this case, since retaining the table
+      // also retains the function in this case, and there is code around 
+      // that depends on unused functions (calling undefined externals) being
+      // dead-stripped to link correctly.  Yes, there really is.
+      if (MMI->getUsedFunctions().count(EHFrameInfo.function))
+        if (const char *UsedDirective = TAI->getUsedDirective())
+          O << UsedDirective << EHFrameInfo.FnName << "\n\n";
+    }
   }
 
   /// EmitExceptionTable - Emit landing pads and actions.
@@ -3022,9 +3134,6 @@ private:
   };
 
   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<unsigned> &FilterIds = MMI->getFilterIds();
     const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
@@ -3147,19 +3256,17 @@ private:
     // 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) {
-          SawPotentiallyThrowing |= TII->isCall(MI->getOpcode());
+          SawPotentiallyThrowing |= MI->getDesc().isCall();
           continue;
         }
 
-        unsigned BeginLabel = MI->getOperand(0).getImmedValue();
+        unsigned BeginLabel = MI->getOperand(0).getImm();
         assert(BeginLabel && "Invalid label!");
 
         // End of the previous try-range?
@@ -3223,13 +3330,20 @@ private:
     }
 
     // Final tallies.
-    unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start.
-                                             sizeof(int32_t) + // Site length.
-                                             sizeof(int32_t)); // Landing pad.
+
+    // Call sites.
+    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)
       SizeSites += Asm->SizeULEB128(CallSites[i].Action);
 
-    unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize();
+    // Type infos.
+    const unsigned TypeInfoSize = TD->getPointerSize(); // DW_EH_PE_absptr
+    unsigned SizeTypes = TypeInfos.size() * TypeInfoSize;
 
     unsigned TypeOffset = sizeof(int8_t) + // Call site format
                           Asm->SizeULEB128(SizeSites) + // Call-site table length
@@ -3245,7 +3359,7 @@ private:
     // Begin the exception table.
     Asm->SwitchToDataSection(TAI->getDwarfExceptionSection());
     O << "GCC_except_table" << SubprogramCount << ":\n";
-    Asm->EmitAlignment(2);
+    Asm->EmitAlignment(2, 0, 0, false);
     for (unsigned i = 0; i != SizeAlign; ++i) {
       Asm->EmitInt8(0);
       Asm->EOL("Padding");
@@ -3279,25 +3393,22 @@ private:
       }
 
       EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount,
-                        false, true);
+                        true, true);
       Asm->EOL("Region start");
 
       if (!S.EndLabel) {
-        EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber);
+        EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber,
+                       true);
       } else {
-        EmitDifference("label", S.EndLabel, BeginTag, BeginNumber);
+        EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true);
       }
       Asm->EOL("Region length");
 
-      if (!S.PadLabel) {
-        if (TD->getPointerSize() == sizeof(int32_t))
-          Asm->EmitInt32(0);
-        else
-          Asm->EmitInt64(0);
-      } else {
+      if (!S.PadLabel)
+        Asm->EmitInt32(0);
+      else
         EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount,
-                          false, true);
-      }
+                          true, true);
       Asm->EOL("Landing pad");
 
       Asm->EmitULEB128Bytes(S.Action);
@@ -3335,7 +3446,7 @@ private:
       Asm->EOL("Filter TypeInfo index");
     }
 
-    Asm->EmitAlignment(2);
+    Asm->EmitAlignment(2, 0, 0, false);
   }
 
 public:
@@ -3344,7 +3455,10 @@ public:
   //
   DwarfException(std::ostream &OS, AsmPrinter *A, const TargetAsmInfo *T)
   : Dwarf(OS, A, T, "eh")
-  , shouldEmit(false)
+  , shouldEmitTable(false)
+  , shouldEmitMoves(false)
+  , shouldEmitTableModule(false)
+  , shouldEmitMovesModule(false)
   {}
   
   virtual ~DwarfException() {}
@@ -3364,48 +3478,61 @@ public:
   /// EndModule - Emit all exception information that should come after the
   /// content.
   void EndModule() {
-    if (!shouldEmit) return;
-
-    const std::vector<Function *> Personalities = MMI->getPersonalities();
-    for (unsigned i =0; i < Personalities.size(); ++i)
-      EmitCommonEHFrame(Personalities[i], i);
-
-    for (std::vector<FunctionEHFrameInfo>::iterator I = EHFrames.begin(),
-           E = EHFrames.end(); I != E; ++I)
-      EmitEHFrame(*I);
+    if (shouldEmitMovesModule || shouldEmitTableModule) {
+      const std::vector<Function *> Personalities = MMI->getPersonalities();
+      for (unsigned i =0; i < Personalities.size(); ++i)
+        EmitCommonEHFrame(Personalities[i], i);
+
+      for (std::vector<FunctionEHFrameInfo>::iterator I = EHFrames.begin(),
+             E = EHFrames.end(); I != E; ++I)
+        EmitEHFrame(*I);
+    }
   }
 
   /// BeginFunction - Gather pre-function exception information.  Assumes being 
   /// emitted immediately after the function entry point.
   void BeginFunction(MachineFunction *MF) {
     this->MF = MF;
-    
-    if (MMI &&
-        ExceptionHandling &&
-        TAI->doesSupportExceptionHandling()) {
-      shouldEmit = true;
-      // Assumes in correct section after the entry point.
-      EmitLabel("eh_func_begin", ++SubprogramCount);
+    shouldEmitTable = shouldEmitMoves = false;
+    if (MMI && TAI->doesSupportExceptionHandling()) {
+
+      // Map all labels and get rid of any dead landing pads.
+      MMI->TidyLandingPads();
+      // If any landing pads survive, we need an EH table.
+      if (MMI->getLandingPads().size())
+        shouldEmitTable = true;
+
+      // See if we need frame move info.
+      if (MMI->hasDebugInfo() || 
+          !MF->getFunction()->doesNotThrow() ||
+          UnwindTablesMandatory)
+        shouldEmitMoves = true;
+
+      if (shouldEmitMoves || shouldEmitTable)
+        // Assumes in correct section after the entry point.
+        EmitLabel("eh_func_begin", ++SubprogramCount);
     }
+    shouldEmitTableModule |= shouldEmitTable;
+    shouldEmitMovesModule |= shouldEmitMoves;
   }
 
   /// EndFunction - Gather and emit post-function exception information.
   ///
   void EndFunction() {
-    if (!shouldEmit) return;
+    if (shouldEmitMoves || shouldEmitTable) {
+      EmitLabel("eh_func_end", SubprogramCount);
+      EmitExceptionTable();
 
-    EmitLabel("eh_func_end", SubprogramCount);
-    EmitExceptionTable();
-
-    // Save EH frame information
-    EHFrames.
-      push_back(FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF),
+      // Save EH frame information
+      EHFrames.
+        push_back(FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF),
                                     SubprogramCount,
                                     MMI->getPersonalityIndex(),
                                     MF->getFrameInfo()->hasCalls(),
                                     !MMI->getLandingPads().empty(),
                                     MMI->getFrameMoves(),
-                                    MF->getFunction()->getLinkage()));
+                                    MF->getFunction()));
+      }
   }
 };
 
@@ -3554,6 +3681,23 @@ unsigned DIEObjectLabel::SizeOf(const DwarfDebug &DD, unsigned Form) const {
     
 //===----------------------------------------------------------------------===//
 
+/// EmitValue - Emit delta value.
+///
+void DIESectionOffset::EmitValue(DwarfDebug &DD, unsigned Form) {
+  bool IsSmall = Form == DW_FORM_data4;
+  DD.EmitSectionOffset(Label.Tag, Section.Tag,
+                       Label.Number, Section.Number, IsSmall, IsEH, UseSet);
+}
+
+/// SizeOf - Determine size of delta value in bytes.
+///
+unsigned DIESectionOffset::SizeOf(const DwarfDebug &DD, unsigned Form) const {
+  if (Form == DW_FORM_data4) return 4;
+  return DD.getTargetData()->getPointerSize();
+}
+    
+//===----------------------------------------------------------------------===//
+
 /// EmitValue - Emit delta value.
 ///
 void DIEDelta::EmitValue(DwarfDebug &DD, unsigned Form) {