1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

Macro debug info support in LLVM IR

Introduced DIMacro and DIMacroFile debug info metadata in the LLVM IR to support macros.

Differential Revision: http://reviews.llvm.org/D14687

llvm-svn: 255245
This commit is contained in:
Amjad Aboud 2015-12-10 12:56:35 +00:00
parent c26660fa6c
commit 85f2758759
20 changed files with 509 additions and 40 deletions

View File

@ -3751,9 +3751,9 @@ DICompileUnit
"""""""""""""
``DICompileUnit`` nodes represent a compile unit. The ``enums:``,
``retainedTypes:``, ``subprograms:``, ``globals:`` and ``imports:`` fields are
tuples containing the debug info to be emitted along with the compile unit,
regardless of code optimizations (some nodes are only emitted if there are
``retainedTypes:``, ``subprograms:``, ``globals:``, ``imports:`` and ``macros:``
fields are tuples containing the debug info to be emitted along with the compile
unit, regardless of code optimizations (some nodes are only emitted if there are
references to them from instructions).
.. code-block:: llvm
@ -3762,7 +3762,7 @@ references to them from instructions).
isOptimized: true, flags: "-O2", runtimeVersion: 2,
splitDebugFilename: "abc.debug", emissionKind: 1,
enums: !2, retainedTypes: !3, subprograms: !4,
globals: !5, imports: !6)
globals: !5, imports: !6, macros: !7, dwoId: 0x0abcd)
Compile unit descriptors provide the root scope for objects declared in a
specific compilation unit. File descriptors are defined using this scope.
@ -4128,6 +4128,32 @@ compile unit.
!2 = !DIImportedEntity(tag: DW_TAG_imported_module, name: "foo", scope: !0,
entity: !1, line: 7)
DIMacro
"""""""
``DIMacro`` nodes represent definition or undefinition of a macro identifiers.
The ``name:`` field is the macro identifier, followed by macro parameters when
definining a function-like macro, and the ``value`` field is the token-string
used to expand the macro identifier.
.. code-block:: llvm
!2 = !DIMacro(macinfo: DW_MACINFO_define, line: 7, name: "foo(x)",
value: "((x) + 1)")
!3 = !DIMacro(macinfo: DW_MACINFO_undef, line: 30, name: "foo")
DIMacroFile
"""""""""""
``DIMacroFile`` nodes represent inclusion of source files.
The ``nodes:`` field is a list of ``DIMacro`` and ``DIMacroFile`` nodes that
appear in the included source file.
.. code-block:: llvm
!2 = !DIMacroFile(macinfo: DW_MACINFO_start_file, line: 7, file: !2,
nodes: !3)
'``tbaa``' Metadata
^^^^^^^^^^^^^^^^^^^

View File

@ -220,7 +220,9 @@ enum { BITCODE_CURRENT_EPOCH = 0 };
METADATA_EXPRESSION = 29, // [distinct, n x element]
METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...]
METADATA_IMPORTED_ENTITY=31, // [distinct, tag, scope, entity, line, name]
METADATA_MODULE=32, // [distinct, scope, name, ...]
METADATA_MODULE = 32, // [distinct, scope, name, ...]
METADATA_MACRO = 33, // [distinct, macinfo, line, name, value]
METADATA_MACRO_FILE = 34, // [distinct, macinfo, line, file, ...]
};
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each

View File

@ -949,15 +949,16 @@ class DICompileUnit : public DIScope {
unsigned EmissionKind, DICompositeTypeArray EnumTypes,
DITypeArray RetainedTypes, DISubprogramArray Subprograms,
DIGlobalVariableArray GlobalVariables,
DIImportedEntityArray ImportedEntities, uint64_t DWOId,
StorageType Storage, bool ShouldCreate = true) {
DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,
uint64_t DWOId, StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, SourceLanguage, File,
getCanonicalMDString(Context, Producer), IsOptimized,
getCanonicalMDString(Context, Flags), RuntimeVersion,
getCanonicalMDString(Context, SplitDebugFilename),
EmissionKind, EnumTypes.get(), RetainedTypes.get(),
Subprograms.get(), GlobalVariables.get(),
ImportedEntities.get(), DWOId, Storage, ShouldCreate);
ImportedEntities.get(), Macros.get(), DWOId, Storage,
ShouldCreate);
}
static DICompileUnit *
getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File,
@ -965,15 +966,15 @@ class DICompileUnit : public DIScope {
unsigned RuntimeVersion, MDString *SplitDebugFilename,
unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
Metadata *Subprograms, Metadata *GlobalVariables,
Metadata *ImportedEntities, uint64_t DWOId, StorageType Storage,
bool ShouldCreate = true);
Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId,
StorageType Storage, bool ShouldCreate = true);
TempDICompileUnit cloneImpl() const {
return getTemporary(
getContext(), getSourceLanguage(), getFile(), getProducer(),
isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(),
getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(),
getGlobalVariables(), getImportedEntities(), DWOId);
getGlobalVariables(), getImportedEntities(), getMacros(), DWOId);
}
static void get() = delete;
@ -987,20 +988,22 @@ public:
StringRef SplitDebugFilename, unsigned EmissionKind,
DICompositeTypeArray EnumTypes, DITypeArray RetainedTypes,
DISubprogramArray Subprograms, DIGlobalVariableArray GlobalVariables,
DIImportedEntityArray ImportedEntities, uint64_t DWOId),
DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,
uint64_t DWOId),
(SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,
SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms,
GlobalVariables, ImportedEntities, DWOId))
GlobalVariables, ImportedEntities, Macros, DWOId))
DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(
DICompileUnit,
(unsigned SourceLanguage, Metadata *File, MDString *Producer,
bool IsOptimized, MDString *Flags, unsigned RuntimeVersion,
MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes,
Metadata *RetainedTypes, Metadata *Subprograms,
Metadata *GlobalVariables, Metadata *ImportedEntities, uint64_t DWOId),
Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros,
uint64_t DWOId),
(SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,
SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms,
GlobalVariables, ImportedEntities, DWOId))
GlobalVariables, ImportedEntities, Macros, DWOId))
TempDICompileUnit clone() const { return cloneImpl(); }
@ -1026,6 +1029,9 @@ public:
DIImportedEntityArray getImportedEntities() const {
return cast_or_null<MDTuple>(getRawImportedEntities());
}
DIMacroNodeArray getMacros() const {
return cast_or_null<MDTuple>(getRawMacros());
}
uint64_t getDWOId() const { return DWOId; }
void setDWOId(uint64_t DwoId) { DWOId = DwoId; }
@ -1039,6 +1045,7 @@ public:
Metadata *getRawSubprograms() const { return getOperand(6); }
Metadata *getRawGlobalVariables() const { return getOperand(7); }
Metadata *getRawImportedEntities() const { return getOperand(8); }
Metadata *getRawMacros() const { return getOperand(9); }
/// \brief Replace arrays.
///
@ -1061,6 +1068,7 @@ public:
void replaceImportedEntities(DIImportedEntityArray N) {
replaceOperandWith(8, N.get());
}
void replaceMacros(DIMacroNodeArray N) { replaceOperandWith(9, N.get()); }
/// @}
static bool classof(const Metadata *MD) {
@ -2199,6 +2207,165 @@ public:
}
};
/// \brief Macro Info DWARF-like metadata node.
///
/// A metadata node with a DWARF macro info (i.e., a constant named
/// \c DW_MACINFO_*, defined in llvm/Support/Dwarf.h). Called \a DIMacroNode
/// because it's potentially used for non-DWARF output.
class DIMacroNode : public MDNode {
friend class LLVMContextImpl;
friend class MDNode;
protected:
DIMacroNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned MIType,
ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None)
: MDNode(C, ID, Storage, Ops1, Ops2) {
assert(MIType < 1u << 16);
SubclassData16 = MIType;
}
~DIMacroNode() = default;
template <class Ty> Ty *getOperandAs(unsigned I) const {
return cast_or_null<Ty>(getOperand(I));
}
StringRef getStringOperand(unsigned I) const {
if (auto *S = getOperandAs<MDString>(I))
return S->getString();
return StringRef();
}
static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) {
if (S.empty())
return nullptr;
return MDString::get(Context, S);
}
public:
unsigned getMacinfoType() const { return SubclassData16; }
static bool classof(const Metadata *MD) {
switch (MD->getMetadataID()) {
default:
return false;
case DIMacroKind:
case DIMacroFileKind:
return true;
}
}
};
class DIMacro : public DIMacroNode {
friend class LLVMContextImpl;
friend class MDNode;
unsigned Line;
DIMacro(LLVMContext &C, StorageType Storage, unsigned MIType, unsigned Line,
ArrayRef<Metadata *> Ops)
: DIMacroNode(C, DIMacroKind, Storage, MIType, Ops), Line(Line) {}
~DIMacro() = default;
static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line,
StringRef Name, StringRef Value, StorageType Storage,
bool ShouldCreate = true) {
return getImpl(Context, MIType, Line, getCanonicalMDString(Context, Name),
getCanonicalMDString(Context, Value), Storage, ShouldCreate);
}
static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line,
MDString *Name, MDString *Value, StorageType Storage,
bool ShouldCreate = true);
TempDIMacro cloneImpl() const {
return getTemporary(getContext(), getMacinfoType(), getLine(), getName(),
getValue());
}
public:
DEFINE_MDNODE_GET(DIMacro, (unsigned MIType, unsigned Line, StringRef Name,
StringRef Value = ""),
(MIType, Line, Name, Value))
DEFINE_MDNODE_GET(DIMacro, (unsigned MIType, unsigned Line, MDString *Name,
MDString *Value),
(MIType, Line, Name, Value))
TempDIMacro clone() const { return cloneImpl(); }
unsigned getLine() const { return Line; }
StringRef getName() const { return getStringOperand(0); }
StringRef getValue() const { return getStringOperand(1); }
MDString *getRawName() const { return getOperandAs<MDString>(0); }
MDString *getRawValue() const { return getOperandAs<MDString>(1); }
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIMacroKind;
}
};
class DIMacroFile : public DIMacroNode {
friend class LLVMContextImpl;
friend class MDNode;
unsigned Line;
DIMacroFile(LLVMContext &C, StorageType Storage, unsigned MIType,
unsigned Line, ArrayRef<Metadata *> Ops)
: DIMacroNode(C, DIMacroFileKind, Storage, MIType, Ops), Line(Line) {}
~DIMacroFile() = default;
static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType,
unsigned Line, DIFile *File,
DIMacroNodeArray Elements, StorageType Storage,
bool ShouldCreate = true) {
return getImpl(Context, MIType, Line, static_cast<Metadata *>(File),
Elements.get(), Storage, ShouldCreate);
}
static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType,
unsigned Line, Metadata *File, Metadata *Elements,
StorageType Storage, bool ShouldCreate = true);
TempDIMacroFile cloneImpl() const {
return getTemporary(getContext(), getMacinfoType(), getLine(), getFile(),
getElements());
}
public:
DEFINE_MDNODE_GET(DIMacroFile, (unsigned MIType, unsigned Line, DIFile *File,
DIMacroNodeArray Elements),
(MIType, Line, File, Elements))
DEFINE_MDNODE_GET(DIMacroFile, (unsigned MIType, unsigned Line,
Metadata *File, Metadata *Elements),
(MIType, Line, File, Elements))
TempDIMacroFile clone() const { return cloneImpl(); }
void replaceElements(DIMacroNodeArray Elements) {
#ifndef NDEBUG
for (DIMacroNode *Op : getElements())
assert(std::find(Elements->op_begin(), Elements->op_end(), Op) &&
"Lost a macro node during macro node list replacement");
#endif
replaceOperandWith(1, Elements.get());
}
unsigned getLine() const { return Line; }
DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); }
DIMacroNodeArray getElements() const {
return cast_or_null<MDTuple>(getRawElements());
}
Metadata *getRawFile() const { return getOperand(0); }
Metadata *getRawElements() const { return getOperand(1); }
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIMacroFileKind;
}
};
} // end namespace llvm
#undef DEFINE_MDNODE_GET_UNPACK_IMPL

View File

@ -108,6 +108,9 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariable)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocalVariable)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIObjCProperty)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity)
HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro)
HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile)
#undef HANDLE_METADATA
#undef HANDLE_METADATA_LEAF

View File

@ -83,7 +83,9 @@ public:
DIImportedEntityKind,
ConstantAsMetadataKind,
LocalAsMetadataKind,
MDStringKind
MDStringKind,
DIMacroKind,
DIMacroFileKind
};
protected:

View File

@ -625,6 +625,7 @@ const char *GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage);
///
/// \li \a getTag() returns \a DW_TAG_invalid on invalid input.
/// \li \a getVirtuality() returns \a DW_VIRTUALITY_invalid on invalid input.
/// \li \a getMacinfo() returns \a DW_MACINFO_invalid on invalid input.
///
/// @{
unsigned getTag(StringRef TagString);
@ -632,6 +633,7 @@ unsigned getOperationEncoding(StringRef OperationEncodingString);
unsigned getVirtuality(StringRef VirtualityString);
unsigned getLanguage(StringRef LanguageString);
unsigned getAttributeEncoding(StringRef EncodingString);
unsigned getMacinfo(StringRef MacinfoString);
/// @}
/// \brief Returns the symbolic string representing Val when used as a value

View File

@ -778,6 +778,7 @@ lltok::Kind LLLexer::LexIdentifier() {
DWKEYWORD(VIRTUALITY, DwarfVirtuality);
DWKEYWORD(LANG, DwarfLang);
DWKEYWORD(OP, DwarfOp);
DWKEYWORD(MACINFO, DwarfMacinfo);
#undef DWKEYWORD
if (Keyword.startswith("DIFlag")) {

View File

@ -3279,6 +3279,11 @@ struct DwarfTagField : public MDUnsignedField {
DwarfTagField(dwarf::Tag DefaultTag)
: MDUnsignedField(DefaultTag, dwarf::DW_TAG_hi_user) {}
};
struct DwarfMacinfoTypeField : public MDUnsignedField {
DwarfMacinfoTypeField() : MDUnsignedField(0, dwarf::DW_MACINFO_vendor_ext) {}
DwarfMacinfoTypeField(dwarf::MacinfoRecordType DefaultType)
: MDUnsignedField(DefaultType, dwarf::DW_MACINFO_vendor_ext) {}
};
struct DwarfAttEncodingField : public MDUnsignedField {
DwarfAttEncodingField() : MDUnsignedField(0, dwarf::DW_ATE_hi_user) {}
};
@ -3370,6 +3375,26 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DwarfTagField &Result) {
return false;
}
template <>
bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
DwarfMacinfoTypeField &Result) {
if (Lex.getKind() == lltok::APSInt)
return ParseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result));
if (Lex.getKind() != lltok::DwarfMacinfo)
return TokError("expected DWARF macinfo type");
unsigned Macinfo = dwarf::getMacinfo(Lex.getStrVal());
if (Macinfo == dwarf::DW_MACINFO_invalid)
return TokError(
"invalid DWARF macinfo type" + Twine(" '") + Lex.getStrVal() + "'");
assert(Macinfo <= Result.Max && "Expected valid DWARF macinfo type");
Result.assign(Macinfo);
Lex.Lex();
return false;
}
template <>
bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
DwarfVirtualityField &Result) {
@ -3782,7 +3807,7 @@ bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) {
/// isOptimized: true, flags: "-O2", runtimeVersion: 1,
/// splitDebugFilename: "abc.debug", emissionKind: 1,
/// enums: !1, retainedTypes: !2, subprograms: !3,
/// globals: !4, imports: !5, dwoId: 0x0abcd)
/// globals: !4, imports: !5, macros: !6, dwoId: 0x0abcd)
bool LLParser::ParseDICompileUnit(MDNode *&Result, bool IsDistinct) {
if (!IsDistinct)
return Lex.Error("missing 'distinct', required for !DICompileUnit");
@ -3801,6 +3826,7 @@ bool LLParser::ParseDICompileUnit(MDNode *&Result, bool IsDistinct) {
OPTIONAL(subprograms, MDField, ); \
OPTIONAL(globals, MDField, ); \
OPTIONAL(imports, MDField, ); \
OPTIONAL(macros, MDField, ); \
OPTIONAL(dwoId, MDUnsignedField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
@ -3808,7 +3834,8 @@ bool LLParser::ParseDICompileUnit(MDNode *&Result, bool IsDistinct) {
Result = DICompileUnit::getDistinct(
Context, language.Val, file.Val, producer.Val, isOptimized.Val, flags.Val,
runtimeVersion.Val, splitDebugFilename.Val, emissionKind.Val, enums.Val,
retainedTypes.Val, subprograms.Val, globals.Val, imports.Val, dwoId.Val);
retainedTypes.Val, subprograms.Val, globals.Val, imports.Val, macros.Val,
dwoId.Val);
return false;
}
@ -3904,6 +3931,39 @@ bool LLParser::ParseDINamespace(MDNode *&Result, bool IsDistinct) {
return false;
}
/// ParseDIMacro:
/// ::= !DIMacro(macinfo: type, line: 9, name: "SomeMacro", value: "SomeValue")
bool LLParser::ParseDIMacro(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
REQUIRED(type, DwarfMacinfoTypeField, ); \
REQUIRED(line, LineField, ); \
REQUIRED(name, MDStringField, ); \
OPTIONAL(value, MDStringField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
Result = GET_OR_DISTINCT(DIMacro,
(Context, type.Val, line.Val, name.Val, value.Val));
return false;
}
/// ParseDIMacroFile:
/// ::= !DIMacroFile(line: 9, file: !2, nodes: !3)
bool LLParser::ParseDIMacroFile(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
OPTIONAL(type, DwarfMacinfoTypeField, (dwarf::DW_MACINFO_start_file)); \
REQUIRED(line, LineField, ); \
REQUIRED(file, MDField, ); \
OPTIONAL(nodes, MDField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
Result = GET_OR_DISTINCT(DIMacroFile,
(Context, type.Val, line.Val, file.Val, nodes.Val));
return false;
}
/// ParseDIModule:
/// ::= !DIModule(scope: !0, name: "SomeModule", configMacros: "-DNDEBUG",
/// includePath: "/usr/include", isysroot: "/")

View File

@ -215,6 +215,7 @@ namespace lltok {
DwarfLang, // DW_LANG_foo
DwarfOp, // DW_OP_foo
DIFlag, // DIFlagFoo
DwarfMacinfo, // DW_MACINFO_foo
// Type valued tokens (TyVal).
Type,

View File

@ -2214,10 +2214,10 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
break;
}
case bitc::METADATA_COMPILE_UNIT: {
if (Record.size() < 14 || Record.size() > 15)
if (Record.size() < 14 || Record.size() > 16)
return error("Invalid record");
// Ignore Record[1], which indicates whether this compile unit is
// Ignore Record[0], which indicates whether this compile unit is
// distinct. It's always distinct.
MDValueList.assignValue(
DICompileUnit::getDistinct(
@ -2226,7 +2226,9 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
Record[6], getMDString(Record[7]), Record[8],
getMDOrNull(Record[9]), getMDOrNull(Record[10]),
getMDOrNull(Record[11]), getMDOrNull(Record[12]),
getMDOrNull(Record[13]), Record.size() == 14 ? 0 : Record[14]),
getMDOrNull(Record[13]),
Record.size() <= 15 ? 0 : getMDOrNull(Record[15]),
Record.size() <= 14 ? 0 : Record[14]),
NextMDValueNo++);
break;
}
@ -2294,6 +2296,28 @@ std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
NextMDValueNo++);
break;
}
case bitc::METADATA_MACRO: {
if (Record.size() != 5)
return error("Invalid record");
MDValueList.assignValue(
GET_OR_DISTINCT(DIMacro, Record[0],
(Context, Record[1], Record[2],
getMDString(Record[3]), getMDString(Record[4]))),
NextMDValueNo++);
break;
}
case bitc::METADATA_MACRO_FILE: {
if (Record.size() != 5)
return error("Invalid record");
MDValueList.assignValue(
GET_OR_DISTINCT(DIMacroFile, Record[0],
(Context, Record[1], Record[2],
getMDOrNull(Record[3]), getMDOrNull(Record[4]))),
NextMDValueNo++);
break;
}
case bitc::METADATA_TEMPLATE_TYPE: {
if (Record.size() != 3)
return error("Invalid record");

View File

@ -1017,6 +1017,7 @@ static void WriteDICompileUnit(const DICompileUnit *N,
Record.push_back(VE.getMetadataOrNullID(N->getGlobalVariables().get()));
Record.push_back(VE.getMetadataOrNullID(N->getImportedEntities().get()));
Record.push_back(N->getDWOId());
Record.push_back(VE.getMetadataOrNullID(N->getMacros().get()));
Stream.EmitRecord(bitc::METADATA_COMPILE_UNIT, Record, Abbrev);
Record.clear();
@ -1092,6 +1093,33 @@ static void WriteDINamespace(const DINamespace *N, const ValueEnumerator &VE,
Record.clear();
}
static void WriteDIMacro(const DIMacro *N, const ValueEnumerator &VE,
BitstreamWriter &Stream,
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev) {
Record.push_back(N->isDistinct());
Record.push_back(N->getMacinfoType());
Record.push_back(N->getLine());
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
Record.push_back(VE.getMetadataOrNullID(N->getRawValue()));
Stream.EmitRecord(bitc::METADATA_MACRO, Record, Abbrev);
Record.clear();
}
static void WriteDIMacroFile(const DIMacroFile *N, const ValueEnumerator &VE,
BitstreamWriter &Stream,
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
Record.push_back(N->isDistinct());
Record.push_back(N->getMacinfoType());
Record.push_back(N->getLine());
Record.push_back(VE.getMetadataOrNullID(N->getFile()));
Record.push_back(VE.getMetadataOrNullID(N->getElements().get()));
Stream.EmitRecord(bitc::METADATA_MACRO_FILE, Record, Abbrev);
Record.clear();
}
static void WriteDIModule(const DIModule *N, const ValueEnumerator &VE,
BitstreamWriter &Stream,
SmallVectorImpl<uint64_t> &Record, unsigned Abbrev) {

View File

@ -1396,6 +1396,7 @@ struct MDFieldPrinter {
: Out(Out), TypePrinter(TypePrinter), Machine(Machine), Context(Context) {
}
void printTag(const DINode *N);
void printMacinfoType(const DIMacroNode *N);
void printString(StringRef Name, StringRef Value,
bool ShouldSkipEmpty = true);
void printMetadata(StringRef Name, const Metadata *MD,
@ -1418,6 +1419,14 @@ void MDFieldPrinter::printTag(const DINode *N) {
Out << N->getTag();
}
void MDFieldPrinter::printMacinfoType(const DIMacroNode *N) {
Out << FS << "type: ";
if (const char *Type = dwarf::MacinfoString(N->getMacinfoType()))
Out << Type;
else
Out << N->getMacinfoType();
}
void MDFieldPrinter::printString(StringRef Name, StringRef Value,
bool ShouldSkipEmpty) {
if (ShouldSkipEmpty && Value.empty())
@ -1643,6 +1652,7 @@ static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N,
Printer.printMetadata("subprograms", N->getRawSubprograms());
Printer.printMetadata("globals", N->getRawGlobalVariables());
Printer.printMetadata("imports", N->getRawImportedEntities());
Printer.printMetadata("macros", N->getRawMacros());
Printer.printInt("dwoId", N->getDWOId());
Out << ")";
}
@ -1711,6 +1721,29 @@ static void writeDINamespace(raw_ostream &Out, const DINamespace *N,
Out << ")";
}
static void writeDIMacro(raw_ostream &Out, const DIMacro *N,
TypePrinting *TypePrinter, SlotTracker *Machine,
const Module *Context) {
Out << "!DIMacro(";
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
Printer.printMacinfoType(N);
Printer.printInt("line", N->getLine());
Printer.printString("name", N->getName());
Printer.printString("value", N->getValue());
Out << ")";
}
static void writeDIMacroFile(raw_ostream &Out, const DIMacroFile *N,
TypePrinting *TypePrinter, SlotTracker *Machine,
const Module *Context) {
Out << "!DIMacroFile(";
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
Printer.printInt("line", N->getLine());
Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false);
Printer.printMetadata("nodes", N->getRawElements());
Out << ")";
}
static void writeDIModule(raw_ostream &Out, const DIModule *N,
TypePrinting *TypePrinter, SlotTracker *Machine,
const Module *Context) {

View File

@ -148,7 +148,7 @@ DICompileUnit *DIBuilder::createCompileUnit(
CUNode = DICompileUnit::getDistinct(
VMContext, Lang, DIFile::get(VMContext, Filename, Directory), Producer,
isOptimized, Flags, RunTimeVer, SplitName, Kind, nullptr,
nullptr, nullptr, nullptr, nullptr, DWOId);
nullptr, nullptr, nullptr, nullptr, nullptr, DWOId);
// Create a named metadata so that it is easier to find cu in a module.
// Note that we only generate this when the caller wants to actually

View File

@ -315,7 +315,7 @@ DICompileUnit *DICompileUnit::getImpl(
unsigned RuntimeVersion, MDString *SplitDebugFilename,
unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
Metadata *Subprograms, Metadata *GlobalVariables,
Metadata *ImportedEntities, uint64_t DWOId,
Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId,
StorageType Storage, bool ShouldCreate) {
assert(Storage != Uniqued && "Cannot unique DICompileUnit");
assert(isCanonical(Producer) && "Expected canonical MDString");
@ -324,7 +324,7 @@ DICompileUnit *DICompileUnit::getImpl(
Metadata *Ops[] = {File, Producer, Flags, SplitDebugFilename, EnumTypes,
RetainedTypes, Subprograms, GlobalVariables,
ImportedEntities};
ImportedEntities, Macros};
return storeImpl(new (ArrayRef<Metadata *>(Ops).size()) DICompileUnit(
Context, Storage, SourceLanguage, IsOptimized,
RuntimeVersion, EmissionKind, DWOId, Ops),
@ -557,3 +557,24 @@ DIImportedEntity *DIImportedEntity::getImpl(LLVMContext &Context, unsigned Tag,
Metadata *Ops[] = {Scope, Entity, Name};
DEFINE_GETIMPL_STORE(DIImportedEntity, (Tag, Line), Ops);
}
DIMacro *DIMacro::getImpl(LLVMContext &Context, unsigned MIType,
unsigned Line, MDString *Name, MDString *Value,
StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
DEFINE_GETIMPL_LOOKUP(DIMacro,
(MIType, Line, getString(Name), getString(Value)));
Metadata *Ops[] = { Name, Value };
DEFINE_GETIMPL_STORE(DIMacro, (MIType, Line), Ops);
}
DIMacroFile *DIMacroFile::getImpl(LLVMContext &Context, unsigned MIType,
unsigned Line, Metadata *File,
Metadata *Elements, StorageType Storage,
bool ShouldCreate) {
DEFINE_GETIMPL_LOOKUP(DIMacroFile,
(MIType, Line, File, Elements));
Metadata *Ops[] = { File, Elements };
DEFINE_GETIMPL_STORE(DIMacroFile, (MIType, Line), Ops);
}

View File

@ -792,6 +792,49 @@ template <> struct MDNodeKeyImpl<DIImportedEntity> {
}
};
template <> struct MDNodeKeyImpl<DIMacro> {
unsigned MIType;
unsigned Line;
StringRef Name;
StringRef Value;
MDNodeKeyImpl(unsigned MIType, unsigned Line, StringRef Name, StringRef Value)
: MIType(MIType), Line(Line), Name(Name), Value(Value) {}
MDNodeKeyImpl(const DIMacro *N)
: MIType(N->getMacinfoType()), Line(N->getLine()), Name(N->getName()),
Value(N->getValue()) {}
bool isKeyOf(const DIMacro *RHS) const {
return MIType == RHS->getMacinfoType() && Line == RHS->getLine() &&
Name == RHS->getName() && Value == RHS->getValue();
}
unsigned getHashValue() const {
return hash_combine(MIType, Line, Name, Value);
}
};
template <> struct MDNodeKeyImpl<DIMacroFile> {
unsigned MIType;
unsigned Line;
Metadata *File;
Metadata *Elements;
MDNodeKeyImpl(unsigned MIType, unsigned Line, Metadata *File,
Metadata *Elements)
: MIType(MIType), Line(Line), File(File), Elements(Elements) {}
MDNodeKeyImpl(const DIMacroFile *N)
: MIType(N->getMacinfoType()), Line(N->getLine()), File(N->getRawFile()),
Elements(N->getRawElements()) {}
bool isKeyOf(const DIMacroFile *RHS) const {
return MIType == RHS->getMacinfoType() && Line == RHS->getLine() &&
File == RHS->getRawFile() && File == RHS->getRawElements();
}
unsigned getHashValue() const {
return hash_combine(MIType, Line, File, Elements);
}
};
/// \brief DenseMapInfo for MDNode subclasses.
template <class NodeTy> struct MDNodeInfo {
typedef MDNodeKeyImpl<NodeTy> KeyTy;

View File

@ -860,8 +860,6 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
"invalid composite elements", &N, N.getRawElements());
Assert(isTypeRef(N, N.getRawVTableHolder()), "invalid vtable holder", &N,
N.getRawVTableHolder());
Assert(!N.getRawElements() || isa<MDTuple>(N.getRawElements()),
"invalid composite elements", &N, N.getRawElements());
Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags",
&N);
if (auto *Params = N.getRawTemplateParams())
@ -935,6 +933,12 @@ void Verifier::visitDICompileUnit(const DICompileUnit &N) {
Op);
}
}
if (auto *Array = N.getRawMacros()) {
Assert(isa<MDTuple>(Array), "invalid macro list", &N, Array);
for (Metadata *Op : N.getMacros()->operands()) {
Assert(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op);
}
}
}
void Verifier::visitDISubprogram(const DISubprogram &N) {
@ -988,6 +992,27 @@ void Verifier::visitDINamespace(const DINamespace &N) {
Assert(isa<DIScope>(S), "invalid scope ref", &N, S);
}
void Verifier::visitDIMacro(const DIMacro &N) {
Assert(N.getMacinfoType() == dwarf::DW_MACINFO_define ||
N.getMacinfoType() == dwarf::DW_MACINFO_undef,
"invalid macinfo type", &N);
Assert(!N.getName().empty(), "anonymous macro", &N);
}
void Verifier::visitDIMacroFile(const DIMacroFile &N) {
Assert(N.getMacinfoType() == dwarf::DW_MACINFO_start_file,
"invalid macinfo type", &N);
if (auto *F = N.getRawFile())
Assert(isa<DIFile>(F), "invalid file", &N, F);
if (auto *Array = N.getRawElements()) {
Assert(isa<MDTuple>(Array), "invalid macro list", &N, Array);
for (Metadata *Op : N.getElements()->operands()) {
Assert(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op);
}
}
}
void Verifier::visitDIModule(const DIModule &N) {
Assert(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N);
Assert(!N.getName().empty(), "anonymous module", &N);

View File

@ -473,6 +473,16 @@ const char *llvm::dwarf::MacinfoString(unsigned Encoding) {
return nullptr;
}
unsigned llvm::dwarf::getMacinfo(StringRef MacinfoString) {
return StringSwitch<unsigned>(MacinfoString)
.Case("DW_MACINFO_define", DW_MACINFO_define)
.Case("DW_MACINFO_undef", DW_MACINFO_undef)
.Case("DW_MACINFO_start_file", DW_MACINFO_start_file)
.Case("DW_MACINFO_end_file", DW_MACINFO_end_file)
.Case("DW_MACINFO_vendor_ext", DW_MACINFO_vendor_ext)
.Default(DW_MACINFO_invalid);
}
const char *llvm::dwarf::CallFrameString(unsigned Encoding) {
switch (Encoding) {
case DW_CFA_nop: return "DW_CFA_nop";

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}
!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}
; 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: !0 = !DISubrange(count: 3)
; CHECK-NEXT: !1 = !DISubrange(count: 3, lowerBound: 4)
@ -63,10 +63,19 @@
!25 = !DICompositeType(tag: DW_TAG_structure_type)
!26 = !DICompositeType(tag: DW_TAG_structure_type, runtimeLang: 6)
; !25 = !{!7, !7}
; !26 = !DISubroutineType(flags: DIFlagPublic | DIFlagStaticMember, types: !25)
; !27 = !DISubroutineType(types: !25)
; CHECK-NEXT: !25 = !{!6, !6}
; CHECK-NEXT: !26 = !DISubroutineType(flags: DIFlagPublic | DIFlagStaticMember, types: !25)
; CHECK-NEXT: !27 = !DISubroutineType(types: !25)
!27 = !{!7, !7}
!28 = !DISubroutineType(flags: DIFlagPublic | DIFlagStaticMember, types: !27)
!29 = !DISubroutineType(flags: 0, types: !27)
!30 = !DISubroutineType(types: !27)
; CHECK-NEXT: !28 = !DIMacro(type: DW_MACINFO_define, line: 9, name: "Name", value: "Value")
; CHECK-NEXT: !29 = distinct !{!28}
; CHECK-NEXT: !30 = !DIMacroFile(line: 9, file: !12, nodes: !29)
; CHECK-NEXT: !31 = !DIMacroFile(line: 11, file: !12)
!31 = !DIMacro(type: DW_MACINFO_define, line: 9, name: "Name", value: "Value")
!32 = distinct !{!31}
!33 = !DIMacroFile(line: 9, file: !14, nodes: !32)
!34 = !DIMacroFile(type: DW_MACINFO_start_file, line: 11, file: !14)

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, !1, !2, !3, !4, !5, !6, !7, !8}
!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9}
!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9}
!0 = distinct !{}
!1 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
@ -11,15 +11,16 @@
!4 = distinct !{}
!5 = distinct !{}
!6 = distinct !{}
!7 = distinct !{}
; CHECK: !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, flags: "-O2", runtimeVersion: 2, splitDebugFilename: "abc.debug", emissionKind: 3, enums: !2, retainedTypes: !3, subprograms: !4, globals: !5, imports: !6, dwoId: 42)
!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
; CHECK: !8 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, flags: "-O2", runtimeVersion: 2, splitDebugFilename: "abc.debug", emissionKind: 3, enums: !2, retainedTypes: !3, subprograms: !4, globals: !5, imports: !6, macros: !7, dwoId: 42)
!8 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
isOptimized: true, flags: "-O2", runtimeVersion: 2,
splitDebugFilename: "abc.debug", emissionKind: 3,
enums: !2, retainedTypes: !3, subprograms: !4,
globals: !5, imports: !6, dwoId: 42)
globals: !5, imports: !6, macros: !7, dwoId: 42)
; CHECK: !8 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: 0)
!8 = distinct !DICompileUnit(language: 12, file: !1, producer: "",
; CHECK: !9 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: 0)
!9 = distinct !DICompileUnit(language: 12, file: !1, producer: "",
isOptimized: false, flags: "", runtimeVersion: 0,
splitDebugFilename: "", emissionKind: 0)

View File

@ -1312,10 +1312,12 @@ TEST_F(DICompileUnitTest, get) {
MDTuple *GlobalVariables = getTuple();
MDTuple *ImportedEntities = getTuple();
uint64_t DWOId = 0x10000000c0ffee;
MDTuple *Macros = getTuple();
auto *N = DICompileUnit::getDistinct(
Context, SourceLanguage, File, Producer, IsOptimized, Flags,
RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
RetainedTypes, Subprograms, GlobalVariables, ImportedEntities, DWOId);
RetainedTypes, Subprograms, GlobalVariables, ImportedEntities, Macros,
DWOId);
EXPECT_EQ(dwarf::DW_TAG_compile_unit, N->getTag());
EXPECT_EQ(SourceLanguage, N->getSourceLanguage());
@ -1331,6 +1333,7 @@ TEST_F(DICompileUnitTest, get) {
EXPECT_EQ(Subprograms, N->getSubprograms().get());
EXPECT_EQ(GlobalVariables, N->getGlobalVariables().get());
EXPECT_EQ(ImportedEntities, N->getImportedEntities().get());
EXPECT_EQ(Macros, N->getMacros().get());
EXPECT_EQ(DWOId, N->getDWOId());
TempDICompileUnit Temp = N->clone();
@ -1348,6 +1351,7 @@ TEST_F(DICompileUnitTest, get) {
EXPECT_EQ(Subprograms, Temp->getSubprograms().get());
EXPECT_EQ(GlobalVariables, Temp->getGlobalVariables().get());
EXPECT_EQ(ImportedEntities, Temp->getImportedEntities().get());
EXPECT_EQ(Macros, Temp->getMacros().get());
EXPECT_EQ(DWOId, Temp->getDWOId());
auto *TempAddress = Temp.get();
@ -1372,7 +1376,7 @@ TEST_F(DICompileUnitTest, replaceArrays) {
auto *N = DICompileUnit::getDistinct(
Context, SourceLanguage, File, Producer, IsOptimized, Flags,
RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
RetainedTypes, nullptr, nullptr, ImportedEntities, DWOId);
RetainedTypes, nullptr, nullptr, ImportedEntities, nullptr, DWOId);
auto *Subprograms = MDTuple::getDistinct(Context, None);
EXPECT_EQ(nullptr, N->getSubprograms().get());
@ -1387,6 +1391,13 @@ TEST_F(DICompileUnitTest, replaceArrays) {
EXPECT_EQ(GlobalVariables, N->getGlobalVariables().get());
N->replaceGlobalVariables(nullptr);
EXPECT_EQ(nullptr, N->getGlobalVariables().get());
auto *Macros = MDTuple::getDistinct(Context, None);
EXPECT_EQ(nullptr, N->getMacros().get());
N->replaceMacros(Macros);
EXPECT_EQ(Macros, N->getMacros().get());
N->replaceMacros(nullptr);
EXPECT_EQ(nullptr, N->getMacros().get());
}
typedef MetadataTest DISubprogramTest;