From: Duncan P. N. Exon Smith Date: Fri, 27 Mar 2015 23:05:04 +0000 (+0000) Subject: Verifier: Check operands of MDType subclasses and MDCompileUnit X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b943370653917d8a674aaa9a47efc2965fd6dad3;p=oota-llvm.git Verifier: Check operands of MDType subclasses and MDCompileUnit Add verify checks for `MDType` subclasses and for `MDCompileUnit`. These new checks don't yet incorporate everything from `Verify()`, but at least they sanity check the operands. Also downcast accessors as possible. A lot of these accessors can't be downcast as far as we'd like because of arrays of typed objects (stored in a generic `MDTuple`) and `MDString`-based type references. Eventually I'll port over `DIRef<>` and `DITypedArray<>` from `DebugInfo.h` to clean those up as well. Updated bitrotted testcases separately in r233415 and r233443 to reduce churn on the off-chance this needs to be reverted. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233446 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 97a7b83c39d..0121db52a67 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -57,11 +57,11 @@ namespace llvm { Module &M; LLVMContext &VMContext; - MDNode *TempEnumTypes; - MDNode *TempRetainTypes; - MDNode *TempSubprograms; - MDNode *TempGVs; - MDNode *TempImportedModules; + MDTuple *TempEnumTypes; + MDTuple *TempRetainTypes; + MDTuple *TempSubprograms; + MDTuple *TempGVs; + MDTuple *TempImportedModules; Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index d174a536c1b..4b08e809b2a 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -282,13 +282,16 @@ protected: ~MDScope() {} public: - /// \brief Return the underlying file. + // FIXME: Downcast to MDFile once we've verified all subclasses. + Metadata *getFile() const { return getRawFile(); } + + /// \brief Return the raw underlying file. /// /// An \a MDFile is an \a MDScope, but it doesn't point at a separate file /// (it\em is the file). If \c this is an \a MDFile, we need to return \c /// this. Otherwise, return the first operand, which is where all other /// subclasses store their file pointer. - Metadata *getFile() const { + Metadata *getRawFile() const { return isa(this) ? const_cast(this) : static_cast(getOperand(0)); } @@ -390,9 +393,14 @@ public: uint64_t getOffsetInBits() const { return OffsetInBits; } unsigned getFlags() const { return Flags; } - Metadata *getScope() const { return getOperand(1); } + // FIXME: Remove this once MDScope::getFile() does the same. + MDFile *getFile() const { return cast_or_null(getRawFile()); } + + Metadata *getScope() const { return getRawScope(); } StringRef getName() const { return getStringOperand(2); } + + Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs(2); } void setFlags(unsigned NewFlags) { @@ -483,7 +491,8 @@ protected: ~MDDerivedTypeBase() {} public: - Metadata *getBaseType() const { return getOperand(3); } + Metadata *getBaseType() const { return getRawBaseType(); } + Metadata *getRawBaseType() const { return getOperand(3); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDDerivedTypeKind || @@ -510,7 +519,7 @@ class MDDerivedType : public MDDerivedTypeBase { ~MDDerivedType() {} static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, Metadata *File, unsigned Line, + StringRef Name, MDFile *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, @@ -545,7 +554,7 @@ public: (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, ExtraData)) DEFINE_MDNODE_GET(MDDerivedType, - (unsigned Tag, StringRef Name, Metadata *File, + (unsigned Tag, StringRef Name, MDFile *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, @@ -562,7 +571,8 @@ public: /// /// TODO: Separate out types that need this extra operand: pointer-to-member /// types and member fields (static members and ivars). - Metadata *getExtraData() const { return getOperand(4); } + Metadata *getExtraData() const { return getRawExtraData(); } + Metadata *getRawExtraData() const { return getOperand(4); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDDerivedTypeKind; @@ -587,12 +597,19 @@ protected: ~MDCompositeTypeBase() {} public: - Metadata *getElements() const { return getOperand(4); } - Metadata *getVTableHolder() const { return getOperand(5); } - Metadata *getTemplateParams() const { return getOperand(6); } + MDTuple *getElements() const { + return cast_or_null(getRawElements()); + } + Metadata *getVTableHolder() const { return getRawVTableHolder(); } + MDTuple *getTemplateParams() const { + return cast_or_null(getRawTemplateParams()); + } StringRef getIdentifier() const { return getStringOperand(7); } unsigned getRuntimeLang() const { return RuntimeLang; } + Metadata *getRawElements() const { return getOperand(4); } + Metadata *getRawVTableHolder() const { return getOperand(5); } + Metadata *getRawTemplateParams() const { return getOperand(6); } MDString *getRawIdentifier() const { return getOperandAs(7); } /// \brief Replace operands. @@ -730,7 +747,8 @@ public: TempMDSubroutineType clone() const { return cloneImpl(); } - Metadata *getTypeArray() const { return getElements(); } + MDTuple *getTypeArray() const { return getElements(); } + Metadata *getRawTypeArray() const { return getRawElements(); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDSubroutineTypeKind; @@ -756,12 +774,12 @@ class MDCompileUnit : public MDScope { ~MDCompileUnit() {} static MDCompileUnit * - getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + getImpl(LLVMContext &Context, unsigned SourceLanguage, MDFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, - unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, - Metadata *Subprograms, Metadata *GlobalVariables, - Metadata *ImportedEntities, StorageType Storage, + unsigned EmissionKind, MDTuple *EnumTypes, MDTuple *RetainedTypes, + MDTuple *Subprograms, MDTuple *GlobalVariables, + MDTuple *ImportedEntities, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), IsOptimized, @@ -789,12 +807,12 @@ class MDCompileUnit : public MDScope { public: DEFINE_MDNODE_GET(MDCompileUnit, - (unsigned SourceLanguage, Metadata *File, - StringRef Producer, bool IsOptimized, StringRef Flags, - unsigned RuntimeVersion, StringRef SplitDebugFilename, - unsigned EmissionKind, Metadata *EnumTypes, - Metadata *RetainedTypes, Metadata *Subprograms, - Metadata *GlobalVariables, Metadata *ImportedEntities), + (unsigned SourceLanguage, MDFile *File, StringRef Producer, + bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, + StringRef SplitDebugFilename, unsigned EmissionKind, + MDTuple *EnumTypes, MDTuple *RetainedTypes, + MDTuple *Subprograms, MDTuple *GlobalVariables, + MDTuple *ImportedEntities), (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms, GlobalVariables, @@ -813,6 +831,9 @@ public: TempMDCompileUnit clone() const { return cloneImpl(); } + // FIXME: Remove this once MDScope::getFile() does the same. + MDFile *getFile() const { return cast_or_null(getRawFile()); } + unsigned getSourceLanguage() const { return SourceLanguage; } bool isOptimized() const { return IsOptimized; } unsigned getRuntimeVersion() const { return RuntimeVersion; } @@ -820,17 +841,32 @@ public: StringRef getProducer() const { return getStringOperand(1); } StringRef getFlags() const { return getStringOperand(2); } StringRef getSplitDebugFilename() const { return getStringOperand(3); } - Metadata *getEnumTypes() const { return getOperand(4); } - Metadata *getRetainedTypes() const { return getOperand(5); } - Metadata *getSubprograms() const { return getOperand(6); } - Metadata *getGlobalVariables() const { return getOperand(7); } - Metadata *getImportedEntities() const { return getOperand(8); } + MDTuple *getEnumTypes() const { + return cast_or_null(getRawEnumTypes()); + } + MDTuple *getRetainedTypes() const { + return cast_or_null(getRawRetainedTypes()); + } + MDTuple *getSubprograms() const { + return cast_or_null(getRawSubprograms()); + } + MDTuple *getGlobalVariables() const { + return cast_or_null(getRawGlobalVariables()); + } + MDTuple *getImportedEntities() const { + return cast_or_null(getRawImportedEntities()); + } MDString *getRawProducer() const { return getOperandAs(1); } MDString *getRawFlags() const { return getOperandAs(2); } MDString *getRawSplitDebugFilename() const { return getOperandAs(3); } + Metadata *getRawEnumTypes() const { return getOperand(4); } + Metadata *getRawRetainedTypes() const { return getOperand(5); } + Metadata *getRawSubprograms() const { return getOperand(6); } + Metadata *getRawGlobalVariables() const { return getOperand(7); } + Metadata *getRawImportedEntities() const { return getOperand(8); } /// \brief Replace arrays. /// diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 460e3f1b619..a3dde894070 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1539,16 +1539,16 @@ static void writeMDDerivedType(raw_ostream &Out, const MDDerivedType *N, MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); Printer.printTag(N); Printer.printString("name", N->getName()); - Printer.printMetadata("scope", N->getScope()); - Printer.printMetadata("file", N->getFile()); + Printer.printMetadata("scope", N->getRawScope()); + Printer.printMetadata("file", N->getRawFile()); Printer.printInt("line", N->getLine()); - Printer.printMetadata("baseType", N->getBaseType(), + Printer.printMetadata("baseType", N->getRawBaseType(), /* ShouldSkipNull */ false); Printer.printInt("size", N->getSizeInBits()); Printer.printInt("align", N->getAlignInBits()); Printer.printInt("offset", N->getOffsetInBits()); Printer.printDIFlags("flags", N->getFlags()); - Printer.printMetadata("extraData", N->getExtraData()); + Printer.printMetadata("extraData", N->getRawExtraData()); Out << ")"; } @@ -1559,19 +1559,19 @@ static void writeMDCompositeType(raw_ostream &Out, const MDCompositeType *N, MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); Printer.printTag(N); Printer.printString("name", N->getName()); - Printer.printMetadata("scope", N->getScope()); - Printer.printMetadata("file", N->getFile()); + Printer.printMetadata("scope", N->getRawScope()); + Printer.printMetadata("file", N->getRawFile()); Printer.printInt("line", N->getLine()); - Printer.printMetadata("baseType", N->getBaseType()); + Printer.printMetadata("baseType", N->getRawBaseType()); Printer.printInt("size", N->getSizeInBits()); Printer.printInt("align", N->getAlignInBits()); Printer.printInt("offset", N->getOffsetInBits()); Printer.printDIFlags("flags", N->getFlags()); - Printer.printMetadata("elements", N->getElements()); + Printer.printMetadata("elements", N->getRawElements()); Printer.printDwarfEnum("runtimeLang", N->getRuntimeLang(), dwarf::LanguageString); - Printer.printMetadata("vtableHolder", N->getVTableHolder()); - Printer.printMetadata("templateParams", N->getTemplateParams()); + Printer.printMetadata("vtableHolder", N->getRawVTableHolder()); + Printer.printMetadata("templateParams", N->getRawTemplateParams()); Printer.printString("identifier", N->getIdentifier()); Out << ")"; } @@ -1582,7 +1582,8 @@ static void writeMDSubroutineType(raw_ostream &Out, const MDSubroutineType *N, Out << "!MDSubroutineType("; MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); Printer.printDIFlags("flags", N->getFlags()); - Printer.printMetadata("types", N->getTypeArray(), /* ShouldSkipNull */ false); + Printer.printMetadata("types", N->getRawTypeArray(), + /* ShouldSkipNull */ false); Out << ")"; } @@ -1604,7 +1605,7 @@ static void writeMDCompileUnit(raw_ostream &Out, const MDCompileUnit *N, MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); Printer.printDwarfEnum("language", N->getSourceLanguage(), dwarf::LanguageString, /* ShouldSkipZero */ false); - Printer.printMetadata("file", N->getFile(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false); Printer.printString("producer", N->getProducer()); Printer.printBool("isOptimized", N->isOptimized()); Printer.printString("flags", N->getFlags()); @@ -1613,11 +1614,11 @@ static void writeMDCompileUnit(raw_ostream &Out, const MDCompileUnit *N, Printer.printString("splitDebugFilename", N->getSplitDebugFilename()); Printer.printInt("emissionKind", N->getEmissionKind(), /* ShouldSkipZero */ false); - Printer.printMetadata("enums", N->getEnumTypes()); - Printer.printMetadata("retainedTypes", N->getRetainedTypes()); - Printer.printMetadata("subprograms", N->getSubprograms()); - Printer.printMetadata("globals", N->getGlobalVariables()); - Printer.printMetadata("imports", N->getImportedEntities()); + Printer.printMetadata("enums", N->getRawEnumTypes()); + Printer.printMetadata("retainedTypes", N->getRawRetainedTypes()); + Printer.printMetadata("subprograms", N->getRawSubprograms()); + Printer.printMetadata("globals", N->getRawGlobalVariables()); + Printer.printMetadata("imports", N->getRawImportedEntities()); Out << ")"; } diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 4b837af9d44..dfbc1315218 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -269,8 +269,8 @@ DIDerivedType DIBuilder::createReferenceType(unsigned Tag, DIType RTy) { DIDerivedType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, unsigned LineNo, DIDescriptor Context) { - return MDDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, - File.getFileNode(), LineNo, + return MDDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File, + LineNo, DIScope(getNonCompileUnitScope(Context)).getRef(), Ty.getRef(), 0, 0, 0, 0); } diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index d735c33d2ac..21999822346 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -347,20 +347,20 @@ template <> struct MDNodeKeyImpl { BaseType(BaseType), SizeInBits(SizeInBits), AlignInBits(AlignInBits), OffsetInBits(OffsetInBits), Flags(Flags), ExtraData(ExtraData) {} MDNodeKeyImpl(const MDDerivedType *N) - : Tag(N->getTag()), Name(N->getName()), File(N->getFile()), - Line(N->getLine()), Scope(N->getScope()), BaseType(N->getBaseType()), - SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()), - OffsetInBits(N->getOffsetInBits()), Flags(N->getFlags()), - ExtraData(N->getExtraData()) {} + : Tag(N->getTag()), Name(N->getName()), File(N->getRawFile()), + Line(N->getLine()), Scope(N->getRawScope()), + BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), + AlignInBits(N->getAlignInBits()), OffsetInBits(N->getOffsetInBits()), + Flags(N->getFlags()), ExtraData(N->getRawExtraData()) {} bool isKeyOf(const MDDerivedType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getName() && - File == RHS->getFile() && Line == RHS->getLine() && - Scope == RHS->getScope() && BaseType == RHS->getBaseType() && + File == RHS->getRawFile() && Line == RHS->getLine() && + Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() && SizeInBits == RHS->getSizeInBits() && AlignInBits == RHS->getAlignInBits() && OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() && - ExtraData == RHS->getExtraData(); + ExtraData == RHS->getRawExtraData(); } unsigned getHashValue() const { return hash_combine(Tag, Name, File, Line, Scope, BaseType, SizeInBits, @@ -397,26 +397,26 @@ template <> struct MDNodeKeyImpl { RuntimeLang(RuntimeLang), VTableHolder(VTableHolder), TemplateParams(TemplateParams), Identifier(Identifier) {} MDNodeKeyImpl(const MDCompositeType *N) - : Tag(N->getTag()), Name(N->getName()), File(N->getFile()), - Line(N->getLine()), Scope(N->getScope()), BaseType(N->getBaseType()), - SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()), - OffsetInBits(N->getOffsetInBits()), Flags(N->getFlags()), - Elements(N->getElements()), RuntimeLang(N->getRuntimeLang()), - VTableHolder(N->getVTableHolder()), - TemplateParams(N->getTemplateParams()), Identifier(N->getIdentifier()) { - } + : Tag(N->getTag()), Name(N->getName()), File(N->getRawFile()), + Line(N->getLine()), Scope(N->getRawScope()), + BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), + AlignInBits(N->getAlignInBits()), OffsetInBits(N->getOffsetInBits()), + Flags(N->getFlags()), Elements(N->getRawElements()), + RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()), + TemplateParams(N->getRawTemplateParams()), + Identifier(N->getIdentifier()) {} bool isKeyOf(const MDCompositeType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getName() && - File == RHS->getFile() && Line == RHS->getLine() && - Scope == RHS->getScope() && BaseType == RHS->getBaseType() && + File == RHS->getRawFile() && Line == RHS->getLine() && + Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() && SizeInBits == RHS->getSizeInBits() && AlignInBits == RHS->getAlignInBits() && OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() && - Elements == RHS->getElements() && + Elements == RHS->getRawElements() && RuntimeLang == RHS->getRuntimeLang() && - VTableHolder == RHS->getVTableHolder() && - TemplateParams == RHS->getTemplateParams() && + VTableHolder == RHS->getRawVTableHolder() && + TemplateParams == RHS->getRawTemplateParams() && Identifier == RHS->getIdentifier(); } unsigned getHashValue() const { @@ -433,10 +433,10 @@ template <> struct MDNodeKeyImpl { MDNodeKeyImpl(int64_t Flags, Metadata *TypeArray) : Flags(Flags), TypeArray(TypeArray) {} MDNodeKeyImpl(const MDSubroutineType *N) - : Flags(N->getFlags()), TypeArray(N->getTypeArray()) {} + : Flags(N->getFlags()), TypeArray(N->getRawTypeArray()) {} bool isKeyOf(const MDSubroutineType *RHS) const { - return Flags == RHS->getFlags() && TypeArray == RHS->getTypeArray(); + return Flags == RHS->getFlags() && TypeArray == RHS->getRawTypeArray(); } unsigned getHashValue() const { return hash_combine(Flags, TypeArray); } }; @@ -484,27 +484,28 @@ template <> struct MDNodeKeyImpl { Subprograms(Subprograms), GlobalVariables(GlobalVariables), ImportedEntities(ImportedEntities) {} MDNodeKeyImpl(const MDCompileUnit *N) - : SourceLanguage(N->getSourceLanguage()), File(N->getFile()), + : SourceLanguage(N->getSourceLanguage()), File(N->getRawFile()), Producer(N->getProducer()), IsOptimized(N->isOptimized()), Flags(N->getFlags()), RuntimeVersion(N->getRuntimeVersion()), SplitDebugFilename(N->getSplitDebugFilename()), - EmissionKind(N->getEmissionKind()), EnumTypes(N->getEnumTypes()), - RetainedTypes(N->getRetainedTypes()), Subprograms(N->getSubprograms()), - GlobalVariables(N->getGlobalVariables()), - ImportedEntities(N->getImportedEntities()) {} + EmissionKind(N->getEmissionKind()), EnumTypes(N->getRawEnumTypes()), + RetainedTypes(N->getRawRetainedTypes()), + Subprograms(N->getRawSubprograms()), + GlobalVariables(N->getRawGlobalVariables()), + ImportedEntities(N->getRawImportedEntities()) {} bool isKeyOf(const MDCompileUnit *RHS) const { return SourceLanguage == RHS->getSourceLanguage() && - File == RHS->getFile() && Producer == RHS->getProducer() && + File == RHS->getRawFile() && Producer == RHS->getProducer() && IsOptimized == RHS->isOptimized() && Flags == RHS->getFlags() && RuntimeVersion == RHS->getRuntimeVersion() && SplitDebugFilename == RHS->getSplitDebugFilename() && EmissionKind == RHS->getEmissionKind() && - EnumTypes == RHS->getEnumTypes() && - RetainedTypes == RHS->getRetainedTypes() && - Subprograms == RHS->getSubprograms() && - GlobalVariables == RHS->getGlobalVariables() && - ImportedEntities == RHS->getImportedEntities(); + EnumTypes == RHS->getRawEnumTypes() && + RetainedTypes == RHS->getRawRetainedTypes() && + Subprograms == RHS->getRawSubprograms() && + GlobalVariables == RHS->getRawGlobalVariables() && + ImportedEntities == RHS->getRawImportedEntities(); } unsigned getHashValue() const { return hash_combine(SourceLanguage, File, Producer, IsOptimized, Flags, diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 22b6bf80807..b2a86e27b75 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -298,6 +298,8 @@ private: #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); #include "llvm/IR/Metadata.def" + void visitMDScope(const MDScope &N); + void visitMDDerivedTypeBase(const MDDerivedTypeBase &N); void visitMDVariable(const MDVariable &N); // InstVisitor overrides... @@ -668,6 +670,15 @@ static bool isTypeRef(const Metadata *MD) { return isa(MD); } +/// \brief Check if a value can be a ScopeRef. +static bool isScopeRef(const Metadata *MD) { + if (!MD) + return true; + if (auto *S = dyn_cast(MD)) + return !S->getString().empty(); + return isa(MD); +} + void Verifier::visitMDLocation(const MDLocation &N) { Assert(N.getRawScope() && isa(N.getRawScope()), "location requires a valid scope", &N, N.getRawScope()); @@ -679,8 +690,14 @@ void Verifier::visitGenericDebugNode(const GenericDebugNode &N) { Assert(N.getTag(), "invalid tag", &N); } +void Verifier::visitMDScope(const MDScope &N) { + if (auto *F = N.getRawFile()) + Assert(isa(F), "invalid file", &N, F); +} + void Verifier::visitMDSubrange(const MDSubrange &N) { Assert(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N); + Assert(N.getCount() >= -1, "invalid subrange count", &N); } void Verifier::visitMDEnumerator(const MDEnumerator &N) { @@ -693,7 +710,18 @@ void Verifier::visitMDBasicType(const MDBasicType &N) { "invalid tag", &N); } +void Verifier::visitMDDerivedTypeBase(const MDDerivedTypeBase &N) { + // Common scope checks. + visitMDScope(N); + + Assert(isScopeRef(N.getScope()), "invalid scope", &N, N.getScope()); + Assert(isTypeRef(N.getBaseType()), "invalid base type", &N, N.getBaseType()); +} + void Verifier::visitMDDerivedType(const MDDerivedType &N) { + // Common derived type checks. + visitMDDerivedTypeBase(N); + Assert(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || @@ -709,6 +737,9 @@ void Verifier::visitMDDerivedType(const MDDerivedType &N) { } void Verifier::visitMDCompositeType(const MDCompositeType &N) { + // Common derived type checks. + visitMDDerivedTypeBase(N); + Assert(N.getTag() == dwarf::DW_TAG_array_type || N.getTag() == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || @@ -716,10 +747,24 @@ void Verifier::visitMDCompositeType(const MDCompositeType &N) { N.getTag() == dwarf::DW_TAG_subroutine_type || N.getTag() == dwarf::DW_TAG_class_type, "invalid tag", &N); + + Assert(!N.getRawElements() || isa(N.getRawElements()), + "invalid composite elements", &N, N.getRawElements()); + Assert(isTypeRef(N.getRawVTableHolder()), "invalid vtable holder", &N, + N.getRawVTableHolder()); + Assert(!N.getRawElements() || isa(N.getRawElements()), + "invalid composite elements", &N, N.getRawElements()); } void Verifier::visitMDSubroutineType(const MDSubroutineType &N) { Assert(N.getTag() == dwarf::DW_TAG_subroutine_type, "invalid tag", &N); + Assert(N.getRawElements() && isa(N.getRawElements()), + "invalid composite elements", &N, N.getRawElements()); + + for (Metadata *Ty : N.getTypeArray()->operands()) { + Assert(isTypeRef(Ty), "invalid subroutine type ref", &N, N.getTypeArray(), + Ty); + } } void Verifier::visitMDFile(const MDFile &N) { @@ -728,6 +773,41 @@ void Verifier::visitMDFile(const MDFile &N) { void Verifier::visitMDCompileUnit(const MDCompileUnit &N) { Assert(N.getTag() == dwarf::DW_TAG_compile_unit, "invalid tag", &N); + + if (auto *Array = N.getRawEnumTypes()) { + Assert(isa(Array), "invalid enum list", &N, Array); + for (Metadata *Op : N.getEnumTypes()->operands()) { + auto *Enum = dyn_cast_or_null(Op); + Assert(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type, + "invalid enum type", &N, N.getEnumTypes(), Op); + } + } + if (auto *Array = N.getRawRetainedTypes()) { + Assert(isa(Array), "invalid retained type list", &N, Array); + for (Metadata *Op : N.getRetainedTypes()->operands()) { + Assert(Op && isa(Op), "invalid retained type", &N, Op); + } + } + if (auto *Array = N.getRawSubprograms()) { + Assert(isa(Array), "invalid subprogram list", &N, Array); + for (Metadata *Op : N.getSubprograms()->operands()) { + Assert(Op && isa(Op), "invalid subprogram ref", &N, Op); + } + } + if (auto *Array = N.getRawGlobalVariables()) { + Assert(isa(Array), "invalid global variable list", &N, Array); + for (Metadata *Op : N.getGlobalVariables()->operands()) { + Assert(Op && isa(Op), "invalid global variable ref", &N, + Op); + } + } + if (auto *Array = N.getRawImportedEntities()) { + Assert(isa(Array), "invalid imported entity list", &N, Array); + for (Metadata *Op : N.getImportedEntities()->operands()) { + Assert(Op && isa(Op), "invalid imported entity ref", &N, + Op); + } + } } void Verifier::visitMDSubprogram(const MDSubprogram &N) { diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index 9d779d92935..ac6d3df6f80 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -75,6 +75,7 @@ protected: return MDNode::get(Context, MDs); } + MDTuple *getTuple() { return MDTuple::getDistinct(Context, None); } MDSubprogram *getSubprogram() { return MDSubprogram::getDistinct(Context, nullptr, "", "", nullptr, 0, nullptr, false, false, 0, nullptr, 0, 0, 0, @@ -95,6 +96,11 @@ protected: return ConstantAsMetadata::get( ConstantInt::get(Type::getInt32Ty(Context), Counter++)); } + MDCompositeType *getCompositeType() { + return MDCompositeType::getDistinct( + Context, dwarf::DW_TAG_structure_type, "", nullptr, 0, nullptr, nullptr, + 32, 32, 0, 0, nullptr, 0, nullptr, nullptr, ""); + } }; typedef MetadataTest MDStringTest; @@ -901,10 +907,10 @@ TEST_F(MDTypeTest, setFlags) { typedef MetadataTest MDDerivedTypeTest; TEST_F(MDDerivedTypeTest, get) { - Metadata *File = MDTuple::getDistinct(Context, None); - Metadata *Scope = MDTuple::getDistinct(Context, None); - Metadata *BaseType = MDTuple::getDistinct(Context, None); - Metadata *ExtraData = MDTuple::getDistinct(Context, None); + MDFile *File = getFile(); + MDScope *Scope = getSubprogram(); + MDType *BaseType = getBasicType("basic"); + MDTuple *ExtraData = getTuple(); auto *N = MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, 4, 5, ExtraData); @@ -930,17 +936,17 @@ TEST_F(MDDerivedTypeTest, get) { File, 1, Scope, BaseType, 2, 3, 4, 5, ExtraData)); EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, - "something", Scope, 1, Scope, BaseType, 2, 3, - 4, 5, ExtraData)); + "something", getFile(), 1, Scope, BaseType, 2, + 3, 4, 5, ExtraData)); EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 2, Scope, BaseType, 2, 3, 4, 5, ExtraData)); - EXPECT_NE(N, - MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", - File, 1, File, BaseType, 2, 3, 4, 5, ExtraData)); - EXPECT_NE(N, - MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", - File, 1, Scope, File, 2, 3, 4, 5, ExtraData)); + EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, + "something", File, 1, getSubprogram(), + BaseType, 2, 3, 4, 5, ExtraData)); + EXPECT_NE(N, MDDerivedType::get( + Context, dwarf::DW_TAG_pointer_type, "something", File, 1, + Scope, getBasicType("basic2"), 2, 3, 4, 5, ExtraData)); EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 3, 3, 4, 5, ExtraData)); @@ -953,19 +959,19 @@ TEST_F(MDDerivedTypeTest, get) { EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, 4, 4, ExtraData)); - EXPECT_NE(N, - MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", - File, 1, Scope, BaseType, 2, 3, 4, 5, File)); + EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, + "something", File, 1, Scope, BaseType, 2, 3, + 4, 5, getTuple())); TempMDDerivedType Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); } TEST_F(MDDerivedTypeTest, getWithLargeValues) { - Metadata *File = MDTuple::getDistinct(Context, None); - Metadata *Scope = MDTuple::getDistinct(Context, None); - Metadata *BaseType = MDTuple::getDistinct(Context, None); - Metadata *ExtraData = MDTuple::getDistinct(Context, None); + MDFile *File = getFile(); + MDScope *Scope = getSubprogram(); + MDType *BaseType = getBasicType("basic"); + MDTuple *ExtraData = getTuple(); auto *N = MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, UINT64_MAX, @@ -980,18 +986,18 @@ typedef MetadataTest MDCompositeTypeTest; TEST_F(MDCompositeTypeTest, get) { unsigned Tag = dwarf::DW_TAG_structure_type; StringRef Name = "some name"; - Metadata *File = MDTuple::getDistinct(Context, None); + MDFile *File = getFile(); unsigned Line = 1; - Metadata *Scope = MDTuple::getDistinct(Context, None); - Metadata *BaseType = MDTuple::getDistinct(Context, None); + MDScope *Scope = getSubprogram(); + MDType *BaseType = getCompositeType(); uint64_t SizeInBits = 2; uint64_t AlignInBits = 3; uint64_t OffsetInBits = 4; unsigned Flags = 5; - Metadata *Elements = MDTuple::getDistinct(Context, None); + MDTuple *Elements = getTuple(); unsigned RuntimeLang = 6; - Metadata *VTableHolder = MDTuple::getDistinct(Context, None); - Metadata *TemplateParams = MDTuple::getDistinct(Context, None); + MDType *VTableHolder = getCompositeType(); + MDTuple *TemplateParams = getTuple(); StringRef Identifier = "some id"; auto *N = MDCompositeType::get(Context, Tag, Name, File, Line, Scope, @@ -1027,7 +1033,7 @@ TEST_F(MDCompositeTypeTest, get) { BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); - EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, Scope, Line, Scope, + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, getFile(), Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); @@ -1035,10 +1041,10 @@ TEST_F(MDCompositeTypeTest, get) { BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); - EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, File, - BaseType, SizeInBits, AlignInBits, - OffsetInBits, Flags, Elements, RuntimeLang, - VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get( + Context, Tag, Name, File, Line, getSubprogram(), BaseType, + SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, + RuntimeLang, VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, File, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, @@ -1059,22 +1065,22 @@ TEST_F(MDCompositeTypeTest, get) { Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags + 1, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)); - EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits, - OffsetInBits, Flags, File, RuntimeLang, - VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, getTuple(), RuntimeLang, + VTableHolder, TemplateParams, Identifier)); EXPECT_NE(N, MDCompositeType::get( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang + 1, VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + getCompositeType(), TemplateParams, Identifier)); EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, - File, TemplateParams, Identifier)); - EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, - BaseType, SizeInBits, AlignInBits, - OffsetInBits, Flags, Elements, RuntimeLang, - VTableHolder, File, Identifier)); + VTableHolder, getTuple(), Identifier)); EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, @@ -1097,18 +1103,18 @@ TEST_F(MDCompositeTypeTest, get) { TEST_F(MDCompositeTypeTest, getWithLargeValues) { unsigned Tag = dwarf::DW_TAG_structure_type; StringRef Name = "some name"; - Metadata *File = MDTuple::getDistinct(Context, None); + MDFile *File = getFile(); unsigned Line = 1; - Metadata *Scope = MDTuple::getDistinct(Context, None); - Metadata *BaseType = MDTuple::getDistinct(Context, None); + MDScope *Scope = getSubprogram(); + MDType *BaseType = getCompositeType(); uint64_t SizeInBits = UINT64_MAX; uint64_t AlignInBits = UINT64_MAX - 1; uint64_t OffsetInBits = UINT64_MAX - 2; unsigned Flags = 5; - Metadata *Elements = MDTuple::getDistinct(Context, None); + MDTuple *Elements = getTuple(); unsigned RuntimeLang = 6; - Metadata *VTableHolder = MDTuple::getDistinct(Context, None); - Metadata *TemplateParams = MDTuple::getDistinct(Context, None); + MDType *VTableHolder = getCompositeType(); + MDTuple *TemplateParams = getTuple(); StringRef Identifier = "some id"; auto *N = MDCompositeType::get(Context, Tag, Name, File, Line, Scope, @@ -1123,10 +1129,10 @@ TEST_F(MDCompositeTypeTest, getWithLargeValues) { TEST_F(MDCompositeTypeTest, replaceOperands) { unsigned Tag = dwarf::DW_TAG_structure_type; StringRef Name = "some name"; - Metadata *File = MDTuple::getDistinct(Context, None); + MDFile *File = getFile(); unsigned Line = 1; - Metadata *Scope = MDTuple::getDistinct(Context, None); - Metadata *BaseType = MDTuple::getDistinct(Context, None); + MDScope *Scope = getSubprogram(); + MDType *BaseType = getCompositeType(); uint64_t SizeInBits = 2; uint64_t AlignInBits = 3; uint64_t OffsetInBits = 4; @@ -1165,7 +1171,7 @@ typedef MetadataTest MDSubroutineTypeTest; TEST_F(MDSubroutineTypeTest, get) { unsigned Flags = 1; - Metadata *TypeArray = MDTuple::getDistinct(Context, None); + MDTuple *TypeArray = getTuple(); auto *N = MDSubroutineType::get(Context, Flags, TypeArray); EXPECT_EQ(dwarf::DW_TAG_subroutine_type, N->getTag()); @@ -1174,8 +1180,7 @@ TEST_F(MDSubroutineTypeTest, get) { EXPECT_EQ(N, MDSubroutineType::get(Context, Flags, TypeArray)); EXPECT_NE(N, MDSubroutineType::get(Context, Flags + 1, TypeArray)); - EXPECT_NE(N, MDSubroutineType::get(Context, Flags, - MDTuple::getDistinct(Context, None))); + EXPECT_NE(N, MDSubroutineType::get(Context, Flags, getTuple())); TempMDSubroutineType Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); @@ -1219,18 +1224,18 @@ typedef MetadataTest MDCompileUnitTest; TEST_F(MDCompileUnitTest, get) { unsigned SourceLanguage = 1; - Metadata *File = MDTuple::getDistinct(Context, None); + MDFile *File = getFile(); StringRef Producer = "some producer"; bool IsOptimized = false; StringRef Flags = "flag after flag"; unsigned RuntimeVersion = 2; StringRef SplitDebugFilename = "another/file"; unsigned EmissionKind = 3; - Metadata *EnumTypes = MDTuple::getDistinct(Context, None); - Metadata *RetainedTypes = MDTuple::getDistinct(Context, None); - Metadata *Subprograms = MDTuple::getDistinct(Context, None); - Metadata *GlobalVariables = MDTuple::getDistinct(Context, None); - Metadata *ImportedEntities = MDTuple::getDistinct(Context, None); + MDTuple *EnumTypes = getTuple(); + MDTuple *RetainedTypes = getTuple(); + MDTuple *Subprograms = getTuple(); + MDTuple *GlobalVariables = getTuple(); + MDTuple *ImportedEntities = getTuple(); auto *N = MDCompileUnit::get( Context, SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, @@ -1261,7 +1266,7 @@ TEST_F(MDCompileUnitTest, get) { SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms, GlobalVariables, ImportedEntities)); - EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, EnumTypes, Producer, + EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, getFile(), Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms, GlobalVariables, @@ -1298,25 +1303,26 @@ TEST_F(MDCompileUnitTest, get) { GlobalVariables, ImportedEntities)); EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, - SplitDebugFilename, EmissionKind, File, + SplitDebugFilename, EmissionKind, getTuple(), RetainedTypes, Subprograms, GlobalVariables, ImportedEntities)); EXPECT_NE(N, MDCompileUnit::get( Context, SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, - File, Subprograms, GlobalVariables, ImportedEntities)); - EXPECT_NE(N, MDCompileUnit::get( - Context, SourceLanguage, File, Producer, IsOptimized, Flags, - RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, - RetainedTypes, File, GlobalVariables, ImportedEntities)); + getTuple(), Subprograms, GlobalVariables, ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer, + IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, getTuple(), GlobalVariables, + ImportedEntities)); EXPECT_NE(N, MDCompileUnit::get( Context, SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, - RetainedTypes, Subprograms, File, ImportedEntities)); + RetainedTypes, Subprograms, getTuple(), ImportedEntities)); EXPECT_NE(N, MDCompileUnit::get( Context, SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, - RetainedTypes, Subprograms, GlobalVariables, File)); + RetainedTypes, Subprograms, GlobalVariables, getTuple())); TempMDCompileUnit Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); @@ -1324,16 +1330,16 @@ TEST_F(MDCompileUnitTest, get) { TEST_F(MDCompileUnitTest, replaceArrays) { unsigned SourceLanguage = 1; - Metadata *File = MDTuple::getDistinct(Context, None); + MDFile *File = getFile(); StringRef Producer = "some producer"; bool IsOptimized = false; StringRef Flags = "flag after flag"; unsigned RuntimeVersion = 2; StringRef SplitDebugFilename = "another/file"; unsigned EmissionKind = 3; - Metadata *EnumTypes = MDTuple::getDistinct(Context, None); - Metadata *RetainedTypes = MDTuple::getDistinct(Context, None); - Metadata *ImportedEntities = MDTuple::getDistinct(Context, None); + MDTuple *EnumTypes = MDTuple::getDistinct(Context, None); + MDTuple *RetainedTypes = MDTuple::getDistinct(Context, None); + MDTuple *ImportedEntities = MDTuple::getDistinct(Context, None); auto *N = MDCompileUnit::get( Context, SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,