summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorScott Linder <scott@scottlinder.com>2018-02-23 23:01:06 +0000
committerScott Linder <scott@scottlinder.com>2018-02-23 23:01:06 +0000
commit16c7bdaf3245d23b9b441144f5efb610e2044927 (patch)
tree870f3b5c5c606b19951cb4433f3887825bc61e56 /llvm/lib
parent5e2f6ba51e89c9b9625902f0c36493ad46e46a3b (diff)
downloadbcm5719-llvm-16c7bdaf3245d23b9b441144f5efb610e2044927.tar.gz
bcm5719-llvm-16c7bdaf3245d23b9b441144f5efb610e2044927.zip
[DebugInfo] Support DWARF v5 source code embedding extension
In DWARF v5 the Line Number Program Header is extensible, allowing values with new content types. In this extension a content type is added, DW_LNCT_LLVM_source, which contains the embedded source code of the file. Add new optional attribute for !DIFile IR metadata called source which contains source text. Use this to output the source to the DWARF line table of code objects. Analogously extend METADATA_FILE in Bitcode and .file directive in ASM to support optional source. Teach llvm-dwarfdump and llvm-objdump about the new values. Update the output format of llvm-dwarfdump to make room for the new attribute on file_names entries, and support embedded sources for the -source option in llvm-objdump. Differential Revision: https://reviews.llvm.org/D42765 llvm-svn: 325970
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp13
-rw-r--r--llvm/lib/Bitcode/Reader/MetadataLoader.cpp9
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp3
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp5
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp6
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp4
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFContext.cpp4
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp98
-rw-r--r--llvm/lib/IR/AsmWriter.cpp2
-rw-r--r--llvm/lib/IR/DIBuilder.cpp6
-rw-r--r--llvm/lib/IR/DebugInfoMetadata.cpp11
-rw-r--r--llvm/lib/IR/LLVMContextImpl.h18
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp10
-rw-r--r--llvm/lib/MC/MCContext.cpp6
-rw-r--r--llvm/lib/MC/MCDwarf.cpp51
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp48
-rw-r--r--llvm/lib/MC/MCStreamer.cpp8
17 files changed, 215 insertions, 87 deletions
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index d5714ea1885..42c579878c1 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4243,9 +4243,10 @@ bool LLParser::ParseDISubroutineType(MDNode *&Result, bool IsDistinct) {
}
/// ParseDIFileType:
-/// ::= !DIFileType(filename: "path/to/file", directory: "/path/to/dir"
+/// ::= !DIFileType(filename: "path/to/file", directory: "/path/to/dir",
/// checksumkind: CSK_MD5,
-/// checksum: "000102030405060708090a0b0c0d0e0f")
+/// checksum: "000102030405060708090a0b0c0d0e0f",
+/// source: "source file contents")
bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) {
// The default constructed value for checksumkind is required, but will never
// be used, as the parser checks if the field was actually Seen before using
@@ -4254,7 +4255,8 @@ bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) {
REQUIRED(filename, MDStringField, ); \
REQUIRED(directory, MDStringField, ); \
OPTIONAL(checksumkind, ChecksumKindField, (DIFile::CSK_MD5)); \
- OPTIONAL(checksum, MDStringField, );
+ OPTIONAL(checksum, MDStringField, ); \
+ OPTIONAL(source, MDStringField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
@@ -4264,8 +4266,11 @@ bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) {
else if (checksumkind.Seen || checksum.Seen)
return Lex.Error("'checksumkind' and 'checksum' must be provided together");
+ Optional<MDString *> OptSource;
+ if (source.Seen)
+ OptSource = source.Val;
Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val,
- OptChecksum));
+ OptChecksum, OptSource));
return false;
}
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 0931192cd18..efaee21a8d8 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1350,7 +1350,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
}
case bitc::METADATA_FILE: {
- if (Record.size() != 3 && Record.size() != 5)
+ if (Record.size() != 3 && Record.size() != 5 && Record.size() != 6)
return error("Invalid record");
IsDistinct = Record[0];
@@ -1360,14 +1360,15 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
// and the old encoding for CSK_None in the ChecksumKind. The new
// representation reserves the value 0 in the ChecksumKind to continue to
// encode None in a backwards-compatible way.
- if (Record.size() == 5 && Record[3] && Record[4])
+ if (Record.size() > 4 && Record[3] && Record[4])
Checksum.emplace(static_cast<DIFile::ChecksumKind>(Record[3]),
getMDString(Record[4]));
MetadataList.assignValue(
GET_OR_DISTINCT(
DIFile,
- (Context, getMDString(Record[1]), getMDString(Record[2]),
- Checksum)),
+ (Context, getMDString(Record[1]), getMDString(Record[2]), Checksum,
+ Record.size() > 5 ? Optional<MDString *>(getMDString(Record[5]))
+ : None)),
NextMetadataNo);
NextMetadataNo++;
break;
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 832f494bc77..0738b907be3 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1560,6 +1560,9 @@ void ModuleBitcodeWriter::writeDIFile(const DIFile *N,
Record.push_back(0);
Record.push_back(VE.getMetadataOrNullID(nullptr));
}
+ auto Source = N->getRawSource();
+ if (Source)
+ Record.push_back(VE.getMetadataOrNullID(*Source));
Stream.EmitRecord(bitc::METADATA_FILE, Record, Abbrev);
Record.clear();
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index dcc3e55a52e..0b2a0469f8c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -102,9 +102,10 @@ unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) {
// extend .file to support this.
unsigned CUID = Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID();
if (!File)
- return Asm->OutStreamer->EmitDwarfFileDirective(0, "", "", nullptr, CUID);
+ return Asm->OutStreamer->EmitDwarfFileDirective(0, "", "", nullptr, None, CUID);
return Asm->OutStreamer->EmitDwarfFileDirective(
- 0, File->getDirectory(), File->getFilename(), getMD5AsBytes(File), CUID);
+ 0, File->getDirectory(), File->getFilename(), getMD5AsBytes(File),
+ File->getSource(), CUID);
}
DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 99ed096d132..6b50fb94d0e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1384,7 +1384,7 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
unsigned Flags) {
StringRef Fn;
- unsigned Src = 1;
+ unsigned FileNo = 1;
unsigned Discriminator = 0;
if (auto *Scope = cast_or_null<DIScope>(S)) {
Fn = Scope->getFilename();
@@ -1393,10 +1393,10 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
Discriminator = LBF->getDiscriminator();
unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID();
- Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
+ FileNo = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
.getOrCreateSourceID(Scope->getFile());
}
- Asm->OutStreamer->EmitDwarfLocDirective(Src, Line, Col, Flags, 0,
+ Asm->OutStreamer->EmitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
Discriminator, Fn);
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index d7d5298d673..377e557f637 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -302,7 +302,9 @@ MD5::MD5Result *DwarfUnit::getMD5AsBytes(const DIFile *File) {
unsigned DwarfTypeUnit::getOrCreateSourceID(const DIFile *File) {
return SplitLineTable
? SplitLineTable->getFile(File->getDirectory(),
- File->getFilename(), getMD5AsBytes(File))
+ File->getFilename(),
+ getMD5AsBytes(File),
+ File->getSource())
: getCU().getOrCreateSourceID(File);
}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index ef097265e04..de7ef662afb 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -466,7 +466,9 @@ void DWARFContext::dump(
uint32_t offset = 0;
uint32_t strOffset = 0;
while (const char *s = strData.getCStr(&offset)) {
- OS << format("0x%8.8x: \"%s\"\n", strOffset, s);
+ OS << format("0x%8.8x: \"", strOffset);
+ OS.write_escaped(s);
+ OS << "\"\n";
strOffset = offset;
}
}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
index 8986af26c03..56e7af24af5 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -40,6 +41,28 @@ using ContentDescriptors = SmallVector<ContentDescriptor, 4>;
} // end anonmyous namespace
+void DWARFDebugLine::ContentTypeTracker::trackContentType(
+ dwarf::LineNumberEntryFormat ContentType) {
+ switch (ContentType) {
+ case dwarf::DW_LNCT_timestamp:
+ HasModTime = true;
+ break;
+ case dwarf::DW_LNCT_size:
+ HasLength = true;
+ break;
+ case dwarf::DW_LNCT_MD5:
+ HasMD5 = true;
+ break;
+ case dwarf::DW_LNCT_LLVM_source:
+ HasSource = true;
+ break;
+ default:
+ // We only care about values we consider optional, and new values may be
+ // added in the vendor extension range, so we do not match exhaustively.
+ break;
+ }
+}
+
DWARFDebugLine::Prologue::Prologue() { clear(); }
void DWARFDebugLine::Prologue::clear() {
@@ -48,7 +71,7 @@ void DWARFDebugLine::Prologue::clear() {
MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
OpcodeBase = 0;
FormParams = DWARFFormParams({0, 0, DWARF32});
- HasMD5 = false;
+ ContentTypes = ContentTypeTracker();
StandardOpcodeLengths.clear();
IncludeDirectories.clear();
FileNames.clear();
@@ -85,28 +108,26 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
}
if (!FileNames.empty()) {
- if (HasMD5)
- OS << " Dir MD5 Checksum File Name\n"
- << " ---- -------------------------------- -----------"
- "---------------\n";
- else
- OS << " Dir Mod Time File Len File Name\n"
- << " ---- ---------- ---------- -----------"
- "----------------\n";
// DWARF v5 starts file indexes at 0.
uint32_t FileBase = getVersion() >= 5 ? 0 : 1;
for (uint32_t I = 0; I != FileNames.size(); ++I) {
const FileNameEntry &FileEntry = FileNames[I];
- OS << format("file_names[%3u] %4" PRIu64 " ", I + FileBase,
- FileEntry.DirIdx);
- if (HasMD5)
- OS << FileEntry.Checksum.digest();
- else
- OS << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64, FileEntry.ModTime,
- FileEntry.Length);
- OS << ' ';
+ OS << format("file_names[%3u]:\n", I + FileBase);
+ OS << " name: ";
FileEntry.Name.dump(OS, DumpOptions);
- OS << '\n';
+ OS << '\n'
+ << format(" dir_index: %" PRIu64 "\n", FileEntry.DirIdx);
+ if (ContentTypes.HasMD5)
+ OS << " md5_checksum: " << FileEntry.Checksum.digest() << '\n';
+ if (ContentTypes.HasModTime)
+ OS << format(" mod_time: 0x%8.8" PRIx64 "\n", FileEntry.ModTime);
+ if (ContentTypes.HasLength)
+ OS << format(" length: 0x%8.8" PRIx64 "\n", FileEntry.Length);
+ if (ContentTypes.HasSource) {
+ OS << " source: ";
+ FileEntry.Source.dump(OS, DumpOptions);
+ OS << '\n';
+ }
}
}
}
@@ -115,6 +136,7 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
static void
parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,
uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
+ DWARFDebugLine::ContentTypeTracker &ContentTypes,
std::vector<DWARFFormValue> &IncludeDirectories,
std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
while (*OffsetPtr < EndPrologueOffset) {
@@ -138,14 +160,18 @@ parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,
FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
FileNames.push_back(FileEntry);
}
+
+ ContentTypes.HasModTime = true;
+ ContentTypes.HasLength = true;
}
// Parse v5 directory/file entry content descriptions.
// Returns the descriptors, or an empty vector if we did not find a path or
// ran off the end of the prologue.
static ContentDescriptors
-parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
- uint64_t EndPrologueOffset, bool *HasMD5) {
+parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t
+ *OffsetPtr, uint64_t EndPrologueOffset, DWARFDebugLine::ContentTypeTracker
+ *ContentTypes) {
ContentDescriptors Descriptors;
int FormatCount = DebugLineData.getU8(OffsetPtr);
bool HasPath = false;
@@ -158,8 +184,8 @@ parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr));
if (Descriptor.Type == dwarf::DW_LNCT_path)
HasPath = true;
- else if (Descriptor.Type == dwarf::DW_LNCT_MD5 && HasMD5)
- *HasMD5 = true;
+ if (ContentTypes)
+ ContentTypes->trackContentType(Descriptor.Type);
Descriptors.push_back(Descriptor);
}
return HasPath ? Descriptors : ContentDescriptors();
@@ -168,8 +194,9 @@ parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
static bool
parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
- const DWARFFormParams &FormParams, const DWARFContext &Ctx,
- const DWARFUnit *U, bool &HasMD5,
+ const DWARFFormParams &FormParams, const DWARFContext
+ &Ctx, const DWARFUnit *U,
+ DWARFDebugLine::ContentTypeTracker &ContentTypes,
std::vector<DWARFFormValue> &IncludeDirectories,
std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
// Get the directory entry description.
@@ -200,7 +227,8 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
// Get the file entry description.
ContentDescriptors FileDescriptors =
- parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, &HasMD5);
+ parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset,
+ &ContentTypes);
if (FileDescriptors.empty())
return false;
@@ -218,6 +246,9 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
case DW_LNCT_path:
FileEntry.Name = Value;
break;
+ case DW_LNCT_LLVM_source:
+ FileEntry.Source = Value;
+ break;
case DW_LNCT_directory_index:
FileEntry.DirIdx = Value.getAsUnsignedConstant().getValue();
break;
@@ -285,8 +316,8 @@ bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
if (getVersion() >= 5) {
if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
- FormParams, Ctx, U, HasMD5, IncludeDirectories,
- FileNames)) {
+ FormParams, Ctx, U, ContentTypes,
+ IncludeDirectories, FileNames)) {
fprintf(stderr,
"warning: parsing line table prologue at 0x%8.8" PRIx64
" found an invalid directory or file table description at"
@@ -295,7 +326,7 @@ bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
}
} else
parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
- IncludeDirectories, FileNames);
+ ContentTypes, IncludeDirectories, FileNames);
if (*OffsetPtr != EndPrologueOffset) {
fprintf(stderr,
@@ -912,6 +943,16 @@ bool DWARFDebugLine::LineTable::hasFileAtIndex(uint64_t FileIndex) const {
return FileIndex != 0 && FileIndex <= Prologue.FileNames.size();
}
+Optional<StringRef> DWARFDebugLine::LineTable::getSourceByIndex(uint64_t FileIndex,
+ FileLineInfoKind Kind) const {
+ if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
+ return None;
+ const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
+ if (Optional<const char *> source = Entry.Source.getAsCString())
+ return StringRef(*source);
+ return None;
+}
+
bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
const char *CompDir,
FileLineInfoKind Kind,
@@ -963,5 +1004,6 @@ bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
Result.Line = Row.Line;
Result.Column = Row.Column;
Result.Discriminator = Row.Discriminator;
+ Result.Source = getSourceByIndex(Row.File, Kind);
return true;
}
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 5a02cf39c1b..ae24040a600 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1723,6 +1723,8 @@ static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *,
// Print all values for checksum together, or not at all.
if (N->getChecksum())
Printer.printChecksum(*N->getChecksum());
+ Printer.printString("source", N->getSource().getValueOr(StringRef()),
+ /* ShouldSkipEmpty */ true);
Out << ")";
}
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 8cb95d2871d..3e5ecdc2091 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -14,6 +14,7 @@
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "LLVMContextImpl.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/Constants.h"
@@ -204,8 +205,9 @@ DIImportedEntity *DIBuilder::createImportedDeclaration(DIScope *Context,
}
DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory,
- Optional<DIFile::ChecksumInfo<StringRef>> CS) {
- return DIFile::get(VMContext, Filename, Directory, CS);
+ Optional<DIFile::ChecksumInfo<StringRef>> CS,
+ Optional<StringRef> Source) {
+ return DIFile::get(VMContext, Filename, Directory, CS, Source);
}
DIMacro *DIBuilder::createMacro(DIMacroFile *Parent, unsigned LineNumber,
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 82f04a65618..c1a9f3f6929 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -417,13 +417,16 @@ Optional<DIFile::ChecksumKind> DIFile::getChecksumKind(StringRef CSKindStr) {
DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,
MDString *Directory,
Optional<DIFile::ChecksumInfo<MDString *>> CS,
- StorageType Storage, bool ShouldCreate) {
+ Optional<MDString *> Source, StorageType Storage,
+ bool ShouldCreate) {
assert(isCanonical(Filename) && "Expected canonical MDString");
assert(isCanonical(Directory) && "Expected canonical MDString");
assert((!CS || isCanonical(CS->Value)) && "Expected canonical MDString");
- DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS));
- Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr};
- DEFINE_GETIMPL_STORE(DIFile, (CS), Ops);
+ assert((!Source || isCanonical(*Source)) && "Expected canonical MDString");
+ DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS, Source));
+ Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr,
+ Source.getValueOr(nullptr)};
+ DEFINE_GETIMPL_STORE(DIFile, (CS, Source), Ops);
}
DICompileUnit *DICompileUnit::getImpl(
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 313b7e16bec..1f2956d54ed 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -575,24 +575,28 @@ template <> struct MDNodeKeyImpl<DIFile> {
MDString *Filename;
MDString *Directory;
Optional<DIFile::ChecksumInfo<MDString *>> Checksum;
+ Optional<MDString *> Source;
MDNodeKeyImpl(MDString *Filename, MDString *Directory,
- Optional<DIFile::ChecksumInfo<MDString *>> Checksum)
- : Filename(Filename), Directory(Directory), Checksum(Checksum) {}
+ Optional<DIFile::ChecksumInfo<MDString *>> Checksum,
+ Optional<MDString *> Source)
+ : Filename(Filename), Directory(Directory), Checksum(Checksum),
+ Source(Source) {}
MDNodeKeyImpl(const DIFile *N)
: Filename(N->getRawFilename()), Directory(N->getRawDirectory()),
- Checksum(N->getRawChecksum()) {}
+ Checksum(N->getRawChecksum()), Source(N->getRawSource()) {}
bool isKeyOf(const DIFile *RHS) const {
return Filename == RHS->getRawFilename() &&
Directory == RHS->getRawDirectory() &&
- Checksum == RHS->getRawChecksum();
+ Checksum == RHS->getRawChecksum() &&
+ Source == RHS->getRawSource();
}
unsigned getHashValue() const {
- if (Checksum)
- return hash_combine(Filename, Directory, Checksum->Kind, Checksum->Value);
- return hash_combine(Filename, Directory);
+ return hash_combine(
+ Filename, Directory, Checksum ? Checksum->Kind : 0,
+ Checksum ? Checksum->Value : nullptr, Source.getValueOr(nullptr));
}
};
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 7ea5b7677b8..f254cb50b60 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
@@ -215,6 +216,7 @@ public:
StringRef Directory,
StringRef Filename,
MD5::MD5Result *Checksum = 0,
+ Optional<StringRef> Source = None,
unsigned CUID = 0) override;
void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
@@ -1076,13 +1078,13 @@ void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
unsigned FileNo, StringRef Directory, StringRef Filename,
- MD5::MD5Result *Checksum, unsigned CUID) {
+ MD5::MD5Result *Checksum, Optional<StringRef> Source, unsigned CUID) {
assert(CUID == 0);
MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
unsigned NumFiles = Table.getMCDwarfFiles().size();
Expected<unsigned> FileNoOrErr =
- Table.tryGetFile(Directory, Filename, Checksum, FileNo);
+ Table.tryGetFile(Directory, Filename, Checksum, Source, FileNo);
if (!FileNoOrErr)
return FileNoOrErr.takeError();
FileNo = FileNoOrErr.get();
@@ -1114,6 +1116,10 @@ Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
OS1 << " md5 ";
PrintQuotedString(Checksum->digest(), OS1);
}
+ if (Source) {
+ OS1 << " source ";
+ PrintQuotedString(*Source, OS1);
+ }
if (MCTargetStreamer *TS = getTargetStreamer()) {
TS->emitDwarfFileDirective(OS1.str());
} else {
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index ea995288b28..69c10f535e5 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCContext.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
@@ -532,7 +533,7 @@ MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) {
// Dwarf Management
//===----------------------------------------------------------------------===//
-/// getDwarfFile - takes a file name an number to place in the dwarf file and
+/// getDwarfFile - takes a file name and number to place in the dwarf file and
/// directory tables. If the file number has already been allocated it is an
/// error and zero is returned and the client reports the error, else the
/// allocated file number is returned. The file numbers may be in any order.
@@ -540,9 +541,10 @@ Expected<unsigned> MCContext::getDwarfFile(StringRef Directory,
StringRef FileName,
unsigned FileNumber,
MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
unsigned CUID) {
MCDwarfLineTable &Table = MCDwarfLineTablesCUMap[CUID];
- return Table.tryGetFile(Directory, FileName, Checksum, FileNumber);
+ return Table.tryGetFile(Directory, FileName, Checksum, Source, FileNumber);
}
/// isValidDwarfFileNumber - takes a dwarf file number and returns true if it
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index 1f0fa78bffc..685b46a606d 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -11,7 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -373,8 +373,13 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
// The file format, which is the inline null-terminated filename and a
// directory index. We don't track file size/timestamp so don't emit them
- // in the v5 table. Emit MD5 checksums if we have them.
- MCOS->EmitIntValue(HasMD5 ? 3 : 2, 1);
+ // in the v5 table. Emit MD5 checksums and source if we have them.
+ uint64_t Entries = 2;
+ if (HasMD5)
+ Entries += 1;
+ if (HasSource)
+ Entries += 1;
+ MCOS->EmitIntValue(Entries, 1);
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
: dwarf::DW_FORM_string);
@@ -384,6 +389,11 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_MD5);
MCOS->EmitULEB128IntValue(dwarf::DW_FORM_data16);
}
+ if (HasSource) {
+ MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
+ MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
+ : dwarf::DW_FORM_string);
+ }
// Then the list of file names. These start at 1.
MCOS->EmitULEB128IntValue(MCDwarfFiles.size() - 1);
for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) {
@@ -401,6 +411,15 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
StringRef(reinterpret_cast<const char *>(Cksum->Bytes.data()),
Cksum->Bytes.size()));
}
+ if (HasSource) {
+ if (LineStr)
+ LineStr->emitRef(MCOS, MCDwarfFiles[i].Source.getValueOr(StringRef()));
+ else {
+ MCOS->EmitBytes(
+ MCDwarfFiles[i].Source.getValueOr(StringRef())); // Source and...
+ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
+ }
+ }
}
}
@@ -500,14 +519,17 @@ void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS,
Expected<unsigned> MCDwarfLineTable::tryGetFile(StringRef &Directory,
StringRef &FileName,
MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
unsigned FileNumber) {
- return Header.tryGetFile(Directory, FileName, Checksum, FileNumber);
+ return Header.tryGetFile(Directory, FileName, Checksum, Source, FileNumber);
}
-Expected<unsigned> MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
- StringRef &FileName,
- MD5::MD5Result *Checksum,
- unsigned FileNumber) {
+Expected<unsigned>
+MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
+ StringRef &FileName,
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> &Source,
+ unsigned FileNumber) {
if (Directory == CompilationDir)
Directory = "";
if (FileName.empty()) {
@@ -515,9 +537,11 @@ Expected<unsigned> MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
Directory = "";
}
assert(!FileName.empty());
- // If any files have an MD5 checksum, they all must.
- if (MCDwarfFiles.empty())
+ // If any files have an MD5 checksum or embedded source, they all must.
+ if (MCDwarfFiles.empty()) {
HasMD5 = (Checksum != nullptr);
+ HasSource = (Source != None);
+ }
if (FileNumber == 0) {
// File numbers start with 1 and/or after any file numbers
// allocated by inline-assembler .file directives.
@@ -545,6 +569,10 @@ Expected<unsigned> MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
if (HasMD5 != (Checksum != nullptr))
return make_error<StringError>("inconsistent use of MD5 checksums",
inconvertibleErrorCode());
+ // If any files have embedded source, they all must.
+ if (HasSource != (Source != None))
+ return make_error<StringError>("inconsistent use of embedded source",
+ inconvertibleErrorCode());
if (Directory.empty()) {
// Separate the directory part from the basename of the FileName.
@@ -582,6 +610,9 @@ Expected<unsigned> MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
File.Checksum = Checksum;
if (Checksum)
HasMD5 = true;
+ File.Source = Source;
+ if (Source)
+ HasSource = true;
// return the allocated FileNumber.
return FileNumber;
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 8ede318e0e1..76eef5e3725 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -3250,7 +3250,7 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
/// parseDirectiveFile
/// ::= .file filename
-/// ::= .file number [directory] filename [md5 checksum]
+/// ::= .file number [directory] filename [md5 checksum] [source source-text]
bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
// FIXME: I'm not sure what this is.
int64_t FileNumber = -1;
@@ -3286,23 +3286,36 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
}
std::string Checksum;
- if (!parseOptionalToken(AsmToken::EndOfStatement)) {
+
+ Optional<StringRef> Source;
+ bool HasSource = false;
+ std::string SourceString;
+
+ while (!parseOptionalToken(AsmToken::EndOfStatement)) {
StringRef Keyword;
if (check(getTok().isNot(AsmToken::Identifier),
"unexpected token in '.file' directive") ||
- parseIdentifier(Keyword) ||
- check(Keyword != "md5", "unexpected token in '.file' directive"))
- return true;
- if (getLexer().is(AsmToken::String) &&
- check(FileNumber == -1, "MD5 checksum specified, but no file number"))
- return true;
- if (check(getTok().isNot(AsmToken::String),
- "unexpected token in '.file' directive") ||
- parseEscapedString(Checksum) ||
- check(Checksum.size() != 32, "invalid MD5 checksum specified") ||
- parseToken(AsmToken::EndOfStatement,
- "unexpected token in '.file' directive"))
+ parseIdentifier(Keyword))
return true;
+ if (Keyword == "md5") {
+ if (check(FileNumber == -1,
+ "MD5 checksum specified, but no file number") ||
+ check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.file' directive") ||
+ parseEscapedString(Checksum) ||
+ check(Checksum.size() != 32, "invalid MD5 checksum specified"))
+ return true;
+ } else if (Keyword == "source") {
+ HasSource = true;
+ if (check(FileNumber == -1,
+ "source specified, but no file number") ||
+ check(getTok().isNot(AsmToken::String),
+ "unexpected token in '.file' directive") ||
+ parseEscapedString(SourceString))
+ return true;
+ } else {
+ return TokError("unexpected token in '.file' directive");
+ }
}
if (FileNumber == -1)
@@ -3316,13 +3329,18 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
CKMem = (MD5::MD5Result *)Ctx.allocate(sizeof(MD5::MD5Result), 1);
memcpy(&CKMem->Bytes, Checksum.data(), 16);
}
+ if (HasSource) {
+ char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
+ memcpy(SourceBuf, SourceString.data(), SourceString.size());
+ Source = StringRef(SourceBuf, SourceString.size());
+ }
// If there is -g option as well as debug info from directive file,
// we turn off -g option, directly use the existing debug info instead.
if (getContext().getGenDwarfForAssembly())
getContext().setGenDwarfForAssembly(false);
else {
Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
- FileNumber, Directory, Filename, CKMem);
+ FileNumber, Directory, Filename, CKMem, Source);
if (!FileNumOrErr)
return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
FileNumber = FileNumOrErr.get();
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index ab6fd9c7bb0..bf27a0abfda 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCStreamer.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@@ -191,8 +192,11 @@ void MCStreamer::EmitZeros(uint64_t NumBytes) {
Expected<unsigned>
MCStreamer::tryEmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
StringRef Filename,
- MD5::MD5Result *Checksum, unsigned CUID) {
- return getContext().getDwarfFile(Directory, Filename, FileNo, Checksum, CUID);
+ MD5::MD5Result *Checksum,
+ Optional<StringRef> Source,
+ unsigned CUID) {
+ return getContext().getDwarfFile(Directory, Filename, FileNo, Checksum,
+ Source, CUID);
}
void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
OpenPOWER on IntegriCloud