blob: 61707cc8350415833027e95f5e62bd10aca56908 [file] [log] [blame] [edit]
//===-- Verifier.cpp - Implement the Module Verifier -----------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the function verifier interface, that can be used for some
// sanity checking of input to the system.
//
// Note that this does not provide full `Java style' security and verifications,
// instead it just tries to ensure that code is well-formed.
//
// * Both of a binary operator's parameters are of the same type
// * Verify that the indices of mem access instructions match other operands
// * Verify that arithmetic and other things are only performed on first-class
// types. Verify that shifts & logicals only happen on integrals f.e.
// * All of the constants in a switch statement are of the correct type
// * The code is in valid SSA form
// * It should be illegal to put a label into any other type (like a structure)
// or to return one. [except constant arrays!]
// * Only phi nodes can be self referential: 'add i32 %0, %0 ; <int>:0' is bad
// * PHI nodes must have an entry for each predecessor, with no extras.
// * PHI nodes must be the first thing in a basic block, all grouped together
// * PHI nodes must have at least one entry
// * All basic blocks should only end with terminator insts, not contain them
// * The entry node to a function must not have predecessors
// * All Instructions must be embedded into a basic block
// * Functions cannot take a void-typed parameter
// * Verify that a function's argument list agrees with it's declared type.
// * It is illegal to specify a name for a void value.
// * It is illegal to have a internal global value with no initializer
// * It is illegal to have a ret instruction that returns a value that does not
// agree with the function return value type.
// * Function call argument types match the function prototype
// * A landing pad is defined by a landingpad instruction, and can be jumped to
// only by the unwind edge of an invoke instruction.
// * A landingpad instruction must be the first non-PHI instruction in the
// block.
// * Landingpad instructions must be in a function with a personality function.
// * All other things that are tested by asserts spread about the code...
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/Verifier.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/ilist.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Comdat.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsWebAssembly.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Statepoint.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
using namespace llvm;
namespace llvm {
struct VerifierSupport {
raw_ostream *OS;
const Module &M;
ModuleSlotTracker MST;
Triple TT;
const DataLayout &DL;
LLVMContext &Context;
/// 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, const Module &M)
: OS(OS), M(M), MST(&M), TT(M.getTargetTriple()), DL(M.getDataLayout()),
Context(M.getContext()) {}
private:
void Write(const Module *M) {
*OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n";
}
void Write(const Value *V) {
if (V)
Write(*V);
}
void Write(const Value &V) {
if (isa<Instruction>(V)) {
V.print(*OS, MST);
*OS << '\n';
} else {
V.printAsOperand(*OS, true, MST);
*OS << '\n';
}
}
void Write(const Metadata *MD) {
if (!MD)
return;
MD->print(*OS, MST, &M);
*OS << '\n';
}
template <class T> void Write(const MDTupleTypedArrayWrapper<T> &MD) {
Write(MD.get());
}
void Write(const NamedMDNode *NMD) {
if (!NMD)
return;
NMD->print(*OS, MST);
*OS << '\n';
}
void Write(Type *T) {
if (!T)
return;
*OS << ' ' << *T;
}
void Write(const Comdat *C) {
if (!C)
return;
*OS << *C;
}
void Write(const APInt *AI) {
if (!AI)
return;
*OS << *AI << '\n';
}
void Write(const unsigned i) { *OS << i << '\n'; }
template <typename T> void Write(ArrayRef<T> Vs) {
for (const T &V : Vs)
Write(V);
}
template <typename T1, typename... Ts>
void WriteTs(const T1 &V1, const Ts &... Vs) {
Write(V1);
WriteTs(Vs...);
}
template <typename... Ts> void WriteTs() {}
public:
/// A check failed, so printout out the condition and the message.
///
/// This provides a nice place to put a breakpoint if you want to see why
/// something is not correct.
void CheckFailed(const Twine &Message) {
if (OS)
*OS << Message << '\n';
Broken = true;
}
/// A check failed (with values to print).
///
/// This calls the Message-only version so that the above is easier to set a
/// breakpoint on.
template <typename T1, typename... Ts>
void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) {
CheckFailed(Message);
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...);
}
};
} // namespace llvm
namespace {
class Verifier : public InstVisitor<Verifier>, VerifierSupport {
friend class InstVisitor<Verifier>;
DominatorTree DT;
/// When verifying a basic block, keep track of all of the
/// instructions we have seen so far.
///
/// This allows us to do efficient dominance checks for the case when an
/// instruction has an operand that is an instruction in the same block.
SmallPtrSet<Instruction *, 16> InstsInThisBlock;
/// Keep track of the metadata nodes that have been checked already.
SmallPtrSet<const Metadata *, 32> MDNodes;
/// Keep track which DISubprogram is attached to which function.
DenseMap<const DISubprogram *, const Function *> DISubprogramAttachments;
/// Track all DICompileUnits visited.
SmallPtrSet<const Metadata *, 2> CUVisited;
/// The result type for a landingpad.
Type *LandingPadResultTy;
/// Whether we've seen a call to @llvm.localescape in this function
/// already.
bool SawFrameEscape;
/// Whether the current function has a DISubprogram attached to it.
bool HasDebugInfo = false;
/// Whether source was present on the first DIFile encountered in each CU.
DenseMap<const DICompileUnit *, bool> HasSourceDebugInfo;
/// Stores the count of how many objects were passed to llvm.localescape for a
/// given function and the largest index passed to llvm.localrecover.
DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo;
// Maps catchswitches and cleanuppads that unwind to siblings to the
// terminators that indicate the unwind, used to detect cycles therein.
MapVector<Instruction *, Instruction *> SiblingFuncletInfo;
/// 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;
// Keeps track of duplicate function argument debug info.
SmallVector<const DILocalVariable *, 16> DebugFnArgs;
TBAAVerifier TBAAVerifyHelper;
void checkAtomicMemAccessSize(Type *Ty, const Instruction *I);
public:
explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError,
const Module &M)
: VerifierSupport(OS, M), LandingPadResultTy(nullptr),
SawFrameEscape(false), TBAAVerifyHelper(this) {
TreatBrokenDebugInfoAsError = ShouldTreatBrokenDebugInfoAsError;
}
bool hasBrokenDebugInfo() const { return BrokenDebugInfo; }
bool verify(const Function &F) {
assert(F.getParent() == &M &&
"An instance of this class only works with a specific module!");
// First ensure the function is well-enough formed to compute dominance
// information, and directly compute a dominance tree. We don't rely on the
// 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;
}
Broken = false;
// FIXME: We strip const here because the inst visitor strips const.
visit(const_cast<Function &>(F));
verifySiblingFuncletUnwinds();
InstsInThisBlock.clear();
DebugFnArgs.clear();
LandingPadResultTy = nullptr;
SawFrameEscape = false;
SiblingFuncletInfo.clear();
return !Broken;
}
/// Verify the module that this instance of \c Verifier was initialized with.
bool verify() {
Broken = false;
// Collect all declarations of the llvm.experimental.deoptimize intrinsic.
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 (const GlobalAlias &GA : M.aliases())
visitGlobalAlias(GA);
for (const NamedMDNode &NMD : M.named_metadata())
visitNamedMDNode(NMD);
for (const StringMapEntry<Comdat> &SMEC : M.getComdatSymbolTable())
visitComdat(SMEC.getValue());
visitModuleFlags(M);
visitModuleIdents(M);
visitModuleCommandLines(M);
verifyCompileUnits();
verifyDeoptimizeCallingConvs();
DISubprogramAttachments.clear();
return !Broken;
}
private:
// Verification methods...
void visitGlobalValue(const GlobalValue &GV);
void visitGlobalVariable(const GlobalVariable &GV);
void visitGlobalAlias(const GlobalAlias &GA);
void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C);
void visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias *> &Visited,
const GlobalAlias &A, const Constant &C);
void visitNamedMDNode(const NamedMDNode &NMD);
void visitMDNode(const MDNode &MD);
void visitMetadataAsValue(const MetadataAsValue &MD, Function *F);
void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F);
void visitComdat(const Comdat &C);
void visitModuleIdents(const Module &M);
void visitModuleCommandLines(const Module &M);
void visitModuleFlags(const Module &M);
void visitModuleFlag(const MDNode *Op,
DenseMap<const MDString *, const MDNode *> &SeenIDs,
SmallVectorImpl<const MDNode *> &Requirements);
void visitModuleFlagCGProfileEntry(const MDOperand &MDO);
void visitFunction(const Function &F);
void visitBasicBlock(BasicBlock &BB);
void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty);
void visitDereferenceableMetadata(Instruction &I, MDNode *MD);
void visitProfMetadata(Instruction &I, MDNode *MD);
template <class Ty> bool isValidMetadataArray(const MDTuple &N);
#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N);
#include "llvm/IR/Metadata.def"
void visitDIScope(const DIScope &N);
void visitDIVariable(const DIVariable &N);
void visitDILexicalBlockBase(const DILexicalBlockBase &N);
void visitDITemplateParameter(const DITemplateParameter &N);
void visitTemplateParams(const MDNode &N, const Metadata &RawParams);
// InstVisitor overrides...
using InstVisitor<Verifier>::visit;
void visit(Instruction &I);
void visitTruncInst(TruncInst &I);
void visitZExtInst(ZExtInst &I);
void visitSExtInst(SExtInst &I);
void visitFPTruncInst(FPTruncInst &I);
void visitFPExtInst(FPExtInst &I);
void visitFPToUIInst(FPToUIInst &I);
void visitFPToSIInst(FPToSIInst &I);
void visitUIToFPInst(UIToFPInst &I);
void visitSIToFPInst(SIToFPInst &I);
void visitIntToPtrInst(IntToPtrInst &I);
void visitPtrToIntInst(PtrToIntInst &I);
void visitBitCastInst(BitCastInst &I);
void visitAddrSpaceCastInst(AddrSpaceCastInst &I);
void visitPHINode(PHINode &PN);
void visitCallBase(CallBase &Call);
void visitUnaryOperator(UnaryOperator &U);
void visitBinaryOperator(BinaryOperator &B);
void visitICmpInst(ICmpInst &IC);
void visitFCmpInst(FCmpInst &FC);
void visitExtractElementInst(ExtractElementInst &EI);
void visitInsertElementInst(InsertElementInst &EI);
void visitShuffleVectorInst(ShuffleVectorInst &EI);
void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); }
void visitCallInst(CallInst &CI);
void visitInvokeInst(InvokeInst &II);
void visitGetElementPtrInst(GetElementPtrInst &GEP);
void visitLoadInst(LoadInst &LI);
void visitStoreInst(StoreInst &SI);
void verifyDominatesUse(Instruction &I, unsigned i);
void visitInstruction(Instruction &I);
void visitTerminator(Instruction &I);
void visitBranchInst(BranchInst &BI);
void visitReturnInst(ReturnInst &RI);
void visitSwitchInst(SwitchInst &SI);
void visitIndirectBrInst(IndirectBrInst &BI);
void visitCallBrInst(CallBrInst &CBI);
void visitSelectInst(SelectInst &SI);
void visitUserOp1(Instruction &I);
void visitUserOp2(Instruction &I) { visitUserOp1(I); }
void visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call);
void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI);
void visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII);
void visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI);
void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI);
void visitAtomicRMWInst(AtomicRMWInst &RMWI);
void visitFenceInst(FenceInst &FI);
void visitAllocaInst(AllocaInst &AI);
void visitExtractValueInst(ExtractValueInst &EVI);
void visitInsertValueInst(InsertValueInst &IVI);
void visitEHPadPredecessors(Instruction &I);
void visitLandingPadInst(LandingPadInst &LPI);
void visitResumeInst(ResumeInst &RI);
void visitCatchPadInst(CatchPadInst &CPI);
void visitCatchReturnInst(CatchReturnInst &CatchReturn);
void visitCleanupPadInst(CleanupPadInst &CPI);
void visitFuncletPadInst(FuncletPadInst &FPI);
void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch);
void visitCleanupReturnInst(CleanupReturnInst &CRI);
void verifySwiftErrorCall(CallBase &Call, const Value *SwiftErrorVal);
void verifySwiftErrorValue(const Value *SwiftErrorVal);
void verifyMustTailCall(CallInst &CI);
bool performTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, int VT,
unsigned ArgNo, std::string &Suffix);
bool verifyAttributeCount(AttributeList Attrs, unsigned Params);
void verifyAttributeTypes(AttributeSet Attrs, bool IsFunction,
const Value *V);
void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V);
void verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
const Value *V, bool IsIntrinsic);
void verifyFunctionMetadata(ArrayRef<std::pair<unsigned, MDNode *>> MDs);
void visitConstantExprsRecursively(const Constant *EntryC);
void visitConstantExpr(const ConstantExpr *CE);
void verifyStatepoint(const CallBase &Call);
void verifyFrameRecoverIndices();
void verifySiblingFuncletUnwinds();
void verifyFragmentExpression(const DbgVariableIntrinsic &I);
template <typename ValueOrMetadata>
void verifyFragmentExpression(const DIVariable &V,
DIExpression::FragmentInfo Fragment,
ValueOrMetadata *Desc);
void verifyFnArgs(const DbgVariableIntrinsic &I);
void verifyNotEntryValue(const DbgVariableIntrinsic &I);
/// Module-level debug info verification...
void verifyCompileUnits();
/// Module-level verification that all @llvm.experimental.deoptimize
/// declarations share the same calling convention.
void verifyDeoptimizeCallingConvs();
/// Verify all-or-nothing property of DIFile source attribute within a CU.
void verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F);
};
} // end anonymous namespace
/// We know that cond should be true, if not print an error message.
#define Assert(C, ...) \
do { if (!(C)) { CheckFailed(__VA_ARGS__); return; } } while (false)
/// We know that a debug info condition should be true, if not print
/// an error message.
#define AssertDI(C, ...) \
do { if (!(C)) { DebugInfoCheckFailed(__VA_ARGS__); return; } } while (false)
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.hasValidDeclarationLinkage(),
"Global is external, but doesn't have external or weak linkage!", &GV);
Assert(GV.getAlignment() <= Value::MaximumAlignment,
"huge alignment values are unsupported", &GV);
Assert(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),
"Only global variables can have appending linkage!", &GV);
if (GV.hasAppendingLinkage()) {
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(&GV);
Assert(GVar && GVar->getValueType()->isArrayTy(),
"Only global arrays can have appending linkage!", GVar);
}
if (GV.isDeclarationForLinker())
Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV);
if (GV.hasDLLImportStorageClass()) {
Assert(!GV.isDSOLocal(),
"GlobalValue with DLLImport Storage is dso_local!", &GV);
Assert((GV.isDeclaration() && GV.hasExternalLinkage()) ||
GV.hasAvailableExternallyLinkage(),
"Global is marked as dllimport, but not external", &GV);
}
if (GV.hasLocalLinkage())
Assert(GV.isDSOLocal(),
"GlobalValue with private or internal linkage must be dso_local!",
&GV);
if (!GV.hasDefaultVisibility() && !GV.hasExternalWeakLinkage())
Assert(GV.isDSOLocal(),
"GlobalValue with non default visibility must be dso_local!", &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.getValueType(),
"Global variable initializer type does not match global "
"variable type!",
&GV);
// If the global has common linkage, it must have a zero initializer and
// cannot be constant.
if (GV.hasCommonLinkage()) {
Assert(GV.getInitializer()->isNullValue(),
"'common' global must have a zero initializer!", &GV);
Assert(!GV.isConstant(), "'common' global may not be marked constant!",
&GV);
Assert(!GV.hasComdat(), "'common' global may not be in a Comdat!", &GV);
}
}
if (GV.hasName() && (GV.getName() == "llvm.global_ctors" ||
GV.getName() == "llvm.global_dtors")) {
Assert(!GV.hasInitializer() || GV.hasAppendingLinkage(),
"invalid linkage for intrinsic global variable", &GV);
// Don't worry about emitting an error for it not being an array,
// visitGlobalValue will complain on appending non-array.
if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) {
StructType *STy = dyn_cast<StructType>(ATy->getElementType());
PointerType *FuncPtrTy =
FunctionType::get(Type::getVoidTy(Context), false)->
getPointerTo(DL.getProgramAddressSpace());
Assert(STy &&
(STy->getNumElements() == 2 || STy->getNumElements() == 3) &&
STy->getTypeAtIndex(0u)->isIntegerTy(32) &&
STy->getTypeAtIndex(1) == FuncPtrTy,
"wrong type for intrinsic global variable", &GV);
Assert(STy->getNumElements() == 3,
"the third field of the element type is mandatory, "
"specify i8* null to migrate from the obsoleted 2-field form");
Type *ETy = STy->getTypeAtIndex(2);
Assert(ETy->isPointerTy() &&
cast<PointerType>(ETy)->getElementType()->isIntegerTy(8),
"wrong type for intrinsic global variable", &GV);
}
}
if (GV.hasName() && (GV.getName() == "llvm.used" ||
GV.getName() == "llvm.compiler.used")) {
Assert(!GV.hasInitializer() || GV.hasAppendingLinkage(),
"invalid linkage for intrinsic global variable", &GV);
Type *GVType = GV.getValueType();
if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) {
PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType());
Assert(PTy, "wrong type for intrinsic global variable", &GV);
if (GV.hasInitializer()) {
const Constant *Init = GV.getInitializer();
const ConstantArray *InitArray = dyn_cast<ConstantArray>(Init);
Assert(InitArray, "wrong initalizer for intrinsic global variable",
Init);
for (Value *Op : InitArray->operands()) {
Value *V = Op->stripPointerCasts();
Assert(isa<GlobalVariable>(V) || isa<Function>(V) ||
isa<GlobalAlias>(V),
"invalid llvm.used member", V);
Assert(V->hasName(), "members of llvm.used must be named", V);
}
}
}
}
// Visit any debug info attachments.
SmallVector<MDNode *, 1> MDs;
GV.getMetadata(LLVMContext::MD_dbg, MDs);
for (auto *MD : MDs) {
if (auto *GVE = dyn_cast<DIGlobalVariableExpression>(MD))
visitDIGlobalVariableExpression(*GVE);
else
AssertDI(false, "!dbg attachment of global variable must be a "
"DIGlobalVariableExpression");
}
// Scalable vectors cannot be global variables, since we don't know
// the runtime size. If the global is a struct or an array containing
// scalable vectors, that will be caught by the isValidElementType methods
// in StructType or ArrayType instead.
if (auto *VTy = dyn_cast<VectorType>(GV.getValueType()))
Assert(!VTy->isScalable(), "Globals cannot contain scalable vectors", &GV);
if (!GV.hasInitializer()) {
visitGlobalValue(GV);
return;
}
// Walk any aggregate initializers looking for bitcasts between address spaces
visitConstantExprsRecursively(GV.getInitializer());
visitGlobalValue(GV);
}
void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) {
SmallPtrSet<const GlobalAlias*, 4> Visited;
Visited.insert(&GA);
visitAliaseeSubExpr(Visited, GA, C);
}
void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited,
const GlobalAlias &GA, const Constant &C) {
if (const auto *GV = dyn_cast<GlobalValue>(&C)) {
Assert(!GV->isDeclarationForLinker(), "Alias must point to a definition",
&GA);
if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) {
Assert(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA);
Assert(!GA2->isInterposable(), "Alias cannot point to an interposable alias",
&GA);
} else {
// Only continue verifying subexpressions of GlobalAliases.
// Do not recurse into global initializers.
return;
}
}
if (const auto *CE = dyn_cast<ConstantExpr>(&C))
visitConstantExprsRecursively(CE);
for (const Use &U : C.operands()) {
Value *V = &*U;
if (const auto *GA2 = dyn_cast<GlobalAlias>(V))
visitAliaseeSubExpr(Visited, GA, *GA2->getAliasee());
else if (const auto *C2 = dyn_cast<Constant>(V))
visitAliaseeSubExpr(Visited, GA, *C2);
}
}
void Verifier::visitGlobalAlias(const GlobalAlias &GA) {
Assert(GlobalAlias::isValidLinkage(GA.getLinkage()),
"Alias should have private, internal, linkonce, weak, linkonce_odr, "
"weak_odr, or external linkage!",
&GA);
const Constant *Aliasee = GA.getAliasee();
Assert(Aliasee, "Aliasee cannot be NULL!", &GA);
Assert(GA.getType() == Aliasee->getType(),
"Alias and aliasee types should match!", &GA);
Assert(isa<GlobalValue>(Aliasee) || isa<ConstantExpr>(Aliasee),
"Aliasee should be either GlobalValue or ConstantExpr", &GA);
visitAliaseeSubExpr(GA, *Aliasee);
visitGlobalValue(GA);
}
void Verifier::visitNamedMDNode(const NamedMDNode &NMD) {
// There used to be various other llvm.dbg.* nodes, but we don't support
// upgrading them and we want to reserve the namespace for future uses.
if (NMD.getName().startswith("llvm.dbg."))
AssertDI(NMD.getName() == "llvm.dbg.cu",
"unrecognized named metadata node in the llvm.dbg namespace",
&NMD);
for (const MDNode *MD : NMD.operands()) {
if (NMD.getName() == "llvm.dbg.cu")
AssertDI(MD && isa<DICompileUnit>(MD), "invalid compile unit", &NMD, MD);
if (!MD)
continue;
visitMDNode(*MD);
}
}
void Verifier::visitMDNode(const MDNode &MD) {
// Only visit each node once. Metadata can be mutually recursive, so this
// avoids infinite recursion here, as well as being an optimization.
if (!MDNodes.insert(&MD).second)
return;
switch (MD.getMetadataID()) {
default:
llvm_unreachable("Invalid MDNode subclass");
case Metadata::MDTupleKind:
break;
#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \
case Metadata::CLASS##Kind: \
visit##CLASS(cast<CLASS>(MD)); \
break;
#include "llvm/IR/Metadata.def"
}
for (const Metadata *Op : MD.operands()) {
if (!Op)
continue;
Assert(!isa<LocalAsMetadata>(Op), "Invalid operand for global metadata!",
&MD, Op);
if (auto *N = dyn_cast<MDNode>(Op)) {
visitMDNode(*N);
continue;
}
if (auto *V = dyn_cast<ValueAsMetadata>(Op)) {
visitValueAsMetadata(*V, nullptr);
continue;
}
}
// Check these last, so we diagnose problems in operands first.
Assert(!MD.isTemporary(), "Expected no forward declarations!", &MD);
Assert(MD.isResolved(), "All nodes should be resolved!", &MD);
}
void Verifier::visitValueAsMetadata(const ValueAsMetadata &MD, Function *F) {
Assert(MD.getValue(), "Expected valid value", &MD);
Assert(!MD.getValue()->getType()->isMetadataTy(),
"Unexpected metadata round-trip through values", &MD, MD.getValue());
auto *L = dyn_cast<LocalAsMetadata>(&MD);
if (!L)
return;
Assert(F, "function-local metadata used outside a function", L);
// If this was an instruction, bb, or argument, verify that it is in the
// function that we expect.
Function *ActualF = nullptr;
if (Instruction *I = dyn_cast<Instruction>(L->getValue())) {
Assert(I->getParent(), "function-local metadata not in basic block", L, I);
ActualF = I->getParent()->getParent();
} else if (BasicBlock *BB = dyn_cast<BasicBlock>(L->getValue()))
ActualF = BB->getParent();
else if (Argument *A = dyn_cast<Argument>(L->getValue()))
ActualF = A->getParent();
assert(ActualF && "Unimplemented function local metadata case!");
Assert(ActualF == F, "function-local metadata used in wrong function", L);
}
void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) {
Metadata *MD = MDV.getMetadata();
if (auto *N = dyn_cast<MDNode>(MD)) {
visitMDNode(*N);
return;
}
// Only visit each node once. Metadata can be mutually recursive, so this
// avoids infinite recursion here, as well as being an optimization.
if (!MDNodes.insert(MD).second)
return;
if (auto *V = dyn_cast<ValueAsMetadata>(MD))
visitValueAsMetadata(*V, F);
}
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); }
void Verifier::visitDILocation(const DILocation &N) {
AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),
"location requires a valid scope", &N, N.getRawScope());
if (auto *IA = N.getRawInlinedAt())
AssertDI(isa<DILocation>(IA), "inlined-at should be a location", &N, IA);
if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope()))
AssertDI(SP->isDefinition(), "scope points into the type hierarchy", &N);
}
void Verifier::visitGenericDINode(const GenericDINode &N) {
AssertDI(N.getTag(), "invalid tag", &N);
}
void Verifier::visitDIScope(const DIScope &N) {
if (auto *F = N.getRawFile())
AssertDI(isa<DIFile>(F), "invalid file", &N, F);
}
void Verifier::visitDISubrange(const DISubrange &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N);
auto Count = N.getCount();
AssertDI(Count, "Count must either be a signed constant or a DIVariable",
&N);
AssertDI(!Count.is<ConstantInt*>() ||
Count.get<ConstantInt*>()->getSExtValue() >= -1,
"invalid subrange count", &N);
}
void Verifier::visitDIEnumerator(const DIEnumerator &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_enumerator, "invalid tag", &N);
}
void Verifier::visitDIBasicType(const DIBasicType &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_base_type ||
N.getTag() == dwarf::DW_TAG_unspecified_type,
"invalid tag", &N);
AssertDI(!(N.isBigEndian() && N.isLittleEndian()) ,
"has conflicting flags", &N);
}
void Verifier::visitDIDerivedType(const DIDerivedType &N) {
// Common scope checks.
visitDIScope(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_atomic_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) {
AssertDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,
N.getRawExtraData());
}
AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope());
AssertDI(isType(N.getRawBaseType()), "invalid base type", &N,
N.getRawBaseType());
if (N.getDWARFAddressSpace()) {
AssertDI(N.getTag() == dwarf::DW_TAG_pointer_type ||
N.getTag() == dwarf::DW_TAG_reference_type ||
N.getTag() == dwarf::DW_TAG_rvalue_reference_type,
"DWARF address space only applies to pointer or reference types",
&N);
}
}
/// Detect mutually exclusive flags.
static bool hasConflictingReferenceFlags(unsigned Flags) {
return ((Flags & DINode::FlagLValueReference) &&
(Flags & DINode::FlagRValueReference)) ||
((Flags & DINode::FlagTypePassByValue) &&
(Flags & DINode::FlagTypePassByReference));
}
void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) {
auto *Params = dyn_cast<MDTuple>(&RawParams);
AssertDI(Params, "invalid template params", &N, &RawParams);
for (Metadata *Op : Params->operands()) {
AssertDI(Op && isa<DITemplateParameter>(Op), "invalid template parameter",
&N, Params, Op);
}
}
void Verifier::visitDICompositeType(const DICompositeType &N) {
// Common scope checks.
visitDIScope(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 ||
N.getTag() == dwarf::DW_TAG_variant_part,
"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);
unsigned DIBlockByRefStruct = 1 << 4;
AssertDI((N.getFlags() & DIBlockByRefStruct) == 0,
"DIBlockByRefStruct on DICompositeType is no longer supported", &N);
if (N.isVector()) {
const DINodeArray Elements = N.getElements();
AssertDI(Elements.size() == 1 &&
Elements[0]->getTag() == dwarf::DW_TAG_subrange_type,
"invalid vector, expected one element of type subrange", &N);
}
if (auto *Params = N.getRawTemplateParams())
visitTemplateParams(N, *Params);
if (N.getTag() == dwarf::DW_TAG_class_type ||
N.getTag() == dwarf::DW_TAG_union_type) {
AssertDI(N.getFile() && !N.getFile()->getFilename().empty(),
"class/union requires a filename", &N, N.getFile());
}
if (auto *D = N.getRawDiscriminator()) {
AssertDI(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part,
"discriminator can only appear on variant part");
}
}
void Verifier::visitDISubroutineType(const DISubroutineType &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_subroutine_type, "invalid tag", &N);
if (auto *Types = N.getRawTypeArray()) {
AssertDI(isa<MDTuple>(Types), "invalid composite elements", &N, Types);
for (Metadata *Ty : N.getTypeArray()->operands()) {
AssertDI(isType(Ty), "invalid subroutine type ref", &N, Types, Ty);
}
}
AssertDI(!hasConflictingReferenceFlags(N.getFlags()),
"invalid reference flags", &N);
}
void Verifier::visitDIFile(const DIFile &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N);
Optional<DIFile::ChecksumInfo<StringRef>> Checksum = N.getChecksum();
if (Checksum) {
AssertDI(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last,
"invalid checksum kind", &N);
size_t Size;
switch (Checksum->Kind) {
case DIFile::CSK_MD5:
Size = 32;
break;
case DIFile::CSK_SHA1:
Size = 40;
break;
}
AssertDI(Checksum->Value.size() == Size, "invalid checksum length", &N);
AssertDI(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos,
"invalid checksum", &N);
}
}
void Verifier::visitDICompileUnit(const DICompileUnit &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.
AssertDI(N.getRawFile() && isa<DIFile>(N.getRawFile()), "invalid file", &N,
N.getRawFile());
AssertDI(!N.getFile()->getFilename().empty(), "invalid filename", &N,
N.getFile());
verifySourceDebugInfo(N, *N.getFile());
AssertDI((N.getEmissionKind() <= DICompileUnit::LastEmissionKind),
"invalid emission kind", &N);
if (auto *Array = N.getRawEnumTypes()) {
AssertDI(isa<MDTuple>(Array), "invalid enum list", &N, Array);
for (Metadata *Op : N.getEnumTypes()->operands()) {
auto *Enum = dyn_cast_or_null<DICompositeType>(Op);
AssertDI(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type,
"invalid enum type", &N, N.getEnumTypes(), Op);
}
}
if (auto *Array = N.getRawRetainedTypes()) {
AssertDI(isa<MDTuple>(Array), "invalid retained type list", &N, Array);
for (Metadata *Op : N.getRetainedTypes()->operands()) {
AssertDI(Op && (isa<DIType>(Op) ||
(isa<DISubprogram>(Op) &&
!cast<DISubprogram>(Op)->isDefinition())),
"invalid retained type", &N, Op);
}
}
if (auto *Array = N.getRawGlobalVariables()) {
AssertDI(isa<MDTuple>(Array), "invalid global variable list", &N, Array);
for (Metadata *Op : N.getGlobalVariables()->operands()) {
AssertDI(Op && (isa<DIGlobalVariableExpression>(Op)),
"invalid global variable ref", &N, Op);
}
}
if (auto *Array = N.getRawImportedEntities()) {
AssertDI(isa<MDTuple>(Array), "invalid imported entity list", &N, Array);
for (Metadata *Op : N.getImportedEntities()->operands()) {
AssertDI(Op && isa<DIImportedEntity>(Op), "invalid imported entity ref",
&N, Op);
}
}
if (auto *Array = N.getRawMacros()) {
AssertDI(isa<MDTuple>(Array), "invalid macro list", &N, Array);
for (Metadata *Op : N.getMacros()->operands()) {
AssertDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op);
}
}
CUVisited.insert(&N);
}
void Verifier::visitDISubprogram(const DISubprogram &N) {
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);
else
AssertDI(N.getLine() == 0, "line specified with no file", &N, N.getLine());
if (auto *T = N.getRawType())
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())
AssertDI(isa<DISubprogram>(S) && !cast<DISubprogram>(S)->isDefinition(),
"invalid subprogram declaration", &N, S);
if (auto *RawNode = N.getRawRetainedNodes()) {
auto *Node = dyn_cast<MDTuple>(RawNode);
AssertDI(Node, "invalid retained nodes list", &N, RawNode);
for (Metadata *Op : Node->operands()) {
AssertDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op)),
"invalid retained nodes, expected DILocalVariable or DILabel",
&N, Node, Op);
}
}
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);
if (N.getFile())
verifySourceDebugInfo(*N.getUnit(), *N.getFile());
} else {
// Subprogram declarations (part of the type hierarchy).
AssertDI(!Unit, "subprogram declarations must not have a compile unit", &N);
}
if (auto *RawThrownTypes = N.getRawThrownTypes()) {
auto *ThrownTypes = dyn_cast<MDTuple>(RawThrownTypes);
AssertDI(ThrownTypes, "invalid thrown types list", &N, RawThrownTypes);
for (Metadata *Op : ThrownTypes->operands())
AssertDI(Op && isa<DIType>(Op), "invalid thrown type", &N, ThrownTypes,
Op);
}
if (N.areAllCallsDescribed())
AssertDI(N.isDefinition(),
"DIFlagAllCallsDescribed must be attached to a definition");
}
void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N);
AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),
"invalid local scope", &N, N.getRawScope());
if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope()))
AssertDI(SP->isDefinition(), "scope points into the type hierarchy", &N);
}
void Verifier::visitDILexicalBlock(const DILexicalBlock &N) {
visitDILexicalBlockBase(N);
AssertDI(N.getLine() || !N.getColumn(),
"cannot have column info without line info", &N);
}
void Verifier::visitDILexicalBlockFile(const DILexicalBlockFile &N) {
visitDILexicalBlockBase(N);
}
void Verifier::visitDICommonBlock(const DICommonBlock &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_common_block, "invalid tag", &N);
if (auto *S = N.getRawScope())
AssertDI(isa<DIScope>(S), "invalid scope ref", &N, S);
if (auto *S = N.getRawDecl())
AssertDI(isa<DIGlobalVariable>(S), "invalid declaration", &N, S);
}
void Verifier::visitDINamespace(const DINamespace &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_namespace, "invalid tag", &N);
if (auto *S = N.getRawScope())
AssertDI(isa<DIScope>(S), "invalid scope ref", &N, S);
}
void Verifier::visitDIMacro(const DIMacro &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) {
AssertDI(N.getMacinfoType() == dwarf::DW_MACINFO_start_file,
"invalid macinfo type", &N);
if (auto *F = N.getRawFile())
AssertDI(isa<DIFile>(F), "invalid file", &N, F);
if (auto *Array = N.getRawElements()) {
AssertDI(isa<MDTuple>(Array), "invalid macro list", &N, Array);
for (Metadata *Op : N.getElements()->operands()) {
AssertDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op);
}
}
}
void Verifier::visitDIModule(const DIModule &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N);
AssertDI(!N.getName().empty(), "anonymous module", &N);
}
void Verifier::visitDITemplateParameter(const DITemplateParameter &N) {
AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType());
}
void Verifier::visitDITemplateTypeParameter(const DITemplateTypeParameter &N) {
visitDITemplateParameter(N);
AssertDI(N.getTag() == dwarf::DW_TAG_template_type_parameter, "invalid tag",
&N);
}
void Verifier::visitDITemplateValueParameter(
const DITemplateValueParameter &N) {
visitDITemplateParameter(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())
AssertDI(isa<DIScope>(S), "invalid scope", &N, S);
if (auto *F = N.getRawFile())
AssertDI(isa<DIFile>(F), "invalid file", &N, F);
}
void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) {
// Checks common to all variables.
visitDIVariable(N);
AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N);
AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType());
AssertDI(N.getType(), "missing global variable type", &N);
if (auto *Member = N.getRawStaticDataMemberDeclaration()) {
AssertDI(isa<DIDerivedType>(Member),
"invalid static data member declaration", &N, Member);
}
}
void Verifier::visitDILocalVariable(const DILocalVariable &N) {
// Checks common to all variables.
visitDIVariable(N);
AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType());
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());
if (auto Ty = N.getType())
AssertDI(!isa<DISubroutineType>(Ty), "invalid type", &N, N.getType());
}
void Verifier::visitDILabel(const DILabel &N) {
if (auto *S = N.getRawScope())
AssertDI(isa<DIScope>(S), "invalid scope", &N, S);
if (auto *F = N.getRawFile())
AssertDI(isa<DIFile>(F), "invalid file", &N, F);
AssertDI(N.getTag() == dwarf::DW_TAG_label, "invalid tag", &N);
AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),
"label requires a valid scope", &N, N.getRawScope());
}
void Verifier::visitDIExpression(const DIExpression &N) {
AssertDI(N.isValid(), "invalid expression", &N);
}
void Verifier::visitDIGlobalVariableExpression(
const DIGlobalVariableExpression &GVE) {
AssertDI(GVE.getVariable(), "missing variable");
if (auto *Var = GVE.getVariable())
visitDIGlobalVariable(*Var);
if (auto *Expr = GVE.getExpression()) {
visitDIExpression(*Expr);
if (auto Fragment = Expr->getFragmentInfo())
verifyFragmentExpression(*GVE.getVariable(), *Fragment, &GVE);
}
}
void Verifier::visitDIObjCProperty(const DIObjCProperty &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_APPLE_property, "invalid tag", &N);
if (auto *T = N.getRawType())
AssertDI(isType(T), "invalid type ref", &N, T);
if (auto *F = N.getRawFile())
AssertDI(isa<DIFile>(F), "invalid file", &N, F);
}
void Verifier::visitDIImportedEntity(const DIImportedEntity &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_imported_module ||
N.getTag() == dwarf::DW_TAG_imported_declaration,
"invalid tag", &N);
if (auto *S = N.getRawScope())
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) {
// In COFF the Module is invalid if the GlobalValue has private linkage.
// Entities with private linkage don't have entries in the symbol table.
if (TT.isOSBinFormatCOFF())
if (const GlobalValue *GV = M.getNamedValue(C.getName()))
Assert(!GV->hasPrivateLinkage(),
"comdat global value has private linkage", GV);
}
void Verifier::visitModuleIdents(const Module &M) {
const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident");
if (!Idents)
return;
// 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 (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)),
("invalid value for llvm.ident metadata entry operand"
"(the operand should be a string)"),
N->getOperand(0));
}
}
void Verifier::visitModuleCommandLines(const Module &M) {
const NamedMDNode *CommandLines = M.getNamedMetadata("llvm.commandline");
if (!CommandLines)
return;
// llvm.commandline takes a list of metadata entry. Each entry has only one
// string. Scan each llvm.commandline entry and make sure that this
// requirement is met.
for (const MDNode *N : CommandLines->operands()) {
Assert(N->getNumOperands() == 1,
"incorrect number of operands in llvm.commandline metadata", N);
Assert(dyn_cast_or_null<MDString>(N->getOperand(0)),
("invalid value for llvm.commandline metadata entry operand"
"(the operand should be a string)"),
N->getOperand(0));
}
}
void Verifier::visitModuleFlags(const Module &M) {
const NamedMDNode *Flags = M.getModuleFlagsMetadata();
if (!Flags) return;
// Scan each flag, and track the flags and requirements.
DenseMap<const MDString*, const MDNode*> SeenIDs;
SmallVector<const MDNode*, 16> Requirements;
for (const MDNode *MDN : Flags->operands())
visitModuleFlag(MDN, SeenIDs, Requirements);
// Validate that the requirements in the module are valid.
for (const MDNode *Requirement : Requirements) {
const MDString *Flag = cast<MDString>(Requirement->getOperand(0));
const Metadata *ReqValue = Requirement->getOperand(1);
const MDNode *Op = SeenIDs.lookup(Flag);
if (!Op) {
CheckFailed("invalid requirement on flag, flag is not present in module",
Flag);
continue;
}
if (Op->getOperand(2) != ReqValue) {
CheckFailed(("invalid requirement on flag, "
"flag does not have the required value"),
Flag);
continue;
}
}
}
void
Verifier::visitModuleFlag(const MDNode *Op,
DenseMap<const MDString *, const MDNode *> &SeenIDs,
SmallVectorImpl<const MDNode *> &Requirements) {
// Each module flag should have three arguments, the merge behavior (a
// constant int), the flag ID (an MDString), and the value.
Assert(Op->getNumOperands() == 3,
"incorrect number of operands in module flag", Op);
Module::ModFlagBehavior MFB;
if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) {
Assert(
mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0)),
"invalid behavior operand in module flag (expected constant integer)",
Op->getOperand(0));
Assert(false,
"invalid behavior operand in module flag (unexpected constant)",
Op->getOperand(0));
}
MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1));
Assert(ID, "invalid ID operand in module flag (expected metadata string)",
Op->getOperand(1));
// Sanity check the values for behaviors with additional requirements.
switch (MFB) {
case Module::Error:
case Module::Warning:
case Module::Override:
// These behavior types accept any value.
break;
case Module::Max: {
Assert(mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)),
"invalid value for 'max' module flag (expected constant integer)",
Op->getOperand(2));
break;
}
case Module::Require: {
// The value should itself be an MDNode with two operands, a flag ID (an
// MDString), and a value.
MDNode *Value = dyn_cast<MDNode>(Op->getOperand(2));
Assert(Value && Value->getNumOperands() == 2,
"invalid value for 'require' module flag (expected metadata pair)",
Op->getOperand(2));
Assert(isa<MDString>(Value->getOperand(0)),
("invalid value for 'require' module flag "
"(first value operand should be a string)"),
Value->getOperand(0));
// Append it to the list of requirements, to check once all module flags are
// scanned.
Requirements.push_back(Value);
break;
}
case Module::Append:
case Module::AppendUnique: {
// These behavior types require the operand be an MDNode.
Assert(isa<MDNode>(Op->getOperand(2)),
"invalid value for 'append'-type module flag "
"(expected a metadata node)",
Op->getOperand(2));
break;
}
}
// Unless this is a "requires" flag, check the ID is unique.
if (MFB != Module::Require) {
bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second;
Assert(Inserted,
"module flag identifiers must be unique (or of 'require' type)", ID);
}
if (ID->getString() == "wchar_size") {
ConstantInt *Value
= mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2));
Assert(Value, "wchar_size metadata requires constant integer argument");
}
if (ID->getString() == "Linker Options") {
// If the llvm.linker.options named metadata exists, we assume that the
// bitcode reader has upgraded the module flag. Otherwise the flag might
// have been created by a client directly.
Assert(M.getNamedMetadata("llvm.linker.options"),
"'Linker Options' named metadata no longer supported");
}
if (ID->getString() == "CG Profile") {
for (const MDOperand &MDO : cast<MDNode>(Op->getOperand(2))->operands())
visitModuleFlagCGProfileEntry(MDO);
}
}
void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) {
auto CheckFunction = [&](const MDOperand &FuncMDO) {
if (!FuncMDO)
return;
auto F = dyn_cast<ValueAsMetadata>(FuncMDO);
Assert(F && isa<Function>(F->getValue()), "expected a Function or null",
FuncMDO);
};
auto Node = dyn_cast_or_null<MDNode>(MDO);
Assert(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO);
CheckFunction(Node->getOperand(0));
CheckFunction(Node->getOperand(1));
auto Count = dyn_cast_or_null<ConstantAsMetadata>(Node->getOperand(2));
Assert(Count && Count->getType()->isIntegerTy(),
"expected an integer constant", Node->getOperand(2));
}
/// Return true if this attribute kind only applies to functions.
static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
switch (Kind) {
case Attribute::NoReturn:
case Attribute::NoSync:
case Attribute::WillReturn:
case Attribute::NoCfCheck:
case Attribute::NoUnwind:
case Attribute::NoInline:
case Attribute::AlwaysInline:
case Attribute::OptimizeForSize:
case Attribute::StackProtect:
case Attribute::StackProtectReq:
case Attribute::StackProtectStrong:
case Attribute::SafeStack:
case Attribute::ShadowCallStack:
case Attribute::NoRedZone:
case Attribute::NoImplicitFloat:
case Attribute::Naked:
case Attribute::InlineHint:
case Attribute::StackAlignment:
case Attribute::UWTable:
case Attribute::NonLazyBind:
case Attribute::ReturnsTwice:
case Attribute::SanitizeAddress:
case Attribute::SanitizeHWAddress:
case Attribute::SanitizeMemTag:
case Attribute::SanitizeThread:
case Attribute::SanitizeMemory:
case Attribute::MinSize:
case Attribute::NoDuplicate:
case Attribute::Builtin:
case Attribute::NoBuiltin:
case Attribute::Cold:
case Attribute::OptForFuzzing:
case Attribute::OptimizeNone:
case Attribute::JumpTable:
case Attribute::Convergent:
case Attribute::ArgMemOnly:
case Attribute::NoRecurse:
case Attribute::InaccessibleMemOnly:
case Attribute::InaccessibleMemOrArgMemOnly:
case Attribute::AllocSize:
case Attribute::SpeculativeLoadHardening:
case Attribute::Speculatable:
case Attribute::StrictFP:
return true;
default:
break;
}
return false;
}
/// Return true if this is a function attribute that can also appear on
/// arguments.
static bool isFuncOrArgAttr(Attribute::AttrKind Kind) {
return Kind == Attribute::ReadOnly || Kind == Attribute::WriteOnly ||
Kind == Attribute::ReadNone || Kind == Attribute::NoFree;
}
void Verifier::verifyAttributeTypes(AttributeSet Attrs, bool IsFunction,
const Value *V) {
for (Attribute A : Attrs) {
if (A.isStringAttribute())
continue;
if (isFuncOnlyAttr(A.getKindAsEnum())) {
if (!IsFunction) {
CheckFailed("Attribute '" + A.getAsString() +
"' only applies to functions!",
V);
return;
}
} else if (IsFunction && !isFuncOrArgAttr(A.getKindAsEnum())) {
CheckFailed("Attribute '" + A.getAsString() +
"' does not apply to functions!",
V);
return;
}
}
}
// 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, Type *Ty,
const Value *V) {
if (!Attrs.hasAttributes())
return;
verifyAttributeTypes(Attrs, /*IsFunction=*/false, V);
if (Attrs.hasAttribute(Attribute::ImmArg)) {
Assert(Attrs.getNumAttributes() == 1,
"Attribute 'immarg' is incompatible with other attributes", V);
}
// Check for mutually incompatible attributes. Only inreg is compatible with
// sret.
unsigned AttrCount = 0;
AttrCount += Attrs.hasAttribute(Attribute::ByVal);
AttrCount += Attrs.hasAttribute(Attribute::InAlloca);
AttrCount += Attrs.hasAttribute(Attribute::StructRet) ||
Attrs.hasAttribute(Attribute::InReg);
AttrCount += Attrs.hasAttribute(Attribute::Nest);
Assert(AttrCount <= 1, "Attributes 'byval', 'inalloca', 'inreg', 'nest', "
"and 'sret' are incompatible!",
V);
Assert(!(Attrs.hasAttribute(Attribute::InAlloca) &&
Attrs.hasAttribute(Attribute::ReadOnly)),
"Attributes "
"'inalloca and readonly' are incompatible!",
V);
Assert(!(Attrs.hasAttribute(Attribute::StructRet) &&
Attrs.hasAttribute(Attribute::Returned)),
"Attributes "
"'sret and returned' are incompatible!",
V);
Assert(!(Attrs.hasAttribute(Attribute::ZExt) &&
Attrs.hasAttribute(Attribute::SExt)),
"Attributes "
"'zeroext and signext' are incompatible!",
V);
Assert(!(Attrs.hasAttribute(Attribute::ReadNone) &&
Attrs.hasAttribute(Attribute::ReadOnly)),
"Attributes "
"'readnone and readonly' are incompatible!",
V);
Assert(!(Attrs.hasAttribute(Attribute::ReadNone) &&
Attrs.hasAttribute(Attribute::WriteOnly)),
"Attributes "
"'readnone and writeonly' are incompatible!",
V);
Assert(!(Attrs.hasAttribute(Attribute::ReadOnly) &&
Attrs.hasAttribute(Attribute::WriteOnly)),
"Attributes "
"'readonly and writeonly' are incompatible!",
V);
Assert(!(Attrs.hasAttribute(Attribute::NoInline) &&
Attrs.hasAttribute(Attribute::AlwaysInline)),
"Attributes "
"'noinline and alwaysinline' are incompatible!",
V);
if (Attrs.hasAttribute(Attribute::ByVal) && Attrs.getByValType()) {
Assert(Attrs.getByValType() == cast<PointerType>(Ty)->getElementType(),
"Attribute 'byval' type does not match parameter!", V);
}
AttrBuilder IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty);
Assert(!AttrBuilder(Attrs).overlaps(IncompatibleAttrs),
"Wrong types for attribute: " +
AttributeSet::get(Context, IncompatibleAttrs).getAsString(),
V);
if (PointerType *PTy = dyn_cast<PointerType>(Ty)) {
SmallPtrSet<Type*, 4> Visited;
if (!PTy->getElementType()->isSized(&Visited)) {
Assert(!Attrs.hasAttribute(Attribute::ByVal) &&
!Attrs.hasAttribute(Attribute::InAlloca),
"Attributes 'byval' and 'inalloca' do not support unsized types!",
V);
}
if (!isa<PointerType>(PTy->getElementType()))
Assert(!Attrs.hasAttribute(Attribute::SwiftError),
"Attribute 'swifterror' only applies to parameters "
"with pointer to pointer type!",
V);
} else {
Assert(!Attrs.hasAttribute(Attribute::ByVal),
"Attribute 'byval' only applies to parameters with pointer type!",
V);
Assert(!Attrs.hasAttribute(Attribute::SwiftError),
"Attribute 'swifterror' only applies to parameters "
"with pointer type!",
V);
}
}
// Check parameter attributes against a function type.
// The value V is printed in error messages.
void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
const Value *V, bool IsIntrinsic) {
if (Attrs.isEmpty())
return;
bool SawNest = false;
bool SawReturned = false;
bool SawSRet = false;
bool SawSwiftSelf = false;
bool SawSwiftError = false;
// Verify return value attributes.
AttributeSet RetAttrs = Attrs.getRetAttributes();
Assert((!RetAttrs.hasAttribute(Attribute::ByVal) &&
!RetAttrs.hasAttribute(Attribute::Nest) &&
!RetAttrs.hasAttribute(Attribute::StructRet) &&
!RetAttrs.hasAttribute(Attribute::NoCapture) &&
!RetAttrs.hasAttribute(Attribute::NoFree) &&
!RetAttrs.hasAttribute(Attribute::Returned) &&
!RetAttrs.hasAttribute(Attribute::InAlloca) &&
!RetAttrs.hasAttribute(Attribute::SwiftSelf) &&
!RetAttrs.hasAttribute(Attribute::SwiftError)),
"Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', 'nofree'"
"'returned', 'swiftself', and 'swifterror' do not apply to return "
"values!",
V);
Assert((!RetAttrs.hasAttribute(Attribute::ReadOnly) &&
!RetAttrs.hasAttribute(Attribute::WriteOnly) &&
!RetAttrs.hasAttribute(Attribute::ReadNone)),
"Attribute '" + RetAttrs.getAsString() +
"' does not apply to function returns",
V);
verifyParameterAttrs(RetAttrs, FT->getReturnType(), V);
// Verify parameter attributes.
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
Type *Ty = FT->getParamType(i);
AttributeSet ArgAttrs = Attrs.getParamAttributes(i);
if (!IsIntrinsic) {
Assert(!ArgAttrs.hasAttribute(Attribute::ImmArg),
"immarg attribute only applies to intrinsics",V);
}
verifyParameterAttrs(ArgAttrs, Ty, V);
if (ArgAttrs.hasAttribute(Attribute::Nest)) {
Assert(!SawNest, "More than one parameter has attribute nest!", V);
SawNest = true;
}
if (ArgAttrs.hasAttribute(Attribute::Returned)) {
Assert(!SawReturned, "More than one parameter has attribute returned!",
V);
Assert(Ty->canLosslesslyBitCastTo(FT->getReturnType()),
"Incompatible argument and return types for 'returned' attribute",
V);
SawReturned = true;
}
if (ArgAttrs.hasAttribute(Attribute::StructRet)) {
Assert(!SawSRet, "Cannot have multiple 'sret' parameters!", V);
Assert(i == 0 || i == 1,
"Attribute 'sret' is not on first or second parameter!", V);
SawSRet = true;
}
if (ArgAttrs.hasAttribute(Attribute::SwiftSelf)) {
Assert(!SawSwiftSelf, "Cannot have multiple 'swiftself' parameters!", V);
SawSwiftSelf = true;
}
if (ArgAttrs.hasAttribute(Attribute::SwiftError)) {
Assert(!SawSwiftError, "Cannot have multiple 'swifterror' parameters!",
V);
SawSwiftError = true;
}
if (ArgAttrs.hasAttribute(Attribute::InAlloca)) {
Assert(i == FT->getNumParams() - 1,
"inalloca isn't on the last parameter!", V);
}
}
if (!Attrs.hasAttributes(AttributeList::FunctionIndex))
return;
verifyAttributeTypes(Attrs.getFnAttributes(), /*IsFunction=*/true, V);
Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&
Attrs.hasFnAttribute(Attribute::ReadOnly)),
"Attributes 'readnone and readonly' are incompatible!", V);
Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&
Attrs.hasFnAttribute(Attribute::WriteOnly)),
"Attributes 'readnone and writeonly' are incompatible!", V);
Assert(!(Attrs.hasFnAttribute(Attribute::ReadOnly) &&
Attrs.hasFnAttribute(Attribute::WriteOnly)),
"Attributes 'readonly and writeonly' are incompatible!", V);
Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&
Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly)),
"Attributes 'readnone and inaccessiblemem_or_argmemonly' are "
"incompatible!",
V);
Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&
Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)),
"Attributes 'readnone and inaccessiblememonly' are incompatible!", V);
Assert(!(Attrs.hasFnAttribute(Attribute::NoInline) &&
Attrs.hasFnAttribute(Attribute::AlwaysInline)),
"Attributes 'noinline and alwaysinline' are incompatible!", V);
if (Attrs.hasFnAttribute(Attribute::OptimizeNone)) {
Assert(Attrs.hasFnAttribute(Attribute::NoInline),
"Attribute 'optnone' requires 'noinline'!", V);
Assert(!Attrs.hasFnAttribute(Attribute::OptimizeForSize),
"Attributes 'optsize and optnone' are incompatible!", V);
Assert(!Attrs.hasFnAttribute(Attribute::MinSize),
"Attributes 'minsize and optnone' are incompatible!", V);
}
if (Attrs.hasFnAttribute(Attribute::JumpTable)) {
const GlobalValue *GV = cast<GlobalValue>(V);
Assert(GV->hasGlobalUnnamedAddr(),
"Attribute 'jumptable' requires 'unnamed_addr'", V);
}
if (Attrs.hasFnAttribute(Attribute::AllocSize)) {
std::pair<unsigned, Optional<unsigned>> Args =
Attrs.getAllocSizeArgs(AttributeList::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;
if (Args.second && !CheckParam("number of elements", *Args.second))
return;
}
if (Attrs.hasFnAttribute("frame-pointer")) {
StringRef FP = Attrs.getAttribute(AttributeList::FunctionIndex,
"frame-pointer").getValueAsString();
if (FP != "all" && FP != "non-leaf" && FP != "none")
CheckFailed("invalid value for 'frame-pointer' attribute: " + FP, V);
}
if (Attrs.hasFnAttribute("patchable-function-prefix")) {
StringRef S = Attrs
.getAttribute(AttributeList::FunctionIndex,
"patchable-function-prefix")
.getValueAsString();
unsigned N;
if (S.getAsInteger(10, N))
CheckFailed(
"\"patchable-function-prefix\" takes an unsigned integer: " + S, V);
}
if (Attrs.hasFnAttribute("patchable-function-entry")) {
StringRef S = Attrs
.getAttribute(AttributeList::FunctionIndex,
"patchable-function-entry")
.getValueAsString();
unsigned N;
if (S.getAsInteger(10, N))
CheckFailed(
"\"patchable-function-entry\" takes an unsigned integer: " + S, V);
}
}
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 no less than 2 operands", MD);
// Check first operand.
Assert(MD->getOperand(0) != nullptr, "first operand should not be null",
MD);
Assert(isa<MDString>(MD->getOperand(0)),
"expected string with name of the !prof annotation", MD);
MDString *MDS = cast<MDString>(MD->getOperand(0));
StringRef ProfName = MDS->getString();
Assert(ProfName.equals("function_entry_count") ||
ProfName.equals("synthetic_function_entry_count"),
"first operand should be 'function_entry_count'"
" or 'synthetic_function_entry_count'",
MD);
// Check second operand.
Assert(MD->getOperand(1) != nullptr, "second operand should not be null",
MD);
Assert(isa<ConstantAsMetadata>(MD->getOperand(1)),
"expected integer argument to function_entry_count", MD);
}
}
}
void Verifier::visitConstantExprsRecursively(const Constant *EntryC) {
if (!ConstantExprVisited.insert(EntryC).second)
return;
SmallVector<const Constant *, 16> Stack;
Stack.push_back(EntryC);
while (!Stack.empty()) {
const Constant *C = Stack.pop_back_val();
// Check this constant expression.
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 (!ConstantExprVisited.insert(OpC).second)
continue;
Stack.push_back(OpC);
}
}
}
void Verifier::visitConstantExpr(const ConstantExpr *CE) {
if (CE->getOpcode() == Instruction::BitCast)
Assert(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0),
CE->getType()),
"Invalid bitcast", CE);
if (CE->getOpcode() == Instruction::IntToPtr ||
CE->getOpcode() == Instruction::PtrToInt) {
auto *PtrTy = CE->getOpcode() == Instruction::IntToPtr
? CE->getType()
: CE->getOperand(0)->getType();
StringRef Msg = CE->getOpcode() == Instruction::IntToPtr
? "inttoptr not supported for non-integral pointers"
: "ptrtoint not supported for non-integral pointers";
Assert(
!DL.isNonIntegralPointerType(cast<PointerType>(PtrTy->getScalarType())),
Msg);
}
}
bool Verifier::verifyAttributeCount(AttributeList Attrs, unsigned Params) {
// There shouldn't be more attribute sets than there are parameters plus the
// function and return value.
return Attrs.getNumAttrSets() <= Params + 2;
}
/// Verify that statepoint intrinsic is well formed.
void Verifier::verifyStatepoint(const CallBase &Call) {
assert(Call.getCalledFunction() &&
Call.getCalledFunction()->getIntrinsicID() ==
Intrinsic::experimental_gc_statepoint);
Assert(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory() &&
!Call.onlyAccessesArgMemory(),
"gc.statepoint must read and write all memory to preserve "
"reordering restrictions required by safepoint semantics",
Call);
const int64_t NumPatchBytes =
cast<ConstantInt>(Call.getArgOperand(1))->getSExtValue();
assert(isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!");
Assert(NumPatchBytes >= 0,
"gc.statepoint number of patchable bytes must be "
"positive",
Call);
const Value *Target = Call.getArgOperand(2);
auto *PT = dyn_cast<PointerType>(Target->getType());
Assert(PT && PT->getElementType()->isFunctionTy(),
"gc.statepoint callee must be of function pointer type", Call, Target);
FunctionType *TargetFuncType = cast<FunctionType>(PT->getElementType());
const int NumCallArgs = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue();
Assert(NumCallArgs >= 0,
"gc.statepoint number of arguments to underlying call "
"must be positive",
Call);
const int NumParams = (int)TargetFuncType->getNumParams();
if (TargetFuncType->isVarArg()) {
Assert(NumCallArgs >= NumParams,
"gc.statepoint mismatch in number of vararg call args", Call);
// TODO: Remove this limitation
Assert(TargetFuncType->getReturnType()->isVoidTy(),
"gc.statepoint doesn't support wrapping non-void "
"vararg functions yet",
Call);
} else
Assert(NumCallArgs == NumParams,
"gc.statepoint mismatch in number of call args", Call);
const uint64_t Flags
= cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue();
Assert((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0,
"unknown flag used in gc.statepoint flags argument", Call);
// Verify that the types of the call parameter arguments match
// the type of the wrapped callee.
AttributeList Attrs = Call.getAttributes();
for (int i = 0; i < NumParams; i++) {
Type *ParamType = TargetFuncType->getParamType(i);
Type *ArgType = Call.getArgOperand(5 + i)->getType();
Assert(ArgType == ParamType,
"gc.statepoint call argument does not match wrapped "
"function type",
Call);
if (TargetFuncType->isVarArg()) {
AttributeSet ArgAttrs = Attrs.getParamAttributes(5 + i);
Assert(!ArgAttrs.hasAttribute(Attribute::StructRet),
"Attribute 'sret' cannot be used for vararg call arguments!",
Call);
}
}
const int EndCallArgsInx = 4 + NumCallArgs;
const Value *NumTransitionArgsV = Call.getArgOperand(EndCallArgsInx + 1);
Assert(isa<ConstantInt>(NumTransitionArgsV),
"gc.statepoint number of transition arguments "
"must be constant integer",
Call);
const int NumTransitionArgs =
cast<ConstantInt>(NumTransitionArgsV)->getZExtValue();
Assert(NumTransitionArgs >= 0,
"gc.statepoint number of transition arguments must be positive", Call);
const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs;
const Value *NumDeoptArgsV = Call.getArgOperand(EndTransitionArgsInx + 1);
Assert(isa<ConstantInt>(NumDeoptArgsV),
"gc.statepoint number of deoptimization arguments "
"must be constant integer",
Call);
const int NumDeoptArgs = cast<ConstantInt>(NumDeoptArgsV)->getZExtValue();
Assert(NumDeoptArgs >= 0,
"gc.statepoint number of deoptimization arguments "
"must be positive",
Call);
const int ExpectedNumArgs =
7 + NumCallArgs + NumTransitionArgs + NumDeoptArgs;
Assert(ExpectedNumArgs <= (int)Call.arg_size(),
"gc.statepoint too few arguments according to length fields", Call);
// Check that the only uses of this gc.statepoint are gc.result or
// gc.relocate calls which are tied to this statepoint and thus part
// of the same statepoint sequence
for (const User *U : Call.users()) {
const CallInst *UserCall = dyn_cast<const CallInst>(U);
Assert(UserCall, "illegal use of statepoint token", Call, U);
if (!UserCall)
continue;
Assert(isa<GCRelocateInst>(UserCall) || isa<GCResultInst>(UserCall),
"gc.result or gc.relocate are the only value uses "
"of a gc.statepoint",
Call, U);
if (isa<GCResultInst>(UserCall)) {
Assert(UserCall->getArgOperand(0) == &Call,
"gc.result connected to wrong gc.statepoint", Call, UserCall);
} else if (isa<GCRelocateInst>(Call)) {
Assert(UserCall->getArgOperand(0) == &Call,
"gc.relocate connected to wrong gc.statepoint", Call, UserCall);
}
}
// Note: It is legal for a single derived pointer to be listed multiple
// times. It's non-optimal, but it is legal. It can also happen after
// insertion if we strip a bitcast away.
// Note: It is really tempting to check that each base is relocated and
// that a derived pointer is never reused as a base pointer. This turns
// out to be problematic since optimizations run after safepoint insertion
// can recognize equality properties that the insertion logic doesn't know
// about. See example statepoint.ll in the verifier subdirectory
}
void Verifier::verifyFrameRecoverIndices() {
for (auto &Counts : FrameEscapeInfo) {
Function *F = Counts.first;
unsigned EscapedObjectCount = Counts.second.first;
unsigned MaxRecoveredIndex = Counts.second.second;
Assert(MaxRecoveredIndex <= EscapedObjectCount,
"all indices passed to llvm.localrecover must be less than the "
"number of arguments passed to llvm.localescape in the parent "
"function",
F);
}
}
static Instruction *getSuccPad(Instruction *Terminator) {
BasicBlock *UnwindDest;
if (auto *II = dyn_cast<InvokeInst>(Terminator))
UnwindDest = II->getUnwindDest();
else if (auto *CSI = dyn_cast<CatchSwitchInst>(Terminator))
UnwindDest = CSI->getUnwindDest();
else
UnwindDest = cast<CleanupReturnInst>(Terminator)->getUnwindDest();
return UnwindDest->getFirstNonPHI();
}
void Verifier::verifySiblingFuncletUnwinds() {
SmallPtrSet<Instruction *, 8> Visited;
SmallPtrSet<Instruction *, 8> Active;
for (const auto &Pair : SiblingFuncletInfo) {
Instruction *PredPad = Pair.first;
if (Visited.count(PredPad))
continue;
Active.insert(PredPad);
Instruction *Terminator = Pair.second;
do {
Instruction *SuccPad = getSuccPad(Terminator);
if (Active.count(SuccPad)) {
// Found a cycle; report error
Instruction *CyclePad = SuccPad;
SmallVector<Instruction *, 8> CycleNodes;
do {
CycleNodes.push_back(CyclePad);
Instruction *CycleTerminator = SiblingFuncletInfo[CyclePad];
if (CycleTerminator != CyclePad)
CycleNodes.push_back(CycleTerminator);
CyclePad = getSuccPad(CycleTerminator);
} while (CyclePad != SuccPad);
Assert(false, "EH pads can't handle each other's exceptions",
ArrayRef<Instruction *>(CycleNodes));
}
// Don't re-walk a node we've already checked
if (!Visited.insert(SuccPad).second)
break;
// Walk to this successor if it has a map entry.
PredPad = SuccPad;
auto TermI = SiblingFuncletInfo.find(PredPad);
if (TermI == SiblingFuncletInfo.end())
break;
Terminator = TermI->second;
Active.insert(PredPad);
} while (true);
// Each node only has one successor, so we've walked all the active
// nodes' successors.
Active.clear();
}
}
// 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();
Assert(&Context == &F.getContext(),
"Function context does not match Module context!", &F);
Assert(!F.hasCommonLinkage(), "Functions may not have common linkage", &F);
Assert(FT->getNumParams() == NumArgs,
"# formal arguments must match # of arguments for function type!", &F,
FT);
Assert(F.getReturnType()->isFirstClassType() ||
F.getReturnType()->isVoidTy() || F.getReturnType()->isStructTy(),
"Functions cannot return aggregate values!", &F);
Assert(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(),
"Invalid struct return type!", &F);
AttributeList Attrs = F.getAttributes();
Assert(verifyAttributeCount(Attrs, FT->getNumParams()),
"Attribute after last parameter!", &F);
bool isLLVMdotName = F.getName().size() >= 5 &&
F.getName().substr(0, 5) == "llvm.";
// Check function attributes.
verifyFunctionAttrs(FT, Attrs, &F, isLLVMdotName);
// On function declarations/definitions, we do not support the builtin
// attribute. We do not check this in VerifyFunctionAttrs since that is
// checking for Attributes that can/can not ever be on functions.
Assert(!Attrs.hasFnAttribute(Attribute::Builtin),
"Attribute 'builtin' can only be applied to a callsite.", &F);
// Check that this function meets the restrictions on this calling convention.
// Sometimes varargs is used for perfectly forwarding thunks, so some of these
// restrictions can be lifted.
switch (F.getCallingConv()) {
default:
case CallingConv::C:
break;
case CallingConv::AMDGPU_KERNEL:
case CallingConv::SPIR_KERNEL:
Assert(F.getReturnType()->isVoidTy(),
"Calling convention requires void return type", &F);
LLVM_FALLTHROUGH;
case CallingConv::AMDGPU_VS:
case CallingConv::AMDGPU_HS:
case CallingConv::AMDGPU_GS:
case CallingConv::AMDGPU_PS:
case CallingConv::AMDGPU_CS:
Assert(!F.hasStructRetAttr(),
"Calling convention does not allow sret", &F);
LLVM_FALLTHROUGH;
case CallingConv::Fast:
case CallingConv::Cold:
case CallingConv::Intel_OCL_BI:
case CallingConv::PTX_Kernel:
case CallingConv::PTX_Device:
Assert(!F.isVarArg(), "Calling convention does not support varargs or "
"perfect forwarding!",
&F);
break;
}
// Check that the argument values match the function type for this function...
unsigned i = 0;
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(Arg.getType()->isFirstClassType(),
"Function arguments must have first-class types!", &Arg);
if (!isLLVMdotName) {
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.hasParamAttribute(i, Attribute::SwiftError)) {
verifySwiftErrorValue(&Arg);
}
++i;
}
if (!isLLVMdotName)
Assert(!F.getReturnType()->isTokenTy(),
"Functions returns a token but isn't an intrinsic", &F);
// Get the function metadata attachments.
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
F.getAllMetadata(MDs);
assert(F.hasMetadata() != MDs.empty() && "Bit out-of-sync");
verifyFunctionMetadata(MDs);
// Check validity of the personality function
if (F.hasPersonalityFn()) {
auto *Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
if (Per)
Assert(Per->getParent() == F.getParent(),
"Referencing personality function in another module!",
&F, F.getParent(), Per, Per->getParent());
}
if (F.isMaterializable()) {
// Function has a body somewhere we can't see.
Assert(MDs.empty(), "unmaterialized function cannot have metadata", &F,
MDs.empty() ? nullptr : MDs.front().second);
} else if (F.isDeclaration()) {
for (const auto &I : MDs) {
// This is used for call site debug information.
AssertDI(I.first != LLVMContext::MD_dbg ||
!cast<DISubprogram>(I.second)->isDistinct(),
"function declaration may only have a unique !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 {
// Verify that this function (which has a body) is not named "llvm.*". It
// is not legal to define intrinsics.
Assert(!isLLVMdotName, "llvm intrinsics cannot be defined!", &F);
// Check the entry node
const BasicBlock *Entry = &F.getEntryBlock();
Assert(pred_empty(Entry),
"Entry block to function must not have predecessors!", Entry);
// The address of the entry block cannot be taken, unless it is dead.
if (Entry->hasAddressTaken()) {
Assert(!BlockAddress::lookup(Entry)->isConstantUsed(),
"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.
switch (I.first) {
default:
break;
case LLVMContext::MD_dbg: {
++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);
auto *SP = cast<DISubprogram>(I.second);
const Function *&AttachedTo = DISubprogramAttachments[SP];
AssertDI(!AttachedTo || AttachedTo == &F,
"DISubprogram attached to more than one function", SP, &F);
AttachedTo = &F;
break;
}
case LLVMContext::MD_prof:
++NumProfAttachments;
Assert(NumProfAttachments == 1,
"function must have a single !prof attachment", &F, I.second);
break;
}
// Verify the metadata itself.
visitMDNode(*I.second);
}
}
// If this function is actually an intrinsic, verify that it is only used in
// direct call/invokes, never having its "address taken".
// Only do this if the module is materialized, otherwise we don't have all the
// uses.
if (F.getIntrinsicID() && F.getParent()->isMaterialized()) {
const User *U;
if (F.hasAddressTaken(&U))
Assert(false, "Invalid user of intrinsic instruction!", U);
}
auto *N = F.getSubprogram();
HasDebugInfo = (N != nullptr);
if (!HasDebugInfo)
return;
// Check that all !dbg attachments lead to back to N (or, at least, another
// subprogram that describes the same function).
//
// FIXME: Check this incrementally while visiting !dbg attachments.
// FIXME: Only check when N is the canonical subprogram for F.
SmallPtrSet<const MDNode *, 32> Seen;
auto VisitDebugLoc = [&](const Instruction &I, const MDNode *Node) {
// Be careful about using DILocation here since we might be dealing with
// broken code (this is the Verifier after all).
const DILocation *DL = dyn_cast_or_null<DILocation>(Node);
if (!DL)
return;
if (!Seen.insert(DL).second)
return;
Metadata *Parent = DL->getRawScope();
AssertDI(Parent && isa<DILocalScope>(Parent),
"DILocation's scope must be a DILocalScope", N, &F, &I, DL,
Parent);
DILocalScope *Scope = DL->getInlinedAtScope();
if (Scope && !Seen.insert(Scope).second)
return;
DISubprogram *SP = Scope ? Scope->getSubprogram() : nullptr;
// Scope and SP could be the same MDNode and we don't want to skip
// validation in that case
if (SP && ((Scope != SP) && !Seen.insert(SP).second))
return;
// FIXME: Once N is canonical, check "SP == &N".
AssertDI(SP->describes(&F),
"!dbg attachment points at wrong subprogram for function", N, &F,
&I, DL, Scope, SP);
};
for (auto &BB : F)
for (auto &I : BB) {
VisitDebugLoc(I, I.getDebugLoc().getAsMDNode());
// The llvm.loop annotations also contain two DILocations.
if (auto MD = I.getMetadata(LLVMContext::MD_loop))
for (unsigned i = 1; i < MD->getNumOperands(); ++i)
VisitDebugLoc(I, dyn_cast_or_null<MDNode>(MD->getOperand(i)));
if (BrokenDebugInfo)
return;
}
}
// verifyBasicBlock - Verify that a basic block is well formed...
//
void Verifier::visitBasicBlock(BasicBlock &BB) {
InstsInThisBlock.clear();
// Ensure that basic blocks have terminators!
Assert(BB.getTerminator(), "Basic Block does not have terminator!", &BB);
// Check constraints that this basic block imposes on all of the PHI nodes in
// it.
if (isa<PHINode>(BB.front())) {
SmallVector<BasicBlock*, 8> Preds(pred_begin(&BB), pred_end(&BB));
SmallVector<std::pair<BasicBlock*, Value*>, 8> Values;
llvm::sort(Preds);
for (const PHINode &PN : BB.phis()) {
// Ensure that PHI nodes have at least one entry!
Assert(PN.getNumIncomingValues() != 0,
"PHI nodes must have at least one entry. If the block is dead, "
"the PHI should be removed!",
&PN);
Assert(PN.getNumIncomingValues() == Preds.size(),
"PHINode should have one entry for each predecessor of its "
"parent basic block!",
&PN);
// Get and sort all incoming values in the PHI node...
Values.clear();
Values.reserve(PN.getNumIncomingValues());
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
Values.push_back(
std::make_pair(PN.getIncomingBlock(i), PN.getIncomingValue(i)));
llvm::sort(Values);
for (unsigned i = 0, e = Values.size(); i != e; ++i) {
// Check to make sure that if there is more than one entry for a
// particular basic block in this PHI node, that the incoming values are
// all identical.
//
Assert(i == 0 || Values[i].first != Values[i - 1].first ||
Values[i].second == Values[i - 1].second,
"PHI node has multiple entries for the same basic block with "
"different incoming values!",
&PN, Values[i].first, Values[i].second, Values[i - 1].second);
// Check to make sure that the predecessors and PHI node entries are
// matched up.
Assert(Values[i].first == Preds[i],
"PHI node entries do not match predecessors!", &PN,
Values[i].first, Preds[i]);
}
}
}
// Check that all instructions have their parent pointers set up correctly.
for (auto &I : BB)
{
Assert(I.getParent() == &BB, "Instruction has bogus parent pointer!");
}
}
void Verifier::visitTerminator(Instruction &I) {
// Ensure that terminators only exist at the end of the basic block.
Assert(&I == I.getParent()->getTerminator(),
"Terminator found in the middle of a basic block!", I.getParent());
visitInstruction(I);
}
void Verifier::visitBranchInst(BranchInst &BI) {
if (BI.isConditional()) {
Assert(BI.getCondition()->getType()->isIntegerTy(1),
"Branch condition is not 'i1' type!", &BI, BI.getCondition());
}
visitTerminator(BI);
}
void Verifier::visitReturnInst(ReturnInst &RI) {
Function *F = RI.getParent()->getParent();
unsigned N = RI.getNumOperands();
if (F->getReturnType()->isVoidTy())
Assert(N == 0,
"Found return instr that returns non-void in Function of void "
"return type!",
&RI, F->getReturnType());
else
Assert(N == 1 && F->getReturnType() == RI.getOperand(0)->getType(),
"Function return type does not match operand "
"type of return inst!",
&RI, F->getReturnType());
// Check to make sure that the return value has necessary properties for
// terminators...
visitTerminator(RI);
}
void Verifier::visitSwitchInst(SwitchInst &SI) {
// Check to make sure that all of the constants in the switch instruction
// have the same type as the switched-on value.
Type *SwitchTy = SI.getCondition()->getType();
SmallPtrSet<ConstantInt*, 32> Constants;
for (auto &Case : SI.cases()) {
Assert(Case.getCaseValue()->getType() == SwitchTy,
"Switch constants must all be same type as switch value!", &SI);
Assert(Constants.insert(Case.getCaseValue()).second,
"Duplicate integer as switch case", &SI, Case.getCaseValue());
}
visitTerminator(SI);
}
void Verifier::visitIndirectBrInst(IndirectBrInst &BI) {
Assert(BI.getAddress()->getType()->isPointerTy(),
"Indirectbr operand must have pointer type!", &BI);
for (unsigned i = 0, e = BI.getNumDestinations(); i != e; ++i)
Assert(BI.getDestination(i)->getType()->isLabelTy(),
"Indirectbr destinations must all have pointer type!", &BI);
visitTerminator(BI);
}
void Verifier::visitCallBrInst(CallBrInst &CBI) {
Assert(CBI.isInlineAsm(), "Callbr is currently only used for asm-goto!",
&CBI);
Assert(CBI.getType()->isVoidTy(), "Callbr return value is not supported!",
&CBI);
for (unsigned i = 0, e = CBI.getNumSuccessors(); i != e; ++i)
Assert(CBI.getSuccessor(i)->getType()->isLabelTy(),
"Callbr successors must all have pointer type!", &CBI);
for (unsigned i = 0, e = CBI.getNumOperands(); i != e; ++i) {
Assert(i >= CBI.getNumArgOperands() || !isa<BasicBlock>(CBI.getOperand(i)),
"Using an unescaped label as a callbr argument!", &CBI);
if (isa<BasicBlock>(CBI.getOperand(i)))
for (unsigned j = i + 1; j != e; ++j)
Assert(CBI.getOperand(i) != CBI.getOperand(j),
"Duplicate callbr destination!", &CBI);
}
{
SmallPtrSet<BasicBlock *, 4> ArgBBs;
for (Value *V : CBI.args())
if (auto *BA = dyn_cast<BlockAddress>(V))
ArgBBs.insert(BA->getBasicBlock());
for (BasicBlock *BB : CBI.getIndirectDests())
Assert(ArgBBs.find(BB) != ArgBBs.end(),
"Indirect label missing from arglist.", &CBI);
}
visitTerminator(CBI);
}
void Verifier::visitSelectInst(SelectInst &SI) {
Assert(!SelectInst::areInvalidOperands(SI.getOperand(0), SI.getOperand(1),
SI.getOperand(2)),
"Invalid operands for select instruction!", &SI);
Assert(SI.getTrueValue()->getType() == SI.getType(),
"Select values must have same type as select instruction!", &SI);
visitInstruction(SI);
}
/// visitUserOp1 - User defined operators shouldn't live beyond the lifetime of
/// a pass, if any exist, it's an error.
///
void Verifier::visitUserOp1(Instruction &I) {
Assert(false, "User-defined operators should not live outside of a pass!", &I);
}
void Verifier