summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2016-02-05 01:55:49 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2016-02-05 01:55:49 +0000
commit408b5e660300f96d9a231ba0e18e75d8e69d17bb (patch)
treee9209cea4a29570a15cbcdb349cf6413b453e3aa
parentadc2376375f32b96daa8c548b11237738945f623 (diff)
downloadbcm5719-llvm-408b5e660300f96d9a231ba0e18e75d8e69d17bb.tar.gz
bcm5719-llvm-408b5e660300f96d9a231ba0e18e75d8e69d17bb.zip
[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. llvm-svn: 259868
-rw-r--r--llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h2
-rw-r--r--llvm/include/llvm/MC/MCAssembler.h1
-rw-r--r--llvm/include/llvm/MC/MCCodeView.h7
-rw-r--r--llvm/include/llvm/MC/MCFragment.h39
-rw-r--r--llvm/include/llvm/MC/MCObjectStreamer.h3
-rw-r--r--llvm/include/llvm/MC/MCStreamer.h6
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp19
-rw-r--r--llvm/lib/MC/MCAssembler.cpp32
-rw-r--r--llvm/lib/MC/MCCodeView.cpp63
-rw-r--r--llvm/lib/MC/MCFragment.cpp14
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp7
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp43
-rw-r--r--llvm/lib/MC/MCStreamer.cpp4
-rw-r--r--llvm/lib/MC/WinCOFFObjectWriter.cpp4
-rw-r--r--llvm/test/MC/COFF/cv-def-range.s97
-rw-r--r--llvm/test/MC/X86/reloc-directive.s4
16 files changed, 332 insertions, 13 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h
index c01b7baa2aa..5af97f57b83 100644
--- a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h
+++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h
@@ -123,6 +123,8 @@ struct LocalVariableAddrGap {
ulittle16_t Range;
};
+enum : uint16_t { MaxDefRange = 0xf000 };
+
// S_DEFRANGE
struct DefRangeSym {
ulittle32_t Program;
diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h
index 3ad31dca22c..f15b9af3051 100644
--- a/llvm/include/llvm/MC/MCAssembler.h
+++ b/llvm/include/llvm/MC/MCAssembler.h
@@ -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);
diff --git a/llvm/include/llvm/MC/MCCodeView.h b/llvm/include/llvm/MC/MCCodeView.h
index 22cf94f45c7..d999ff55599 100644
--- a/llvm/include/llvm/MC/MCCodeView.h
+++ b/llvm/include/llvm/MC/MCCodeView.h
@@ -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);
diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h
index a7548be6a97..e0a2bfc2374 100644
--- a/llvm/include/llvm/MC/MCFragment.h
+++ b/llvm/include/llvm/MC/MCFragment.h
@@ -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
diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h
index 6a4ee8c363c..7123072a5e3 100644
--- a/llvm/include/llvm/MC/MCObjectStreamer.h
+++ b/llvm/include/llvm/MC/MCObjectStreamer.h
@@ -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;
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 8c4d4eef506..c0177c18361 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -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() {}
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 9fcfcf76756..c615752808c 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -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::EmitCVInlineLinetableDirective(
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();
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index 9a55ef3931e..ca8ccb40e09 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -303,6 +303,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
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 MCAssembler &Asm, const MCAsmLayout &Layout,
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 &Layout) {
// 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 &Layout) {
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(MCAsmLayout &Layout,
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(MCAsmLayout &Layout, MCSection &Sec) {
RelaxedFrag =
relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I));
break;
+ case MCFragment::FT_CVDefRange:
+ RelaxedFrag = relaxCVDefRange(Layout, *cast<MCCVDefRangeFragment>(I));
+ break;
}
if (RelaxedFrag && !FirstRelaxedFragment)
FirstRelaxedFragment = &*I;
diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp
index f50fdab8dfa..029bab1f7f8 100644
--- a/llvm/lib/MC/MCCodeView.cpp
+++ b/llvm/lib/MC/MCCodeView.cpp
@@ -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::emitInlineLineTableForFunction(
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::encodeInlineLineTable(MCAsmLayout &Layout,
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
diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp
index bfadfda47f2..b9889049b22 100644
--- a/llvm/lib/MC/MCFragment.cpp
+++ b/llvm/lib/MC/MCFragment.cpp
@@ -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;
}
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 40c2e8dab9f..b90f0a80cfe 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -396,6 +396,13 @@ void MCObjectStreamer::EmitCVInlineLinetableDirective(
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);
}
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 2db7504b377..1332ef4cde9 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -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(ParseStatementInfo &Info,
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::parseDirectiveCVInlineLinetable() {
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::initializeDirectiveKindMap() {
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;
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index 8ee41261d59..663ed8326ee 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -201,6 +201,10 @@ void MCStreamer::EmitCVInlineLinetableDirective(
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) {
}
diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 825e488755b..dd7adbf3ead 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -785,6 +785,10 @@ void WinCOFFObjectWriter::recordRelocation(
}
}
+ // 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);
}
diff --git a/llvm/test/MC/COFF/cv-def-range.s b/llvm/test/MC/COFF/cv-def-range.s
new file mode 100644
index 00000000000..781275d209f
--- /dev/null
+++ b/llvm/test/MC/COFF/cv-def-range.s
@@ -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
+@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
+
diff --git a/llvm/test/MC/X86/reloc-directive.s b/llvm/test/MC/X86/reloc-directive.s
index 0cc96b3d741..901427a6ab6 100644
--- a/llvm/test/MC/X86/reloc-directive.s
+++ b/llvm/test/MC/X86/reloc-directive.s
@@ -20,7 +20,7 @@ foo:
.reloc 16, dir32, foo@imgrel # ASM: .reloc 16, dir32, foo@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
OpenPOWER on IntegriCloud