[llvm] r259868 - [MC] Add support for encoding CodeView variable definition ranges

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 4 17:55:50 PST 2016


Author: majnemer
Date: Thu Feb  4 19:55:49 2016
New Revision: 259868

URL: http://llvm.org/viewvc/llvm-project?rev=259868&view=rev
Log:
[MC] Add support for encoding CodeView variable definition ranges

CodeView, like most other debug formats, represents the live range of a
variable so that debuggers might print them out.

They use a variety of records to represent how a particular variable
might be available (in a register, in a frame pointer, etc.) along with
a set of ranges where this debug information is relevant.

However, the format only allows us to use ranges which are limited to a
maximum of 0xF000 in size.  This means that we need to split our debug
information into chunks of 0xF000.

Because the layout of code is not known until *very* late, we must use a
new fragment to record the information we need until we can know
*exactly* what the range is.

Added:
    llvm/trunk/test/MC/COFF/cv-def-range.s
Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h
    llvm/trunk/include/llvm/MC/MCAssembler.h
    llvm/trunk/include/llvm/MC/MCCodeView.h
    llvm/trunk/include/llvm/MC/MCFragment.h
    llvm/trunk/include/llvm/MC/MCObjectStreamer.h
    llvm/trunk/include/llvm/MC/MCStreamer.h
    llvm/trunk/lib/MC/MCAsmStreamer.cpp
    llvm/trunk/lib/MC/MCAssembler.cpp
    llvm/trunk/lib/MC/MCCodeView.cpp
    llvm/trunk/lib/MC/MCFragment.cpp
    llvm/trunk/lib/MC/MCObjectStreamer.cpp
    llvm/trunk/lib/MC/MCParser/AsmParser.cpp
    llvm/trunk/lib/MC/MCStreamer.cpp
    llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp
    llvm/trunk/test/MC/X86/reloc-directive.s

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h Thu Feb  4 19:55:49 2016
@@ -123,6 +123,8 @@ struct LocalVariableAddrGap {
   ulittle16_t Range;
 };
 
+enum : uint16_t { MaxDefRange = 0xf000 };
+
 // S_DEFRANGE
 struct DefRangeSym {
   ulittle32_t Program;

Modified: llvm/trunk/include/llvm/MC/MCAssembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAssembler.h?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCAssembler.h (original)
+++ llvm/trunk/include/llvm/MC/MCAssembler.h Thu Feb  4 19:55:49 2016
@@ -191,6 +191,7 @@ private:
                                    MCDwarfCallFrameFragment &DF);
   bool relaxCVInlineLineTable(MCAsmLayout &Layout,
                               MCCVInlineLineTableFragment &DF);
+  bool relaxCVDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &DF);
 
   /// finishLayout - Finalize a layout, including fragment lowering.
   void finishLayout(MCAsmLayout &Layout);

Modified: llvm/trunk/include/llvm/MC/MCCodeView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCCodeView.h?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCCodeView.h (original)
+++ llvm/trunk/include/llvm/MC/MCCodeView.h Thu Feb  4 19:55:49 2016
@@ -166,6 +166,13 @@ public:
   void encodeInlineLineTable(MCAsmLayout &Layout,
                              MCCVInlineLineTableFragment &F);
 
+  void
+  emitDefRange(MCObjectStreamer &OS,
+               ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+               StringRef FixedSizePortion);
+
+  void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F);
+
   /// Emits the string table substream.
   void emitStringTable(MCObjectStreamer &OS);
 

Modified: llvm/trunk/include/llvm/MC/MCFragment.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCFragment.h?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCFragment.h (original)
+++ llvm/trunk/include/llvm/MC/MCFragment.h Thu Feb  4 19:55:49 2016
@@ -41,6 +41,7 @@ public:
     FT_LEB,
     FT_SafeSEH,
     FT_CVInlineLines,
+    FT_CVDefRange,
     FT_Dummy
   };
 
@@ -211,7 +212,8 @@ public:
 
   static bool classof(const MCFragment *F) {
     MCFragment::FragmentType Kind = F->getKind();
-    return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data;
+    return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
+           Kind == MCFragment::FT_CVDefRange;
   }
 };
 
@@ -509,9 +511,7 @@ public:
       : MCFragment(FT_CVInlineLines, false, 0, Sec), SiteFuncId(SiteFuncId),
         StartFileId(StartFileId), StartLineNum(StartLineNum),
         FnStartSym(FnStartSym), FnEndSym(FnEndSym),
-        SecondaryFuncs(SecondaryFuncs.begin(), SecondaryFuncs.end()) {
-    Contents.push_back(0);
-  }
+        SecondaryFuncs(SecondaryFuncs.begin(), SecondaryFuncs.end()) {}
 
   /// \name Accessors
   /// @{
@@ -529,6 +529,37 @@ public:
   }
 };
 
+/// Fragment representing the .cv_def_range directive.
+class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
+  SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
+  SmallString<32> FixedSizePortion;
+
+  /// CodeViewContext has the real knowledge about this format, so let it access
+  /// our members.
+  friend class CodeViewContext;
+
+public:
+  MCCVDefRangeFragment(
+      ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+      StringRef FixedSizePortion, MCSection *Sec = nullptr)
+      : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
+        Ranges(Ranges.begin(), Ranges.end()),
+        FixedSizePortion(FixedSizePortion) {}
+
+  /// \name Accessors
+  /// @{
+  ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
+    return Ranges;
+  }
+
+  StringRef getFixedSizePortion() const { return FixedSizePortion; }
+  /// @}
+
+  static bool classof(const MCFragment *F) {
+    return F->getKind() == MCFragment::FT_CVDefRange;
+  }
+};
+
 } // end namespace llvm
 
 #endif

Modified: llvm/trunk/include/llvm/MC/MCObjectStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectStreamer.h?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCObjectStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h Thu Feb  4 19:55:49 2016
@@ -131,6 +131,9 @@ public:
       unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
       const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
       ArrayRef<unsigned> SecondaryFunctionIds) override;
+  void EmitCVDefRangeDirective(
+      ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+      StringRef FixedSizePortion) override;
   void EmitCVStringTableDirective() override;
   void EmitCVFileChecksumsDirective() override;
   void EmitGPRel32Value(const MCExpr *Value) override;

Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCStreamer.h Thu Feb  4 19:55:49 2016
@@ -662,6 +662,12 @@ public:
       const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
       ArrayRef<unsigned> SecondaryFunctionIds);
 
+  /// \brief This implements the CodeView '.cv_def_range' assembler
+  /// directive.
+  virtual void EmitCVDefRangeDirective(
+      ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+      StringRef FixedSizePortion);
+
   /// \brief This implements the CodeView '.cv_stringtable' assembler directive.
   virtual void EmitCVStringTableDirective() {}
 

Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Thu Feb  4 19:55:49 2016
@@ -209,6 +209,9 @@ public:
       unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
       const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
       ArrayRef<unsigned> SecondaryFunctionIds) override;
+  void EmitCVDefRangeDirective(
+      ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+      StringRef FixedSizePortion) override;
   void EmitCVStringTableDirective() override;
   void EmitCVFileChecksumsDirective() override;
 
@@ -1038,6 +1041,22 @@ void MCAsmStreamer::EmitCVInlineLinetabl
       SecondaryFunctionIds);
 }
 
+void MCAsmStreamer::EmitCVDefRangeDirective(
+    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+    StringRef FixedSizePortion) {
+  OS << "\t.cv_def_range\t";
+  for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
+    OS << ' ';
+    Range.first->print(OS, MAI);
+    OS << ' ';
+    Range.second->print(OS, MAI);
+  }
+  OS << ", ";
+  PrintQuotedString(FixedSizePortion, OS);
+  EmitEOL();
+  this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
+}
+
 void MCAsmStreamer::EmitCVStringTableDirective() {
   OS << "\t.cv_stringtable";
   EmitEOL();

Modified: llvm/trunk/lib/MC/MCAssembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAssembler.cpp?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAssembler.cpp (original)
+++ llvm/trunk/lib/MC/MCAssembler.cpp Thu Feb  4 19:55:49 2016
@@ -303,6 +303,8 @@ uint64_t MCAssembler::computeFragmentSiz
     return cast<MCDwarfCallFrameFragment>(F).getContents().size();
   case MCFragment::FT_CVInlineLines:
     return cast<MCCVInlineLineTableFragment>(F).getContents().size();
+  case MCFragment::FT_CVDefRange:
+    return cast<MCCVDefRangeFragment>(F).getContents().size();
   case MCFragment::FT_Dummy:
     llvm_unreachable("Should not have been added");
   }
@@ -545,6 +547,11 @@ static void writeFragment(const MCAssemb
     OW->writeBytes(OF.getContents());
     break;
   }
+  case MCFragment::FT_CVDefRange: {
+    const auto &DRF = cast<MCCVDefRangeFragment>(F);
+    OW->writeBytes(DRF.getContents());
+    break;
+  }
   case MCFragment::FT_Dummy:
     llvm_unreachable("Should not have been added");
   }
@@ -673,19 +680,24 @@ void MCAssembler::layout(MCAsmLayout &La
   // Evaluate and apply the fixups, generating relocation entries as necessary.
   for (MCSection &Sec : *this) {
     for (MCFragment &Frag : Sec) {
-      MCEncodedFragment *F = dyn_cast<MCEncodedFragment>(&Frag);
       // Data and relaxable fragments both have fixups.  So only process
       // those here.
       // FIXME: Is there a better way to do this?  MCEncodedFragmentWithFixups
       // being templated makes this tricky.
-      if (!F || isa<MCCompactEncodedInstFragment>(F))
+      if (isa<MCEncodedFragment>(&Frag) &&
+          isa<MCCompactEncodedInstFragment>(&Frag))
+        continue;
+      if (!isa<MCEncodedFragment>(&Frag) && !isa<MCCVDefRangeFragment>(&Frag))
         continue;
       ArrayRef<MCFixup> Fixups;
       MutableArrayRef<char> Contents;
-      if (auto *FragWithFixups = dyn_cast<MCDataFragment>(F)) {
+      if (auto *FragWithFixups = dyn_cast<MCDataFragment>(&Frag)) {
+        Fixups = FragWithFixups->getFixups();
+        Contents = FragWithFixups->getContents();
+      } else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(&Frag)) {
         Fixups = FragWithFixups->getFixups();
         Contents = FragWithFixups->getContents();
-      } else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(F)) {
+      } else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) {
         Fixups = FragWithFixups->getFixups();
         Contents = FragWithFixups->getContents();
       } else
@@ -693,7 +705,7 @@ void MCAssembler::layout(MCAsmLayout &La
       for (const MCFixup &Fixup : Fixups) {
         uint64_t FixedValue;
         bool IsPCRel;
-        std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup);
+        std::tie(FixedValue, IsPCRel) = handleFixup(Layout, Frag, Fixup);
         getBackend().applyFixup(Fixup, Contents.data(),
                                 Contents.size(), FixedValue, IsPCRel);
       }
@@ -828,6 +840,13 @@ bool MCAssembler::relaxCVInlineLineTable
   return OldSize != F.getContents().size();
 }
 
+bool MCAssembler::relaxCVDefRange(MCAsmLayout &Layout,
+                                  MCCVDefRangeFragment &F) {
+  unsigned OldSize = F.getContents().size();
+  getContext().getCVContext().encodeDefRange(Layout, F);
+  return OldSize != F.getContents().size();
+}
+
 bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) {
   // Holds the first fragment which needed relaxing during this layout. It will
   // remain NULL if none were relaxed.
@@ -863,6 +882,9 @@ bool MCAssembler::layoutSectionOnce(MCAs
       RelaxedFrag =
           relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I));
       break;
+    case MCFragment::FT_CVDefRange:
+      RelaxedFrag = relaxCVDefRange(Layout, *cast<MCCVDefRangeFragment>(I));
+      break;
     }
     if (RelaxedFrag && !FirstRelaxedFragment)
       FirstRelaxedFragment = &*I;

Modified: llvm/trunk/lib/MC/MCCodeView.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCCodeView.cpp?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCCodeView.cpp (original)
+++ llvm/trunk/lib/MC/MCCodeView.cpp Thu Feb  4 19:55:49 2016
@@ -19,6 +19,7 @@
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCValue.h"
 #include "llvm/Support/COFF.h"
 
 using namespace llvm;
@@ -236,6 +237,16 @@ void CodeViewContext::emitInlineLineTabl
       SecondaryFunctionIds, OS.getCurrentSectionOnly());
 }
 
+void CodeViewContext::emitDefRange(
+    MCObjectStreamer &OS,
+    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+    StringRef FixedSizePortion) {
+  // Create and insert a fragment into the current section that will be encoded
+  // later.
+  new MCCVDefRangeFragment(Ranges, FixedSizePortion,
+                           OS.getCurrentSectionOnly());
+}
+
 static unsigned computeLabelDiff(MCAsmLayout &Layout, const MCSymbol *Begin,
                                  const MCSymbol *End) {
   MCContext &Ctx = Layout.getAssembler().getContext();
@@ -352,6 +363,58 @@ void CodeViewContext::encodeInlineLineTa
   compressAnnotation(std::min(EndSymLength, LocAfterLength), Buffer);
 }
 
+void CodeViewContext::encodeDefRange(MCAsmLayout &Layout,
+                                     MCCVDefRangeFragment &Frag) {
+  MCContext &Ctx = Layout.getAssembler().getContext();
+  SmallVectorImpl<char> &Contents = Frag.getContents();
+  Contents.clear();
+  SmallVectorImpl<MCFixup> &Fixups = Frag.getFixups();
+  Fixups.clear();
+  raw_svector_ostream OS(Contents);
+
+  // Write down each range where the variable is defined.
+  for (std::pair<const MCSymbol *, const MCSymbol *> Range : Frag.getRanges()) {
+    unsigned RangeSize = computeLabelDiff(Layout, Range.first, Range.second);
+    unsigned Bias = 0;
+    // We must split the range into chunks of MaxDefRange, this is a fundamental
+    // limitation of the file format.
+    do {
+      uint16_t Chunk = std::min((uint32_t)MaxDefRange, RangeSize);
+
+      const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Range.first, Ctx);
+      const MCBinaryExpr *BE =
+          MCBinaryExpr::createAdd(SRE, MCConstantExpr::create(Bias, Ctx), Ctx);
+      MCValue Res;
+      BE->evaluateAsRelocatable(Res, &Layout, /*Fixup=*/nullptr);
+
+      // Each record begins with a 2-byte number indicating how large the record
+      // is.
+      StringRef FixedSizePortion = Frag.getFixedSizePortion();
+      // Our record is a fixed sized prefix and a LocalVariableAddrRange that we
+      // are artificially constructing.
+      size_t RecordSize =
+          FixedSizePortion.size() + sizeof(LocalVariableAddrRange);
+      // Write out the recrod size.
+      support::endian::Writer<support::little>(OS).write<uint16_t>(RecordSize);
+      // Write out the fixed size prefix.
+      OS << FixedSizePortion;
+      // Make space for a fixup that will eventually have a section relative
+      // relocation pointing at the offset where the variable becomes live.
+      Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_4));
+      Contents.resize(Contents.size() + 4); // Fixup for code start.
+      // Make space for a fixup that will record the section index for the code.
+      Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_2));
+      Contents.resize(Contents.size() + 2); // Fixup for section index.
+      // Write down the range's extent.
+      support::endian::Writer<support::little>(OS).write<uint16_t>(Chunk);
+
+      // Move on to the next range.
+      Bias += Chunk;
+      RangeSize -= Chunk;
+    } while (RangeSize > 0);
+  }
+}
+
 //
 // This is called when an instruction is assembled into the specified section
 // and if there is information from the last .cv_loc directive that has yet to have

Modified: llvm/trunk/lib/MC/MCFragment.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCFragment.cpp?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCFragment.cpp (original)
+++ llvm/trunk/lib/MC/MCFragment.cpp Thu Feb  4 19:55:49 2016
@@ -292,6 +292,9 @@ void MCFragment::destroy() {
     case FT_CVInlineLines:
       delete cast<MCCVInlineLineTableFragment>(this);
       return;
+    case FT_CVDefRange:
+      delete cast<MCCVDefRangeFragment>(this);
+      return;
     case FT_Dummy:
       delete cast<MCDummyFragment>(this);
       return;
@@ -331,6 +334,7 @@ LLVM_DUMP_METHOD void MCFragment::dump()
   case MCFragment::FT_LEB:   OS << "MCLEBFragment"; break;
   case MCFragment::FT_SafeSEH:    OS << "MCSafeSEHFragment"; break;
   case MCFragment::FT_CVInlineLines: OS << "MCCVInlineLineTableFragment"; break;
+  case MCFragment::FT_CVDefRange: OS << "MCCVDefRangeTableFragment"; break;
   case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break;
   }
 
@@ -435,6 +439,16 @@ LLVM_DUMP_METHOD void MCFragment::dump()
     OS << " Sym:" << *F->getFnStartSym();
     break;
   }
+  case MCFragment::FT_CVDefRange: {
+    const auto *F = cast<MCCVDefRangeFragment>(this);
+    OS << "\n       ";
+    for (std::pair<const MCSymbol *, const MCSymbol *> RangeStartEnd :
+         F->getRanges()) {
+      OS << " RangeStart:" << RangeStartEnd.first;
+      OS << " RangeEnd:" << RangeStartEnd.second;
+    }
+    break;
+  }
   case MCFragment::FT_Dummy:
     break;
   }

Modified: llvm/trunk/lib/MC/MCObjectStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectStreamer.cpp?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectStreamer.cpp Thu Feb  4 19:55:49 2016
@@ -396,6 +396,13 @@ void MCObjectStreamer::EmitCVInlineLinet
       SecondaryFunctionIds);
 }
 
+void MCObjectStreamer::EmitCVDefRangeDirective(
+    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+    StringRef FixedSizePortion) {
+  getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);
+  this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
+}
+
 void MCObjectStreamer::EmitCVStringTableDirective() {
   getContext().getCVContext().emitStringTable(*this);
 }

Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Thu Feb  4 19:55:49 2016
@@ -358,7 +358,7 @@ private:
     DK_IFNOTDEF, DK_ELSEIF, DK_ELSE, DK_ENDIF,
     DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS,
     DK_CV_FILE, DK_CV_LOC, DK_CV_LINETABLE, DK_CV_INLINE_LINETABLE,
-    DK_CV_STRINGTABLE, DK_CV_FILECHECKSUMS,
+    DK_CV_DEF_RANGE, DK_CV_STRINGTABLE, DK_CV_FILECHECKSUMS,
     DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA,
     DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER,
     DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA,
@@ -396,11 +396,13 @@ private:
   bool parseDirectiveLoc();
   bool parseDirectiveStabs();
 
-  // ".cv_file", ".cv_loc", ".cv_linetable", "cv_inline_linetable"
+  // ".cv_file", ".cv_loc", ".cv_linetable", "cv_inline_linetable",
+  // ".cv_def_range"
   bool parseDirectiveCVFile();
   bool parseDirectiveCVLoc();
   bool parseDirectiveCVLinetable();
   bool parseDirectiveCVInlineLinetable();
+  bool parseDirectiveCVDefRange();
   bool parseDirectiveCVStringTable();
   bool parseDirectiveCVFileChecksums();
 
@@ -1656,6 +1658,8 @@ bool AsmParser::parseStatement(ParseStat
       return parseDirectiveCVLinetable();
     case DK_CV_INLINE_LINETABLE:
       return parseDirectiveCVInlineLinetable();
+    case DK_CV_DEF_RANGE:
+      return parseDirectiveCVDefRange();
     case DK_CV_STRINGTABLE:
       return parseDirectiveCVStringTable();
     case DK_CV_FILECHECKSUMS:
@@ -3286,6 +3290,40 @@ bool AsmParser::parseDirectiveCVInlineLi
   return false;
 }
 
+/// parseDirectiveCVDefRange
+/// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
+bool AsmParser::parseDirectiveCVDefRange() {
+  SMLoc Loc;
+  std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
+  while (getLexer().is(AsmToken::Identifier)) {
+    Loc = getLexer().getLoc();
+    StringRef GapStartName;
+    if (parseIdentifier(GapStartName))
+      return Error(Loc, "expected identifier in directive");
+    MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName);
+
+    Loc = getLexer().getLoc();
+    StringRef GapEndName;
+    if (parseIdentifier(GapEndName))
+      return Error(Loc, "expected identifier in directive");
+    MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName);
+
+    Ranges.push_back({GapStartSym, GapEndSym});
+  }
+
+  if (getLexer().isNot(AsmToken::Comma))
+    return TokError("unexpected token in directive");
+  Lex();
+
+  std::string FixedSizePortion;
+  if (parseEscapedString(FixedSizePortion))
+    return true;
+  Lex();
+
+  getStreamer().EmitCVDefRangeDirective(Ranges, FixedSizePortion);
+  return false;
+}
+
 /// parseDirectiveCVStringTable
 /// ::= .cv_stringtable
 bool AsmParser::parseDirectiveCVStringTable() {
@@ -4615,6 +4653,7 @@ void AsmParser::initializeDirectiveKindM
   DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
   DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
   DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
+  DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
   DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
   DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
   DirectiveKindMap[".sleb128"] = DK_SLEB128;

Modified: llvm/trunk/lib/MC/MCStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCStreamer.cpp Thu Feb  4 19:55:49 2016
@@ -201,6 +201,10 @@ void MCStreamer::EmitCVInlineLinetableDi
     const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
     ArrayRef<unsigned> SecondaryFunctionIds) {}
 
+void MCStreamer::EmitCVDefRangeDirective(
+    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
+    StringRef FixedSizePortion) {}
+
 void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
                                      MCSymbol *EHSymbol) {
 }

Modified: llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp Thu Feb  4 19:55:49 2016
@@ -785,6 +785,10 @@ void WinCOFFObjectWriter::recordRelocati
     }
   }
 
+  // The fixed value never makes sense for section indicies, ignore it.
+  if (Fixup.getKind() == FK_SecRel_2)
+    FixedValue = 0;
+
   if (TargetObjectWriter->recordRelocation(Fixup))
     coff_section->Relocations.push_back(Reloc);
 }

Added: llvm/trunk/test/MC/COFF/cv-def-range.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-def-range.s?rev=259868&view=auto
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-def-range.s (added)
+++ llvm/trunk/test/MC/COFF/cv-def-range.s Thu Feb  4 19:55:49 2016
@@ -0,0 +1,97 @@
+# RUN: llvm-mc -triple=i686-pc-win32 -filetype=obj < %s | llvm-readobj -codeview -codeview-subsection-bytes | FileCheck %s
+	.text
+	.def	 @feat.00;
+	.scl	3;
+	.type	0;
+	.endef
+	.globl	@feat.00
+ at feat.00 = 1
+	.def	 _g;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	_g
+	.p2align	4, 0x90
+_g:                                     # @g
+Lfunc_begin0:
+	.cv_file	1 "\\usr\\local\\google\\home\\majnemer\\llvm\\src\\<stdin>"
+	.cv_loc	0 1 3 0 is_stmt 0       # <stdin>:3:0
+# BB#0:                                 # %entry
+	pushl	%ebp
+	movl	%esp, %ebp
+	subl	$8, %esp
+	leal	-4(%ebp), %eax
+Lvar_begin0:
+	#DEBUG_VALUE: g:x <- %EAX
+	.cv_loc	0 1 4 7                 # <stdin>:4:7
+	movl	$0, -4(%ebp)
+	.cv_loc	0 1 5 3                 # <stdin>:5:3
+	movl	%eax, (%esp)
+	calll	_f
+	.cv_loc	0 1 6 1                 # <stdin>:6:1
+Lvar_end0:
+	addl	$8, %esp
+	popl	%ebp
+	retl
+Lfunc_end0:
+
+	.section	.debug$T,"dr"
+	.long	4                       # Debug section magic
+	.short	6                       # Type record length
+	.short	4609                    # Leaf type: LF_ARGLIST
+	.long	0                       # Number of arguments
+	.short	14                      # Type record length
+	.short	4104                    # Leaf type: LF_PROCEDURE
+	.long	3                       # Return type index
+	.byte	0                       # Calling convention
+	.byte	0                       # Function options
+	.short	0                       # # of parameters
+	.long	4096                    # Argument list type index
+	.short	12                      # Type record length
+	.short	5633                    # Leaf type: LF_FUNC_ID
+	.long	0                       # Scope type index
+	.long	4097                    # Function type
+	.asciz	"g"                     # Function name
+	.section	.debug$S,"dr"
+	.long	4                       # Debug section magic
+	.long	241                     # Symbol subsection for g
+	.long	Ltmp1-Ltmp0             # Subsection size
+Ltmp0:
+	.short	Ltmp3-Ltmp2             # Record length
+Ltmp2:
+	.short	4423                    # Record kind: S_GPROC32_ID
+	.long	0                       # PtrParent
+	.long	0                       # PtrEnd
+	.long	0                       # PtrNext
+	.long	Lfunc_end0-_g           # Code size
+	.long	0                       # Offset after prologue
+	.long	0                       # Offset before epilogue
+	.long	0                       # Function type index
+	.secrel32	_g              # Function section relative address
+	.secidx	_g                      # Function section index
+	.byte	0                       # Flags
+	.asciz	"g"                     # Function name
+Ltmp3:
+	.short	2                       # Record length
+	.short	4431                    # Record kind: S_PROC_ID_END
+	.cv_def_range	Lvar_begin0 Lvar_end0, "\102\021\374\377\377\377"
+
+# CHECK:    DefRangeFramePointerRel {
+# CHECK:      Offset: -4
+# CHECK:      LocalVariableAddrRange {
+# CHECK:        OffsetStart: .text+0x9
+# CHECK:        ISectStart: 0x0
+# CHECK:        Range: 15
+# CHECK:      }
+# CHECK:    }
+# CHECK:    BlockRelocations [
+# CHECK:      0x4 IMAGE_REL_I386_SECREL .text
+# CHECK:      0x8 IMAGE_REL_I386_SECTION .text
+# CHECK:    ]
+
+Ltmp1:
+	.p2align	2
+	.cv_linetable	0, _g, Lfunc_end0
+	.cv_filechecksums               # File index to string table offset subsection
+	.cv_stringtable                 # String table
+

Modified: llvm/trunk/test/MC/X86/reloc-directive.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/reloc-directive.s?rev=259868&r1=259867&r2=259868&view=diff
==============================================================================
--- llvm/trunk/test/MC/X86/reloc-directive.s (original)
+++ llvm/trunk/test/MC/X86/reloc-directive.s Thu Feb  4 19:55:49 2016
@@ -20,7 +20,7 @@ foo:
 	.reloc 16, dir32,   foo at imgrel   # ASM: .reloc 16, dir32, foo at IMGREL
 
 # OBJ-32-LABEL: Name: .text
-# OBJ-32:       0000: 04000000 00000000 08000000
+# OBJ-32:       0000: 04000000 00000000 00000000
 # OBJ-32-LABEL: }
 # OBJ-32-LABEL: Relocations [
 # OBJ-32:       0x4  IMAGE_REL_I386_DIR32   foo
@@ -30,7 +30,7 @@ foo:
 # OBJ-32:       0x10 IMAGE_REL_I386_DIR32NB foo
 
 # OBJ-64-LABEL: Name: .text
-# OBJ-64:       0000: 04000000 00000000 08000000
+# OBJ-64:       0000: 04000000 00000000 00000000
 # OBJ-64-LABEL: }
 # OBJ-64-LABEL: Relocations [
 # OBJ-64:       0x4  IMAGE_REL_AMD64_ADDR32   foo




More information about the llvm-commits mailing list