diff options
author | dim <dim@FreeBSD.org> | 2016-12-26 20:36:37 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2016-12-26 20:36:37 +0000 |
commit | 06210ae42d418d50d8d9365d5c9419308ae9e7ee (patch) | |
tree | ab60b4cdd6e430dda1f292a46a77ddb744723f31 /contrib/llvm/lib/IR/Verifier.cpp | |
parent | 2dd166267f53df1c3748b4325d294b9b839de74b (diff) | |
download | FreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.zip FreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.tar.gz |
MFC r309124:
Upgrade our copies of clang, llvm, lldb, compiler-rt and libc++ to 3.9.0
release, and add lld 3.9.0. Also completely revamp the build system for
clang, llvm, lldb and their related tools.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Release notes for llvm, clang and lld are available here:
<http://llvm.org/releases/3.9.0/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.9.0/tools/clang/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.9.0/tools/lld/docs/ReleaseNotes.html>
Thanks to Ed Maste, Bryan Drewery, Andrew Turner, Antoine Brodin and Jan
Beich for their help.
Relnotes: yes
MFC r309147:
Pull in r282174 from upstream llvm trunk (by Krzysztof Parzyszek):
[PPC] Set SP after loading data from stack frame, if no red zone is
present
Follow-up to r280705: Make sure that the SP is only restored after
all data is loaded from the stack frame, if there is no red zone.
This completes the fix for
https://llvm.org/bugs/show_bug.cgi?id=26519.
Differential Revision: https://reviews.llvm.org/D24466
Reported by: Mark Millard
PR: 214433
MFC r309149:
Pull in r283060 from upstream llvm trunk (by Hal Finkel):
[PowerPC] Refactor soft-float support, and enable PPC64 soft float
This change enables soft-float for PowerPC64, and also makes
soft-float disable all vector instruction sets for both 32-bit and
64-bit modes. This latter part is necessary because the PPC backend
canonicalizes many Altivec vector types to floating-point types, and
so soft-float breaks scalarization support for many operations. Both
for embedded targets and for operating-system kernels desiring
soft-float support, it seems reasonable that disabling hardware
floating-point also disables vector instructions (embedded targets
without hardware floating point support are unlikely to have Altivec,
etc. and operating system kernels desiring not to use floating-point
registers to lower syscall cost are unlikely to want to use vector
registers either). If someone needs this to work, we'll need to
change the fact that we promote many Altivec operations to act on
v4f32. To make it possible to disable Altivec when soft-float is
enabled, hardware floating-point support needs to be expressed as a
positive feature, like the others, and not a negative feature,
because target features cannot have dependencies on the disabling of
some other feature. So +soft-float has now become -hard-float.
Fixes PR26970.
Pull in r283061 from upstream clang trunk (by Hal Finkel):
[PowerPC] Enable soft-float for PPC64, and +soft-float -> -hard-float
Enable soft-float support on PPC64, as the backend now supports it.
Also, the backend now uses -hard-float instead of +soft-float, so set
the target features accordingly.
Fixes PR26970.
Reported by: Mark Millard
PR: 214433
MFC r309212:
Add a few missed clang 3.9.0 files to OptionalObsoleteFiles.
MFC r309262:
Fix packaging for clang, lldb and lld 3.9.0
During the upgrade of clang/llvm etc to 3.9.0 in r309124, the PACKAGE
directive in the usr.bin/clang/*.mk files got dropped accidentally.
Restore it, with a few minor changes and additions:
* Correct license in clang.ucl to NCSA
* Add PACKAGE=clang for clang and most of the "ll" tools
* Put lldb in its own package
* Put lld in its own package
Reviewed by: gjb, jmallett
Differential Revision: https://reviews.freebsd.org/D8666
MFC r309656:
During the bootstrap phase, when building the minimal llvm library on
PowerPC, add lib/Support/Atomic.cpp. This is needed because upstream
llvm revision r271821 disabled the use of std::call_once, which causes
some fallback functions from Atomic.cpp to be used instead.
Reported by: Mark Millard
PR: 214902
MFC r309835:
Tentatively apply https://reviews.llvm.org/D18730 to work around gcc PR
70528 (bogus error: constructor required before non-static data member).
This should fix buildworld with the external gcc package.
Reported by: https://jenkins.freebsd.org/job/FreeBSD_HEAD_amd64_gcc/
MFC r310194:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
3.9.1 release.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Release notes for llvm, clang and lld will be available here:
<http://releases.llvm.org/3.9.1/docs/ReleaseNotes.html>
<http://releases.llvm.org/3.9.1/tools/clang/docs/ReleaseNotes.html>
<http://releases.llvm.org/3.9.1/tools/lld/docs/ReleaseNotes.html>
Relnotes: yes
Diffstat (limited to 'contrib/llvm/lib/IR/Verifier.cpp')
-rw-r--r-- | contrib/llvm/lib/IR/Verifier.cpp | 1461 |
1 files changed, 802 insertions, 659 deletions
diff --git a/contrib/llvm/lib/IR/Verifier.cpp b/contrib/llvm/lib/IR/Verifier.cpp index 9198b0e..682e934 100644 --- a/contrib/llvm/lib/IR/Verifier.cpp +++ b/contrib/llvm/lib/IR/Verifier.cpp @@ -59,6 +59,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstIterator.h" @@ -67,6 +68,7 @@ #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/Pass.h" @@ -82,14 +84,18 @@ static cl::opt<bool> VerifyDebugInfo("verify-debug-info", cl::init(true)); namespace { struct VerifierSupport { - raw_ostream &OS; - const Module *M; + raw_ostream *OS; + const Module *M = nullptr; + Optional<ModuleSlotTracker> MST; - /// \brief Track the brokenness of the module while recursively visiting. - bool Broken; + /// Track the brokenness of the module while recursively visiting. + bool Broken = false; + /// Broken debug info can be "recovered" from by stripping the debug info. + bool BrokenDebugInfo = false; + /// Whether to treat broken debug info as an error. + bool TreatBrokenDebugInfoAsError = true; - explicit VerifierSupport(raw_ostream &OS) - : OS(OS), M(nullptr), Broken(false) {} + explicit VerifierSupport(raw_ostream *OS) : OS(OS) {} private: template <class NodeTy> void Write(const ilist_iterator<NodeTy> &I) { @@ -99,17 +105,18 @@ private: void Write(const Module *M) { if (!M) return; - OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n"; + *OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n"; } void Write(const Value *V) { if (!V) return; if (isa<Instruction>(V)) { - OS << *V << '\n'; + V->print(*OS, *MST); + *OS << '\n'; } else { - V->printAsOperand(OS, true, M); - OS << '\n'; + V->printAsOperand(*OS, true, *MST); + *OS << '\n'; } } void Write(ImmutableCallSite CS) { @@ -119,8 +126,8 @@ private: void Write(const Metadata *MD) { if (!MD) return; - MD->print(OS, M); - OS << '\n'; + MD->print(*OS, *MST, M); + *OS << '\n'; } template <class T> void Write(const MDTupleTypedArrayWrapper<T> &MD) { @@ -130,20 +137,20 @@ private: void Write(const NamedMDNode *NMD) { if (!NMD) return; - NMD->print(OS); - OS << '\n'; + NMD->print(*OS, *MST); + *OS << '\n'; } void Write(Type *T) { if (!T) return; - OS << ' ' << *T; + *OS << ' ' << *T; } void Write(const Comdat *C) { if (!C) return; - OS << *C; + *OS << *C; } template <typename T> void Write(ArrayRef<T> Vs) { @@ -165,7 +172,8 @@ public: /// This provides a nice place to put a breakpoint if you want to see why /// something is not correct. void CheckFailed(const Twine &Message) { - OS << Message << '\n'; + if (OS) + *OS << Message << '\n'; Broken = true; } @@ -176,7 +184,25 @@ public: template <typename T1, typename... Ts> void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) { CheckFailed(Message); - WriteTs(V1, Vs...); + if (OS) + WriteTs(V1, Vs...); + } + + /// A debug info check failed. + void DebugInfoCheckFailed(const Twine &Message) { + if (OS) + *OS << Message << '\n'; + Broken |= TreatBrokenDebugInfoAsError; + BrokenDebugInfo = true; + } + + /// A debug info check failed (with values to print). + template <typename T1, typename... Ts> + void DebugInfoCheckFailed(const Twine &Message, const T1 &V1, + const Ts &... Vs) { + DebugInfoCheckFailed(Message); + if (OS) + WriteTs(V1, Vs...); } }; @@ -196,8 +222,8 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport { /// \brief Keep track of the metadata nodes that have been checked already. SmallPtrSet<const Metadata *, 32> MDNodes; - /// \brief Track unresolved string-based type references. - SmallDenseMap<const MDString *, const MDNode *, 32> UnresolvedTypeRefs; + /// Track all DICompileUnits visited. + SmallPtrSet<const Metadata *, 2> CUVisited; /// \brief The result type for a landingpad. Type *LandingPadResultTy; @@ -217,41 +243,60 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport { /// Cache of constants visited in search of ConstantExprs. SmallPtrSet<const Constant *, 32> ConstantExprVisited; + /// Cache of declarations of the llvm.experimental.deoptimize.<ty> intrinsic. + SmallVector<const Function *, 4> DeoptimizeDeclarations; + + // Verify that this GlobalValue is only used in this module. + // This map is used to avoid visiting uses twice. We can arrive at a user + // twice, if they have multiple operands. In particular for very large + // 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); + + void updateModule(const Module *NewM) { + if (M == NewM) + return; + MST.emplace(NewM); + M = NewM; + } + public: - explicit Verifier(raw_ostream &OS) + explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError) : VerifierSupport(OS), Context(nullptr), LandingPadResultTy(nullptr), - SawFrameEscape(false) {} + SawFrameEscape(false) { + TreatBrokenDebugInfoAsError = ShouldTreatBrokenDebugInfoAsError; + } + + bool hasBrokenDebugInfo() const { return BrokenDebugInfo; } bool verify(const Function &F) { - M = F.getParent(); + updateModule(F.getParent()); Context = &M->getContext(); // First ensure the function is well-enough formed to compute dominance - // information. - if (F.empty()) { - OS << "Function '" << F.getName() - << "' does not contain an entry block!\n"; - return false; - } - for (Function::const_iterator I = F.begin(), E = F.end(); I != E; ++I) { - if (I->empty() || !I->back().isTerminator()) { - OS << "Basic Block in function '" << F.getName() - << "' does not have terminator!\n"; - I->printAsOperand(OS, true); - OS << "\n"; - return false; + // information, and directly compute a dominance tree. We don't rely on the + // pass manager to provide this as it isolates us from a potentially + // out-of-date dominator tree and makes it significantly more complex to run + // this code outside of a pass manager. + // FIXME: It's really gross that we have to cast away constness here. + if (!F.empty()) + DT.recalculate(const_cast<Function &>(F)); + + for (const BasicBlock &BB : F) { + if (!BB.empty() && BB.back().isTerminator()) + continue; + + if (OS) { + *OS << "Basic Block in function '" << F.getName() + << "' does not have terminator!\n"; + BB.printAsOperand(*OS, true, *MST); + *OS << "\n"; } + return false; } - // Now directly compute a dominance tree. We don't rely on the pass - // manager to provide this as it isolates us from a potentially - // out-of-date dominator tree and makes it significantly more complex to - // run this code outside of a pass manager. - // FIXME: It's really gross that we have to cast away constness here. - DT.recalculate(const_cast<Function &>(F)); - Broken = false; // FIXME: We strip const here because the inst visitor strips const. visit(const_cast<Function &>(F)); @@ -265,35 +310,26 @@ public: } bool verify(const Module &M) { - this->M = &M; + updateModule(&M); Context = &M.getContext(); Broken = false; - // Scan through, checking all of the external function's linkage now... - for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) { - visitGlobalValue(*I); - - // Check to make sure function prototypes are okay. - if (I->isDeclaration()) - visitFunction(*I); - } + // Collect all declarations of the llvm.experimental.deoptimize intrinsic. + for (const Function &F : M) + if (F.getIntrinsicID() == Intrinsic::experimental_deoptimize) + DeoptimizeDeclarations.push_back(&F); // Now that we've visited every function, verify that we never asked to // recover a frame index that wasn't escaped. verifyFrameRecoverIndices(); + for (const GlobalVariable &GV : M.globals()) + visitGlobalVariable(GV); - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) - visitGlobalVariable(*I); + for (const GlobalAlias &GA : M.aliases()) + visitGlobalAlias(GA); - for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); - I != E; ++I) - visitGlobalAlias(*I); - - for (Module::const_named_metadata_iterator I = M.named_metadata_begin(), - E = M.named_metadata_end(); - I != E; ++I) - visitNamedMDNode(*I); + for (const NamedMDNode &NMD : M.named_metadata()) + visitNamedMDNode(NMD); for (const StringMapEntry<Comdat> &SMEC : M.getComdatSymbolTable()) visitComdat(SMEC.getValue()); @@ -301,8 +337,9 @@ public: visitModuleFlags(M); visitModuleIdents(M); - // Verify type referneces last. - verifyTypeRefs(); + verifyCompileUnits(); + + verifyDeoptimizeCallingConvs(); return !Broken; } @@ -340,27 +377,6 @@ private: void visitTemplateParams(const MDNode &N, const Metadata &RawParams); - /// \brief Check for a valid string-based type reference. - /// - /// Checks if \c MD is a string-based type reference. If it is, keeps track - /// of it (and its user, \c N) for error messages later. - bool isValidUUID(const MDNode &N, const Metadata *MD); - - /// \brief Check for a valid type reference. - /// - /// Checks for subclasses of \a DIType, or \a isValidUUID(). - bool isTypeRef(const MDNode &N, const Metadata *MD); - - /// \brief Check for a valid scope reference. - /// - /// Checks for subclasses of \a DIScope, or \a isValidUUID(). - bool isScopeRef(const MDNode &N, const Metadata *MD); - - /// \brief Check for a valid debug info reference. - /// - /// Checks for subclasses of \a DINode, or \a isValidUUID(). - bool isDIRef(const MDNode &N, const Metadata *MD); - // InstVisitor overrides... using InstVisitor<Verifier>::visit; void visit(Instruction &I); @@ -419,53 +435,69 @@ private: void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch); void visitCleanupReturnInst(CleanupReturnInst &CRI); - void VerifyCallSite(CallSite CS); + void verifyCallSite(CallSite CS); + void verifySwiftErrorCallSite(CallSite CS, const Value *SwiftErrorVal); + void verifySwiftErrorValue(const Value *SwiftErrorVal); void verifyMustTailCall(CallInst &CI); - bool PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, int VT, + bool performTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, int VT, unsigned ArgNo, std::string &Suffix); - bool VerifyIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos, - SmallVectorImpl<Type *> &ArgTys); - bool VerifyIntrinsicIsVarArg(bool isVarArg, - ArrayRef<Intrinsic::IITDescriptor> &Infos); - bool VerifyAttributeCount(AttributeSet Attrs, unsigned Params); - void VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, bool isFunction, + bool verifyAttributeCount(AttributeSet Attrs, unsigned Params); + void verifyAttributeTypes(AttributeSet Attrs, unsigned Idx, bool isFunction, const Value *V); - void VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, + void verifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, bool isReturnValue, const Value *V); - void VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, + void verifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, const Value *V); - void VerifyFunctionMetadata( - const SmallVector<std::pair<unsigned, MDNode *>, 4> MDs); + void verifyFunctionMetadata(ArrayRef<std::pair<unsigned, MDNode *>> MDs); void visitConstantExprsRecursively(const Constant *EntryC); void visitConstantExpr(const ConstantExpr *CE); - void VerifyStatepoint(ImmutableCallSite CS); + void verifyStatepoint(ImmutableCallSite CS); void verifyFrameRecoverIndices(); void verifySiblingFuncletUnwinds(); - // Module-level debug info verification... - void verifyTypeRefs(); - template <class MapTy> - void verifyBitPieceExpression(const DbgInfoIntrinsic &I, - const MapTy &TypeRefs); - void visitUnresolvedTypeRef(const MDString *S, const MDNode *N); + void verifyBitPieceExpression(const DbgInfoIntrinsic &I); + + /// Module-level debug info verification... + void verifyCompileUnits(); + + /// Module-level verification that all @llvm.experimental.deoptimize + /// declarations share the same calling convention. + void verifyDeoptimizeCallingConvs(); }; } // End anonymous namespace -// Assert - We know that cond should be true, if not print an error message. +/// 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) +/// 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) + + void Verifier::visit(Instruction &I) { for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) Assert(I.getOperand(i) != nullptr, "Operand is null", &I); InstVisitor<Verifier>::visit(I); } +// Helper to recursively iterate over indirect users. By +// returning false, the callback can ask to stop recursing +// further. +static void forEachUser(const Value *User, + SmallPtrSet<const Value *, 32> &Visited, + llvm::function_ref<bool(const Value *)> Callback) { + if (!Visited.insert(User).second) + return; + for (const Value *TheNextUser : User->materialized_users()) + if (Callback(TheNextUser)) + forEachUser(TheNextUser, Visited, Callback); +} void Verifier::visitGlobalValue(const GlobalValue &GV) { - Assert(!GV.isDeclaration() || GV.hasExternalLinkage() || - GV.hasExternalWeakLinkage(), + Assert(!GV.isDeclaration() || GV.hasValidDeclarationLinkage(), "Global is external, but doesn't have external or weak linkage!", &GV); Assert(GV.getAlignment() <= Value::MaximumAlignment, @@ -481,11 +513,30 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) { if (GV.isDeclarationForLinker()) Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &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(), + 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()); + return false; + } + return true; + }); } void Verifier::visitGlobalVariable(const GlobalVariable &GV) { if (GV.hasInitializer()) { - Assert(GV.getInitializer()->getType() == GV.getType()->getElementType(), + Assert(GV.getInitializer()->getType() == GV.getValueType(), "Global variable initializer type does not match global " "variable type!", &GV); @@ -499,9 +550,6 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { &GV); Assert(!GV.hasComdat(), "'common' global may not be in a Comdat!", &GV); } - } else { - Assert(GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(), - "invalid linkage type for global declaration", &GV); } if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || @@ -542,8 +590,8 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { const ConstantArray *InitArray = dyn_cast<ConstantArray>(Init); Assert(InitArray, "wrong initalizer for intrinsic global variable", Init); - for (unsigned i = 0, e = InitArray->getNumOperands(); i != e; ++i) { - Value *V = Init->getOperand(i)->stripPointerCastsNoFollowAliases(); + for (Value *Op : InitArray->operands()) { + Value *V = Op->stripPointerCastsNoFollowAliases(); Assert(isa<GlobalVariable>(V) || isa<Function>(V) || isa<GlobalAlias>(V), "invalid llvm.used member", V); @@ -584,7 +632,7 @@ void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited, if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) { Assert(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA); - Assert(!GA2->mayBeOverridden(), "Alias cannot point to a weak alias", + Assert(!GA2->isInterposable(), "Alias cannot point to an interposable alias", &GA); } else { // Only continue verifying subexpressions of GlobalAliases. @@ -624,11 +672,9 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) { } void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { - for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i) { - MDNode *MD = NMD.getOperand(i); - + for (const MDNode *MD : NMD.operands()) { if (NMD.getName() == "llvm.dbg.cu") { - Assert(MD && isa<DICompileUnit>(MD), "invalid compile unit", &NMD, MD); + AssertDI(MD && isa<DICompileUnit>(MD), "invalid compile unit", &NMD, MD); } if (!MD) @@ -656,8 +702,7 @@ void Verifier::visitMDNode(const MDNode &MD) { #include "llvm/IR/Metadata.def" } - for (unsigned i = 0, e = MD.getNumOperands(); i != e; ++i) { - Metadata *Op = MD.getOperand(i); + for (const Metadata *Op : MD.operands()) { if (!Op) continue; Assert(!isa<LocalAsMetadata>(Op), "Invalid operand for global metadata!", @@ -719,33 +764,9 @@ void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) { visitValueAsMetadata(*V, F); } -bool Verifier::isValidUUID(const MDNode &N, const Metadata *MD) { - auto *S = dyn_cast<MDString>(MD); - if (!S) - return false; - if (S->getString().empty()) - return false; - - // Keep track of names of types referenced via UUID so we can check that they - // actually exist. - UnresolvedTypeRefs.insert(std::make_pair(S, &N)); - return true; -} - -/// \brief Check if a value can be a reference to a type. -bool Verifier::isTypeRef(const MDNode &N, const Metadata *MD) { - return !MD || isValidUUID(N, MD) || isa<DIType>(MD); -} - -/// \brief Check if a value can be a ScopeRef. -bool Verifier::isScopeRef(const MDNode &N, const Metadata *MD) { - return !MD || isValidUUID(N, MD) || isa<DIScope>(MD); -} - -/// \brief Check if a value can be a debug info ref. -bool Verifier::isDIRef(const MDNode &N, const Metadata *MD) { - return !MD || isValidUUID(N, MD) || isa<DINode>(MD); -} +static bool isType(const Metadata *MD) { return !MD || isa<DIType>(MD); } +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) { @@ -772,60 +793,60 @@ bool isValidMetadataNullArray(const MDTuple &N) { } void Verifier::visitDILocation(const DILocation &N) { - Assert(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), - "location requires a valid scope", &N, N.getRawScope()); + AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), + "location requires a valid scope", &N, N.getRawScope()); if (auto *IA = N.getRawInlinedAt()) - Assert(isa<DILocation>(IA), "inlined-at should be a location", &N, IA); + AssertDI(isa<DILocation>(IA), "inlined-at should be a location", &N, IA); } void Verifier::visitGenericDINode(const GenericDINode &N) { - Assert(N.getTag(), "invalid tag", &N); + AssertDI(N.getTag(), "invalid tag", &N); } void Verifier::visitDIScope(const DIScope &N) { if (auto *F = N.getRawFile()) - Assert(isa<DIFile>(F), "invalid file", &N, F); + AssertDI(isa<DIFile>(F), "invalid file", &N, F); } void Verifier::visitDISubrange(const DISubrange &N) { - Assert(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N); - Assert(N.getCount() >= -1, "invalid subrange count", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N); + AssertDI(N.getCount() >= -1, "invalid subrange count", &N); } void Verifier::visitDIEnumerator(const DIEnumerator &N) { - Assert(N.getTag() == dwarf::DW_TAG_enumerator, "invalid tag", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_enumerator, "invalid tag", &N); } void Verifier::visitDIBasicType(const DIBasicType &N) { - Assert(N.getTag() == dwarf::DW_TAG_base_type || - N.getTag() == dwarf::DW_TAG_unspecified_type, - "invalid tag", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_base_type || + N.getTag() == dwarf::DW_TAG_unspecified_type, + "invalid tag", &N); } void Verifier::visitDIDerivedType(const DIDerivedType &N) { // Common scope checks. visitDIScope(N); - Assert(N.getTag() == dwarf::DW_TAG_typedef || - N.getTag() == dwarf::DW_TAG_pointer_type || - N.getTag() == dwarf::DW_TAG_ptr_to_member_type || - N.getTag() == dwarf::DW_TAG_reference_type || - N.getTag() == dwarf::DW_TAG_rvalue_reference_type || - 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_member || - N.getTag() == dwarf::DW_TAG_inheritance || - N.getTag() == dwarf::DW_TAG_friend, - "invalid tag", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_typedef || + N.getTag() == dwarf::DW_TAG_pointer_type || + N.getTag() == dwarf::DW_TAG_ptr_to_member_type || + N.getTag() == dwarf::DW_TAG_reference_type || + N.getTag() == dwarf::DW_TAG_rvalue_reference_type || + 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_member || + N.getTag() == dwarf::DW_TAG_inheritance || + N.getTag() == dwarf::DW_TAG_friend, + "invalid tag", &N); if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) { - Assert(isTypeRef(N, N.getExtraData()), "invalid pointer to member type", &N, - N.getExtraData()); + AssertDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N, + N.getRawExtraData()); } - Assert(isScopeRef(N, N.getScope()), "invalid scope", &N, N.getScope()); - Assert(isTypeRef(N, N.getBaseType()), "invalid base type", &N, - N.getBaseType()); + AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope()); + AssertDI(isType(N.getRawBaseType()), "invalid base type", &N, + N.getRawBaseType()); } static bool hasConflictingReferenceFlags(unsigned Flags) { @@ -835,10 +856,10 @@ static bool hasConflictingReferenceFlags(unsigned Flags) { void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) { auto *Params = dyn_cast<MDTuple>(&RawParams); - Assert(Params, "invalid template params", &N, &RawParams); + AssertDI(Params, "invalid template params", &N, &RawParams); for (Metadata *Op : Params->operands()) { - Assert(Op && isa<DITemplateParameter>(Op), "invalid template parameter", &N, - Params, Op); + AssertDI(Op && isa<DITemplateParameter>(Op), "invalid template parameter", + &N, Params, Op); } } @@ -846,141 +867,151 @@ void Verifier::visitDICompositeType(const DICompositeType &N) { // Common scope checks. visitDIScope(N); - Assert(N.getTag() == dwarf::DW_TAG_array_type || - N.getTag() == dwarf::DW_TAG_structure_type || - N.getTag() == dwarf::DW_TAG_union_type || - N.getTag() == dwarf::DW_TAG_enumeration_type || - N.getTag() == dwarf::DW_TAG_class_type, - "invalid tag", &N); - - Assert(isScopeRef(N, N.getScope()), "invalid scope", &N, N.getScope()); - Assert(isTypeRef(N, N.getBaseType()), "invalid base type", &N, - N.getBaseType()); - - Assert(!N.getRawElements() || isa<MDTuple>(N.getRawElements()), - "invalid composite elements", &N, N.getRawElements()); - Assert(isTypeRef(N, N.getRawVTableHolder()), "invalid vtable holder", &N, - N.getRawVTableHolder()); - Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags", - &N); + AssertDI(N.getTag() == dwarf::DW_TAG_array_type || + N.getTag() == dwarf::DW_TAG_structure_type || + N.getTag() == dwarf::DW_TAG_union_type || + N.getTag() == dwarf::DW_TAG_enumeration_type || + N.getTag() == dwarf::DW_TAG_class_type, + "invalid tag", &N); + + AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope()); + AssertDI(isType(N.getRawBaseType()), "invalid base type", &N, + N.getRawBaseType()); + + AssertDI(!N.getRawElements() || isa<MDTuple>(N.getRawElements()), + "invalid composite elements", &N, N.getRawElements()); + AssertDI(isType(N.getRawVTableHolder()), "invalid vtable holder", &N, + N.getRawVTableHolder()); + AssertDI(!hasConflictingReferenceFlags(N.getFlags()), + "invalid reference flags", &N); if (auto *Params = N.getRawTemplateParams()) visitTemplateParams(N, *Params); if (N.getTag() == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_union_type) { - Assert(N.getFile() && !N.getFile()->getFilename().empty(), - "class/union requires a filename", &N, N.getFile()); + AssertDI(N.getFile() && !N.getFile()->getFilename().empty(), + "class/union requires a filename", &N, N.getFile()); } } void Verifier::visitDISubroutineType(const DISubroutineType &N) { - Assert(N.getTag() == dwarf::DW_TAG_subroutine_type, "invalid tag", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_subroutine_type, "invalid tag", &N); if (auto *Types = N.getRawTypeArray()) { - Assert(isa<MDTuple>(Types), "invalid composite elements", &N, Types); + AssertDI(isa<MDTuple>(Types), "invalid composite elements", &N, Types); for (Metadata *Ty : N.getTypeArray()->operands()) { - Assert(isTypeRef(N, Ty), "invalid subroutine type ref", &N, Types, Ty); + AssertDI(isType(Ty), "invalid subroutine type ref", &N, Types, Ty); } } - Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags", - &N); + AssertDI(!hasConflictingReferenceFlags(N.getFlags()), + "invalid reference flags", &N); } void Verifier::visitDIFile(const DIFile &N) { - Assert(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N); } void Verifier::visitDICompileUnit(const DICompileUnit &N) { - Assert(N.isDistinct(), "compile units must be distinct", &N); - Assert(N.getTag() == dwarf::DW_TAG_compile_unit, "invalid tag", &N); + AssertDI(N.isDistinct(), "compile units must be distinct", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_compile_unit, "invalid tag", &N); // Don't bother verifying the compilation directory or producer string // as those could be empty. - Assert(N.getRawFile() && isa<DIFile>(N.getRawFile()), "invalid file", &N, - N.getRawFile()); - Assert(!N.getFile()->getFilename().empty(), "invalid filename", &N, - N.getFile()); + AssertDI(N.getRawFile() && isa<DIFile>(N.getRawFile()), "invalid file", &N, + N.getRawFile()); + AssertDI(!N.getFile()->getFilename().empty(), "invalid filename", &N, + N.getFile()); + + AssertDI((N.getEmissionKind() <= DICompileUnit::LastEmissionKind), + "invalid emission kind", &N); if (auto *Array = N.getRawEnumTypes()) { - Assert(isa<MDTuple>(Array), "invalid enum list", &N, Array); + AssertDI(isa<MDTuple>(Array), "invalid enum list", &N, Array); for (Metadata *Op : N.getEnumTypes()->operands()) { auto *Enum = dyn_cast_or_null<DICompositeType>(Op); - Assert(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type, - "invalid enum type", &N, N.getEnumTypes(), Op); + AssertDI(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type, + "invalid enum type", &N, N.getEnumTypes(), Op); } } if (auto *Array = N.getRawRetainedTypes()) { - Assert(isa<MDTuple>(Array), "invalid retained type list", &N, Array); + AssertDI(isa<MDTuple>(Array), "invalid retained type list", &N, Array); for (Metadata *Op : N.getRetainedTypes()->operands()) { - Assert(Op && isa<DIType>(Op), "invalid retained type", &N, Op); - } - } - if (auto *Array = N.getRawSubprograms()) { - Assert(isa<MDTuple>(Array), "invalid subprogram list", &N, Array); - for (Metadata *Op : N.getSubprograms()->operands()) { - Assert(Op && isa<DISubprogram>(Op), "invalid subprogram ref", &N, Op); + AssertDI(Op && (isa<DIType>(Op) || + (isa<DISubprogram>(Op) && + cast<DISubprogram>(Op)->isDefinition() == false)), + "invalid retained type", &N, Op); } } if (auto *Array = N.getRawGlobalVariables()) { - Assert(isa<MDTuple>(Array), "invalid global variable list", &N, Array); + AssertDI(isa<MDTuple>(Array), "invalid global variable list", &N, Array); for (Metadata *Op : N.getGlobalVariables()->operands()) { - Assert(Op && isa<DIGlobalVariable>(Op), "invalid global variable ref", &N, - Op); + AssertDI(Op && isa<DIGlobalVariable>(Op), "invalid global variable ref", + &N, Op); } } if (auto *Array = N.getRawImportedEntities()) { - Assert(isa<MDTuple>(Array), "invalid imported entity list", &N, Array); + AssertDI(isa<MDTuple>(Array), "invalid imported entity list", &N, Array); for (Metadata *Op : N.getImportedEntities()->operands()) { - Assert(Op && isa<DIImportedEntity>(Op), "invalid imported entity ref", &N, - Op); + AssertDI(Op && isa<DIImportedEntity>(Op), "invalid imported entity ref", + &N, Op); } } if (auto *Array = N.getRawMacros()) { - Assert(isa<MDTuple>(Array), "invalid macro list", &N, Array); + AssertDI(isa<MDTuple>(Array), "invalid macro list", &N, Array); for (Metadata *Op : N.getMacros()->operands()) { - Assert(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op); + AssertDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op); } } + CUVisited.insert(&N); } void Verifier::visitDISubprogram(const DISubprogram &N) { - Assert(N.getTag() == dwarf::DW_TAG_subprogram, "invalid tag", &N); - Assert(isScopeRef(N, N.getRawScope()), "invalid scope", &N, N.getRawScope()); + AssertDI(N.getTag() == dwarf::DW_TAG_subprogram, "invalid tag", &N); + AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope()); + if (auto *F = N.getRawFile()) + AssertDI(isa<DIFile>(F), "invalid file", &N, F); if (auto *T = N.getRawType()) - Assert(isa<DISubroutineType>(T), "invalid subroutine type", &N, T); - Assert(isTypeRef(N, N.getRawContainingType()), "invalid containing type", &N, - N.getRawContainingType()); + AssertDI(isa<DISubroutineType>(T), "invalid subroutine type", &N, T); + AssertDI(isType(N.getRawContainingType()), "invalid containing type", &N, + N.getRawContainingType()); if (auto *Params = N.getRawTemplateParams()) visitTemplateParams(N, *Params); - if (auto *S = N.getRawDeclaration()) { - Assert(isa<DISubprogram>(S) && !cast<DISubprogram>(S)->isDefinition(), - "invalid subprogram declaration", &N, S); - } + if (auto *S = N.getRawDeclaration()) + AssertDI(isa<DISubprogram>(S) && !cast<DISubprogram>(S)->isDefinition(), + "invalid subprogram declaration", &N, S); if (auto *RawVars = N.getRawVariables()) { auto *Vars = dyn_cast<MDTuple>(RawVars); - Assert(Vars, "invalid variable list", &N, RawVars); + AssertDI(Vars, "invalid variable list", &N, RawVars); for (Metadata *Op : Vars->operands()) { - Assert(Op && isa<DILocalVariable>(Op), "invalid local variable", &N, Vars, - Op); + AssertDI(Op && isa<DILocalVariable>(Op), "invalid local variable", &N, + Vars, Op); } } - Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags", - &N); - - if (N.isDefinition()) - Assert(N.isDistinct(), "subprogram definitions must be distinct", &N); + AssertDI(!hasConflictingReferenceFlags(N.getFlags()), + "invalid reference flags", &N); + + auto *Unit = N.getRawUnit(); + if (N.isDefinition()) { + // Subprogram definitions (not part of the type hierarchy). + AssertDI(N.isDistinct(), "subprogram definitions must be distinct", &N); + AssertDI(Unit, "subprogram definitions must have a compile unit", &N); + AssertDI(isa<DICompileUnit>(Unit), "invalid unit type", &N, Unit); + } else { + // Subprogram declarations (part of the type hierarchy). + AssertDI(!Unit, "subprogram declarations must not have a compile unit", &N); + } } void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) { - Assert(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N); - Assert(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), - "invalid local scope", &N, N.getRawScope()); + AssertDI(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N); + AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), + "invalid local scope", &N, N.getRawScope()); } void Verifier::visitDILexicalBlock(const DILexicalBlock &N) { visitDILexicalBlockBase(N); - Assert(N.getLine() || !N.getColumn(), - "cannot have column info without line info", &N); + AssertDI(N.getLine() || !N.getColumn(), + "cannot have column info without line info", &N); } void Verifier::visitDILexicalBlockFile(const DILexicalBlockFile &N) { @@ -988,83 +1019,84 @@ void Verifier::visitDILexicalBlockFile(const DILexicalBlockFile &N) { } void Verifier::visitDINamespace(const DINamespace &N) { - Assert(N.getTag() == dwarf::DW_TAG_namespace, "invalid tag", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_namespace, "invalid tag", &N); if (auto *S = N.getRawScope()) - Assert(isa<DIScope>(S), "invalid scope ref", &N, S); + AssertDI(isa<DIScope>(S), "invalid scope ref", &N, S); } void Verifier::visitDIMacro(const DIMacro &N) { - Assert(N.getMacinfoType() == dwarf::DW_MACINFO_define || - N.getMacinfoType() == dwarf::DW_MACINFO_undef, - "invalid macinfo type", &N); - Assert(!N.getName().empty(), "anonymous macro", &N); + AssertDI(N.getMacinfoType() == dwarf::DW_MACINFO_define || + N.getMacinfoType() == dwarf::DW_MACINFO_undef, + "invalid macinfo type", &N); + AssertDI(!N.getName().empty(), "anonymous macro", &N); if (!N.getValue().empty()) { assert(N.getValue().data()[0] != ' ' && "Macro value has a space prefix"); } } void Verifier::visitDIMacroFile(const DIMacroFile &N) { - Assert(N.getMacinfoType() == dwarf::DW_MACINFO_start_file, - "invalid macinfo type", &N); + AssertDI(N.getMacinfoType() == dwarf::DW_MACINFO_start_file, + "invalid macinfo type", &N); if (auto *F = N.getRawFile()) - Assert(isa<DIFile>(F), "invalid file", &N, F); + AssertDI(isa<DIFile>(F), "invalid file", &N, F); if (auto *Array = N.getRawElements()) { - Assert(isa<MDTuple>(Array), "invalid macro list", &N, Array); + AssertDI(isa<MDTuple>(Array), "invalid macro list", &N, Array); for (Metadata *Op : N.getElements()->operands()) { - Assert(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op); + AssertDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op); } } } void Verifier::visitDIModule(const DIModule &N) { - Assert(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N); - Assert(!N.getName().empty(), "anonymous module", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N); + AssertDI(!N.getName().empty(), "anonymous module", &N); } void Verifier::visitDITemplateParameter(const DITemplateParameter &N) { - Assert(isTypeRef(N, N.getType()), "invalid type ref", &N, N.getType()); + AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType()); } void Verifier::visitDITemplateTypeParameter(const DITemplateTypeParameter &N) { visitDITemplateParameter(N); - Assert(N.getTag() == dwarf::DW_TAG_template_type_parameter, "invalid tag", - &N); + AssertDI(N.getTag() == dwarf::DW_TAG_template_type_parameter, "invalid tag", + &N); } void Verifier::visitDITemplateValueParameter( const DITemplateValueParameter &N) { visitDITemplateParameter(N); - Assert(N.getTag() == dwarf::DW_TAG_template_value_parameter || - N.getTag() == dwarf::DW_TAG_GNU_template_template_param || - N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack, - "invalid tag", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_template_value_parameter || + N.getTag() == dwarf::DW_TAG_GNU_template_template_param || + N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack, + "invalid tag", &N); } void Verifier::visitDIVariable(const DIVariable &N) { if (auto *S = N.getRawScope()) - Assert(isa<DIScope>(S), "invalid scope", &N, S); - Assert(isTypeRef(N, N.getRawType()), "invalid type ref", &N, N.getRawType()); + AssertDI(isa<DIScope>(S), "invalid scope", &N, S); + AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType()); if (auto *F = N.getRawFile()) - Assert(isa<DIFile>(F), "invalid file", &N, F); + AssertDI(isa<DIFile>(F), "invalid file", &N, F); } void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) { // Checks common to all variables. visitDIVariable(N); - Assert(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N); - Assert(!N.getName().empty(), "missing global variable name", &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()) { - Assert(isa<ConstantAsMetadata>(V) && - !isa<Function>(cast<ConstantAsMetadata>(V)->getValue()), - "invalid global varaible ref", &N, V); + 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()) { - Assert(isa<DIDerivedType>(Member), "invalid static data member declaration", - &N, Member); + AssertDI(isa<DIDerivedType>(Member), + "invalid static data member declaration", &N, Member); } } @@ -1072,31 +1104,31 @@ void Verifier::visitDILocalVariable(const DILocalVariable &N) { // Checks common to all variables. visitDIVariable(N); - Assert(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N); - Assert(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), - "local variable requires a valid scope", &N, N.getRawScope()); + AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N); + AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()), + "local variable requires a valid scope", &N, N.getRawScope()); } void Verifier::visitDIExpression(const DIExpression &N) { - Assert(N.isValid(), "invalid expression", &N); + AssertDI(N.isValid(), "invalid expression", &N); } void Verifier::visitDIObjCProperty(const DIObjCProperty &N) { - Assert(N.getTag() == dwarf::DW_TAG_APPLE_property, "invalid tag", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_APPLE_property, "invalid tag", &N); if (auto *T = N.getRawType()) - Assert(isTypeRef(N, T), "invalid type ref", &N, T); + AssertDI(isType(T), "invalid type ref", &N, T); if (auto *F = N.getRawFile()) - Assert(isa<DIFile>(F), "invalid file", &N, F); + AssertDI(isa<DIFile>(F), "invalid file", &N, F); } void Verifier::visitDIImportedEntity(const DIImportedEntity &N) { - Assert(N.getTag() == dwarf::DW_TAG_imported_module || - N.getTag() == dwarf::DW_TAG_imported_declaration, - "invalid tag", &N); + AssertDI(N.getTag() == dwarf::DW_TAG_imported_module || + N.getTag() == dwarf::DW_TAG_imported_declaration, + "invalid tag", &N); if (auto *S = N.getRawScope()) - Assert(isa<DIScope>(S), "invalid scope for imported entity", &N, S); - Assert(isDIRef(N, N.getEntity()), "invalid imported entity", &N, - N.getEntity()); + AssertDI(isa<DIScope>(S), "invalid scope for imported entity", &N, S); + AssertDI(isDINode(N.getRawEntity()), "invalid imported entity", &N, + N.getRawEntity()); } void Verifier::visitComdat(const Comdat &C) { @@ -1114,8 +1146,7 @@ void Verifier::visitModuleIdents(const Module &M) { // llvm.ident takes a list of metadata entry. Each entry has only one string. // Scan each llvm.ident entry and make sure that this requirement is met. - for (unsigned i = 0, e = Idents->getNumOperands(); i != e; ++i) { - const MDNode *N = Idents->getOperand(i); + for (const MDNode *N : Idents->operands()) { Assert(N->getNumOperands() == 1, "incorrect number of operands in llvm.ident metadata", N); Assert(dyn_cast_or_null<MDString>(N->getOperand(0)), @@ -1132,13 +1163,11 @@ void Verifier::visitModuleFlags(const Module &M) { // Scan each flag, and track the flags and requirements. DenseMap<const MDString*, const MDNode*> SeenIDs; SmallVector<const MDNode*, 16> Requirements; - for (unsigned I = 0, E = Flags->getNumOperands(); I != E; ++I) { - visitModuleFlag(Flags->getOperand(I), SeenIDs, Requirements); - } + for (const MDNode *MDN : Flags->operands()) + visitModuleFlag(MDN, SeenIDs, Requirements); // Validate that the requirements in the module are valid. - for (unsigned I = 0, E = Requirements.size(); I != E; ++I) { - const MDNode *Requirement = Requirements[I]; + for (const MDNode *Requirement : Requirements) { const MDString *Flag = cast<MDString>(Requirement->getOperand(0)); const Metadata *ReqValue = Requirement->getOperand(1); @@ -1225,7 +1254,7 @@ Verifier::visitModuleFlag(const MDNode *Op, } } -void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, +void Verifier::verifyAttributeTypes(AttributeSet Attrs, unsigned Idx, bool isFunction, const Value *V) { unsigned Slot = ~0U; for (unsigned I = 0, E = Attrs.getNumSlots(); I != E; ++I) @@ -1272,13 +1301,15 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, I->getKindAsEnum() == Attribute::ArgMemOnly || I->getKindAsEnum() == Attribute::NoRecurse || I->getKindAsEnum() == Attribute::InaccessibleMemOnly || - I->getKindAsEnum() == Attribute::InaccessibleMemOrArgMemOnly) { + I->getKindAsEnum() == Attribute::InaccessibleMemOrArgMemOnly || + I->getKindAsEnum() == Attribute::AllocSize) { if (!isFunction) { CheckFailed("Attribute '" + I->getAsString() + "' only applies to functions!", V); return; } } else if (I->getKindAsEnum() == Attribute::ReadOnly || + I->getKindAsEnum() == Attribute::WriteOnly || I->getKindAsEnum() == Attribute::ReadNone) { if (Idx == 0) { CheckFailed("Attribute '" + I->getAsString() + @@ -1295,12 +1326,12 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, // VerifyParameterAttrs - Check the given attributes for an argument or return // value of the specified type. The value V is printed in error messages. -void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, +void Verifier::verifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, bool isReturnValue, const Value *V) { if (!Attrs.hasAttributes(Idx)) return; - VerifyAttributeTypes(Attrs, Idx, false, V); + verifyAttributeTypes(Attrs, Idx, false, V); if (isReturnValue) Assert(!Attrs.hasAttribute(Idx, Attribute::ByVal) && @@ -1308,9 +1339,12 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, !Attrs.hasAttribute(Idx, Attribute::StructRet) && !Attrs.hasAttribute(Idx, Attribute::NoCapture) && !Attrs.hasAttribute(Idx, Attribute::Returned) && - !Attrs.hasAttribute(Idx, Attribute::InAlloca), - "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', and " - "'returned' do not apply to return values!", + !Attrs.hasAttribute(Idx, Attribute::InAlloca) && + !Attrs.hasAttribute(Idx, Attribute::SwiftSelf) && + !Attrs.hasAttribute(Idx, Attribute::SwiftError), + "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', " + "'returned', 'swiftself', and 'swifterror' do not apply to return " + "values!", V); // Check for mutually incompatible attributes. Only inreg is compatible with @@ -1349,6 +1383,18 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, "'readnone and readonly' are incompatible!", V); + Assert(!(Attrs.hasAttribute(Idx, Attribute::ReadNone) && + Attrs.hasAttribute(Idx, Attribute::WriteOnly)), + "Attributes " + "'readnone and writeonly' are incompatible!", + V); + + Assert(!(Attrs.hasAttribute(Idx, Attribute::ReadOnly) && + Attrs.hasAttribute(Idx, Attribute::WriteOnly)), + "Attributes " + "'readonly and writeonly' are incompatible!", + V); + Assert(!(Attrs.hasAttribute(Idx, Attribute::NoInline) && Attrs.hasAttribute(Idx, Attribute::AlwaysInline)), "Attributes " @@ -1370,16 +1416,25 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty, "Attributes 'byval' and 'inalloca' do not support unsized types!", V); } + if (!isa<PointerType>(PTy->getElementType())) + Assert(!Attrs.hasAttribute(Idx, Attribute::SwiftError), + "Attribute 'swifterror' only applies to parameters " + "with pointer to pointer type!", + V); } else { Assert(!Attrs.hasAttribute(Idx, Attribute::ByVal), "Attribute 'byval' only applies to parameters with pointer type!", V); + Assert(!Attrs.hasAttribute(Idx, Attribute::SwiftError), + "Attribute 'swifterror' only applies to parameters " + "with pointer type!", + V); } } -// VerifyFunctionAttrs - Check parameter attributes against a function type. +// Check parameter attributes against a function type. // The value V is printed in error messages. -void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, +void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, const Value *V) { if (Attrs.isEmpty()) return; @@ -1387,6 +1442,8 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, bool SawNest = false; bool SawReturned = false; bool SawSRet = false; + bool SawSwiftSelf = false; + bool SawSwiftError = false; for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) { unsigned Idx = Attrs.getSlotIndex(i); @@ -1399,7 +1456,7 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, else break; // VarArgs attributes, verified elsewhere. - VerifyParameterAttrs(Attrs, Idx, Ty, Idx == 0, V); + verifyParameterAttrs(Attrs, Idx, Ty, Idx == 0, V); if (Idx == 0) continue; @@ -1426,6 +1483,17 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, SawSRet = true; } + if (Attrs.hasAttribute(Idx, Attribute::SwiftSelf)) { + Assert(!SawSwiftSelf, "Cannot have multiple 'swiftself' parameters!", V); + SawSwiftSelf = true; + } + + if (Attrs.hasAttribute(Idx, Attribute::SwiftError)) { + Assert(!SawSwiftError, "Cannot have multiple 'swifterror' parameters!", + V); + SawSwiftError = true; + } + if (Attrs.hasAttribute(Idx, Attribute::InAlloca)) { Assert(Idx == FT->getNumParams(), "inalloca isn't on the last parameter!", V); @@ -1435,7 +1503,7 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, if (!Attrs.hasAttributes(AttributeSet::FunctionIndex)) return; - VerifyAttributeTypes(Attrs, AttributeSet::FunctionIndex, true, V); + verifyAttributeTypes(Attrs, AttributeSet::FunctionIndex, true, V); Assert( !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) && @@ -1444,6 +1512,16 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, Assert( !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) && + Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly)), + "Attributes 'readnone and writeonly' are incompatible!", V); + + Assert( + !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly) && + Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly)), + "Attributes 'readonly and writeonly' are incompatible!", V); + + Assert( + !(Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone) && Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly)), "Attributes 'readnone and inaccessiblemem_or_argmemonly' are incompatible!", V); @@ -1476,19 +1554,43 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, if (Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::JumpTable)) { const GlobalValue *GV = cast<GlobalValue>(V); - Assert(GV->hasUnnamedAddr(), + Assert(GV->hasGlobalUnnamedAddr(), "Attribute 'jumptable' requires 'unnamed_addr'", V); } -} -void Verifier::VerifyFunctionMetadata( - const SmallVector<std::pair<unsigned, MDNode *>, 4> MDs) { - if (MDs.empty()) - return; + if (Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::AllocSize)) { + std::pair<unsigned, Optional<unsigned>> Args = + Attrs.getAllocSizeArgs(AttributeSet::FunctionIndex); + + auto CheckParam = [&](StringRef Name, unsigned ParamNo) { + if (ParamNo >= FT->getNumParams()) { + CheckFailed("'allocsize' " + Name + " argument is out of bounds", V); + return false; + } + + if (!FT->getParamType(ParamNo)->isIntegerTy()) { + CheckFailed("'allocsize' " + Name + + " argument must refer to an integer parameter", + V); + return false; + } + + return true; + }; + + if (!CheckParam("element size", Args.first)) + return; - for (unsigned i = 0; i < MDs.size(); i++) { - if (MDs[i].first == LLVMContext::MD_prof) { - MDNode *MD = MDs[i].second; + if (Args.second && !CheckParam("number of elements", *Args.second)) + return; + } +} + +void Verifier::verifyFunctionMetadata( + ArrayRef<std::pair<unsigned, MDNode *>> MDs) { + for (const auto &Pair : MDs) { + if (Pair.first == LLVMContext::MD_prof) { + MDNode *MD = Pair.second; Assert(MD->getNumOperands() == 2, "!prof annotations should have exactly 2 operands", MD); @@ -1525,13 +1627,19 @@ void Verifier::visitConstantExprsRecursively(const Constant *EntryC) { if (const auto *CE = dyn_cast<ConstantExpr>(C)) visitConstantExpr(CE); + 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()); + continue; + } + // Visit all sub-expressions. for (const Use &U : C->operands()) { const auto *OpC = dyn_cast<Constant>(U); if (!OpC) continue; - if (isa<GlobalValue>(OpC)) - continue; // Global values get visited separately. if (!ConstantExprVisited.insert(OpC).second) continue; Stack.push_back(OpC); @@ -1548,7 +1656,7 @@ void Verifier::visitConstantExpr(const ConstantExpr *CE) { "Invalid bitcast", CE); } -bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) { +bool Verifier::verifyAttributeCount(AttributeSet Attrs, unsigned Params) { if (Attrs.getNumSlots() == 0) return true; @@ -1562,8 +1670,8 @@ bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) { return false; } -/// \brief Verify that statepoint intrinsic is well formed. -void Verifier::VerifyStatepoint(ImmutableCallSite CS) { +/// Verify that statepoint intrinsic is well formed. +void Verifier::verifyStatepoint(ImmutableCallSite CS) { assert(CS.getCalledFunction() && CS.getCalledFunction()->getIntrinsicID() == Intrinsic::experimental_gc_statepoint); @@ -1674,11 +1782,11 @@ void Verifier::VerifyStatepoint(ImmutableCallSite CS) { const CallInst *Call = dyn_cast<const CallInst>(U); Assert(Call, "illegal use of statepoint token", &CI, U); if (!Call) continue; - Assert(isa<GCRelocateInst>(Call) || isGCResult(Call), + Assert(isa<GCRelocateInst>(Call) || isa<GCResultInst>(Call), "gc.result or gc.relocate are the only value uses" "of a gc.statepoint", &CI, U); - if (isGCResult(Call)) { + if (isa<GCResultInst>(Call)) { Assert(Call->getArgOperand(0) == &CI, "gc.result connected to wrong gc.statepoint", &CI, Call); } else if (isa<GCRelocateInst>(Call)) { @@ -1766,6 +1874,8 @@ void Verifier::verifySiblingFuncletUnwinds() { // visitFunction - Verify that a function is ok. // void Verifier::visitFunction(const Function &F) { + visitGlobalValue(F); + // Check function arguments. FunctionType *FT = F.getFunctionType(); unsigned NumArgs = F.arg_size(); @@ -1786,11 +1896,11 @@ void Verifier::visitFunction(const Function &F) { AttributeSet Attrs = F.getAttributes(); - Assert(VerifyAttributeCount(Attrs, FT->getNumParams()), + Assert(verifyAttributeCount(Attrs, FT->getNumParams()), "Attribute after last parameter!", &F); // Check function attributes. - VerifyFunctionAttrs(FT, Attrs, &F); + verifyFunctionAttrs(FT, Attrs, &F); // On function declarations/definitions, we do not support the builtin // attribute. We do not check this in VerifyFunctionAttrs since that is @@ -1821,19 +1931,24 @@ void Verifier::visitFunction(const Function &F) { // Check that the argument values match the function type for this function... unsigned i = 0; - for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; - ++I, ++i) { - Assert(I->getType() == FT->getParamType(i), - "Argument value does not match function argument type!", I, + for (const Argument &Arg : F.args()) { + Assert(Arg.getType() == FT->getParamType(i), + "Argument value does not match function argument type!", &Arg, FT->getParamType(i)); - Assert(I->getType()->isFirstClassType(), - "Function arguments must have first-class types!", I); + Assert(Arg.getType()->isFirstClassType(), + "Function arguments must have first-class types!", &Arg); if (!isLLVMdotName) { - Assert(!I->getType()->isMetadataTy(), - "Function takes metadata but isn't an intrinsic", I, &F); - Assert(!I->getType()->isTokenTy(), - "Function takes token but isn't an intrinsic", I, &F); + Assert(!Arg.getType()->isMetadataTy(), + "Function takes metadata but isn't an intrinsic", &Arg, &F); + Assert(!Arg.getType()->isTokenTy(), + "Function takes token but isn't an intrinsic", &Arg, &F); + } + + // Check that swifterror argument is only used by loads and stores. + if (Attrs.hasAttribute(i+1, Attribute::SwiftError)) { + verifySwiftErrorValue(&Arg); } + ++i; } if (!isLLVMdotName) @@ -1844,7 +1959,7 @@ void Verifier::visitFunction(const Function &F) { SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; F.getAllMetadata(MDs); assert(F.hasMetadata() != MDs.empty() && "Bit out-of-sync"); - VerifyFunctionMetadata(MDs); + verifyFunctionMetadata(MDs); // Check validity of the personality function if (F.hasPersonalityFn()) { @@ -1860,10 +1975,15 @@ void Verifier::visitFunction(const Function &F) { Assert(MDs.empty(), "unmaterialized function cannot have metadata", &F, MDs.empty() ? nullptr : MDs.front().second); } else if (F.isDeclaration()) { - Assert(F.hasExternalLinkage() || F.hasExternalWeakLinkage(), - "invalid linkage type for function declaration", &F); - Assert(MDs.empty(), "function without a body cannot have metadata", &F, - MDs.empty() ? nullptr : MDs.front().second); + for (const auto &I : MDs) { + AssertDI(I.first != LLVMContext::MD_dbg, + "function declaration may not have a !dbg attachment", &F); + Assert(I.first != LLVMContext::MD_prof, + "function declaration may not have a !prof attachment", &F); + + // Verify the metadata itself. + visitMDNode(*I.second); + } Assert(!F.hasPersonalityFn(), "Function declaration shouldn't have a personality routine", &F); } else { @@ -1882,6 +2002,7 @@ void Verifier::visitFunction(const Function &F) { "blockaddress may not be used with the entry block!", Entry); } + unsigned NumDebugAttachments = 0, NumProfAttachments = 0; // Visit metadata attachments. for (const auto &I : MDs) { // Verify that the attachment is legal. @@ -1889,8 +2010,16 @@ void Verifier::visitFunction(const Function &F) { default: break; case LLVMContext::MD_dbg: - Assert(isa<DISubprogram>(I.second), - "function !dbg attachment must be a subprogram", &F, I.second); + ++NumDebugAttachments; + AssertDI(NumDebugAttachments == 1, + "function must have a single !dbg attachment", &F, I.second); + AssertDI(isa<DISubprogram>(I.second), + "function !dbg attachment must be a subprogram", &F, I.second); + break; + case LLVMContext::MD_prof: + ++NumProfAttachments; + Assert(NumProfAttachments == 1, + "function must have a single !prof attachment", &F, I.second); break; } @@ -1918,6 +2047,8 @@ void Verifier::visitFunction(const Function &F) { if (!N) return; + visitDISubprogram(*N); + // Check that all !dbg attachments lead to back to N (or, at least, another // subprogram that describes the same function). // @@ -2053,11 +2184,11 @@ void Verifier::visitSwitchInst(SwitchInst &SI) { // have the same type as the switched-on value. Type *SwitchTy = SI.getCondition()->getType(); SmallPtrSet<ConstantInt*, 32> Constants; - for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; ++i) { - Assert(i.getCaseValue()->getType() == SwitchTy, + for (auto &Case : SI.cases()) { + Assert(Case.getCaseValue()->getType() == SwitchTy, "Switch constants must all be same type as switch value!", &SI); - Assert(Constants.insert(i.getCaseValue()).second, - "Duplicate integer as switch case", &SI, i.getCaseValue()); + Assert(Constants.insert(Case.getCaseValue()).second, + "Duplicate integer as switch case", &SI, Case.getCaseValue()); } visitTerminatorInst(SI); @@ -2362,7 +2493,7 @@ void Verifier::visitPHINode(PHINode &PN) { visitInstruction(PN); } -void Verifier::VerifyCallSite(CallSite CS) { +void Verifier::verifyCallSite(CallSite CS) { Instruction *I = CS.getInstruction(); Assert(CS.getCalledValue()->getType()->isPointerTy(), @@ -2393,11 +2524,11 @@ void Verifier::VerifyCallSite(CallSite CS) { AttributeSet Attrs = CS.getAttributes(); - Assert(VerifyAttributeCount(Attrs, CS.arg_size()), + Assert(verifyAttributeCount(Attrs, CS.arg_size()), "Attribute after last parameter!", I); // Verify call attributes. - VerifyFunctionAttrs(FTy, Attrs, I); + verifyFunctionAttrs(FTy, Attrs, I); // Conservatively check the inalloca argument. // We have a bug if we can find that there is an underlying alloca without @@ -2409,6 +2540,18 @@ void Verifier::VerifyCallSite(CallSite CS) { "inalloca argument for call has mismatched alloca", AI, I); } + // For each argument of the callsite, if it has the swifterror argument, + // make sure the underlying alloca has 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) + Assert(AI->isSwiftError(), + "swifterror argument for call has mismatched alloca", AI, I); + } + if (FTy->isVarArg()) { // FIXME? is 'nest' even legal here? bool SawNest = false; @@ -2424,7 +2567,7 @@ void Verifier::VerifyCallSite(CallSite CS) { // Check attributes on the varargs part. for (unsigned Idx = 1 + FTy->getNumParams(); Idx <= CS.arg_size(); ++Idx) { Type *Ty = CS.getArgument(Idx-1)->getType(); - VerifyParameterAttrs(Attrs, Idx, Ty, false, I); + verifyParameterAttrs(Attrs, Idx, Ty, false, I); if (Attrs.hasAttribute(Idx, Attribute::Nest)) { Assert(!SawNest, "More than one parameter has attribute nest!", I); @@ -2469,17 +2612,21 @@ void Verifier::VerifyCallSite(CallSite CS) { if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) visitIntrinsicCallSite(ID, CS); - // Verify that a callsite has at most one "deopt" and one "funclet" operand - // bundle. - bool FoundDeoptBundle = false, FoundFuncletBundle = false; + // Verify that a callsite has at most one "deopt", at most one "funclet" and + // at most one "gc-transition" operand bundle. + bool FoundDeoptBundle = false, FoundFuncletBundle = false, + FoundGCTransitionBundle = false; for (unsigned i = 0, e = CS.getNumOperandBundles(); i < e; ++i) { OperandBundleUse BU = CS.getOperandBundleAt(i); uint32_t Tag = BU.getTagID(); if (Tag == LLVMContext::OB_deopt) { Assert(!FoundDeoptBundle, "Multiple deopt operand bundles", I); FoundDeoptBundle = true; - } - if (Tag == LLVMContext::OB_funclet) { + } else if (Tag == LLVMContext::OB_gc_transition) { + Assert(!FoundGCTransitionBundle, "Multiple gc-transition operand bundles", + I); + FoundGCTransitionBundle = true; + } else if (Tag == LLVMContext::OB_funclet) { Assert(!FoundFuncletBundle, "Multiple funclet operand bundles", I); FoundFuncletBundle = true; Assert(BU.Inputs.size() == 1, @@ -2490,6 +2637,15 @@ void Verifier::VerifyCallSite(CallSite CS) { } } + // Verify that each inlinable callsite of a debug-info-bearing function in a + // debug-info-bearing function has a debug location attached to it. Failure to + // do so causes assertion failures when the inliner sets up inline scope info. + if (I->getFunction()->getSubprogram() && CS.getCalledFunction() && + CS.getCalledFunction()->getSubprogram()) + Assert(I->getDebugLoc(), "inlinable function call in a function with debug " + "info must have a !dbg location", + I); + visitInstruction(*I); } @@ -2508,7 +2664,8 @@ static bool isTypeCongruent(Type *L, Type *R) { static AttrBuilder getParameterABIAttributes(int I, AttributeSet Attrs) { static const Attribute::AttrKind ABIAttrs[] = { Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca, - Attribute::InReg, Attribute::Returned}; + Attribute::InReg, Attribute::Returned, Attribute::SwiftSelf, + Attribute::SwiftError}; AttrBuilder Copy; for (auto AK : ABIAttrs) { if (Attrs.hasAttribute(I + 1, AK)) @@ -2581,14 +2738,14 @@ void Verifier::verifyMustTailCall(CallInst &CI) { } void Verifier::visitCallInst(CallInst &CI) { - VerifyCallSite(&CI); + verifyCallSite(&CI); if (CI.isMustTailCall()) verifyMustTailCall(CI); } void Verifier::visitInvokeInst(InvokeInst &II) { - VerifyCallSite(&II); + verifyCallSite(&II); // Verify that the first non-PHI instruction of the unwind destination is an // exception handling instruction. @@ -2741,8 +2898,8 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { if (GEP.getPointerOperandType()->isVectorTy()) Assert(GEPWidth == GEP.getPointerOperandType()->getVectorNumElements(), "Vector GEP result width doesn't match operand's", &GEP); - for (unsigned i = 0, e = Idxs.size(); i != e; ++i) { - Type *IndexTy = Idxs[i]->getType(); + for (Value *Idx : Idxs) { + Type *IndexTy = Idx->getType(); if (IndexTy->isVectorTy()) { unsigned IndexWidth = IndexTy->getVectorNumElements(); Assert(IndexWidth == GEPWidth, "Invalid GEP index vector width", &GEP); @@ -2822,8 +2979,10 @@ void Verifier::visitLoadInst(LoadInst &LI) { Type *ElTy = LI.getType(); Assert(LI.getAlignment() <= Value::MaximumAlignment, "huge alignment values are unsupported", &LI); + Assert(ElTy->isSized(), "loading unsized types is not allowed", &LI); if (LI.isAtomic()) { - Assert(LI.getOrdering() != Release && LI.getOrdering() != AcquireRelease, + Assert(LI.getOrdering() != AtomicOrdering::Release && + LI.getOrdering() != AtomicOrdering::AcquireRelease, "Load cannot have Release ordering", &LI); Assert(LI.getAlignment() != 0, "Atomic load must specify explicit alignment", &LI); @@ -2849,8 +3008,10 @@ void Verifier::visitStoreInst(StoreInst &SI) { "Stored value type does not match pointer operand type!", &SI, ElTy); Assert(SI.getAlignment() <= Value::MaximumAlignment, "huge alignment values are unsupported", &SI); + Assert(ElTy->isSized(), "storing unsized types is not allowed", &SI); if (SI.isAtomic()) { - Assert(SI.getOrdering() != Acquire && SI.getOrdering() != AcquireRelease, + Assert(SI.getOrdering() != AtomicOrdering::Acquire && + SI.getOrdering() != AtomicOrdering::AcquireRelease, "Store cannot have Acquire ordering", &SI); Assert(SI.getAlignment() != 0, "Atomic store must specify explicit alignment", &SI); @@ -2867,6 +3028,42 @@ void Verifier::visitStoreInst(StoreInst &SI) { visitInstruction(SI); } +/// Check that SwiftErrorVal is used as a swifterror argument in CS. +void Verifier::verifySwiftErrorCallSite(CallSite CS, + const Value *SwiftErrorVal) { + unsigned Idx = 0; + for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); + I != E; ++I, ++Idx) { + if (*I == SwiftErrorVal) { + Assert(CS.paramHasAttr(Idx+1, Attribute::SwiftError), + "swifterror value when used in a callsite should be marked " + "with swifterror attribute", + SwiftErrorVal, CS); + } + } +} + +void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) { + // Check that swifterror value is only used by loads, stores, or as + // a swifterror argument. + for (const User *U : SwiftErrorVal->users()) { + Assert(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || + isa<InvokeInst>(U), + "swifterror value can only be loaded and stored from, or " + "as a swifterror argument!", + SwiftErrorVal, U); + // If it is used by a store, check it is the second operand. + if (auto StoreI = dyn_cast<StoreInst>(U)) + Assert(StoreI->getOperand(1) == SwiftErrorVal, + "swifterror value should be the second operand when used " + "by stores", SwiftErrorVal, U); + if (auto CallI = dyn_cast<CallInst>(U)) + verifySwiftErrorCallSite(const_cast<CallInst*>(CallI), SwiftErrorVal); + if (auto II = dyn_cast<InvokeInst>(U)) + verifySwiftErrorCallSite(const_cast<InvokeInst*>(II), SwiftErrorVal); + } +} + void Verifier::visitAllocaInst(AllocaInst &AI) { SmallPtrSet<Type*, 4> Visited; PointerType *PTy = AI.getType(); @@ -2880,32 +3077,38 @@ void Verifier::visitAllocaInst(AllocaInst &AI) { Assert(AI.getAlignment() <= Value::MaximumAlignment, "huge alignment values are unsupported", &AI); + if (AI.isSwiftError()) { + verifySwiftErrorValue(&AI); + } + visitInstruction(AI); } void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) { // FIXME: more conditions??? - Assert(CXI.getSuccessOrdering() != NotAtomic, + Assert(CXI.getSuccessOrdering() != AtomicOrdering::NotAtomic, "cmpxchg instructions must be atomic.", &CXI); - Assert(CXI.getFailureOrdering() != NotAtomic, + Assert(CXI.getFailureOrdering() != AtomicOrdering::NotAtomic, "cmpxchg instructions must be atomic.", &CXI); - Assert(CXI.getSuccessOrdering() != Unordered, + Assert(CXI.getSuccessOrdering() != AtomicOrdering::Unordered, "cmpxchg instructions cannot be unordered.", &CXI); - Assert(CXI.getFailureOrdering() != Unordered, + Assert(CXI.getFailureOrdering() != AtomicOrdering::Unordered, "cmpxchg instructions cannot be unordered.", &CXI); - Assert(CXI.getSuccessOrdering() >= CXI.getFailureOrdering(), - "cmpxchg instructions be at least as constrained on success as fail", + Assert(!isStrongerThan(CXI.getFailureOrdering(), CXI.getSuccessOrdering()), + "cmpxchg instructions failure argument shall be no stronger than the " + "success argument", &CXI); - Assert(CXI.getFailureOrdering() != Release && - CXI.getFailureOrdering() != AcquireRelease, + Assert(CXI.getFailureOrdering() != AtomicOrdering::Release && + CXI.getFailureOrdering() != AtomicOrdering::AcquireRelease, "cmpxchg failure ordering cannot include release semantics", &CXI); PointerType *PTy = dyn_cast<PointerType>(CXI.getOperand(0)->getType()); Assert(PTy, "First cmpxchg operand must be a pointer.", &CXI); Type *ElTy = PTy->getElementType(); - Assert(ElTy->isIntegerTy(), "cmpxchg operand must have integer type!", &CXI, - ElTy); + Assert(ElTy->isIntegerTy() || ElTy->isPointerTy(), + "cmpxchg operand must have integer or pointer type", + ElTy, &CXI); checkAtomicMemAccessSize(M, ElTy, &CXI); Assert(ElTy == CXI.getOperand(1)->getType(), "Expected value type does not match pointer operand type!", &CXI, @@ -2916,9 +3119,9 @@ void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) { } void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { - Assert(RMWI.getOrdering() != NotAtomic, + Assert(RMWI.getOrdering() != AtomicOrdering::NotAtomic, "atomicrmw instructions must be atomic.", &RMWI); - Assert(RMWI.getOrdering() != Unordered, + Assert(RMWI.getOrdering() != AtomicOrdering::Unordered, "atomicrmw instructions cannot be unordered.", &RMWI); PointerType *PTy = dyn_cast<PointerType>(RMWI.getOperand(0)->getType()); Assert(PTy, "First atomicrmw operand must be a pointer.", &RMWI); @@ -2937,10 +3140,12 @@ void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { void Verifier::visitFenceInst(FenceInst &FI) { const AtomicOrdering Ordering = FI.getOrdering(); - Assert(Ordering == Acquire || Ordering == Release || - Ordering == AcquireRelease || Ordering == SequentiallyConsistent, - "fence instructions may only have " - "acquire, release, acq_rel, or seq_cst ordering.", + Assert(Ordering == AtomicOrdering::Acquire || + Ordering == AtomicOrdering::Release || + Ordering == AtomicOrdering::AcquireRelease || + Ordering == AtomicOrdering::SequentiallyConsistent, + "fence instructions may only have acquire, release, acq_rel, or " + "seq_cst ordering.", &FI); visitInstruction(FI); } @@ -3017,7 +3222,7 @@ void Verifier::visitEHPadPredecessors(Instruction &I) { else FromPad = ConstantTokenNone::get(II->getContext()); } else if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) { - FromPad = CRI->getCleanupPad(); + FromPad = CRI->getOperand(0); Assert(FromPad != ToPadParent, "A cleanupret must exit its cleanup", CRI); } else if (auto *CSI = dyn_cast<CatchSwitchInst>(TI)) { FromPad = CSI; @@ -3026,6 +3231,7 @@ void Verifier::visitEHPadPredecessors(Instruction &I) { } // The edge may exit from zero or more nested pads. + SmallSet<Value *, 8> Seen; for (;; FromPad = getParentPad(FromPad)) { Assert(FromPad != ToPad, "EH pad cannot handle exceptions raised within it", FromPad, TI); @@ -3035,6 +3241,8 @@ void Verifier::visitEHPadPredecessors(Instruction &I) { } Assert(!isa<ConstantTokenNone>(FromPad), "A single unwind edge may only enter one EH pad", TI); + Assert(Seen.insert(FromPad).second, + "EH pad jumps through a cycle of pads", FromPad); } } } @@ -3081,8 +3289,6 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) { } void Verifier::visitCatchPadInst(CatchPadInst &CPI) { - visitEHPadPredecessors(CPI); - BasicBlock *BB = CPI.getParent(); Function *F = BB->getParent(); @@ -3098,6 +3304,7 @@ void Verifier::visitCatchPadInst(CatchPadInst &CPI) { Assert(BB->getFirstNonPHI() == &CPI, "CatchPadInst not the first non-PHI instruction in the block.", &CPI); + visitEHPadPredecessors(CPI); visitFuncletPadInst(CPI); } @@ -3110,8 +3317,6 @@ void Verifier::visitCatchReturnInst(CatchReturnInst &CatchReturn) { } void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) { - visitEHPadPredecessors(CPI); - BasicBlock *BB = CPI.getParent(); Function *F = BB->getParent(); @@ -3128,6 +3333,7 @@ void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) { Assert(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad), "CleanupPadInst has an invalid parent.", &CPI); + visitEHPadPredecessors(CPI); visitFuncletPadInst(CPI); } @@ -3135,8 +3341,12 @@ void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) { User *FirstUser = nullptr; Value *FirstUnwindPad = nullptr; SmallVector<FuncletPadInst *, 8> Worklist({&FPI}); + SmallSet<FuncletPadInst *, 8> Seen; + while (!Worklist.empty()) { FuncletPadInst *CurrentPad = Worklist.pop_back_val(); + Assert(Seen.insert(CurrentPad).second, + "FuncletPadInst must not be nested within itself", CurrentPad); Value *UnresolvedAncestorPad = nullptr; for (User *U : CurrentPad->users()) { BasicBlock *UnwindDest; @@ -3172,6 +3382,8 @@ void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) { bool ExitsFPI; if (UnwindDest) { UnwindPad = UnwindDest->getFirstNonPHI(); + if (!cast<Instruction>(UnwindPad)->isEHPad()) + continue; Value *UnwindParent = getParentPad(UnwindPad); // Ignore unwind edges that don't exit CurrentPad. if (UnwindParent == CurrentPad) @@ -3285,8 +3497,6 @@ void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) { } void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) { - visitEHPadPredecessors(CatchSwitch); - BasicBlock *BB = CatchSwitch.getParent(); Function *F = BB->getParent(); @@ -3324,6 +3534,7 @@ void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) { "CatchSwitchInst handlers must be catchpads", &CatchSwitch, Handler); } + visitEHPadPredecessors(CatchSwitch); visitTerminatorInst(CatchSwitch); } @@ -3353,8 +3564,18 @@ void Verifier::verifyDominatesUse(Instruction &I, unsigned i) { return; } + // Quick check whether the def has already been encountered in the same block. + // PHI nodes are not checked to prevent accepting preceeding PHIs, because PHI + // uses are defined to happen on the incoming edge, not at the instruction. + // + // FIXME: If this operand is a MetadataAsValue (wrapping a LocalAsMetadata) + // wrapping an SSA value, assert that we've already encountered it. See + // related FIXME in Mapper::mapLocalAsMetadata in ValueMapper.cpp. + if (!isa<PHINode>(I) && InstsInThisBlock.count(Op)) + return; + const Use &U = I.getOperandUse(i); - Assert(InstsInThisBlock.count(Op) || DT.dominates(Op, U), + Assert(DT.dominates(Op, U), "Instruction does not dominate all uses!", Op, &I); } @@ -3435,8 +3656,8 @@ void Verifier::visitInstruction(Instruction &I) { F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint, - "Cannot invoke an intrinsinc other than" - " donothing or patchpoint", + "Cannot invoke an intrinsic other than donothing, patchpoint or " + "statepoint", &I); Assert(F->getParent() == M, "Referencing function in another module!", &I, M, F, F->getParent()); @@ -3469,7 +3690,9 @@ void Verifier::visitInstruction(Instruction &I) { Assert(MD->getNumOperands() == 1, "fpmath takes one operand!", &I); if (ConstantFP *CFP0 = mdconst::dyn_extract_or_null<ConstantFP>(MD->getOperand(0))) { - APFloat Accuracy = CFP0->getValueAPF(); + const APFloat &Accuracy = CFP0->getValueAPF(); + Assert(&Accuracy.getSemantics() == &APFloat::IEEEsingle, + "fpmath accuracy must have float type", &I); Assert(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(), "fpmath accuracy not a positive number!", &I); } else { @@ -3515,182 +3738,14 @@ void Verifier::visitInstruction(Instruction &I) { } if (MDNode *N = I.getDebugLoc().getAsMDNode()) { - Assert(isa<DILocation>(N), "invalid !dbg metadata attachment", &I, N); + AssertDI(isa<DILocation>(N), "invalid !dbg metadata attachment", &I, N); visitMDNode(*N); } - InstsInThisBlock.insert(&I); -} - -/// VerifyIntrinsicType - Verify that the specified type (which comes from an -/// intrinsic argument or return value) matches the type constraints specified -/// by the .td file (e.g. an "any integer" argument really is an integer). -/// -/// This return true on error but does not print a message. -bool Verifier::VerifyIntrinsicType(Type *Ty, - ArrayRef<Intrinsic::IITDescriptor> &Infos, - SmallVectorImpl<Type*> &ArgTys) { - using namespace Intrinsic; - - // If we ran out of descriptors, there are too many arguments. - if (Infos.empty()) return true; - IITDescriptor D = Infos.front(); - Infos = Infos.slice(1); - - switch (D.Kind) { - case IITDescriptor::Void: return !Ty->isVoidTy(); - case IITDescriptor::VarArg: return true; - case IITDescriptor::MMX: return !Ty->isX86_MMXTy(); - case IITDescriptor::Token: return !Ty->isTokenTy(); - case IITDescriptor::Metadata: return !Ty->isMetadataTy(); - case IITDescriptor::Half: return !Ty->isHalfTy(); - case IITDescriptor::Float: return !Ty->isFloatTy(); - case IITDescriptor::Double: return !Ty->isDoubleTy(); - case IITDescriptor::Integer: return !Ty->isIntegerTy(D.Integer_Width); - case IITDescriptor::Vector: { - VectorType *VT = dyn_cast<VectorType>(Ty); - return !VT || VT->getNumElements() != D.Vector_Width || - VerifyIntrinsicType(VT->getElementType(), Infos, ArgTys); - } - case IITDescriptor::Pointer: { - PointerType *PT = dyn_cast<PointerType>(Ty); - return !PT || PT->getAddressSpace() != D.Pointer_AddressSpace || - VerifyIntrinsicType(PT->getElementType(), Infos, ArgTys); - } - - case IITDescriptor::Struct: { - StructType *ST = dyn_cast<StructType>(Ty); - if (!ST || ST->getNumElements() != D.Struct_NumElements) - return true; - - for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) - if (VerifyIntrinsicType(ST->getElementType(i), Infos, ArgTys)) - return true; - return false; - } - - case IITDescriptor::Argument: - // Two cases here - If this is the second occurrence of an argument, verify - // that the later instance matches the previous instance. - if (D.getArgumentNumber() < ArgTys.size()) - return Ty != ArgTys[D.getArgumentNumber()]; - - // Otherwise, if this is the first instance of an argument, record it and - // verify the "Any" kind. - assert(D.getArgumentNumber() == ArgTys.size() && "Table consistency error"); - ArgTys.push_back(Ty); - - switch (D.getArgumentKind()) { - case IITDescriptor::AK_Any: return false; // Success - case IITDescriptor::AK_AnyInteger: return !Ty->isIntOrIntVectorTy(); - case IITDescriptor::AK_AnyFloat: return !Ty->isFPOrFPVectorTy(); - case IITDescriptor::AK_AnyVector: return !isa<VectorType>(Ty); - case IITDescriptor::AK_AnyPointer: return !isa<PointerType>(Ty); - } - llvm_unreachable("all argument kinds not covered"); - - case IITDescriptor::ExtendArgument: { - // This may only be used when referring to a previous vector argument. - if (D.getArgumentNumber() >= ArgTys.size()) - return true; - - Type *NewTy = ArgTys[D.getArgumentNumber()]; - if (VectorType *VTy = dyn_cast<VectorType>(NewTy)) - NewTy = VectorType::getExtendedElementVectorType(VTy); - else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy)) - NewTy = IntegerType::get(ITy->getContext(), 2 * ITy->getBitWidth()); - else - return true; - - return Ty != NewTy; - } - case IITDescriptor::TruncArgument: { - // This may only be used when referring to a previous vector argument. - if (D.getArgumentNumber() >= ArgTys.size()) - return true; - - Type *NewTy = ArgTys[D.getArgumentNumber()]; - if (VectorType *VTy = dyn_cast<VectorType>(NewTy)) - NewTy = VectorType::getTruncatedElementVectorType(VTy); - else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy)) - NewTy = IntegerType::get(ITy->getContext(), ITy->getBitWidth() / 2); - else - return true; - - return Ty != NewTy; - } - case IITDescriptor::HalfVecArgument: - // This may only be used when referring to a previous vector argument. - return D.getArgumentNumber() >= ArgTys.size() || - !isa<VectorType>(ArgTys[D.getArgumentNumber()]) || - VectorType::getHalfElementsVectorType( - cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty; - case IITDescriptor::SameVecWidthArgument: { - if (D.getArgumentNumber() >= ArgTys.size()) - return true; - VectorType * ReferenceType = - dyn_cast<VectorType>(ArgTys[D.getArgumentNumber()]); - VectorType *ThisArgType = dyn_cast<VectorType>(Ty); - if (!ThisArgType || !ReferenceType || - (ReferenceType->getVectorNumElements() != - ThisArgType->getVectorNumElements())) - return true; - return VerifyIntrinsicType(ThisArgType->getVectorElementType(), - Infos, ArgTys); - } - case IITDescriptor::PtrToArgument: { - if (D.getArgumentNumber() >= ArgTys.size()) - return true; - Type * ReferenceType = ArgTys[D.getArgumentNumber()]; - PointerType *ThisArgType = dyn_cast<PointerType>(Ty); - return (!ThisArgType || ThisArgType->getElementType() != ReferenceType); - } - case IITDescriptor::VecOfPtrsToElt: { - if (D.getArgumentNumber() >= ArgTys.size()) - return true; - VectorType * ReferenceType = - dyn_cast<VectorType> (ArgTys[D.getArgumentNumber()]); - VectorType *ThisArgVecTy = dyn_cast<VectorType>(Ty); - if (!ThisArgVecTy || !ReferenceType || - (ReferenceType->getVectorNumElements() != - ThisArgVecTy->getVectorNumElements())) - return true; - PointerType *ThisArgEltTy = - dyn_cast<PointerType>(ThisArgVecTy->getVectorElementType()); - if (!ThisArgEltTy) - return true; - return ThisArgEltTy->getElementType() != - ReferenceType->getVectorElementType(); - } - } - llvm_unreachable("unhandled"); -} - -/// \brief Verify if the intrinsic has variable arguments. -/// This method is intended to be called after all the fixed arguments have been -/// verified first. -/// -/// This method returns true on error and does not print an error message. -bool -Verifier::VerifyIntrinsicIsVarArg(bool isVarArg, - ArrayRef<Intrinsic::IITDescriptor> &Infos) { - using namespace Intrinsic; - - // If there are no descriptors left, then it can't be a vararg. - if (Infos.empty()) - return isVarArg; - - // There should be only one descriptor remaining at this point. - if (Infos.size() != 1) - return true; - - // Check and verify the descriptor. - IITDescriptor D = Infos.front(); - Infos = Infos.slice(1); - if (D.Kind == IITDescriptor::VarArg) - return !isVarArg; + if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I)) + verifyBitPieceExpression(*DII); - return true; + InstsInThisBlock.insert(&I); } /// Allow intrinsics to be verified in different ways. @@ -3709,18 +3764,20 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { ArrayRef<Intrinsic::IITDescriptor> TableRef = Table; SmallVector<Type *, 4> ArgTys; - Assert(!VerifyIntrinsicType(IFTy->getReturnType(), TableRef, ArgTys), + Assert(!Intrinsic::matchIntrinsicType(IFTy->getReturnType(), + TableRef, ArgTys), "Intrinsic has incorrect return type!", IF); for (unsigned i = 0, e = IFTy->getNumParams(); i != e; ++i) - Assert(!VerifyIntrinsicType(IFTy->getParamType(i), TableRef, ArgTys), + Assert(!Intrinsic::matchIntrinsicType(IFTy->getParamType(i), + TableRef, ArgTys), "Intrinsic has incorrect argument type!", IF); // Verify if the intrinsic call matches the vararg property. if (IsVarArg) - Assert(!VerifyIntrinsicIsVarArg(IsVarArg, TableRef), + Assert(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef), "Intrinsic was not defined with variable arguments!", IF); else - Assert(!VerifyIntrinsicIsVarArg(IsVarArg, TableRef), + Assert(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef), "Callsite was not defined with variable arguments!", IF); // All descriptors should be absorbed by now. @@ -3863,7 +3920,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { Assert(CS.getParent()->getParent()->hasGC(), "Enclosing function does not use GC.", CS); - VerifyStatepoint(CS); + verifyStatepoint(CS); break; case Intrinsic::experimental_gc_result: { Assert(CS.getParent()->getParent()->hasGC(), @@ -3913,18 +3970,18 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { else { // In all other cases relocate should be tied to the statepoint directly. // This covers relocates on a normal return path of invoke statepoint and - // relocates of a call statepoint + // relocates of a call statepoint. auto Token = CS.getArgOperand(0); Assert(isa<Instruction>(Token) && isStatepoint(cast<Instruction>(Token)), "gc relocate is incorrectly tied to the statepoint", CS, Token); } - // Verify rest of the relocate arguments + // Verify rest of the relocate arguments. ImmutableCallSite StatepointCS( cast<GCRelocateInst>(*CS.getInstruction()).getStatepoint()); - // Both the base and derived must be piped through the safepoint + // Both the base and derived must be piped through the safepoint. Value* Base = CS.getArgOperand(1); Assert(isa<ConstantInt>(Base), "gc.relocate operand #2 must be integer offset", CS); @@ -3942,7 +3999,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { "gc.relocate: statepoint derived index out of bounds", CS); // Check that BaseIndex and DerivedIndex fall within the 'gc parameters' - // section of the statepoint's argument + // section of the statepoint's argument. Assert(StatepointCS.arg_size() > 0, "gc.statepoint: insufficient arguments"); Assert(isa<ConstantInt>(StatepointCS.getArgument(3)), @@ -3962,7 +4019,8 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { "gc.statepoint: number of deoptimization arguments must be " "a constant integer"); const int NumDeoptArgs = - cast<ConstantInt>(StatepointCS.getArgument(DeoptArgsStart))->getZExtValue(); + cast<ConstantInt>(StatepointCS.getArgument(DeoptArgsStart)) + ->getZExtValue(); const int GCParamArgsStart = DeoptArgsStart + 1 + NumDeoptArgs; const int GCParamArgsEnd = StatepointCS.arg_size(); Assert(GCParamArgsStart <= BaseIndex && BaseIndex < GCParamArgsEnd, @@ -3985,10 +4043,13 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { auto ResultType = CS.getType(); auto DerivedType = Relocate.getDerivedPtr()->getType(); Assert(ResultType->isVectorTy() == DerivedType->isVectorTy(), - "gc.relocate: vector relocates to vector and pointer to pointer", CS); - Assert(ResultType->getPointerAddressSpace() == - DerivedType->getPointerAddressSpace(), - "gc.relocate: relocating a pointer shouldn't change its address space", CS); + "gc.relocate: vector relocates to vector and pointer to pointer", + CS); + Assert( + ResultType->getPointerAddressSpace() == + DerivedType->getPointerAddressSpace(), + "gc.relocate: relocating a pointer shouldn't change its address space", + CS); break; } case Intrinsic::eh_exceptioncode: @@ -3997,6 +4058,75 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { "eh.exceptionpointer argument must be a catchpad", CS); break; } + case Intrinsic::masked_load: { + Assert(CS.getType()->isVectorTy(), "masked_load: must return a vector", CS); + + Value *Ptr = CS.getArgOperand(0); + //Value *Alignment = CS.getArgOperand(1); + Value *Mask = CS.getArgOperand(2); + Value *PassThru = CS.getArgOperand(3); + Assert(Mask->getType()->isVectorTy(), + "masked_load: mask must be vector", CS); + + // DataTy is the overloaded type + Type *DataTy = cast<PointerType>(Ptr->getType())->getElementType(); + Assert(DataTy == CS.getType(), + "masked_load: return must match pointer type", CS); + Assert(PassThru->getType() == DataTy, + "masked_load: pass through and data type must match", CS); + Assert(Mask->getType()->getVectorNumElements() == + DataTy->getVectorNumElements(), + "masked_load: vector mask must be same length as data", CS); + break; + } + case Intrinsic::masked_store: { + Value *Val = CS.getArgOperand(0); + Value *Ptr = CS.getArgOperand(1); + //Value *Alignment = CS.getArgOperand(2); + Value *Mask = CS.getArgOperand(3); + Assert(Mask->getType()->isVectorTy(), + "masked_store: mask must be vector", CS); + + // DataTy is the overloaded type + Type *DataTy = cast<PointerType>(Ptr->getType())->getElementType(); + Assert(DataTy == Val->getType(), + "masked_store: storee must match pointer type", CS); + Assert(Mask->getType()->getVectorNumElements() == + DataTy->getVectorNumElements(), + "masked_store: vector mask must be same length as data", CS); + break; + } + + case Intrinsic::experimental_guard: { + Assert(CS.isCall(), "experimental_guard cannot be invoked", CS); + Assert(CS.countOperandBundlesOfType(LLVMContext::OB_deopt) == 1, + "experimental_guard must have exactly one " + "\"deopt\" operand bundle"); + break; + } + + case Intrinsic::experimental_deoptimize: { + Assert(CS.isCall(), "experimental_deoptimize cannot be invoked", CS); + Assert(CS.countOperandBundlesOfType(LLVMContext::OB_deopt) == 1, + "experimental_deoptimize must have exactly one " + "\"deopt\" operand bundle"); + Assert(CS.getType() == CS.getInstruction()->getFunction()->getReturnType(), + "experimental_deoptimize return type must match caller return type"); + + if (CS.isCall()) { + auto *DeoptCI = CS.getInstruction(); + auto *RI = dyn_cast<ReturnInst>(DeoptCI->getNextNode()); + Assert(RI, + "calls to experimental_deoptimize must be followed by a return"); + + if (!CS.getType()->isVoidTy() && RI) + Assert(RI->getReturnValue() == DeoptCI, + "calls to experimental_deoptimize must be followed by a return " + "of the value computed by experimental_deoptimize"); + } + + break; + } }; } @@ -4022,13 +4152,13 @@ static DISubprogram *getSubprogram(Metadata *LocalScope) { template <class DbgIntrinsicTy> void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { auto *MD = cast<MetadataAsValue>(DII.getArgOperand(0))->getMetadata(); - Assert(isa<ValueAsMetadata>(MD) || + AssertDI(isa<ValueAsMetadata>(MD) || (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()), "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); - Assert(isa<DILocalVariable>(DII.getRawVariable()), + AssertDI(isa<DILocalVariable>(DII.getRawVariable()), "invalid llvm.dbg." + Kind + " intrinsic variable", &DII, DII.getRawVariable()); - Assert(isa<DIExpression>(DII.getRawExpression()), + AssertDI(isa<DIExpression>(DII.getRawExpression()), "invalid llvm.dbg." + Kind + " intrinsic expression", &DII, DII.getRawExpression()); @@ -4057,8 +4187,7 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { Loc->getScope()->getSubprogram()); } -template <class MapTy> -static uint64_t getVariableSize(const DILocalVariable &V, const MapTy &Map) { +static uint64_t getVariableSize(const DILocalVariable &V) { // Be careful of broken types (checked elsewhere). const Metadata *RawType = V.getRawType(); while (RawType) { @@ -4073,12 +4202,6 @@ static uint64_t getVariableSize(const DILocalVariable &V, const MapTy &Map) { continue; } - if (auto *S = dyn_cast<MDString>(RawType)) { - // Don't error on missing types (checked elsewhere). - RawType = Map.lookup(S); - continue; - } - // Missing type or size. break; } @@ -4087,9 +4210,7 @@ static uint64_t getVariableSize(const DILocalVariable &V, const MapTy &Map) { return 0; } -template <class MapTy> -void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I, - const MapTy &TypeRefs) { +void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I) { DILocalVariable *V; DIExpression *E; if (auto *DVI = dyn_cast<DbgValueInst>(&I)) { @@ -4120,7 +4241,7 @@ void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I, // If there's no size, the type is broken, but that should be checked // elsewhere. - uint64_t VarSize = getVariableSize(*V, TypeRefs); + uint64_t VarSize = getVariableSize(*V); if (!VarSize) return; @@ -4131,54 +4252,29 @@ void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I, Assert(PieceSize != VarSize, "piece covers entire variable", &I, V, E); } -void Verifier::visitUnresolvedTypeRef(const MDString *S, const MDNode *N) { - // This is in its own function so we get an error for each bad type ref (not - // just the first). - Assert(false, "unresolved type ref", S, N); -} - -void Verifier::verifyTypeRefs() { +void Verifier::verifyCompileUnits() { auto *CUs = M->getNamedMetadata("llvm.dbg.cu"); - if (!CUs) - return; - - // Visit all the compile units again to map the type references. - SmallDenseMap<const MDString *, const DIType *, 32> TypeRefs; - for (auto *CU : CUs->operands()) - if (auto Ts = cast<DICompileUnit>(CU)->getRetainedTypes()) - for (DIType *Op : Ts) - if (auto *T = dyn_cast_or_null<DICompositeType>(Op)) - if (auto *S = T->getRawIdentifier()) { - UnresolvedTypeRefs.erase(S); - TypeRefs.insert(std::make_pair(S, T)); - } + 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); }), + "All DICompileUnits must be listed in llvm.dbg.cu"); + CUVisited.clear(); +} - // Verify debug info intrinsic bit piece expressions. This needs a second - // pass through the intructions, since we haven't built TypeRefs yet when - // verifying functions, and simply queuing the DbgInfoIntrinsics to evaluate - // later/now would queue up some that could be later deleted. - for (const Function &F : *M) - for (const BasicBlock &BB : F) - for (const Instruction &I : BB) - if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I)) - verifyBitPieceExpression(*DII, TypeRefs); - - // Return early if all typerefs were resolved. - if (UnresolvedTypeRefs.empty()) +void Verifier::verifyDeoptimizeCallingConvs() { + if (DeoptimizeDeclarations.empty()) return; - // Sort the unresolved references by name so the output is deterministic. - typedef std::pair<const MDString *, const MDNode *> TypeRef; - SmallVector<TypeRef, 32> Unresolved(UnresolvedTypeRefs.begin(), - UnresolvedTypeRefs.end()); - std::sort(Unresolved.begin(), Unresolved.end(), - [](const TypeRef &LHS, const TypeRef &RHS) { - return LHS.first->getString() < RHS.first->getString(); - }); - - // Visit the unresolved refs (printing out the errors). - for (const TypeRef &TR : Unresolved) - visitUnresolvedTypeRef(TR.first, TR.second); + const Function *First = DeoptimizeDeclarations[0]; + for (auto *F : makeArrayRef(DeoptimizeDeclarations).slice(1)) { + Assert(First->getCallingConv() == F->getCallingConv(), + "All llvm.experimental.deoptimize declarations must have the same " + "calling convention", + First, F); + } } //===----------------------------------------------------------------------===// @@ -4187,28 +4283,30 @@ void Verifier::verifyTypeRefs() { bool llvm::verifyFunction(const Function &f, raw_ostream *OS) { Function &F = const_cast<Function &>(f); - assert(!F.isDeclaration() && "Cannot verify external functions"); - raw_null_ostream NullStr; - Verifier V(OS ? *OS : NullStr); + // Don't use a raw_null_ostream. Printing IR is expensive. + Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true); // Note that this function's return value is inverted from what you would // expect of a function called "verify". return !V.verify(F); } -bool llvm::verifyModule(const Module &M, raw_ostream *OS) { - raw_null_ostream NullStr; - Verifier V(OS ? *OS : NullStr); +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); bool Broken = false; - for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isDeclaration() && !I->isMaterializable()) - Broken |= !V.verify(*I); + for (const Function &F : M) + Broken |= !V.verify(F); + Broken |= !V.verify(M); + if (BrokenDebugInfo) + *BrokenDebugInfo = V.hasBrokenDebugInfo(); // Note that this function's return value is inverted from what you would // expect of a function called "verify". - return !V.verify(M) || Broken; + return Broken; } namespace { @@ -4216,13 +4314,17 @@ struct VerifierLegacyPass : public FunctionPass { static char ID; Verifier V; - bool FatalErrors; + bool FatalErrors = true; - VerifierLegacyPass() : FunctionPass(ID), V(dbgs()), FatalErrors(true) { + VerifierLegacyPass() + : FunctionPass(ID), + V(&dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false) { initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); } explicit VerifierLegacyPass(bool FatalErrors) - : FunctionPass(ID), V(dbgs()), FatalErrors(FatalErrors) { + : FunctionPass(ID), + V(&dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false), + FatalErrors(FatalErrors) { initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); } @@ -4234,9 +4336,25 @@ struct VerifierLegacyPass : public FunctionPass { } bool doFinalization(Module &M) override { - if (!V.verify(M) && FatalErrors) - report_fatal_error("Broken module found, compilation aborted!"); + bool HasErrors = false; + for (Function &F : M) + if (F.isDeclaration()) + HasErrors |= !V.verify(F); + + HasErrors |= !V.verify(M); + if (FatalErrors) { + if (HasErrors) + report_fatal_error("Broken module found, compilation aborted!"); + assert(!V.hasBrokenDebugInfo() && "Module contains invalid debug info"); + } + // Strip broken debug info. + if (V.hasBrokenDebugInfo()) { + DiagnosticInfoIgnoringInvalidDebugMetadata DiagInvalid(M); + M.getContext().diagnose(DiagInvalid); + if (!StripDebugInfo(M)) + report_fatal_error("Failed to strip malformed debug info"); + } return false; } @@ -4253,15 +4371,40 @@ FunctionPass *llvm::createVerifierPass(bool FatalErrors) { return new VerifierLegacyPass(FatalErrors); } -PreservedAnalyses VerifierPass::run(Module &M) { - if (verifyModule(M, &dbgs()) && FatalErrors) - report_fatal_error("Broken module found, compilation aborted!"); +char VerifierAnalysis::PassID; +VerifierAnalysis::Result VerifierAnalysis::run(Module &M, + ModuleAnalysisManager &) { + Result Res; + Res.IRBroken = llvm::verifyModule(M, &dbgs(), &Res.DebugInfoBroken); + return Res; +} + +VerifierAnalysis::Result VerifierAnalysis::run(Function &F, + FunctionAnalysisManager &) { + return { llvm::verifyFunction(F, &dbgs()), false }; +} +PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { + auto Res = AM.getResult<VerifierAnalysis>(M); + if (FatalErrors) { + if (Res.IRBroken) + report_fatal_error("Broken module found, compilation aborted!"); + assert(!Res.DebugInfoBroken && "Module contains invalid debug info"); + } + + // Strip broken debug info. + if (Res.DebugInfoBroken) { + DiagnosticInfoIgnoringInvalidDebugMetadata DiagInvalid(M); + M.getContext().diagnose(DiagInvalid); + if (!StripDebugInfo(M)) + report_fatal_error("Failed to strip malformed debug info"); + } return PreservedAnalyses::all(); } -PreservedAnalyses VerifierPass::run(Function &F) { - if (verifyFunction(F, &dbgs()) && FatalErrors) +PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) { + auto res = AM.getResult<VerifierAnalysis>(F); + if (res.IRBroken && FatalErrors) report_fatal_error("Broken function found, compilation aborted!"); return PreservedAnalyses::all(); |