Skip to content

Commit

Permalink
[DebugInfo] IR/Bitcode changes for DISubprogram flags.
Browse files Browse the repository at this point in the history
Packing the flags into one bitcode word will save effort in
adding new flags in the future.

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

llvm-svn: 347806
  • Loading branch information
pogo59 committed Nov 28, 2018
1 parent 7304f0a commit adcdc1b
Show file tree
Hide file tree
Showing 19 changed files with 295 additions and 59 deletions.
4 changes: 2 additions & 2 deletions llvm/include/llvm/IR/DebugInfoFlags.def
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ HANDLE_DI_FLAG((1 << 29), Largest)
// Use this as a zero/initialization value.
// For example: void foo(DISPFlags Flags = SPFlagZero).
HANDLE_DISP_FLAG(0, Zero)
// Virtuality is a two-bit valued field.
HANDLE_DISP_FLAG(0u, Nonvirtual)
// Virtuality is a two-bit enum field in the LSB of the word.
// Values should match DW_VIRTUALITY_*.
HANDLE_DISP_FLAG(1u, Virtual)
HANDLE_DISP_FLAG(2u, PureVirtual)
HANDLE_DISP_FLAG((1u << 2), LocalToUnit)
Expand Down
14 changes: 13 additions & 1 deletion llvm/include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -1620,9 +1620,21 @@ class DISubprogram : public DILocalScope {
#define HANDLE_DISP_FLAG(ID, NAME) SPFlag##NAME = ID,
#define DISP_FLAG_LARGEST_NEEDED
#include "llvm/IR/DebugInfoFlags.def"
SPFlagVirtuality = SPFlagNonvirtual | SPFlagVirtual | SPFlagPureVirtual,
SPFlagNonvirtual = SPFlagZero,
SPFlagVirtuality = SPFlagVirtual | SPFlagPureVirtual,
LLVM_MARK_AS_BITMASK_ENUM(SPFlagLargest)
};

static DISPFlags getFlag(StringRef Flag);
static StringRef getFlagString(DISPFlags Flag);

/// Split up a flags bitfield for easier printing.
///
/// Split \c Flags into \c SplitFlags, a vector of its components. Returns
/// any remaining (unrecognized) bits.
static DISPFlags splitFlags(DISPFlags Flags,
SmallVectorImpl<DISPFlags> &SplitFlags);

// Helper for converting old bitfields to new flags word.
static DISPFlags toSPFlags(bool IsLocalToUnit, bool IsDefinition,
bool IsOptimized,
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,11 @@ lltok::Kind LLLexer::LexIdentifier() {
return lltok::DIFlag;
}

if (Keyword.startswith("DISPFlag")) {
StrVal.assign(Keyword.begin(), Keyword.end());
return lltok::DISPFlag;
}

if (Keyword.startswith("CSK_")) {
StrVal.assign(Keyword.begin(), Keyword.end());
return lltok::ChecksumKind;
Expand Down
63 changes: 56 additions & 7 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3749,6 +3749,10 @@ struct DIFlagField : public MDFieldImpl<DINode::DIFlags> {
DIFlagField() : MDFieldImpl(DINode::FlagZero) {}
};

struct DISPFlagField : public MDFieldImpl<DISubprogram::DISPFlags> {
DISPFlagField() : MDFieldImpl(DISubprogram::SPFlagZero) {}
};

struct MDSignedField : public MDFieldImpl<int64_t> {
int64_t Min;
int64_t Max;
Expand Down Expand Up @@ -4041,6 +4045,46 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DIFlagField &Result) {
return false;
}

/// DISPFlagField
/// ::= uint32
/// ::= DISPFlagVector
/// ::= DISPFlagVector '|' DISPFlag* '|' uint32
template <>
bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DISPFlagField &Result) {

// Parser for a single flag.
auto parseFlag = [&](DISubprogram::DISPFlags &Val) {
if (Lex.getKind() == lltok::APSInt && !Lex.getAPSIntVal().isSigned()) {
uint32_t TempVal = static_cast<uint32_t>(Val);
bool Res = ParseUInt32(TempVal);
Val = static_cast<DISubprogram::DISPFlags>(TempVal);
return Res;
}

if (Lex.getKind() != lltok::DISPFlag)
return TokError("expected debug info flag");

Val = DISubprogram::getFlag(Lex.getStrVal());
if (!Val)
return TokError(Twine("invalid subprogram debug info flag '") +
Lex.getStrVal() + "'");
Lex.Lex();
return false;
};

// Parse the flags and combine them together.
DISubprogram::DISPFlags Combined = DISubprogram::SPFlagZero;
do {
DISubprogram::DISPFlags Val;
if (parseFlag(Val))
return true;
Combined |= Val;
} while (EatIfPresent(lltok::bar));

Result.assign(Combined);
return false;
}

template <>
bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
MDSignedField &Result) {
Expand Down Expand Up @@ -4517,8 +4561,8 @@ bool LLParser::ParseDICompileUnit(MDNode *&Result, bool IsDistinct) {
/// isDefinition: true, scopeLine: 8, containingType: !3,
/// virtuality: DW_VIRTUALTIY_pure_virtual,
/// virtualIndex: 10, thisAdjustment: 4, flags: 11,
/// isOptimized: false, templateParams: !4, declaration: !5,
/// retainedNodes: !6, thrownTypes: !7)
/// spFlags: 10, isOptimized: false, templateParams: !4,
/// declaration: !5, retainedNodes: !6, thrownTypes: !7)
bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) {
auto Loc = Lex.getLoc();
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
Expand All @@ -4536,21 +4580,26 @@ bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) {
OPTIONAL(virtualIndex, MDUnsignedField, (0, UINT32_MAX)); \
OPTIONAL(thisAdjustment, MDSignedField, (0, INT32_MIN, INT32_MAX)); \
OPTIONAL(flags, DIFlagField, ); \
OPTIONAL(spFlags, DISPFlagField, ); \
OPTIONAL(isOptimized, MDBoolField, ); \
OPTIONAL(unit, MDField, ); \
OPTIONAL(templateParams, MDField, ); \
OPTIONAL(declaration, MDField, ); \
OPTIONAL(retainedNodes, MDField, ); \
OPTIONAL(retainedNodes, MDField, ); \
OPTIONAL(thrownTypes, MDField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS

if (isDefinition.Val && !IsDistinct)
// An explicit spFlags field takes precedence over individual fields in
// older IR versions.
DISubprogram::DISPFlags SPFlags =
spFlags.Seen ? spFlags.Val
: DISubprogram::toSPFlags(isLocal.Val, isDefinition.Val,
isOptimized.Val, virtuality.Val);
if ((SPFlags & DISubprogram::SPFlagDefinition) && !IsDistinct)
return Lex.Error(
Loc,
"missing 'distinct', required for !DISubprogram when 'isDefinition'");
DISubprogram::DISPFlags SPFlags = DISubprogram::toSPFlags(
isLocal.Val, isDefinition.Val, isOptimized.Val, virtuality.Val);
"missing 'distinct', required for !DISubprogram that is a Definition");
Result = GET_OR_DISTINCT(
DISubprogram,
(Context, scope.Val, name.Val, linkageName.Val, file.Val, line.Val,
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ enum Kind {
NameTableKind, // GNU
DwarfOp, // DW_OP_foo
DIFlag, // DIFlagFoo
DISPFlag, // DISPFlagFoo
DwarfMacinfo, // DW_MACINFO_foo
ChecksumKind, // CSK_foo

Expand Down
63 changes: 42 additions & 21 deletions llvm/lib/Bitcode/Reader/MetadataLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1406,23 +1406,43 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
if (Record.size() < 18 || Record.size() > 21)
return error("Invalid record");

IsDistinct =
(Record[0] & 1) || Record[8]; // All definitions should be distinct.
bool HasSPFlags = Record[0] & 4;
DISubprogram::DISPFlags SPFlags =
HasSPFlags
? static_cast<DISubprogram::DISPFlags>(Record[9])
: DISubprogram::toSPFlags(
/*IsLocalToUnit=*/Record[7], /*IsDefinition=*/Record[8],
/*IsOptimized=*/Record[14], /*Virtuality=*/Record[11]);

// All definitions should be distinct.
IsDistinct = (Record[0] & 1) || (SPFlags & DISubprogram::SPFlagDefinition);
// Version 1 has a Function as Record[15].
// Version 2 has removed Record[15].
// Version 3 has the Unit as Record[15].
// Version 4 added thisAdjustment.
bool HasUnit = Record[0] >= 2;
if (HasUnit && Record.size() < 19)
// Version 5 repacked flags into DISPFlags, changing many element numbers.
bool HasUnit = Record[0] & 2;
if (!HasSPFlags && HasUnit && Record.size() < 19)
return error("Invalid record");
Metadata *CUorFn = getMDOrNull(Record[15]);
unsigned Offset = Record.size() >= 19 ? 1 : 0;
bool HasFn = Offset && !HasUnit;
bool HasThisAdj = Record.size() >= 20;
bool HasThrownTypes = Record.size() >= 21;
DISubprogram::DISPFlags SPFlags = DISubprogram::toSPFlags(
/*IsLocalToUnit=*/Record[7], /*IsDefinition=*/Record[8],
/*IsOptimized=*/Record[14], /*Virtuality=*/Record[11]);
if (HasSPFlags && !HasUnit)
return error("Invalid record");
// Accommodate older formats.
bool HasFn = false;
bool HasThisAdj = true;
bool HasThrownTypes = true;
unsigned OffsetA = 0;
unsigned OffsetB = 0;
if (!HasSPFlags) {
OffsetA = 2;
OffsetB = 2;
if (Record.size() >= 19) {
HasFn = !HasUnit;
OffsetB++;
}
HasThisAdj = Record.size() >= 20;
HasThrownTypes = Record.size() >= 21;
}
Metadata *CUorFn = getMDOrNull(Record[12 + OffsetB]);
DISubprogram *SP = GET_OR_DISTINCT(
DISubprogram,
(Context,
Expand All @@ -1432,17 +1452,18 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
getMDOrNull(Record[4]), // file
Record[5], // line
getMDOrNull(Record[6]), // type
Record[9], // scopeLine
getDITypeRefOrNull(Record[10]), // containingType
Record[12], // virtualIndex
HasThisAdj ? Record[19] : 0, // thisAdjustment
static_cast<DINode::DIFlags>(Record[13]), // flags
Record[7 + OffsetA], // scopeLine
getDITypeRefOrNull(Record[8 + OffsetA]), // containingType
Record[10 + OffsetA], // virtualIndex
HasThisAdj ? Record[16 + OffsetB] : 0, // thisAdjustment
static_cast<DINode::DIFlags>(Record[11 + OffsetA]),// flags
SPFlags, // SPFlags
HasUnit ? CUorFn : nullptr, // unit
getMDOrNull(Record[15 + Offset]), // templateParams
getMDOrNull(Record[16 + Offset]), // declaration
getMDOrNull(Record[17 + Offset]), // retainedNodes
HasThrownTypes ? getMDOrNull(Record[20]) : nullptr // thrownTypes
getMDOrNull(Record[13 + OffsetB]), // templateParams
getMDOrNull(Record[14 + OffsetB]), // declaration
getMDOrNull(Record[15 + OffsetB]), // retainedNodes
HasThrownTypes ? getMDOrNull(Record[17 + OffsetB])
: nullptr // thrownTypes
));
MetadataList.assignValue(SP, NextMetadataNo);
NextMetadataNo++;
Expand Down
10 changes: 4 additions & 6 deletions llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1633,22 +1633,20 @@ void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
void ModuleBitcodeWriter::writeDISubprogram(const DISubprogram *N,
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
uint64_t HasUnitFlag = 1 << 1;
Record.push_back(N->isDistinct() | HasUnitFlag);
const uint64_t HasUnitFlag = 1 << 1;
const uint64_t HasSPFlagsFlag = 1 << 2;
Record.push_back(uint64_t(N->isDistinct()) | HasUnitFlag | HasSPFlagsFlag);
Record.push_back(VE.getMetadataOrNullID(N->getScope()));
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
Record.push_back(VE.getMetadataOrNullID(N->getRawLinkageName()));
Record.push_back(VE.getMetadataOrNullID(N->getFile()));
Record.push_back(N->getLine());
Record.push_back(VE.getMetadataOrNullID(N->getType()));
Record.push_back(N->isLocalToUnit());
Record.push_back(N->isDefinition());
Record.push_back(N->getScopeLine());
Record.push_back(VE.getMetadataOrNullID(N->getContainingType()));
Record.push_back(N->getVirtuality());
Record.push_back(N->getSPFlags());
Record.push_back(N->getVirtualIndex());
Record.push_back(N->getFlags());
Record.push_back(N->isOptimized());
Record.push_back(VE.getMetadataOrNullID(N->getRawUnit()));
Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get()));
Record.push_back(VE.getMetadataOrNullID(N->getDeclaration()));
Expand Down
31 changes: 26 additions & 5 deletions llvm/lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1607,6 +1607,7 @@ struct MDFieldPrinter {
void printInt(StringRef Name, IntTy Int, bool ShouldSkipZero = true);
void printBool(StringRef Name, bool Value, Optional<bool> Default = None);
void printDIFlags(StringRef Name, DINode::DIFlags Flags);
void printDISPFlags(StringRef Name, DISubprogram::DISPFlags Flags);
template <class IntTy, class Stringifier>
void printDwarfEnum(StringRef Name, IntTy Value, Stringifier toString,
bool ShouldSkipZero = true);
Expand Down Expand Up @@ -1705,6 +1706,30 @@ void MDFieldPrinter::printDIFlags(StringRef Name, DINode::DIFlags Flags) {
Out << FlagsFS << Extra;
}

void MDFieldPrinter::printDISPFlags(StringRef Name,
DISubprogram::DISPFlags Flags) {
// Always print this field, because no flags in the IR at all will be
// interpreted as old-style isDefinition: true.
Out << FS << Name << ": ";

if (!Flags) {
Out << 0;
return;
}

SmallVector<DISubprogram::DISPFlags, 8> SplitFlags;
auto Extra = DISubprogram::splitFlags(Flags, SplitFlags);

FieldSeparator FlagsFS(" | ");
for (auto F : SplitFlags) {
auto StringF = DISubprogram::getFlagString(F);
assert(!StringF.empty() && "Expected valid flag");
Out << FlagsFS << StringF;
}
if (Extra || SplitFlags.empty())
Out << FlagsFS << Extra;
}

void MDFieldPrinter::printEmissionKind(StringRef Name,
DICompileUnit::DebugEmissionKind EK) {
Out << FS << Name << ": " << DICompileUnit::emissionKindString(EK);
Expand Down Expand Up @@ -1925,18 +1950,14 @@ static void writeDISubprogram(raw_ostream &Out, const DISubprogram *N,
Printer.printMetadata("file", N->getRawFile());
Printer.printInt("line", N->getLine());
Printer.printMetadata("type", N->getRawType());
Printer.printBool("isLocal", N->isLocalToUnit());
Printer.printBool("isDefinition", N->isDefinition());
Printer.printInt("scopeLine", N->getScopeLine());
Printer.printMetadata("containingType", N->getRawContainingType());
Printer.printDwarfEnum("virtuality", N->getVirtuality(),
dwarf::VirtualityString);
if (N->getVirtuality() != dwarf::DW_VIRTUALITY_none ||
N->getVirtualIndex() != 0)
Printer.printInt("virtualIndex", N->getVirtualIndex(), false);
Printer.printInt("thisAdjustment", N->getThisAdjustment());
Printer.printDIFlags("flags", N->getFlags());
Printer.printBool("isOptimized", N->isOptimized());
Printer.printDISPFlags("spFlags", N->getSPFlags());
Printer.printMetadata("unit", N->getRawUnit());
Printer.printMetadata("templateParams", N->getRawTemplateParams());
Printer.printMetadata("declaration", N->getRawDeclaration());
Expand Down
34 changes: 34 additions & 0 deletions llvm/lib/IR/DebugInfoMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,40 @@ DILocalScope *DILocalScope::getNonLexicalBlockFileScope() const {
return const_cast<DILocalScope *>(this);
}

DISubprogram::DISPFlags DISubprogram::getFlag(StringRef Flag) {
return StringSwitch<DISPFlags>(Flag)
#define HANDLE_DISP_FLAG(ID, NAME) .Case("DISPFlag" #NAME, SPFlag##NAME)
#include "llvm/IR/DebugInfoFlags.def"
.Default(SPFlagZero);
}

StringRef DISubprogram::getFlagString(DISPFlags Flag) {
switch (Flag) {
case SPFlagVirtuality: // Appease a warning.
return "";
#define HANDLE_DISP_FLAG(ID, NAME) \
case SPFlag##NAME: \
return "DISPFlag" #NAME;
#include "llvm/IR/DebugInfoFlags.def"
}
return "";
}

DISubprogram::DISPFlags
DISubprogram::splitFlags(DISPFlags Flags,
SmallVectorImpl<DISPFlags> &SplitFlags) {
// Multi-bit fields can require special handling. In our case, however, the
// only multi-bit field is virtuality, and all its values happen to be
// single-bit values, so the right behavior just falls out.
#define HANDLE_DISP_FLAG(ID, NAME) \
if (DISPFlags Bit = Flags & SPFlag##NAME) { \
SplitFlags.push_back(Bit); \
Flags &= ~Bit; \
}
#include "llvm/IR/DebugInfoFlags.def"
return Flags;
}

DISubprogram *DISubprogram::getImpl(
LLVMContext &Context, Metadata *Scope, MDString *Name,
MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
Expand Down
Loading

0 comments on commit adcdc1b

Please sign in to comment.