Index: cfe/trunk/lib/CodeGen/CGDebugInfo.h =================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.h +++ cfe/trunk/lib/CodeGen/CGDebugInfo.h @@ -442,6 +442,10 @@ /// Remap a given path with the current debug prefix map std::string remapDIPath(StringRef) const; + /// Compute the file checksum debug info for input file ID. + llvm::DIFile::ChecksumKind computeChecksum(FileID FID, + SmallString<32> &Checksum) const; + /// Get the file debug info descriptor for the input location. llvm::DIFile *getOrCreateFile(SourceLocation Loc); Index: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" using namespace clang; using namespace clang::CodeGen; @@ -320,11 +321,36 @@ return StringRef(); } +llvm::DIFile::ChecksumKind +CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const { + Checksum.clear(); + + if (!CGM.getCodeGenOpts().EmitCodeView) + return llvm::DIFile::CSK_None; + + SourceManager &SM = CGM.getContext().getSourceManager(); + bool Invalid; + llvm::MemoryBuffer *MemBuffer = SM.getBuffer(FID, &Invalid); + if (Invalid) + return llvm::DIFile::CSK_None; + + llvm::MD5 Hash; + llvm::MD5::MD5Result Result; + + Hash.update(MemBuffer->getBuffer()); + Hash.final(Result); + + Hash.stringifyResult(Result, Checksum); + return llvm::DIFile::CSK_MD5; +} + llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { if (!Loc.isValid()) // If Location is not valid then use main input file. return DBuilder.createFile(remapDIPath(TheCU->getFilename()), - remapDIPath(TheCU->getDirectory())); + remapDIPath(TheCU->getDirectory()), + TheCU->getFile()->getChecksumKind(), + TheCU->getFile()->getChecksum()); SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc); @@ -332,7 +358,9 @@ if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty()) // If the location is not valid then use main input file. return DBuilder.createFile(remapDIPath(TheCU->getFilename()), - remapDIPath(TheCU->getDirectory())); + remapDIPath(TheCU->getDirectory()), + TheCU->getFile()->getChecksumKind(), + TheCU->getFile()->getChecksum()); // Cache the results. const char *fname = PLoc.getFilename(); @@ -344,8 +372,13 @@ return cast(V); } + SmallString<32> Checksum; + llvm::DIFile::ChecksumKind CSKind = + computeChecksum(SM.getFileID(Loc), Checksum); + llvm::DIFile *F = DBuilder.createFile(remapDIPath(PLoc.getFilename()), - remapDIPath(getCurrentDirname())); + remapDIPath(getCurrentDirname()), + CSKind, Checksum); DIFileCache[fname].reset(F); return F; @@ -353,7 +386,9 @@ llvm::DIFile *CGDebugInfo::getOrCreateMainFile() { return DBuilder.createFile(remapDIPath(TheCU->getFilename()), - remapDIPath(TheCU->getDirectory())); + remapDIPath(TheCU->getDirectory()), + TheCU->getFile()->getChecksumKind(), + TheCU->getFile()->getChecksum()); } std::string CGDebugInfo::remapDIPath(StringRef Path) const { @@ -396,6 +431,8 @@ } void CGDebugInfo::CreateCompileUnit() { + SmallString<32> Checksum; + llvm::DIFile::ChecksumKind CSKind = llvm::DIFile::CSK_None; // Should we be asking the SourceManager for the main file name, instead of // accepting it as an argument? This just causes the main file name to @@ -422,6 +459,7 @@ llvm::sys::path::append(MainFileDirSS, MainFileName); MainFileName = MainFileDirSS.str(); } + CSKind = computeChecksum(SM.getMainFileID(), Checksum); } llvm::dwarf::SourceLanguage LangTag; @@ -467,7 +505,8 @@ // FIXME - Eliminate TheCU. TheCU = DBuilder.createCompileUnit( LangTag, DBuilder.createFile(remapDIPath(MainFileName), - remapDIPath(getCurrentDirname())), + remapDIPath(getCurrentDirname()), CSKind, + Checksum), Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers, CGM.getCodeGenOpts().SplitDwarfFile, EmissionKind, 0 /* DWOid */, CGM.getCodeGenOpts().SplitDwarfInlining); Index: cfe/trunk/test/CodeGen/Inputs/debug-info-file-checksum.c =================================================================== --- cfe/trunk/test/CodeGen/Inputs/debug-info-file-checksum.c +++ cfe/trunk/test/CodeGen/Inputs/debug-info-file-checksum.c @@ -0,0 +1,3 @@ +int foo(int x) { + return x+1; +} Index: cfe/trunk/test/CodeGen/debug-info-file-checksum.c =================================================================== --- cfe/trunk/test/CodeGen/debug-info-file-checksum.c +++ cfe/trunk/test/CodeGen/debug-info-file-checksum.c @@ -0,0 +1,5 @@ +// RUN: %clang -emit-llvm -S -g -gcodeview -x c %S/Inputs/debug-info-file-checksum.c -o - | FileCheck %s + +// Check that "checksum" is created correctly for the compiled file. + +// CHECK: !DIFile(filename:{{.*}}, directory:{{.*}}, checksumkind: CSK_MD5, checksum: "a3b7d27af071accdeccaa933fc603608")