Index: llvm/include/llvm/IR/DIBuilder.h =================================================================== --- llvm/include/llvm/IR/DIBuilder.h +++ llvm/include/llvm/IR/DIBuilder.h @@ -127,7 +127,7 @@ /// \param CSKind Checksum kind (e.g. CSK_None, CSK_MD5, CSK_SHA1, etc.). /// \param Checksum Checksum data. DIFile *createFile(StringRef Filename, StringRef Directory, - DIFile::ChecksumKind CSKind = DIFile::CSK_None, + DIFile::ChecksumKind CSKind = DIFile::ChecksumKind::CSK_None, StringRef Checksum = StringRef()); /// Create debugging information entry for a macro. Index: llvm/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/include/llvm/IR/DebugInfoMetadata.h +++ llvm/include/llvm/IR/DebugInfoMetadata.h @@ -473,7 +473,7 @@ friend class MDNode; public: - enum ChecksumKind { + enum class ChecksumKind : uint8_t { CSK_None, CSK_MD5, CSK_SHA1, @@ -507,11 +507,11 @@ public: DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory, - ChecksumKind CSK = CSK_None, + ChecksumKind CSK = ChecksumKind::CSK_None, StringRef CS = StringRef()), (Filename, Directory, CSK, CS)) DEFINE_MDNODE_GET(DIFile, (MDString *Filename, MDString *Directory, - ChecksumKind CSK = CSK_None, + ChecksumKind CSK = ChecksumKind::CSK_None, MDString *CS = nullptr), (Filename, Directory, CSK, CS)) Index: llvm/include/llvm/MC/MCCodeView.h =================================================================== --- llvm/include/llvm/MC/MCCodeView.h +++ llvm/include/llvm/MC/MCCodeView.h @@ -161,7 +161,7 @@ ~CodeViewContext(); bool isValidFileNumber(unsigned FileNumber) const; - bool addFile(unsigned FileNumber, StringRef Filename); + bool addFile(unsigned FileNumber, StringRef Filename, StringRef Checksum, uint8_t ChecksumKind); ArrayRef getFilenames() { return Filenames; } /// Records the function id of a normal function. Returns false if the @@ -296,6 +296,9 @@ /// An array of absolute paths. Eventually this may include the file checksum. SmallVector Filenames; + // Map from filename to checksum. + StringMap> Checksums; + /// The offset of the first and last .cv_loc directive for a given function /// id. std::map> MCCVLineStartStop; Index: llvm/include/llvm/MC/MCStreamer.h =================================================================== --- llvm/include/llvm/MC/MCStreamer.h +++ llvm/include/llvm/MC/MCStreamer.h @@ -732,7 +732,7 @@ /// \brief Associate a filename with a specified logical file number. This /// implements the '.cv_file 4 "foo.c"' assembler directive. Returns true on /// success. - virtual bool EmitCVFileDirective(unsigned FileNo, StringRef Filename); + virtual bool EmitCVFileDirective(unsigned FileNo, StringRef Filename, StringRef Checksum, uint8_t ChecksumKind); /// \brief Introduces a function id for use with .cv_loc. virtual bool EmitCVFuncIdDirective(unsigned FunctionId); Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -3525,7 +3525,7 @@ }; struct ChecksumKindField : public MDFieldImpl { - ChecksumKindField() : ImplTy(DIFile::CSK_None) {} + ChecksumKindField() : ImplTy(DIFile::ChecksumKind::CSK_None) {} ChecksumKindField(DIFile::ChecksumKind CSKind) : ImplTy(CSKind) {} }; Index: llvm/lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1347,7 +1347,7 @@ GET_OR_DISTINCT( DIFile, (Context, getMDString(Record[1]), getMDString(Record[2]), - Record.size() == 3 ? DIFile::CSK_None + Record.size() == 3 ? DIFile::ChecksumKind::CSK_None : static_cast(Record[3]), Record.size() == 3 ? nullptr : getMDString(Record[4]))), NextMetadataNo); Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1483,7 +1483,7 @@ Record.push_back(N->isDistinct()); Record.push_back(VE.getMetadataOrNullID(N->getRawFilename())); Record.push_back(VE.getMetadataOrNullID(N->getRawDirectory())); - Record.push_back(N->getChecksumKind()); + Record.push_back(static_cast(N->getChecksumKind())); Record.push_back(VE.getMetadataOrNullID(N->getRawChecksum())); Stream.EmitRecord(bitc::METADATA_FILE, Record, Abbrev); Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -159,7 +159,10 @@ if (Insertion.second) { // We have to compute the full filepath and emit a .cv_file directive. StringRef FullPath = getFullFilepath(F); - bool Success = OS.EmitCVFileDirective(NextId, FullPath); + StringRef Checksum = F->getChecksum(); + uint8_t ChecksumKind = static_cast(F->getChecksumKind()); + errs() << "kind " << ChecksumKind << "\n"; + bool Success = OS.EmitCVFileDirective(NextId, FullPath, Checksum, ChecksumKind); (void)Success; assert(Success && ".cv_file directive failed"); } Index: llvm/lib/IR/AsmWriter.cpp =================================================================== --- llvm/lib/IR/AsmWriter.cpp +++ llvm/lib/IR/AsmWriter.cpp @@ -1493,7 +1493,7 @@ } void MDFieldPrinter::printChecksumKind(const DIFile *N) { - if (N->getChecksumKind() == DIFile::CSK_None) + if (N->getChecksumKind() == DIFile::ChecksumKind::CSK_None) // Skip CSK_None checksum kind. return; Out << FS << "checksumkind: " << N->getChecksumKindAsString(); Index: llvm/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/lib/IR/DebugInfoMetadata.cpp +++ llvm/lib/IR/DebugInfoMetadata.cpp @@ -354,7 +354,7 @@ DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops); } -static const char *ChecksumKindName[DIFile::CSK_Last + 1] = { +static const char *ChecksumKindName[static_cast(DIFile::ChecksumKind::CSK_Last) + 1] = { "CSK_None", "CSK_MD5", "CSK_SHA1" @@ -362,14 +362,14 @@ DIFile::ChecksumKind DIFile::getChecksumKind(StringRef CSKindStr) { return StringSwitch(CSKindStr) - .Case("CSK_MD5", DIFile::CSK_MD5) - .Case("CSK_SHA1", DIFile::CSK_SHA1) - .Default(DIFile::CSK_None); + .Case("CSK_MD5", DIFile::ChecksumKind::CSK_MD5) + .Case("CSK_SHA1", DIFile::ChecksumKind::CSK_SHA1) + .Default(DIFile::ChecksumKind::CSK_None); } StringRef DIFile::getChecksumKindAsString() const { - assert(CSKind <= DIFile::CSK_Last && "Invalid checksum kind"); - return ChecksumKindName[CSKind]; + assert(CSKind <= DIFile::ChecksumKind::CSK_Last && "Invalid checksum kind"); + return ChecksumKindName[static_cast(CSKind)]; } DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename, Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -960,7 +960,7 @@ void Verifier::visitDIFile(const DIFile &N) { AssertDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N); - AssertDI((N.getChecksumKind() != DIFile::CSK_None || + AssertDI((N.getChecksumKind() != DIFile::ChecksumKind::CSK_None || N.getChecksum().empty()), "invalid checksum kind", &N); } Index: llvm/lib/MC/MCAsmStreamer.cpp =================================================================== --- llvm/lib/MC/MCAsmStreamer.cpp +++ llvm/lib/MC/MCAsmStreamer.cpp @@ -225,7 +225,7 @@ StringRef FileName) override; MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override; - bool EmitCVFileDirective(unsigned FileNo, StringRef Filename) override; + bool EmitCVFileDirective(unsigned FileNo, StringRef Filename, StringRef Checksum, uint8_t ChecksumKind) override; bool EmitCVFuncIdDirective(unsigned FuncId) override; bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, unsigned IAFile, unsigned IALine, @@ -1120,13 +1120,22 @@ return MCStreamer::getDwarfLineTableSymbol(0); } -bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) { - if (!getContext().getCVContext().addFile(FileNo, Filename)) +bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename, StringRef Checksum, uint8_t ChecksumKind) { + if (!getContext().getCVContext().addFile(FileNo, Filename, Checksum, ChecksumKind)) return false; OS << "\t.cv_file\t" << FileNo << ' '; - PrintQuotedString(Filename, OS); + + if (!ChecksumKind) { + EmitEOL(); + return true; + } + + OS << ' '; + PrintQuotedString(Checksum, OS); + OS << ' ' << ChecksumKind; + EmitEOL(); return true; } Index: llvm/lib/MC/MCCodeView.cpp =================================================================== --- llvm/lib/MC/MCCodeView.cpp +++ llvm/lib/MC/MCCodeView.cpp @@ -44,7 +44,7 @@ return false; } -bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) { +bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename, StringRef Checksum, uint8_t ChecksumKind) { assert(FileNumber > 0); Filename = addToStringTable(Filename); unsigned Idx = FileNumber - 1; @@ -62,6 +62,9 @@ Filename = addToStringTable(Filename); Filenames[Idx] = Filename; + + Checksums.insert(std::make_pair(Filename, std::make_pair(Checksum,ChecksumKind))); + return true; } @@ -181,9 +184,17 @@ // emit checksums. for (StringRef Filename : Filenames) { OS.EmitIntValue(getStringTableOffset(Filename), 4); - // Zero the next two fields and align back to 4 bytes. This indicates that - // no checksum is present. - OS.EmitIntValue(0, 4); + + std::pair Checksum = Checksums[Filename]; + if (!Checksum.second) { + // There is no checksum. + OS.EmitIntValue(0, 4); + continue; + } + OS.EmitIntValue(static_cast(Checksum.first.size()), 1); + OS.EmitIntValue(Checksum.second, 1); + OS.EmitBytes(Checksum.first); + OS.EmitValueToAlignment(4); } OS.EmitLabel(FileEnd); Index: llvm/lib/MC/MCParser/AsmParser.cpp =================================================================== --- llvm/lib/MC/MCParser/AsmParser.cpp +++ llvm/lib/MC/MCParser/AsmParser.cpp @@ -3452,25 +3452,33 @@ } /// parseDirectiveCVFile -/// ::= .cv_file number filename +/// ::= .cv_file number filename [Checksum] [ChecksumKind] bool AsmParser::parseDirectiveCVFile() { SMLoc FileNumberLoc = getTok().getLoc(); int64_t FileNumber; std::string Filename; + std::string Checksum; + int64_t ChecksumKind = 0; if (parseIntToken(FileNumber, "expected file number in '.cv_file' directive") || check(FileNumber < 1, FileNumberLoc, "file number less than one") || check(getTok().isNot(AsmToken::String), - "unexpected token in '.cv_file' directive") || - // Usually directory and filename are together, otherwise just - // directory. Allow the strings to have escaped octal character sequence. - parseEscapedString(Filename) || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.cv_file' directive")) + "a") || + parseEscapedString(Filename)) return true; + if (!parseOptionalToken(AsmToken::EndOfStatement)) { + if(check(getTok().isNot(AsmToken::String), + "b") || + parseEscapedString(Checksum) || + parseIntToken(ChecksumKind, "expected checksum kind in '.cv_file' directive") || + parseToken(AsmToken::EndOfStatement, + "c")) + return true; + } + - if (!getStreamer().EmitCVFileDirective(FileNumber, Filename)) + if (!getStreamer().EmitCVFileDirective(FileNumber, Filename, Checksum, static_cast(ChecksumKind))) return Error(FileNumberLoc, "file number already allocated"); return false; Index: llvm/lib/MC/MCStreamer.cpp =================================================================== --- llvm/lib/MC/MCStreamer.cpp +++ llvm/lib/MC/MCStreamer.cpp @@ -224,8 +224,8 @@ report_fatal_error("No open frame"); } -bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) { - return getContext().getCVContext().addFile(FileNo, Filename); +bool MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename, StringRef Checksum, uint8_t ChecksumKind) { + return getContext().getCVContext().addFile(FileNo, Filename, Checksum, ChecksumKind); } bool MCStreamer::EmitCVFuncIdDirective(unsigned FunctionId) { Index: llvm/test/DebugInfo/COFF/multifile.ll =================================================================== --- llvm/test/DebugInfo/COFF/multifile.ll +++ llvm/test/DebugInfo/COFF/multifile.ll @@ -189,7 +189,7 @@ !2 = !{} !4 = distinct !DISubprogram(name: "f", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 3, file: !5, scope: !6, type: !7, variables: !2) !5 = !DIFile(filename: "input.c", directory: "D:\5C") -!6 = !DIFile(filename: "input.c", directory: "D:C") +!6 = !DIFile(filename: "input.c", directory: "D:C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6") !7 = !DISubroutineType(types: !8) !8 = !{null} !9 = !{i32 2, !"CodeView", i32 1} @@ -197,9 +197,9 @@ !11 = !{!"clang version 3.5 "} !12 = !DILocation(line: 1, scope: !13) !13 = !DILexicalBlockFile(discriminator: 0, file: !14, scope: !4) -!14 = !DIFile(filename: "one.c", directory: "D:\5C") +!14 = !DIFile(filename: "one.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum: "70b51f534d80639d033ae92c6a856af6") !15 = !DILocation(line: 2, scope: !16) !16 = !DILexicalBlockFile(discriminator: 0, file: !17, scope: !4) -!17 = !DIFile(filename: "two.c", directory: "D:\5C") +!17 = !DIFile(filename: "two.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033ae92c6a856af6") !18 = !DILocation(line: 7, scope: !13) !19 = !DILocation(line: 8, scope: !13) Index: llvm/unittests/IR/MetadataTest.cpp =================================================================== --- llvm/unittests/IR/MetadataTest.cpp +++ llvm/unittests/IR/MetadataTest.cpp @@ -1370,7 +1370,7 @@ TEST_F(DIFileTest, get) { StringRef Filename = "file"; StringRef Directory = "dir"; - DIFile::ChecksumKind CSKind = DIFile::CSK_MD5; + DIFile::ChecksumKind CSKind = DIFile::ChecksumKind::CSK_MD5; StringRef Checksum = "000102030405060708090a0b0c0d0e0f"; auto *N = DIFile::get(Context, Filename, Directory, CSKind, Checksum); @@ -1383,7 +1383,7 @@ EXPECT_NE(N, DIFile::get(Context, "other", Directory, CSKind, Checksum)); EXPECT_NE(N, DIFile::get(Context, Filename, "other", CSKind, Checksum)); - EXPECT_NE(N, DIFile::get(Context, Filename, Directory, DIFile::CSK_SHA1, Checksum)); + EXPECT_NE(N, DIFile::get(Context, Filename, Directory, DIFile::ChecksumKind::CSK_SHA1, Checksum)); EXPECT_NE(N, DIFile::get(Context, Filename, Directory)); TempDIFile Temp = N->clone();