[DebugInfo] Added support for Checksum debug info feature.

Differential Revision: https://reviews.llvm.org/D27642

llvm-svn: 290514
This commit is contained in:
Amjad Aboud 2016-12-25 10:12:09 +00:00
parent 5dc0bba4e4
commit 7faeecc8f7
16 changed files with 163 additions and 40 deletions

View File

@ -3998,10 +3998,13 @@ DIFile
.. code-block:: llvm
!0 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
!0 = !DIFile(filename: "path/to/file", directory: "/path/to/dir",
checksumkind: CSK_MD5,
checksum: "000102030405060708090a0b0c0d0e0f")
Files are sometimes used in ``scope:`` fields, and are the only valid target
for ``file:`` fields.
Valid values for ``checksumkind:`` field are: {CSK_None, CSK_MD5, CSK_SHA1}
.. _DIBasicType:

View File

@ -233,7 +233,7 @@ enum MetadataCodes {
METADATA_SUBRANGE = 13, // [distinct, count, lo]
METADATA_ENUMERATOR = 14, // [distinct, value, name]
METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc]
METADATA_FILE = 16, // [distinct, filename, directory]
METADATA_FILE = 16, // [distinct, filename, directory, checksumkind, checksum]
METADATA_DERIVED_TYPE = 17, // [distinct, ...]
METADATA_COMPOSITE_TYPE = 18, // [distinct, ...]
METADATA_SUBROUTINE_TYPE = 19, // [distinct, flags, types, cc]

View File

@ -107,9 +107,14 @@ namespace llvm {
DICompileUnit::DebugEmissionKind::FullDebug,
uint64_t DWOId = 0, bool SplitDebugInlining = true);
/// Create a file descriptor to hold debugging information
/// for a file.
DIFile *createFile(StringRef Filename, StringRef Directory);
/// Create a file descriptor to hold debugging information for a file.
/// \param File File name.
/// \param Dir Directory.
/// \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,
StringRef Checksum = StringRef());
/// Create a single enumerator value.
DIEnumerator *createEnumerator(StringRef Name, int64_t Val);

View File

@ -470,38 +470,62 @@ class DIFile : public DIScope {
friend class LLVMContextImpl;
friend class MDNode;
DIFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops)
: DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {}
public:
enum ChecksumKind {
CSK_None,
CSK_MD5,
CSK_SHA1,
CSK_Last = CSK_SHA1 // Should be last enumeration.
};
private:
ChecksumKind CSKind;
DIFile(LLVMContext &C, StorageType Storage, ChecksumKind CSK,
ArrayRef<Metadata *> Ops)
: DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops),
CSKind(CSK) {}
~DIFile() = default;
static DIFile *getImpl(LLVMContext &Context, StringRef Filename,
StringRef Directory, StorageType Storage,
bool ShouldCreate = true) {
StringRef Directory, ChecksumKind CSK, StringRef CS,
StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, getCanonicalMDString(Context, Filename),
getCanonicalMDString(Context, Directory), Storage,
ShouldCreate);
getCanonicalMDString(Context, Directory), CSK,
getCanonicalMDString(Context, CS), Storage, ShouldCreate);
}
static DIFile *getImpl(LLVMContext &Context, MDString *Filename,
MDString *Directory, StorageType Storage,
bool ShouldCreate = true);
MDString *Directory, ChecksumKind CSK, MDString *CS,
StorageType Storage, bool ShouldCreate = true);
TempDIFile cloneImpl() const {
return getTemporary(getContext(), getFilename(), getDirectory());
return getTemporary(getContext(), getFilename(), getDirectory(),
getChecksumKind(), getChecksum());
}
public:
DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory),
(Filename, Directory))
DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory),
(Filename, Directory))
DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory,
ChecksumKind CSK = CSK_None,
StringRef CS = StringRef()),
(Filename, Directory, CSK, CS))
DEFINE_MDNODE_GET(DIFile, (MDString *Filename, MDString *Directory,
ChecksumKind CSK = CSK_None,
MDString *CS = nullptr),
(Filename, Directory, CSK, CS))
TempDIFile clone() const { return cloneImpl(); }
StringRef getFilename() const { return getStringOperand(0); }
StringRef getDirectory() const { return getStringOperand(1); }
StringRef getChecksum() const { return getStringOperand(2); }
ChecksumKind getChecksumKind() const { return CSKind; }
StringRef getChecksumKindAsString() const;
MDString *getRawFilename() const { return getOperandAs<MDString>(0); }
MDString *getRawDirectory() const { return getOperandAs<MDString>(1); }
MDString *getRawChecksum() const { return getOperandAs<MDString>(2); }
static ChecksumKind getChecksumKind(StringRef CSKindStr);
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIFileKind;

View File

@ -808,6 +808,12 @@ lltok::Kind LLLexer::LexIdentifier() {
StrVal.assign(Keyword.begin(), Keyword.end());
return lltok::DIFlag;
}
if (Keyword.startswith("CSK_")) {
StrVal.assign(Keyword.begin(), Keyword.end());
return lltok::ChecksumKind;
}
if (Keyword == "NoDebug" || Keyword == "FullDebug" ||
Keyword == "LineTablesOnly") {
StrVal.assign(Keyword.begin(), Keyword.end());

View File

@ -3465,6 +3465,11 @@ struct MDFieldList : public MDFieldImpl<SmallVector<Metadata *, 4>> {
MDFieldList() : ImplTy(SmallVector<Metadata *, 4>()) {}
};
struct ChecksumKindField : public MDFieldImpl<DIFile::ChecksumKind> {
ChecksumKindField() : ImplTy(DIFile::CSK_None) {}
ChecksumKindField(DIFile::ChecksumKind CSKind) : ImplTy(CSKind) {}
};
} // end anonymous namespace
namespace llvm {
@ -3742,6 +3747,20 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDFieldList &Result) {
return false;
}
template <>
bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
ChecksumKindField &Result) {
if (Lex.getKind() != lltok::ChecksumKind)
return TokError(
"invalid checksum kind" + Twine(" '") + Lex.getStrVal() + "'");
DIFile::ChecksumKind CSKind = DIFile::getChecksumKind(Lex.getStrVal());
Result.assign(CSKind);
Lex.Lex();
return false;
}
} // end namespace llvm
template <class ParserTy>
@ -3971,15 +3990,20 @@ 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")
bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
REQUIRED(filename, MDStringField, ); \
REQUIRED(directory, MDStringField, );
REQUIRED(directory, MDStringField, ); \
OPTIONAL(checksumkind, ChecksumKindField, ); \
OPTIONAL(checksum, MDStringField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val));
Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val,
checksumkind.Val, checksum.Val));
return false;
}

View File

@ -353,6 +353,7 @@ enum Kind {
DwarfOp, // DW_OP_foo
DIFlag, // DIFlagFoo
DwarfMacinfo, // DW_MACINFO_foo
ChecksumKind, // CSK_foo
// Type valued tokens (TyVal).
Type,

View File

@ -815,13 +815,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
}
case bitc::METADATA_FILE: {
if (Record.size() != 3)
if (Record.size() != 3 && Record.size() != 5)
return error("Invalid record");
IsDistinct = Record[0];
MetadataList.assignValue(
GET_OR_DISTINCT(
DIFile, (Context, getMDString(Record[1]), getMDString(Record[2]))),
DIFile,
(Context, getMDString(Record[1]), getMDString(Record[2]),
Record.size() == 3 ? DIFile::CSK_None
: static_cast<DIFile::ChecksumKind>(Record[3]),
Record.size() == 3 ? nullptr : getMDString(Record[4]))),
NextMetadataNo++);
break;
}

View File

@ -1515,6 +1515,8 @@ void ModuleBitcodeWriter::writeDIFile(const DIFile *N,
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(VE.getMetadataOrNullID(N->getRawChecksum()));
Stream.EmitRecord(bitc::METADATA_FILE, Record, Abbrev);
Record.clear();

View File

@ -1408,6 +1408,7 @@ struct MDFieldPrinter {
}
void printTag(const DINode *N);
void printMacinfoType(const DIMacroNode *N);
void printChecksumKind(const DIFile *N);
void printString(StringRef Name, StringRef Value,
bool ShouldSkipEmpty = true);
void printMetadata(StringRef Name, const Metadata *MD,
@ -1441,6 +1442,13 @@ void MDFieldPrinter::printMacinfoType(const DIMacroNode *N) {
Out << N->getMacinfoType();
}
void MDFieldPrinter::printChecksumKind(const DIFile *N) {
if (N->getChecksumKind() == DIFile::CSK_None)
// Skip CSK_None checksum kind.
return;
Out << FS << "checksumkind: " << N->getChecksumKindAsString();
}
void MDFieldPrinter::printString(StringRef Name, StringRef Value,
bool ShouldSkipEmpty) {
if (ShouldSkipEmpty && Value.empty())
@ -1653,6 +1661,8 @@ static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *,
/* ShouldSkipEmpty */ false);
Printer.printString("directory", N->getDirectory(),
/* ShouldSkipEmpty */ false);
Printer.printChecksumKind(N);
Printer.printString("checksum", N->getChecksum(), /* ShouldSkipEmpty */ true);
Out << ")";
}

View File

@ -174,8 +174,9 @@ DIImportedEntity *DIBuilder::createImportedDeclaration(DIScope *Context,
Context, Decl, Line, Name, AllImportedModules);
}
DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory) {
return DIFile::get(VMContext, Filename, Directory);
DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory,
DIFile::ChecksumKind CSKind, StringRef Checksum) {
return DIFile::get(VMContext, Filename, Directory, CSKind, Checksum);
}
DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val) {

View File

@ -347,14 +347,34 @@ DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,
DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);
}
static const char *ChecksumKindName[DIFile::CSK_Last + 1] = {
"CSK_None",
"CSK_MD5",
"CSK_SHA1"
};
DIFile::ChecksumKind DIFile::getChecksumKind(StringRef CSKindStr) {
return StringSwitch<DIFile::ChecksumKind>(CSKindStr)
.Case("CSK_MD5", DIFile::CSK_MD5)
.Case("CSK_SHA1", DIFile::CSK_SHA1)
.Default(DIFile::CSK_None);
}
StringRef DIFile::getChecksumKindAsString() const {
assert(CSKind <= DIFile::CSK_Last && "Invalid checksum kind");
return ChecksumKindName[CSKind];
}
DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,
MDString *Directory, StorageType Storage,
MDString *Directory, DIFile::ChecksumKind CSKind,
MDString *Checksum, StorageType Storage,
bool ShouldCreate) {
assert(isCanonical(Filename) && "Expected canonical MDString");
assert(isCanonical(Directory) && "Expected canonical MDString");
DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory));
Metadata *Ops[] = {Filename, Directory};
DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIFile, Ops);
assert(isCanonical(Checksum) && "Expected canonical MDString");
DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CSKind, Checksum));
Metadata *Ops[] = {Filename, Directory, Checksum};
DEFINE_GETIMPL_STORE(DIFile, (CSKind), Ops);
}
DICompileUnit *DICompileUnit::getImpl(

View File

@ -503,17 +503,26 @@ template <> struct MDNodeKeyImpl<DISubroutineType> {
template <> struct MDNodeKeyImpl<DIFile> {
MDString *Filename;
MDString *Directory;
DIFile::ChecksumKind CSKind;
MDString *Checksum;
MDNodeKeyImpl(MDString *Filename, MDString *Directory)
: Filename(Filename), Directory(Directory) {}
MDNodeKeyImpl(MDString *Filename, MDString *Directory,
DIFile::ChecksumKind CSKind, MDString *Checksum)
: Filename(Filename), Directory(Directory), CSKind(CSKind),
Checksum(Checksum) {}
MDNodeKeyImpl(const DIFile *N)
: Filename(N->getRawFilename()), Directory(N->getRawDirectory()) {}
: Filename(N->getRawFilename()), Directory(N->getRawDirectory()),
CSKind(N->getChecksumKind()), Checksum(N->getRawChecksum()) {}
bool isKeyOf(const DIFile *RHS) const {
return Filename == RHS->getRawFilename() &&
Directory == RHS->getRawDirectory();
Directory == RHS->getRawDirectory() &&
CSKind == RHS->getChecksumKind() &&
Checksum == RHS->getRawChecksum();
}
unsigned getHashValue() const {
return hash_combine(Filename, Directory, CSKind, Checksum);
}
unsigned getHashValue() const { return hash_combine(Filename, Directory); }
};
template <> struct MDNodeKeyImpl<DISubprogram> {

View File

@ -961,6 +961,8 @@ void Verifier::visitDISubroutineType(const DISubroutineType &N) {
void Verifier::visitDIFile(const DIFile &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N);
AssertDI((N.getChecksumKind() != DIFile::CSK_None ||
N.getChecksum().empty()), "invalid checksum kind", &N);
}
void Verifier::visitDICompileUnit(const DICompileUnit &N) {

View File

@ -1,8 +1,8 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
; RUN: verify-uselistorder %s
; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31}
!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34}
; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !33}
!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37}
; CHECK: !0 = !DISubrange(count: 3)
; CHECK-NEXT: !1 = !DISubrange(count: 3, lowerBound: 4)
@ -79,3 +79,9 @@
!32 = distinct !{!31}
!33 = !DIMacroFile(line: 9, file: !14, nodes: !32)
!34 = !DIMacroFile(type: DW_MACINFO_start_file, line: 11, file: !14)
; CHECK-NEXT: !32 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_MD5, checksum: "000102030405060708090a0b0c0d0e0f")
; CHECK-NEXT: !33 = !DIFile(filename: "file", directory: "dir")
!35 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_MD5, checksum: "000102030405060708090a0b0c0d0e0f")
!36 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_None)
!37 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_None, checksum: "")

View File

@ -1360,15 +1360,21 @@ typedef MetadataTest DIFileTest;
TEST_F(DIFileTest, get) {
StringRef Filename = "file";
StringRef Directory = "dir";
auto *N = DIFile::get(Context, Filename, Directory);
DIFile::ChecksumKind CSKind = DIFile::CSK_MD5;
StringRef Checksum = "000102030405060708090a0b0c0d0e0f";
auto *N = DIFile::get(Context, Filename, Directory, CSKind, Checksum);
EXPECT_EQ(dwarf::DW_TAG_file_type, N->getTag());
EXPECT_EQ(Filename, N->getFilename());
EXPECT_EQ(Directory, N->getDirectory());
EXPECT_EQ(N, DIFile::get(Context, Filename, Directory));
EXPECT_EQ(CSKind, N->getChecksumKind());
EXPECT_EQ(Checksum, N->getChecksum());
EXPECT_EQ(N, DIFile::get(Context, Filename, Directory, CSKind, Checksum));
EXPECT_NE(N, DIFile::get(Context, "other", Directory));
EXPECT_NE(N, DIFile::get(Context, Filename, "other"));
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));
TempDIFile Temp = N->clone();
EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));