diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 13 | ||||
| -rw-r--r-- | llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 9 | ||||
| -rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp | 98 | ||||
| -rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/IR/DIBuilder.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/IR/DebugInfoMetadata.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/IR/LLVMContextImpl.h | 18 | ||||
| -rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 10 | ||||
| -rw-r--r-- | llvm/lib/MC/MCContext.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/MC/MCDwarf.cpp | 51 | ||||
| -rw-r--r-- | llvm/lib/MC/MCParser/AsmParser.cpp | 48 | ||||
| -rw-r--r-- | llvm/lib/MC/MCStreamer.cpp | 8 |
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, |

