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/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -159,7 +159,9 @@ 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()); + bool Success = OS.EmitCVFileDirective(NextId, FullPath, Checksum, ChecksumKind); (void)Success; assert(Success && ".cv_file directive failed"); } 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,17 @@ 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); + 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); + return; + } + 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 @@ -3457,6 +3457,8 @@ SMLoc FileNumberLoc = getTok().getLoc(); int64_t FileNumber; std::string Filename; + std::string Checksum; + int64_t ChecksumKind; if (parseIntToken(FileNumber, "expected file number in '.cv_file' directive") || @@ -3466,11 +3468,15 @@ // Usually directory and filename are together, otherwise just // directory. Allow the strings to have escaped octal character sequence. parseEscapedString(Filename) || + check(getTok().isNot(AsmToken::String), + "unexpected token in '.cv_file' directive") || + parseEscapedString(Checksum) || + parseIntToken(ChecksumKind, "expected checksum kind in '.cv_file' directive") || parseToken(AsmToken::EndOfStatement, "unexpected token in '.cv_file' directive")) 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) {