diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index 810f3668d05d4..eca908a24aac7 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -548,7 +548,6 @@ namespace llvm { bool parseMetadataAsValue(Value *&V, PerFunctionState &PFS); bool parseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg, PerFunctionState *PFS); - bool parseDIArgList(Metadata *&MD, PerFunctionState *PFS); bool parseMetadata(Metadata *&MD, PerFunctionState *PFS); bool parseMDTuple(MDNode *&MD, bool IsDistinct = false); bool parseMDNode(MDNode *&N); @@ -570,6 +569,8 @@ namespace llvm { #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ bool parse##CLASS(MDNode *&Result, bool IsDistinct); #include "llvm/IR/Metadata.def" + bool parseDIArgList(MDNode *&Result, bool IsDistinct, + PerFunctionState *PFS); // Function Parsing. struct ArgInfo { diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 50ba00cf8df3e..3d9ee1c33e946 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -3753,38 +3753,49 @@ class DIMacroFile : public DIMacroNode { /// List of ValueAsMetadata, to be used as an argument to a dbg.value /// intrinsic. -class DIArgList : public Metadata, ReplaceableMetadataImpl { - friend class ReplaceableMetadataImpl; +class DIArgList : public MDNode { friend class LLVMContextImpl; + friend class MDNode; using iterator = SmallVectorImpl::iterator; SmallVector Args; - DIArgList(LLVMContext &Context, ArrayRef Args) - : Metadata(DIArgListKind, Uniqued), ReplaceableMetadataImpl(Context), + DIArgList(LLVMContext &C, StorageType Storage, + ArrayRef Args) + : MDNode(C, DIArgListKind, Storage, std::nullopt), Args(Args.begin(), Args.end()) { track(); } ~DIArgList() { untrack(); } + static DIArgList *getImpl(LLVMContext &Context, + ArrayRef Args, + StorageType Storage, bool ShouldCreate = true); + + TempDIArgList cloneImpl() const { + return getTemporary(getContext(), getArgs()); + } + void track(); void untrack(); - void dropAllReferences(bool Untrack); + void dropAllReferences(); public: - static DIArgList *get(LLVMContext &Context, ArrayRef Args); + DEFINE_MDNODE_GET(DIArgList, (ArrayRef Args), (Args)) + + TempDIArgList clone() const { return cloneImpl(); } ArrayRef getArgs() const { return Args; } iterator args_begin() { return Args.begin(); } iterator args_end() { return Args.end(); } - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == DIArgListKind; + ReplaceableMetadataImpl *getReplaceableUses() { + return Context.getReplaceableUses(); } - SmallVector getAllDPValueUsers() { - return ReplaceableMetadataImpl::getAllDPValueUsers(); + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIArgListKind; } void handleChangedOperand(void *Ref, Metadata *New); diff --git a/llvm/include/llvm/IR/Metadata.def b/llvm/include/llvm/IR/Metadata.def index a3cfb9ad6e3e7..36c34c1d2347c 100644 --- a/llvm/include/llvm/IR/Metadata.def +++ b/llvm/include/llvm/IR/Metadata.def @@ -77,7 +77,6 @@ HANDLE_METADATA_BRANCH(ValueAsMetadata) HANDLE_METADATA_LEAF(ConstantAsMetadata) HANDLE_METADATA_LEAF(LocalAsMetadata) HANDLE_METADATA_LEAF(DistinctMDOperandPlaceholder) -HANDLE_METADATA_LEAF(DIArgList) HANDLE_MDNODE_BRANCH(MDNode) HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation) @@ -116,6 +115,7 @@ HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIArgList) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange) diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h index 4498423c4c460..a245dabe086f0 100644 --- a/llvm/include/llvm/IR/Metadata.h +++ b/llvm/include/llvm/IR/Metadata.h @@ -1037,6 +1037,7 @@ struct TempMDNodeDeleter { class MDNode : public Metadata { friend class ReplaceableMetadataImpl; friend class LLVMContextImpl; + friend class DIArgList; /// The header that is coallocated with an MDNode along with its "small" /// operands. It is located immediately before the main body of the node. @@ -1219,7 +1220,9 @@ class MDNode : public Metadata { bool isDistinct() const { return Storage == Distinct; } bool isTemporary() const { return Storage == Temporary; } - bool isReplaceable() const { return isTemporary(); } + bool isReplaceable() const { + return isTemporary() || getMetadataID() == DIArgListKind; + } /// RAUW a temporary. /// diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 2d2c1bf65311c..a09d19c11c6eb 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -5488,9 +5488,13 @@ bool LLParser::parseDIExpression(MDNode *&Result, bool IsDistinct) { return false; } +bool LLParser::parseDIArgList(MDNode *&Result, bool IsDistinct) { + return parseDIArgList(Result, IsDistinct, nullptr); +} /// ParseDIArgList: /// ::= !DIArgList(i32 7, i64 %0) -bool LLParser::parseDIArgList(Metadata *&MD, PerFunctionState *PFS) { +bool LLParser::parseDIArgList(MDNode *&Result, bool IsDistinct, + PerFunctionState *PFS) { assert(PFS && "Expected valid function state"); assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); Lex.Lex(); @@ -5510,7 +5514,7 @@ bool LLParser::parseDIArgList(Metadata *&MD, PerFunctionState *PFS) { if (parseToken(lltok::rparen, "expected ')' here")) return true; - MD = DIArgList::get(Context, Args); + Result = GET_OR_DISTINCT(DIArgList, (Context, Args)); return false; } @@ -5624,17 +5628,13 @@ bool LLParser::parseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg, /// ::= !DILocation(...) bool LLParser::parseMetadata(Metadata *&MD, PerFunctionState *PFS) { if (Lex.getKind() == lltok::MetadataVar) { + MDNode *N; // DIArgLists are a special case, as they are a list of ValueAsMetadata and // so parsing this requires a Function State. if (Lex.getStrVal() == "DIArgList") { - Metadata *AL; - if (parseDIArgList(AL, PFS)) + if (parseDIArgList(N, false, PFS)) return true; - MD = AL; - return false; - } - MDNode *N; - if (parseSpecializedMDNode(N)) { + } else if (parseSpecializedMDNode(N)) { return true; } MD = N; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 9c21cc69179e5..d16b5c7781c24 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -336,7 +336,8 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase { unsigned Abbrev); void writeDIMacroFile(const DIMacroFile *N, SmallVectorImpl &Record, unsigned Abbrev); - void writeDIArgList(const DIArgList *N, SmallVectorImpl &Record); + void writeDIArgList(const DIArgList *N, SmallVectorImpl &Record, + unsigned Abbrev); void writeDIModule(const DIModule *N, SmallVectorImpl &Record, unsigned Abbrev); void writeDIAssignID(const DIAssignID *N, SmallVectorImpl &Record, @@ -1974,12 +1975,13 @@ void ModuleBitcodeWriter::writeDIMacroFile(const DIMacroFile *N, } void ModuleBitcodeWriter::writeDIArgList(const DIArgList *N, - SmallVectorImpl &Record) { + SmallVectorImpl &Record, + unsigned Abbrev) { Record.reserve(N->getArgs().size()); for (ValueAsMetadata *MD : N->getArgs()) Record.push_back(VE.getMetadataID(MD)); - Stream.EmitRecord(bitc::METADATA_ARG_LIST, Record); + Stream.EmitRecord(bitc::METADATA_ARG_LIST, Record, Abbrev); Record.clear(); } @@ -2262,10 +2264,6 @@ void ModuleBitcodeWriter::writeMetadataRecords( #include "llvm/IR/Metadata.def" } } - if (auto *AL = dyn_cast(MD)) { - writeDIArgList(AL, Record); - continue; - } writeValueAsMetadata(cast(MD), Record); } } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index c37adb4233970..f681e8b994366 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1266,8 +1266,9 @@ void SlotTracker::CreateFunctionSlot(const Value *V) { void SlotTracker::CreateMetadataSlot(const MDNode *N) { assert(N && "Can't insert a null Value into SlotTracker!"); - // Don't make slots for DIExpressions. We just print them inline everywhere. - if (isa(N)) + // Don't make slots for DIExpressions or DIArgLists. We just print them inline + // everywhere. + if (isa(N) || isa(N)) return; unsigned DestSlot = mdnNext; @@ -3516,6 +3517,8 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) { // Write DIExpressions inline. // FIXME: Ban DIExpressions in NamedMDNodes, they will serve no purpose. MDNode *Op = NMD->getOperand(i); + assert(!isa(Op) && + "DIArgLists should not appear in NamedMDNodes"); if (auto *Expr = dyn_cast(Op)) { writeDIExpression(Out, Expr, AsmWriterContext::getEmpty()); continue; @@ -4916,7 +4919,7 @@ static void printMetadataImplRec(raw_ostream &ROS, const Metadata &MD, WriteAsOperandInternal(OS, &MD, WriterCtx, /* FromValue */ true); auto *N = dyn_cast(&MD); - if (!N || isa(MD)) + if (!N || isa(MD) || isa(MD)) return; OS << " = "; @@ -4984,7 +4987,7 @@ static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD, WriteAsOperandInternal(OS, &MD, *WriterCtx, /* FromValue */ true); auto *N = dyn_cast(&MD); - if (OnlyAsOperand || !N || isa(MD)) + if (OnlyAsOperand || !N || isa(MD) || isa(MD)) return; OS << " = "; diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index c507346710b8d..927aefb8bd477 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -2115,14 +2115,11 @@ DIMacroFile *DIMacroFile::getImpl(LLVMContext &Context, unsigned MIType, DEFINE_GETIMPL_STORE(DIMacroFile, (MIType, Line), Ops); } -DIArgList *DIArgList::get(LLVMContext &Context, - ArrayRef Args) { - auto ExistingIt = Context.pImpl->DIArgLists.find_as(DIArgListKeyInfo(Args)); - if (ExistingIt != Context.pImpl->DIArgLists.end()) - return *ExistingIt; - DIArgList *NewArgList = new DIArgList(Context, Args); - Context.pImpl->DIArgLists.insert(NewArgList); - return NewArgList; +DIArgList *DIArgList::getImpl(LLVMContext &Context, + ArrayRef Args, + StorageType Storage, bool ShouldCreate) { + DEFINE_GETIMPL_LOOKUP(DIArgList, (Args)); + DEFINE_GETIMPL_STORE_NO_OPS(DIArgList, (Args)); } void DIArgList::handleChangedOperand(void *Ref, Metadata *New) { @@ -2130,9 +2127,12 @@ void DIArgList::handleChangedOperand(void *Ref, Metadata *New) { assert((!New || isa(New)) && "DIArgList must be passed a ValueAsMetadata"); untrack(); - // We need to update the set storage once the Args are updated since they - // form the key to the DIArgLists store. - getContext().pImpl->DIArgLists.erase(this); + bool Uniq = isUniqued(); + if (Uniq) { + // We need to update the uniqueness once the Args are updated since they + // form the key to the DIArgLists store. + eraseFromStore(); + } ValueAsMetadata *NewVM = cast_or_null(New); for (ValueAsMetadata *&VM : Args) { if (&VM == OldVMPtr) { @@ -2142,19 +2142,28 @@ void DIArgList::handleChangedOperand(void *Ref, Metadata *New) { VM = ValueAsMetadata::get(PoisonValue::get(VM->getValue()->getType())); } } - // We've changed the contents of this DIArgList, and the set storage may - // already contain a DIArgList with our new set of args; if it does, then we - // must RAUW this with the existing DIArgList, otherwise we simply insert this - // back into the set storage. - DIArgList *ExistingArgList = getUniqued(getContext().pImpl->DIArgLists, this); - if (ExistingArgList) { - replaceAllUsesWith(ExistingArgList); - // Clear this here so we don't try to untrack in the destructor. - Args.clear(); - delete this; - return; + if (Uniq) { + // In the RemoveDIs project (eliminating debug-info-intrinsics), DIArgLists + // can be referred to by DebugValueUser objects, which necessitates them + // being unique and replaceable metadata. This causes a slight + // performance regression that's to be avoided during the early stages of + // the RemoveDIs prototype, see D154080. +#ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS + MDNode *UniqueArgList = uniquify(); + if (UniqueArgList != this) { + replaceAllUsesWith(UniqueArgList); + // Clear this here so we don't try to untrack in the destructor. + Args.clear(); + delete this; + return; + } +#else + // Otherwise, don't fully unique, become distinct instead. See D108968, + // there's a latent bug that presents here as nondeterminism otherwise. + if (uniquify() != this) + storeDistinctInContext(); +#endif } - getContext().pImpl->DIArgLists.insert(this); track(); } void DIArgList::track() { @@ -2167,9 +2176,8 @@ void DIArgList::untrack() { if (VAM) MetadataTracking::untrack(&VAM, *VAM); } -void DIArgList::dropAllReferences(bool Untrack) { - if (Untrack) - untrack(); +void DIArgList::dropAllReferences() { + untrack(); Args.clear(); - ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false); + MDNode::dropAllReferences(); } diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp index 993deafe66270..406850b7de248 100644 --- a/llvm/lib/IR/LLVMContextImpl.cpp +++ b/llvm/lib/IR/LLVMContextImpl.cpp @@ -68,8 +68,15 @@ LLVMContextImpl::~LLVMContextImpl() { // Drop references for MDNodes. Do this before Values get deleted to avoid // unnecessary RAUW when nodes are still unresolved. - for (auto *I : DistinctMDNodes) + for (auto *I : DistinctMDNodes) { + // We may have DIArgList that were uniqued, and as it has a custom + // implementation of dropAllReferences, it needs to be explicitly invoked. + if (auto *AL = dyn_cast(I)) { + AL->dropAllReferences(); + continue; + } I->dropAllReferences(); + } #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \ for (auto *I : CLASS##s) \ I->dropAllReferences(); @@ -80,10 +87,6 @@ LLVMContextImpl::~LLVMContextImpl() { Pair.second->dropUsers(); for (auto &Pair : MetadataAsValues) Pair.second->dropUse(); - // Do not untrack ValueAsMetadata references for DIArgLists, as they have - // already been more efficiently untracked above. - for (DIArgList *AL : DIArgLists) - AL->dropAllReferences(/* Untrack */ false); // Destroy MDNodes. for (MDNode *I : DistinctMDNodes) diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index b55107beba556..ebc444fcb6896 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1308,13 +1308,11 @@ template <> struct MDNodeKeyImpl { } }; -// DIArgLists are not MDNodes, but we still want to unique them in a DenseSet -// based on a hash of their arguments. -struct DIArgListKeyInfo { +template <> struct MDNodeKeyImpl { ArrayRef Args; - DIArgListKeyInfo(ArrayRef Args) : Args(Args) {} - DIArgListKeyInfo(const DIArgList *N) : Args(N->getArgs()) {} + MDNodeKeyImpl(ArrayRef Args) : Args(Args) {} + MDNodeKeyImpl(const DIArgList *N) : Args(N->getArgs()) {} bool isKeyOf(const DIArgList *RHS) const { return Args == RHS->getArgs(); } @@ -1323,35 +1321,6 @@ struct DIArgListKeyInfo { } }; -/// DenseMapInfo for DIArgList. -struct DIArgListInfo { - using KeyTy = DIArgListKeyInfo; - - static inline DIArgList *getEmptyKey() { - return DenseMapInfo::getEmptyKey(); - } - - static inline DIArgList *getTombstoneKey() { - return DenseMapInfo::getTombstoneKey(); - } - - static unsigned getHashValue(const KeyTy &Key) { return Key.getHashValue(); } - - static unsigned getHashValue(const DIArgList *N) { - return KeyTy(N).getHashValue(); - } - - static bool isEqual(const KeyTy &LHS, const DIArgList *RHS) { - if (RHS == getEmptyKey() || RHS == getTombstoneKey()) - return false; - return LHS.isKeyOf(RHS); - } - - static bool isEqual(const DIArgList *LHS, const DIArgList *RHS) { - return LHS == RHS; - } -}; - /// DenseMapInfo for MDNode subclasses. template struct MDNodeInfo { using KeyTy = MDNodeKeyImpl; @@ -1502,7 +1471,6 @@ class LLVMContextImpl { StringMap MDStringCache; DenseMap ValuesAsMetadata; DenseMap MetadataAsValues; - DenseSet DIArgLists; #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \ DenseSet CLASS##s; diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp index 415e256c817b8..e040387fceb74 100644 --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -413,25 +413,33 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) { // commentry in DIArgList::handleChangedOperand for details. Hidden behind // conditional compilation to avoid a compile time regression. ReplaceableMetadataImpl *ReplaceableMetadataImpl::getOrCreate(Metadata &MD) { +#ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS + if (auto *ArgList = dyn_cast(&MD)) + return ArgList->Context.getOrCreateReplaceableUses(); +#endif if (auto *N = dyn_cast(&MD)) return N->isResolved() ? nullptr : N->Context.getOrCreateReplaceableUses(); - if (auto ArgList = dyn_cast(&MD)) - return ArgList; return dyn_cast(&MD); } ReplaceableMetadataImpl *ReplaceableMetadataImpl::getIfExists(Metadata &MD) { +#ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS + if (auto *ArgList = dyn_cast(&MD)) + return ArgList->Context.getReplaceableUses(); +#endif if (auto *N = dyn_cast(&MD)) return N->isResolved() ? nullptr : N->Context.getReplaceableUses(); - if (auto ArgList = dyn_cast(&MD)) - return ArgList; return dyn_cast(&MD); } bool ReplaceableMetadataImpl::isReplaceable(const Metadata &MD) { +#ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS + if (isa(&MD)) + return true; +#endif if (auto *N = dyn_cast(&MD)) return !N->isResolved(); - return isa(&MD) || isa(&MD); + return isa(&MD); } static DISubprogram *getLocalFunctionMetadata(Value *V) { diff --git a/llvm/lib/IR/TypeFinder.cpp b/llvm/lib/IR/TypeFinder.cpp index 003155a4af487..904af7e737ccf 100644 --- a/llvm/lib/IR/TypeFinder.cpp +++ b/llvm/lib/IR/TypeFinder.cpp @@ -136,11 +136,6 @@ void TypeFinder::incorporateValue(const Value *V) { return incorporateMDNode(N); if (const auto *MDV = dyn_cast(M->getMetadata())) return incorporateValue(MDV->getValue()); - if (const auto *AL = dyn_cast(M->getMetadata())) { - for (auto *Arg : AL->getArgs()) - incorporateValue(Arg->getValue()); - return; - } return; } @@ -173,6 +168,14 @@ void TypeFinder::incorporateMDNode(const MDNode *V) { if (!VisitedMetadata.insert(V).second) return; + // The arguments in DIArgList are not exposed as operands, so handle such + // nodes specifically here. + if (const auto *AL = dyn_cast(V)) { + for (auto *Arg : AL->getArgs()) + incorporateValue(Arg->getValue()); + return; + } + // Look in operands for types. for (Metadata *Op : V->operands()) { if (!Op) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 5560c037aa3ee..25981d8dccb11 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -483,7 +483,6 @@ class Verifier : public InstVisitor, VerifierSupport { void visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs); void visitMetadataAsValue(const MetadataAsValue &MD, Function *F); void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F); - void visitDIArgList(const DIArgList &AL, Function *F); void visitComdat(const Comdat &C); void visitModuleIdents(); void visitModuleCommandLines(); @@ -1047,11 +1046,6 @@ void Verifier::visitValueAsMetadata(const ValueAsMetadata &MD, Function *F) { Check(ActualF == F, "function-local metadata used in wrong function", L); } -void Verifier::visitDIArgList(const DIArgList &AL, Function *F) { - for (const ValueAsMetadata *VAM : AL.getArgs()) - visitValueAsMetadata(*VAM, F); -} - void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) { Metadata *MD = MDV.getMetadata(); if (auto *N = dyn_cast(MD)) { @@ -1066,9 +1060,6 @@ void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) { if (auto *V = dyn_cast(MD)) visitValueAsMetadata(*V, F); - - if (auto *AL = dyn_cast(MD)) - visitDIArgList(*AL, F); } static bool isType(const Metadata *MD) { return !MD || isa(MD); } @@ -1521,6 +1512,13 @@ void Verifier::visitDIMacroFile(const DIMacroFile &N) { } } +void Verifier::visitDIArgList(const DIArgList &N) { + CheckDI(!N.getNumOperands(), + "DIArgList should have no operands other than a list of " + "ValueAsMetadata", + &N); +} + void Verifier::visitDIModule(const DIModule &N) { CheckDI(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N); CheckDI(!N.getName().empty(), "anonymous module", &N);