diff options
Diffstat (limited to 'contrib/llvm/lib/IR/Verifier.cpp')
-rw-r--r-- | contrib/llvm/lib/IR/Verifier.cpp | 711 |
1 files changed, 566 insertions, 145 deletions
diff --git a/contrib/llvm/lib/IR/Verifier.cpp b/contrib/llvm/lib/IR/Verifier.cpp index 682e934..5855059 100644 --- a/contrib/llvm/lib/IR/Verifier.cpp +++ b/contrib/llvm/lib/IR/Verifier.cpp @@ -45,48 +45,86 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/Verifier.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ilist.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/CallingConv.h" +#include "llvm/IR/Comdat.h" +#include "llvm/IR/Constant.h" #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Dominators.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/InlineAsm.h" -#include "llvm/IR/InstIterator.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/ModuleSlotTracker.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/Statepoint.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Use.h" +#include "llvm/IR/User.h" +#include "llvm/IR/Value.h" #include "llvm/Pass.h" +#include "llvm/Support/AtomicOrdering.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> -#include <cstdarg> +#include <cassert> +#include <cstdint> +#include <memory> +#include <string> +#include <utility> + using namespace llvm; static cl::opt<bool> VerifyDebugInfo("verify-debug-info", cl::init(true)); -namespace { +namespace llvm { + struct VerifierSupport { raw_ostream *OS; - const Module *M = nullptr; - Optional<ModuleSlotTracker> MST; + const Module &M; + ModuleSlotTracker MST; + const DataLayout &DL; + LLVMContext &Context; /// Track the brokenness of the module while recursively visiting. bool Broken = false; @@ -95,16 +133,11 @@ struct VerifierSupport { /// Whether to treat broken debug info as an error. bool TreatBrokenDebugInfoAsError = true; - explicit VerifierSupport(raw_ostream *OS) : OS(OS) {} + explicit VerifierSupport(raw_ostream *OS, const Module &M) + : OS(OS), M(M), MST(&M), DL(M.getDataLayout()), Context(M.getContext()) {} private: - template <class NodeTy> void Write(const ilist_iterator<NodeTy> &I) { - Write(&*I); - } - void Write(const Module *M) { - if (!M) - return; *OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n"; } @@ -112,13 +145,14 @@ private: if (!V) return; if (isa<Instruction>(V)) { - V->print(*OS, *MST); + V->print(*OS, MST); *OS << '\n'; } else { - V->printAsOperand(*OS, true, *MST); + V->printAsOperand(*OS, true, MST); *OS << '\n'; } } + void Write(ImmutableCallSite CS) { Write(CS.getInstruction()); } @@ -126,7 +160,7 @@ private: void Write(const Metadata *MD) { if (!MD) return; - MD->print(*OS, *MST, M); + MD->print(*OS, MST, &M); *OS << '\n'; } @@ -137,7 +171,7 @@ private: void Write(const NamedMDNode *NMD) { if (!NMD) return; - NMD->print(*OS, *MST); + NMD->print(*OS, MST); *OS << '\n'; } @@ -153,6 +187,14 @@ private: *OS << *C; } + void Write(const APInt *AI) { + if (!AI) + return; + *OS << *AI << '\n'; + } + + void Write(const unsigned i) { *OS << i << '\n'; } + template <typename T> void Write(ArrayRef<T> Vs) { for (const T &V : Vs) Write(V); @@ -206,10 +248,13 @@ public: } }; +} // namespace llvm + +namespace { + class Verifier : public InstVisitor<Verifier>, VerifierSupport { friend class InstVisitor<Verifier>; - LLVMContext *Context; DominatorTree DT; /// \brief When verifying a basic block, keep track of all of the @@ -252,28 +297,23 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport { // constant expressions, we can arrive at a particular user many times. SmallPtrSet<const Value *, 32> GlobalValueVisited; - void checkAtomicMemAccessSize(const Module *M, Type *Ty, - const Instruction *I); + TBAAVerifier TBAAVerifyHelper; - void updateModule(const Module *NewM) { - if (M == NewM) - return; - MST.emplace(NewM); - M = NewM; - } + void checkAtomicMemAccessSize(Type *Ty, const Instruction *I); public: - explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError) - : VerifierSupport(OS), Context(nullptr), LandingPadResultTy(nullptr), - SawFrameEscape(false) { + explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError, + const Module &M) + : VerifierSupport(OS, M), LandingPadResultTy(nullptr), + SawFrameEscape(false), TBAAVerifyHelper(this) { TreatBrokenDebugInfoAsError = ShouldTreatBrokenDebugInfoAsError; } bool hasBrokenDebugInfo() const { return BrokenDebugInfo; } bool verify(const Function &F) { - updateModule(F.getParent()); - Context = &M->getContext(); + assert(F.getParent() == &M && + "An instance of this class only works with a specific module!"); // First ensure the function is well-enough formed to compute dominance // information, and directly compute a dominance tree. We don't rely on the @@ -291,7 +331,7 @@ public: if (OS) { *OS << "Basic Block in function '" << F.getName() << "' does not have terminator!\n"; - BB.printAsOperand(*OS, true, *MST); + BB.printAsOperand(*OS, true, MST); *OS << "\n"; } return false; @@ -309,9 +349,8 @@ public: return !Broken; } - bool verify(const Module &M) { - updateModule(&M); - Context = &M.getContext(); + /// Verify the module that this instance of \c Verifier was initialized with. + bool verify() { Broken = false; // Collect all declarations of the llvm.experimental.deoptimize intrinsic. @@ -364,8 +403,8 @@ private: SmallVectorImpl<const MDNode *> &Requirements); void visitFunction(const Function &F); void visitBasicBlock(BasicBlock &BB); - void visitRangeMetadata(Instruction& I, MDNode* Range, Type* Ty); - void visitDereferenceableMetadata(Instruction& I, MDNode* MD); + void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty); + void visitDereferenceableMetadata(Instruction &I, MDNode *MD); template <class Ty> bool isValidMetadataArray(const MDTuple &N); #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); @@ -428,6 +467,7 @@ private: void visitInsertValueInst(InsertValueInst &IVI); void visitEHPadPredecessors(Instruction &I); void visitLandingPadInst(LandingPadInst &LPI); + void visitResumeInst(ResumeInst &RI); void visitCatchPadInst(CatchPadInst &CPI); void visitCatchReturnInst(CatchReturnInst &CatchReturn); void visitCleanupPadInst(CleanupPadInst &CPI); @@ -456,7 +496,7 @@ private: void verifyFrameRecoverIndices(); void verifySiblingFuncletUnwinds(); - void verifyBitPieceExpression(const DbgInfoIntrinsic &I); + void verifyFragmentExpression(const DbgInfoIntrinsic &I); /// Module-level debug info verification... void verifyCompileUnits(); @@ -465,17 +505,17 @@ private: /// declarations share the same calling convention. void verifyDeoptimizeCallingConvs(); }; -} // End anonymous namespace + +} // end anonymous namespace /// We know that cond should be true, if not print an error message. #define Assert(C, ...) \ - do { if (!(C)) { CheckFailed(__VA_ARGS__); return; } } while (0) + do { if (!(C)) { CheckFailed(__VA_ARGS__); return; } } while (false) /// We know that a debug info condition should be true, if not print /// an error message. #define AssertDI(C, ...) \ - do { if (!(C)) { DebugInfoCheckFailed(__VA_ARGS__); return; } } while (0) - + do { if (!(C)) { DebugInfoCheckFailed(__VA_ARGS__); return; } } while (false) void Verifier::visit(Instruction &I) { for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) @@ -517,17 +557,17 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) { forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool { if (const Instruction *I = dyn_cast<Instruction>(V)) { if (!I->getParent() || !I->getParent()->getParent()) - CheckFailed("Global is referenced by parentless instruction!", &GV, - M, I); - else if (I->getParent()->getParent()->getParent() != M) - CheckFailed("Global is referenced in a different module!", &GV, - M, I, I->getParent()->getParent(), + CheckFailed("Global is referenced by parentless instruction!", &GV, &M, + I); + else if (I->getParent()->getParent()->getParent() != &M) + CheckFailed("Global is referenced in a different module!", &GV, &M, I, + I->getParent()->getParent(), I->getParent()->getParent()->getParent()); return false; } else if (const Function *F = dyn_cast<Function>(V)) { - if (F->getParent() != M) - CheckFailed("Global is used by function in a different module", &GV, - M, F, F->getParent()); + if (F->getParent() != &M) + CheckFailed("Global is used by function in a different module", &GV, &M, + F, F->getParent()); return false; } return true; @@ -540,7 +580,6 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { "Global variable initializer type does not match global " "variable type!", &GV); - // If the global has common linkage, it must have a zero initializer and // cannot be constant. if (GV.hasCommonLinkage()) { @@ -561,7 +600,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) { StructType *STy = dyn_cast<StructType>(ATy->getElementType()); PointerType *FuncPtrTy = - FunctionType::get(Type::getVoidTy(*Context), false)->getPointerTo(); + FunctionType::get(Type::getVoidTy(Context), false)->getPointerTo(); // FIXME: Reject the 2-field form in LLVM 4.0. Assert(STy && (STy->getNumElements() == 2 || STy->getNumElements() == 3) && @@ -606,6 +645,16 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { GV.hasAvailableExternallyLinkage(), "Global is marked as dllimport, but not external", &GV); + // Visit any debug info attachments. + SmallVector<MDNode *, 1> MDs; + GV.getMetadata(LLVMContext::MD_dbg, MDs); + for (auto *MD : MDs) { + if (auto *GVE = dyn_cast<DIGlobalVariableExpression>(MD)) + visitDIGlobalVariableExpression(*GVE); + else + AssertDI(false, "!dbg attachment of global variable must be a DIGlobalVariableExpression"); + } + if (!GV.hasInitializer()) { visitGlobalValue(GV); return; @@ -672,10 +721,15 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) { } void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { + // There used to be various other llvm.dbg.* nodes, but we don't support + // upgrading them and we want to reserve the namespace for future uses. + if (NMD.getName().startswith("llvm.dbg.")) + AssertDI(NMD.getName() == "llvm.dbg.cu", + "unrecognized named metadata node in the llvm.dbg namespace", + &NMD); for (const MDNode *MD : NMD.operands()) { - if (NMD.getName() == "llvm.dbg.cu") { + if (NMD.getName() == "llvm.dbg.cu") AssertDI(MD && isa<DICompileUnit>(MD), "invalid compile unit", &NMD, MD); - } if (!MD) continue; @@ -769,7 +823,7 @@ static bool isScope(const Metadata *MD) { return !MD || isa<DIScope>(MD); } static bool isDINode(const Metadata *MD) { return !MD || isa<DINode>(MD); } template <class Ty> -bool isValidMetadataArrayImpl(const MDTuple &N, bool AllowNull) { +static bool isValidMetadataArrayImpl(const MDTuple &N, bool AllowNull) { for (Metadata *MD : N.operands()) { if (MD) { if (!isa<Ty>(MD)) @@ -782,13 +836,11 @@ bool isValidMetadataArrayImpl(const MDTuple &N, bool AllowNull) { return true; } -template <class Ty> -bool isValidMetadataArray(const MDTuple &N) { +template <class Ty> static bool isValidMetadataArray(const MDTuple &N) { return isValidMetadataArrayImpl<Ty>(N, /* AllowNull */ false); } -template <class Ty> -bool isValidMetadataNullArray(const MDTuple &N) { +template <class Ty> static bool isValidMetadataNullArray(const MDTuple &N) { return isValidMetadataArrayImpl<Ty>(N, /* AllowNull */ true); } @@ -835,6 +887,7 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) { N.getTag() == dwarf::DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || + N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend, @@ -908,6 +961,8 @@ void Verifier::visitDISubroutineType(const DISubroutineType &N) { void Verifier::visitDIFile(const DIFile &N) { AssertDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N); + AssertDI((N.getChecksumKind() != DIFile::CSK_None || + N.getChecksum().empty()), "invalid checksum kind", &N); } void Verifier::visitDICompileUnit(const DICompileUnit &N) { @@ -937,15 +992,15 @@ void Verifier::visitDICompileUnit(const DICompileUnit &N) { for (Metadata *Op : N.getRetainedTypes()->operands()) { AssertDI(Op && (isa<DIType>(Op) || (isa<DISubprogram>(Op) && - cast<DISubprogram>(Op)->isDefinition() == false)), + !cast<DISubprogram>(Op)->isDefinition())), "invalid retained type", &N, Op); } } if (auto *Array = N.getRawGlobalVariables()) { AssertDI(isa<MDTuple>(Array), "invalid global variable list", &N, Array); for (Metadata *Op : N.getGlobalVariables()->operands()) { - AssertDI(Op && isa<DIGlobalVariable>(Op), "invalid global variable ref", - &N, Op); + AssertDI(Op && (isa<DIGlobalVariableExpression>(Op)), + "invalid global variable ref", &N, Op); } } if (auto *Array = N.getRawImportedEntities()) { @@ -1088,12 +1143,6 @@ void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) { AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N); AssertDI(!N.getName().empty(), "missing global variable name", &N); - if (auto *V = N.getRawVariable()) { - AssertDI(isa<ConstantAsMetadata>(V) && - !isa<Function>(cast<ConstantAsMetadata>(V)->getValue()), - "invalid global varaible ref", &N, V); - visitConstantExprsRecursively(cast<ConstantAsMetadata>(V)->getValue()); - } if (auto *Member = N.getRawStaticDataMemberDeclaration()) { AssertDI(isa<DIDerivedType>(Member), "invalid static data member declaration", &N, Member); @@ -1113,6 +1162,15 @@ void Verifier::visitDIExpression(const DIExpression &N) { AssertDI(N.isValid(), "invalid expression", &N); } +void Verifier::visitDIGlobalVariableExpression( + const DIGlobalVariableExpression &GVE) { + AssertDI(GVE.getVariable(), "missing variable"); + if (auto *Var = GVE.getVariable()) + visitDIGlobalVariable(*Var); + if (auto *Expr = GVE.getExpression()) + visitDIExpression(*Expr); +} + void Verifier::visitDIObjCProperty(const DIObjCProperty &N) { AssertDI(N.getTag() == dwarf::DW_TAG_APPLE_property, "invalid tag", &N); if (auto *T = N.getRawType()) @@ -1134,7 +1192,7 @@ void Verifier::visitDIImportedEntity(const DIImportedEntity &N) { void Verifier::visitComdat(const Comdat &C) { // The Module is invalid if the GlobalValue has private linkage. Entities // with private linkage don't have entries in the symbol table. - if (const GlobalValue *GV = M->getNamedValue(C.getName())) + if (const GlobalValue *GV = M.getNamedValue(C.getName())) Assert(!GV->hasPrivateLinkage(), "comdat global value has private linkage", GV); } @@ -1401,12 +1459,12 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, "'noinline and alwaysinline' are incompatible!", V); - Assert(!AttrBuilder(Attrs, Idx) - .overlaps(AttributeFuncs::typeIncompatible(Ty)), - "Wrong types for attribute: " + - AttributeSet::get(*Context, Idx, - AttributeFuncs::typeIncompatible(Ty)).getAsString(Idx), - V); + Assert( + !AttrBuilder(Attrs, Idx).overlaps(AttributeFuncs::typeIncompatible(Ty)), + "Wrong types for attribute: " + + AttributeSet::get(Context, Idx, AttributeFuncs::typeIncompatible(Ty)) + .getAsString(Idx), + V); if (PointerType *PTy = dyn_cast<PointerType>(Ty)) { SmallPtrSet<Type*, 4> Visited; @@ -1630,8 +1688,8 @@ void Verifier::visitConstantExprsRecursively(const Constant *EntryC) { if (const auto *GV = dyn_cast<GlobalValue>(C)) { // Global Values get visited separately, but we do need to make sure // that the global value is in the correct module - Assert(GV->getParent() == M, "Referencing global in another module!", - EntryC, M, GV, GV->getParent()); + Assert(GV->getParent() == &M, "Referencing global in another module!", + EntryC, &M, GV, GV->getParent()); continue; } @@ -1648,12 +1706,23 @@ void Verifier::visitConstantExprsRecursively(const Constant *EntryC) { } void Verifier::visitConstantExpr(const ConstantExpr *CE) { - if (CE->getOpcode() != Instruction::BitCast) - return; - - Assert(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0), - CE->getType()), - "Invalid bitcast", CE); + if (CE->getOpcode() == Instruction::BitCast) + Assert(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0), + CE->getType()), + "Invalid bitcast", CE); + + if (CE->getOpcode() == Instruction::IntToPtr || + CE->getOpcode() == Instruction::PtrToInt) { + auto *PtrTy = CE->getOpcode() == Instruction::IntToPtr + ? CE->getType() + : CE->getOperand(0)->getType(); + StringRef Msg = CE->getOpcode() == Instruction::IntToPtr + ? "inttoptr not supported for non-integral pointers" + : "ptrtoint not supported for non-integral pointers"; + Assert( + !DL.isNonIntegralPointerType(cast<PointerType>(PtrTy->getScalarType())), + Msg); + } } bool Verifier::verifyAttributeCount(AttributeSet Attrs, unsigned Params) { @@ -1783,7 +1852,7 @@ void Verifier::verifyStatepoint(ImmutableCallSite CS) { Assert(Call, "illegal use of statepoint token", &CI, U); if (!Call) continue; Assert(isa<GCRelocateInst>(Call) || isa<GCResultInst>(Call), - "gc.result or gc.relocate are the only value uses" + "gc.result or gc.relocate are the only value uses " "of a gc.statepoint", &CI, U); if (isa<GCResultInst>(Call)) { @@ -1880,7 +1949,7 @@ void Verifier::visitFunction(const Function &F) { FunctionType *FT = F.getFunctionType(); unsigned NumArgs = F.arg_size(); - Assert(Context == &F.getContext(), + Assert(&Context == &F.getContext(), "Function context does not match Module context!", &F); Assert(!F.hasCommonLinkage(), "Functions may not have common linkage", &F); @@ -2035,7 +2104,7 @@ void Verifier::visitFunction(const Function &F) { if (F.getIntrinsicID() && F.getParent()->isMaterialized()) { const User *U; if (F.hasAddressTaken(&U)) - Assert(0, "Invalid user of intrinsic instruction!", U); + Assert(false, "Invalid user of intrinsic instruction!", U); } Assert(!F.hasDLLImportStorageClass() || @@ -2078,9 +2147,9 @@ void Verifier::visitFunction(const Function &F) { continue; // FIXME: Once N is canonical, check "SP == &N". - Assert(SP->describes(&F), - "!dbg attachment points at wrong subprogram for function", N, &F, - &I, DL, Scope, SP); + AssertDI(SP->describes(&F), + "!dbg attachment points at wrong subprogram for function", N, &F, + &I, DL, Scope, SP); } } @@ -2218,7 +2287,7 @@ void Verifier::visitSelectInst(SelectInst &SI) { /// a pass, if any exist, it's an error. /// void Verifier::visitUserOp1(Instruction &I) { - Assert(0, "User-defined operators should not live outside of a pass!", &I); + Assert(false, "User-defined operators should not live outside of a pass!", &I); } void Verifier::visitTruncInst(TruncInst &I) { @@ -2409,6 +2478,11 @@ void Verifier::visitPtrToIntInst(PtrToIntInst &I) { Assert(SrcTy->getScalarType()->isPointerTy(), "PtrToInt source must be pointer", &I); + + if (auto *PTy = dyn_cast<PointerType>(SrcTy->getScalarType())) + Assert(!DL.isNonIntegralPointerType(PTy), + "ptrtoint not supported for non-integral pointers"); + Assert(DestTy->getScalarType()->isIntegerTy(), "PtrToInt result must be integral", &I); Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToInt type mismatch", @@ -2433,6 +2507,11 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) { "IntToPtr source must be an integral", &I); Assert(DestTy->getScalarType()->isPointerTy(), "IntToPtr result must be a pointer", &I); + + if (auto *PTy = dyn_cast<PointerType>(DestTy->getScalarType())) + Assert(!DL.isNonIntegralPointerType(PTy), + "inttoptr not supported for non-integral pointers"); + Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "IntToPtr type mismatch", &I); if (SrcTy->isVectorTy()) { @@ -2541,15 +2620,20 @@ void Verifier::verifyCallSite(CallSite CS) { } // For each argument of the callsite, if it has the swifterror argument, - // make sure the underlying alloca has swifterror as well. + // make sure the underlying alloca/parameter it comes from has a swifterror as + // well. for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) if (CS.paramHasAttr(i+1, Attribute::SwiftError)) { Value *SwiftErrorArg = CS.getArgument(i); - auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets()); - Assert(AI, "swifterror argument should come from alloca", AI, I); - if (AI) + if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) { Assert(AI->isSwiftError(), "swifterror argument for call has mismatched alloca", AI, I); + continue; + } + auto ArgI = dyn_cast<Argument>(SwiftErrorArg); + Assert(ArgI, "swifterror argument should come from an alloca or parameter", SwiftErrorArg, I); + Assert(ArgI->hasSwiftErrorAttr(), + "swifterror argument for call has mismatched parameter", ArgI, I); } if (FTy->isVarArg()) { @@ -2915,10 +2999,8 @@ static bool isContiguous(const ConstantRange &A, const ConstantRange &B) { return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); } -void Verifier::visitRangeMetadata(Instruction& I, - MDNode* Range, Type* Ty) { - assert(Range && - Range == I.getMetadata(LLVMContext::MD_range) && +void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) { + assert(Range && Range == I.getMetadata(LLVMContext::MD_range) && "precondition violation"); unsigned NumOperands = Range->getNumOperands(); @@ -2965,9 +3047,8 @@ void Verifier::visitRangeMetadata(Instruction& I, } } -void Verifier::checkAtomicMemAccessSize(const Module *M, Type *Ty, - const Instruction *I) { - unsigned Size = M->getDataLayout().getTypeSizeInBits(Ty); +void Verifier::checkAtomicMemAccessSize(Type *Ty, const Instruction *I) { + unsigned Size = DL.getTypeSizeInBits(Ty); Assert(Size >= 8, "atomic memory access' size must be byte-sized", Ty, I); Assert(!(Size & (Size - 1)), "atomic memory access' operand must have a power-of-two size", Ty, I); @@ -2991,7 +3072,7 @@ void Verifier::visitLoadInst(LoadInst &LI) { "atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); - checkAtomicMemAccessSize(M, ElTy, &LI); + checkAtomicMemAccessSize(ElTy, &LI); } else { Assert(LI.getSynchScope() == CrossThread, "Non-atomic load cannot have SynchronizationScope specified", &LI); @@ -3020,7 +3101,7 @@ void Verifier::visitStoreInst(StoreInst &SI) { "atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); - checkAtomicMemAccessSize(M, ElTy, &SI); + checkAtomicMemAccessSize(ElTy, &SI); } else { Assert(SI.getSynchScope() == CrossThread, "Non-atomic store cannot have SynchronizationScope specified", &SI); @@ -3109,7 +3190,7 @@ void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) { Assert(ElTy->isIntegerTy() || ElTy->isPointerTy(), "cmpxchg operand must have integer or pointer type", ElTy, &CXI); - checkAtomicMemAccessSize(M, ElTy, &CXI); + checkAtomicMemAccessSize(ElTy, &CXI); Assert(ElTy == CXI.getOperand(1)->getType(), "Expected value type does not match pointer operand type!", &CXI, ElTy); @@ -3128,7 +3209,7 @@ void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { Type *ElTy = PTy->getElementType(); Assert(ElTy->isIntegerTy(), "atomicrmw operand must have integer type!", &RMWI, ElTy); - checkAtomicMemAccessSize(M, ElTy, &RMWI); + checkAtomicMemAccessSize(ElTy, &RMWI); Assert(ElTy == RMWI.getOperand(1)->getType(), "Argument value type does not match pointer operand type!", &RMWI, ElTy); @@ -3288,6 +3369,21 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) { visitInstruction(LPI); } +void Verifier::visitResumeInst(ResumeInst &RI) { + Assert(RI.getFunction()->hasPersonalityFn(), + "ResumeInst needs to be in a function with a personality.", &RI); + + if (!LandingPadResultTy) + LandingPadResultTy = RI.getValue()->getType(); + else + Assert(LandingPadResultTy == RI.getValue()->getType(), + "The resume instruction should have a consistent result type " + "inside a function.", + &RI); + + visitTerminatorInst(RI); +} + void Verifier::visitCatchPadInst(CatchPadInst &CPI) { BasicBlock *BB = CPI.getParent(); @@ -3640,7 +3736,7 @@ void Verifier::visitInstruction(Instruction &I) { // Check to make sure that only first-class-values are operands to // instructions. if (!I.getOperand(i)->getType()->isFirstClassType()) { - Assert(0, "Instruction operands must be first-class values!", &I); + Assert(false, "Instruction operands must be first-class values!", &I); } if (Function *F = dyn_cast<Function>(I.getOperand(i))) { @@ -3653,14 +3749,16 @@ void Verifier::visitInstruction(Instruction &I) { Assert( !F->isIntrinsic() || isa<CallInst>(I) || F->getIntrinsicID() == Intrinsic::donothing || + F->getIntrinsicID() == Intrinsic::coro_resume || + F->getIntrinsicID() == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint, - "Cannot invoke an intrinsic other than donothing, patchpoint or " - "statepoint", + "Cannot invoke an intrinsic other than donothing, patchpoint, " + "statepoint, coro_resume or coro_destroy", &I); - Assert(F->getParent() == M, "Referencing function in another module!", - &I, M, F, F->getParent()); + Assert(F->getParent() == &M, "Referencing function in another module!", + &I, &M, F, F->getParent()); } else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) { Assert(OpBB->getParent() == BB->getParent(), "Referring to a basic block in another function!", &I); @@ -3668,7 +3766,8 @@ void Verifier::visitInstruction(Instruction &I) { Assert(OpArg->getParent() == BB->getParent(), "Referring to an argument in another function!", &I); } else if (GlobalValue *GV = dyn_cast<GlobalValue>(I.getOperand(i))) { - Assert(GV->getParent() == M, "Referencing global in another module!", &I, M, GV, GV->getParent()); + Assert(GV->getParent() == &M, "Referencing global in another module!", &I, + &M, GV, GV->getParent()); } else if (isa<Instruction>(I.getOperand(i))) { verifyDominatesUse(I, i); } else if (isa<InlineAsm>(I.getOperand(i))) { @@ -3676,9 +3775,12 @@ void Verifier::visitInstruction(Instruction &I) { (i + 3 == e && isa<InvokeInst>(I)), "Cannot take the address of an inline asm!", &I); } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(i))) { - if (CE->getType()->isPtrOrPtrVectorTy()) { + if (CE->getType()->isPtrOrPtrVectorTy() || + !DL.getNonIntegralAddressSpaces().empty()) { // If we have a ConstantExpr pointer, we need to see if it came from an - // illegal bitcast (inttoptr <constant int> ) + // illegal bitcast. If the datalayout string specifies non-integral + // address spaces then we also need to check for illegal ptrtoint and + // inttoptr expressions. visitConstantExprsRecursively(CE); } } @@ -3691,7 +3793,7 @@ void Verifier::visitInstruction(Instruction &I) { if (ConstantFP *CFP0 = mdconst::dyn_extract_or_null<ConstantFP>(MD->getOperand(0))) { const APFloat &Accuracy = CFP0->getValueAPF(); - Assert(&Accuracy.getSemantics() == &APFloat::IEEEsingle, + Assert(&Accuracy.getSemantics() == &APFloat::IEEEsingle(), "fpmath accuracy must have float type", &I); Assert(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(), "fpmath accuracy not a positive number!", &I); @@ -3721,6 +3823,9 @@ void Verifier::visitInstruction(Instruction &I) { if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) visitDereferenceableMetadata(I, MD); + if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) + TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); + if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) { Assert(I.getType()->isPointerTy(), "align applies only to pointer types", &I); @@ -3743,7 +3848,7 @@ void Verifier::visitInstruction(Instruction &I) { } if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I)) - verifyBitPieceExpression(*DII); + verifyFragmentExpression(*DII); InstsInThisBlock.insert(&I); } @@ -3803,6 +3908,20 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { switch (ID) { default: break; + case Intrinsic::coro_id: { + auto *InfoArg = CS.getArgOperand(3)->stripPointerCasts(); + if (isa<ConstantPointerNull>(InfoArg)) + break; + auto *GV = dyn_cast<GlobalVariable>(InfoArg); + Assert(GV && GV->isConstant() && GV->hasDefinitiveInitializer(), + "info argument of llvm.coro.begin must refer to an initialized " + "constant"); + Constant *Init = GV->getInitializer(); + Assert(isa<ConstantStruct>(Init) || isa<ConstantArray>(Init), + "info argument of llvm.coro.begin must refer to either a struct or " + "an array"); + break; + } case Intrinsic::ctlz: // llvm.ctlz case Intrinsic::cttz: // llvm.cttz Assert(isa<ConstantInt>(CS.getArgOperand(1)), @@ -3833,6 +3952,32 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { CS); break; } + case Intrinsic::memcpy_element_atomic: { + ConstantInt *ElementSizeCI = dyn_cast<ConstantInt>(CS.getArgOperand(3)); + Assert(ElementSizeCI, "element size of the element-wise atomic memory " + "intrinsic must be a constant int", + CS); + const APInt &ElementSizeVal = ElementSizeCI->getValue(); + Assert(ElementSizeVal.isPowerOf2(), + "element size of the element-wise atomic memory intrinsic " + "must be a power of 2", + CS); + + auto IsValidAlignment = [&](uint64_t Alignment) { + return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment); + }; + + uint64_t DstAlignment = CS.getParamAlignment(1), + SrcAlignment = CS.getParamAlignment(2); + + Assert(IsValidAlignment(DstAlignment), + "incorrect alignment of the destination argument", + CS); + Assert(IsValidAlignment(SrcAlignment), + "incorrect alignment of the source argument", + CS); + break; + } case Intrinsic::gcroot: case Intrinsic::gcwrite: case Intrinsic::gcread: @@ -4181,10 +4326,10 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { if (!VarSP || !LocSP) return; // Broken scope chains are checked elsewhere. - Assert(VarSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind + - " variable and !dbg attachment", - &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc, - Loc->getScope()->getSubprogram()); + AssertDI(VarSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind + + " variable and !dbg attachment", + &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc, + Loc->getScope()->getSubprogram()); } static uint64_t getVariableSize(const DILocalVariable &V) { @@ -4210,7 +4355,7 @@ static uint64_t getVariableSize(const DILocalVariable &V) { return 0; } -void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I) { +void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) { DILocalVariable *V; DIExpression *E; if (auto *DVI = dyn_cast<DbgValueInst>(&I)) { @@ -4227,7 +4372,8 @@ void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I) { return; // Nothing to do if this isn't a bit piece expression. - if (!E->isBitPiece()) + auto Fragment = E->getFragmentInfo(); + if (!Fragment) return; // The frontend helps out GDB by emitting the members of local anonymous @@ -4245,21 +4391,21 @@ void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I) { if (!VarSize) return; - unsigned PieceSize = E->getBitPieceSize(); - unsigned PieceOffset = E->getBitPieceOffset(); - Assert(PieceSize + PieceOffset <= VarSize, - "piece is larger than or outside of variable", &I, V, E); - Assert(PieceSize != VarSize, "piece covers entire variable", &I, V, E); + unsigned FragSize = Fragment->SizeInBits; + unsigned FragOffset = Fragment->OffsetInBits; + AssertDI(FragSize + FragOffset <= VarSize, + "fragment is larger than or outside of variable", &I, V, E); + AssertDI(FragSize != VarSize, "fragment covers entire variable", &I, V, E); } void Verifier::verifyCompileUnits() { - auto *CUs = M->getNamedMetadata("llvm.dbg.cu"); + auto *CUs = M.getNamedMetadata("llvm.dbg.cu"); SmallPtrSet<const Metadata *, 2> Listed; if (CUs) Listed.insert(CUs->op_begin(), CUs->op_end()); - Assert( - std::all_of(CUVisited.begin(), CUVisited.end(), - [&Listed](const Metadata *CU) { return Listed.count(CU); }), + AssertDI( + all_of(CUVisited, + [&Listed](const Metadata *CU) { return Listed.count(CU); }), "All DICompileUnits must be listed in llvm.dbg.cu"); CUVisited.clear(); } @@ -4285,7 +4431,7 @@ bool llvm::verifyFunction(const Function &f, raw_ostream *OS) { Function &F = const_cast<Function &>(f); // Don't use a raw_null_ostream. Printing IR is expensive. - Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true); + Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true, *f.getParent()); // Note that this function's return value is inverted from what you would // expect of a function called "verify". @@ -4295,13 +4441,13 @@ bool llvm::verifyFunction(const Function &f, raw_ostream *OS) { bool llvm::verifyModule(const Module &M, raw_ostream *OS, bool *BrokenDebugInfo) { // Don't use a raw_null_ostream. Printing IR is expensive. - Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/!BrokenDebugInfo); + Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/!BrokenDebugInfo, M); bool Broken = false; for (const Function &F : M) Broken |= !V.verify(F); - Broken |= !V.verify(M); + Broken |= !V.verify(); if (BrokenDebugInfo) *BrokenDebugInfo = V.hasBrokenDebugInfo(); // Note that this function's return value is inverted from what you would @@ -4310,26 +4456,30 @@ bool llvm::verifyModule(const Module &M, raw_ostream *OS, } namespace { + struct VerifierLegacyPass : public FunctionPass { static char ID; - Verifier V; + std::unique_ptr<Verifier> V; bool FatalErrors = true; - VerifierLegacyPass() - : FunctionPass(ID), - V(&dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false) { + VerifierLegacyPass() : FunctionPass(ID) { initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); } explicit VerifierLegacyPass(bool FatalErrors) : FunctionPass(ID), - V(&dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false), FatalErrors(FatalErrors) { initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); } + bool doInitialization(Module &M) override { + V = llvm::make_unique<Verifier>( + &dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false, M); + return false; + } + bool runOnFunction(Function &F) override { - if (!V.verify(F) && FatalErrors) + if (!V->verify(F) && FatalErrors) report_fatal_error("Broken function found, compilation aborted!"); return false; @@ -4339,17 +4489,17 @@ struct VerifierLegacyPass : public FunctionPass { bool HasErrors = false; for (Function &F : M) if (F.isDeclaration()) - HasErrors |= !V.verify(F); + HasErrors |= !V->verify(F); - HasErrors |= !V.verify(M); + HasErrors |= !V->verify(); if (FatalErrors) { if (HasErrors) report_fatal_error("Broken module found, compilation aborted!"); - assert(!V.hasBrokenDebugInfo() && "Module contains invalid debug info"); + assert(!V->hasBrokenDebugInfo() && "Module contains invalid debug info"); } // Strip broken debug info. - if (V.hasBrokenDebugInfo()) { + if (V->hasBrokenDebugInfo()) { DiagnosticInfoIgnoringInvalidDebugMetadata DiagInvalid(M); M.getContext().diagnose(DiagInvalid); if (!StripDebugInfo(M)) @@ -4362,6 +4512,277 @@ struct VerifierLegacyPass : public FunctionPass { AU.setPreservesAll(); } }; + +} // end anonymous namespace + +/// Helper to issue failure from the TBAA verification +template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&... Args) { + if (Diagnostic) + return Diagnostic->CheckFailed(Args...); +} + +#define AssertTBAA(C, ...) \ + do { \ + if (!(C)) { \ + CheckFailed(__VA_ARGS__); \ + return false; \ + } \ + } while (false) + +/// Verify that \p BaseNode can be used as the "base type" in the struct-path +/// TBAA scheme. This means \p BaseNode is either a scalar node, or a +/// struct-type node describing an aggregate data structure (like a struct). +TBAAVerifier::TBAABaseNodeSummary +TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode) { + if (BaseNode->getNumOperands() < 2) { + CheckFailed("Base nodes must have at least two operands", &I, BaseNode); + return {true, ~0u}; + } + + auto Itr = TBAABaseNodes.find(BaseNode); + if (Itr != TBAABaseNodes.end()) + return Itr->second; + + auto Result = verifyTBAABaseNodeImpl(I, BaseNode); + auto InsertResult = TBAABaseNodes.insert({BaseNode, Result}); + (void)InsertResult; + assert(InsertResult.second && "We just checked!"); + return Result; +} + +TBAAVerifier::TBAABaseNodeSummary +TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode) { + const TBAAVerifier::TBAABaseNodeSummary InvalidNode = {true, ~0u}; + + if (BaseNode->getNumOperands() == 2) { + // Scalar nodes can only be accessed at offset 0. + return isValidScalarTBAANode(BaseNode) + ? TBAAVerifier::TBAABaseNodeSummary({false, 0}) + : InvalidNode; + } + + if (BaseNode->getNumOperands() % 2 != 1) { + CheckFailed("Struct tag nodes must have an odd number of operands!", + BaseNode); + return InvalidNode; + } + + if (!isa<MDString>(BaseNode->getOperand(0))) { + CheckFailed("Struct tag nodes have a string as their first operand", + BaseNode); + return InvalidNode; + } + + bool Failed = false; + + Optional<APInt> PrevOffset; + unsigned BitWidth = ~0u; + + // We've already checked that BaseNode is not a degenerate root node with one + // operand in \c verifyTBAABaseNode, so this loop should run at least once. + for (unsigned Idx = 1; Idx < BaseNode->getNumOperands(); Idx += 2) { + const MDOperand &FieldTy = BaseNode->getOperand(Idx); + const MDOperand &FieldOffset = BaseNode->getOperand(Idx + 1); + if (!isa<MDNode>(FieldTy)) { + CheckFailed("Incorrect field entry in struct type node!", &I, BaseNode); + Failed = true; + continue; + } + + auto *OffsetEntryCI = + mdconst::dyn_extract_or_null<ConstantInt>(FieldOffset); + if (!OffsetEntryCI) { + CheckFailed("Offset entries must be constants!", &I, BaseNode); + Failed = true; + continue; + } + + if (BitWidth == ~0u) + BitWidth = OffsetEntryCI->getBitWidth(); + + if (OffsetEntryCI->getBitWidth() != BitWidth) { + CheckFailed( + "Bitwidth between the offsets and struct type entries must match", &I, + BaseNode); + Failed = true; + continue; + } + + // NB! As far as I can tell, we generate a non-strictly increasing offset + // sequence only from structs that have zero size bit fields. When + // recursing into a contained struct in \c getFieldNodeFromTBAABaseNode we + // pick the field lexically the latest in struct type metadata node. This + // mirrors the actual behavior of the alias analysis implementation. + bool IsAscending = + !PrevOffset || PrevOffset->ule(OffsetEntryCI->getValue()); + + if (!IsAscending) { + CheckFailed("Offsets must be increasing!", &I, BaseNode); + Failed = true; + } + + PrevOffset = OffsetEntryCI->getValue(); + } + + return Failed ? InvalidNode + : TBAAVerifier::TBAABaseNodeSummary(false, BitWidth); +} + +static bool IsRootTBAANode(const MDNode *MD) { + return MD->getNumOperands() < 2; +} + +static bool IsScalarTBAANodeImpl(const MDNode *MD, + SmallPtrSetImpl<const MDNode *> &Visited) { + if (MD->getNumOperands() != 2 && MD->getNumOperands() != 3) + return false; + + if (!isa<MDString>(MD->getOperand(0))) + return false; + + if (MD->getNumOperands() == 3) { + auto *Offset = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2)); + if (!(Offset && Offset->isZero() && isa<MDString>(MD->getOperand(0)))) + return false; + } + + auto *Parent = dyn_cast_or_null<MDNode>(MD->getOperand(1)); + return Parent && Visited.insert(Parent).second && + (IsRootTBAANode(Parent) || IsScalarTBAANodeImpl(Parent, Visited)); +} + +bool TBAAVerifier::isValidScalarTBAANode(const MDNode *MD) { + auto ResultIt = TBAAScalarNodes.find(MD); + if (ResultIt != TBAAScalarNodes.end()) + return ResultIt->second; + + SmallPtrSet<const MDNode *, 4> Visited; + bool Result = IsScalarTBAANodeImpl(MD, Visited); + auto InsertResult = TBAAScalarNodes.insert({MD, Result}); + (void)InsertResult; + assert(InsertResult.second && "Just checked!"); + + return Result; +} + +/// Returns the field node at the offset \p Offset in \p BaseNode. Update \p +/// Offset in place to be the offset within the field node returned. +/// +/// We assume we've okayed \p BaseNode via \c verifyTBAABaseNode. +MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I, + const MDNode *BaseNode, + APInt &Offset) { + assert(BaseNode->getNumOperands() >= 2 && "Invalid base node!"); + + // Scalar nodes have only one possible "field" -- their parent in the access + // hierarchy. Offset must be zero at this point, but our caller is supposed + // to Assert that. + if (BaseNode->getNumOperands() == 2) + return cast<MDNode>(BaseNode->getOperand(1)); + + for (unsigned Idx = 1; Idx < BaseNode->getNumOperands(); Idx += 2) { + auto *OffsetEntryCI = + mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx + 1)); + if (OffsetEntryCI->getValue().ugt(Offset)) { + if (Idx == 1) { + CheckFailed("Could not find TBAA parent in struct type node", &I, + BaseNode, &Offset); + return nullptr; + } + + auto *PrevOffsetEntryCI = + mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx - 1)); + Offset -= PrevOffsetEntryCI->getValue(); + return cast<MDNode>(BaseNode->getOperand(Idx - 2)); + } + } + + auto *LastOffsetEntryCI = mdconst::extract<ConstantInt>( + BaseNode->getOperand(BaseNode->getNumOperands() - 1)); + + Offset -= LastOffsetEntryCI->getValue(); + return cast<MDNode>(BaseNode->getOperand(BaseNode->getNumOperands() - 2)); +} + +bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { + AssertTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || + isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) || + isa<AtomicCmpXchgInst>(I), + "TBAA is only for loads, stores and calls!", &I); + + bool IsStructPathTBAA = + isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3; + + AssertTBAA( + IsStructPathTBAA, + "Old-style TBAA is no longer allowed, use struct-path TBAA instead", &I); + + AssertTBAA(MD->getNumOperands() < 5, + "Struct tag metadata must have either 3 or 4 operands", &I, MD); + + MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0)); + MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1)); + + if (MD->getNumOperands() == 4) { + auto *IsImmutableCI = + mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(3)); + AssertTBAA(IsImmutableCI, + "Immutability tag on struct tag metadata must be a constant", &I, + MD); + AssertTBAA( + IsImmutableCI->isZero() || IsImmutableCI->isOne(), + "Immutability part of the struct tag metadata must be either 0 or 1", + &I, MD); + } + + AssertTBAA(BaseNode && AccessType, + "Malformed struct tag metadata: base and access-type " + "should be non-null and point to Metadata nodes", + &I, MD, BaseNode, AccessType); + + AssertTBAA(isValidScalarTBAANode(AccessType), + "Access type node must be a valid scalar type", &I, MD, + AccessType); + + auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2)); + AssertTBAA(OffsetCI, "Offset must be constant integer", &I, MD); + + APInt Offset = OffsetCI->getValue(); + bool SeenAccessTypeInPath = false; + + SmallPtrSet<MDNode *, 4> StructPath; + + for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode); + BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset)) { + if (!StructPath.insert(BaseNode).second) { + CheckFailed("Cycle detected in struct path", &I, MD); + return false; + } + + bool Invalid; + unsigned BaseNodeBitWidth; + std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode); + + // If the base node is invalid in itself, then we've already printed all the + // errors we wanted to print. + if (Invalid) + return false; + + SeenAccessTypeInPath |= BaseNode == AccessType; + + if (isValidScalarTBAANode(BaseNode) || BaseNode == AccessType) + AssertTBAA(Offset == 0, "Offset not zero at the point of scalar access", + &I, MD, &Offset); + + AssertTBAA(BaseNodeBitWidth == Offset.getBitWidth() || + (BaseNodeBitWidth == 0 && Offset == 0), + "Access bit-width not the same as description bit-width", &I, MD, + BaseNodeBitWidth, Offset.getBitWidth()); + } + + AssertTBAA(SeenAccessTypeInPath, "Did not see access type in access path!", + &I, MD); + return true; } char VerifierLegacyPass::ID = 0; @@ -4371,7 +4792,7 @@ FunctionPass *llvm::createVerifierPass(bool FatalErrors) { return new VerifierLegacyPass(FatalErrors); } -char VerifierAnalysis::PassID; +AnalysisKey VerifierAnalysis::Key; VerifierAnalysis::Result VerifierAnalysis::run(Module &M, ModuleAnalysisManager &) { Result Res; |