blob: c0bcb2acb2cf9d5099405db3c95f07dd8dc47742 [file] [log] [blame]
//===-- 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
// basic correctness 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;
static cl::opt<bool> VerifyNoAliasScopeDomination(
"verify-noalias-scope-decl-dom", cl::Hidden, cl::init(false),
cl::desc("Ensure that llvm.experimental.noalias.scope.decl for identical "
"scopes are not dominating"));
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'; }
// NOLINTNEXTLINE(readability-identifier-naming)
void Write(const Attribute *A) {
if (!A)
return;
*OS << A->getAsString() << '\n';
}
// NOLINTNEXTLINE(readability-identifier-naming)
void Write(const AttributeSet *AS) {
if (!AS)
return;
*OS << AS->getAsString() << '\n';
}
// NOLINTNEXTLINE(readability-identifier-naming)
void Write(const AttributeList *AL) {
if (!AL)
return;
AL->print(*OS);
}
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;
/// The current source language.
dwarf::SourceLanguage CurrentSourceLang = dwarf::DW_LANG_lo_user;
/// 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;
/// Cache of attribute lists verified.
SmallPtrSet<const void *, 32> AttributeListsVisited;
// 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;
SmallVector<IntrinsicInst *, 4> NoAliasScopeDecls;
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();
verifyNoAliasScopeDecl();
NoAliasScopeDecls.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 GlobalIFunc &GI : M.ifuncs())
visitGlobalIFunc(GI);
for (const NamedMDNode &NMD : M.named_metadata())
visitNamedMDNode(NMD);
for (const StringMapEntry<Comdat> &SMEC : M.getComdatSymbolTable())
visitComdat(SMEC.getValue());
visitModuleFlags();
visitModuleIdents();
visitModuleCommandLines();
verifyCompileUnits();
verifyDeoptimizeCallingConvs();
DISubprogramAttachments.clear();
return !Broken;
}
private:
/// Whether a metadata node is allowed to be, or contain, a DILocation.
enum class AreDebugLocsAllowed { No, Yes };
// Verification methods...
void visitGlobalValue(const GlobalValue &GV);
void visitGlobalVariable(const GlobalVariable &GV);
void visitGlobalAlias(const GlobalAlias &GA);
void visitGlobalIFunc(const GlobalIFunc &GI);
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, AreDebugLocsAllowed AllowLocs);
void visitMetadataAsValue(const MetadataAsValue &MD, Function *F);
void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F);
void visitComdat(const Comdat &C);
void visitModuleIdents();
void visitModuleCommandLines();
void visitModuleFlags();
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);
void visitAnnotationMetadata(MDNode *Annotation);
void visitAliasScopeMetadata(const MDNode *MD);
void visitAliasScopeListMetadata(const 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 verifyTailCCMustTailAttrs(AttrBuilder Attrs, StringRef Context);
void verifyMustTailCall(CallInst &CI);
bool verifyAttributeCount(AttributeList Attrs, unsigned Params);
void verifyAttributeTypes(AttributeSet Attrs, const Value *V);
void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V);
void checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr,
const Value *V);
void verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
const Value *V, bool IsIntrinsic);
void verifyFunctionMetadata(ArrayRef<std::pair<unsigned, MDNode *>> MDs);
template <typename T>
void verifyODRTypeAsScopeOperand(const MDNode &MD, T * = nullptr);
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();
void verifyAttachedCallBundle(const CallBase &Call,
const OperandBundleUse &BU);
/// Verify all-or-nothing property of DIFile source attribute within a CU.
void verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F);
/// Verify the llvm.experimental.noalias.scope.decl declarations
void verifyNoAliasScopeDecl();
};
} // 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);
if (const GlobalObject *GO = dyn_cast<GlobalObject>(&GV))
Assert(GO->getAlignment() <= Value::MaximumAlignment,
"huge alignment values are unsupported", GO);
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.hasExternalWeakLinkage())) ||
GV.hasAvailableExternallyLinkage(),
"Global is marked as dllimport, but not external", &GV);
}
if (GV.isImplicitDSOLocal())
Assert(GV.isDSOLocal(),
"GlobalValue with local linkage or 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);
Type *Int8Ty = Type::getInt8Ty(ETy->getContext());
Assert(ETy->isPointerTy() &&
cast<PointerType>(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty),
"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 an array containing scalable vectors,
// that will be caught by the isValidElementType methods in StructType or
// ArrayType instead.
Assert(!isa<ScalableVectorType>(GV.getValueType()),
"Globals cannot contain scalable vectors", &GV);
if (auto *STy = dyn_cast<StructType>(GV.getValueType()))
Assert(!STy->containsScalableVectorType(),
"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::visitGlobalIFunc(const GlobalIFunc &GI) {
// Pierce through ConstantExprs and GlobalAliases and check that the resolver
// has a Function
const Function *Resolver = GI.getResolverFunction();
Assert(Resolver, "IFunc must have a Function resolver", &GI);
// Check that the immediate resolver operand (prior to any bitcasts) has the
// correct type
const Type *ResolverTy = GI.getResolver()->getType();
const Type *ResolverFuncTy =
GlobalIFunc::getResolverFunctionType(GI.getValueType());
Assert(ResolverTy == ResolverFuncTy->getPointerTo(),
"IFunc resolver has incorrect type", &GI);
}
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, AreDebugLocsAllowed::Yes);
}
}
template <typename T>
void Verifier::verifyODRTypeAsScopeOperand(const MDNode &MD, T *) {
if (isa<T>(MD)) {
if (auto *N = dyn_cast_or_null<DICompositeType>(cast<T>(MD).getScope()))
// Of all the supported tags for DICompositeType(see visitDICompositeType)
// we know that enum type cannot be a scope.
AssertDI(N->getTag() != dwarf::DW_TAG_enumeration_type,
"enum type is not a scope; check enum type ODR "
"violation",
N, &MD);
}
}
void Verifier::visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs) {
// 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;
Assert(&MD.getContext() == &Context,
"MDNode context does not match Module context!", &MD);
// Makes sure when a scope operand is a ODR type, the ODR type uniquing does
// not create invalid debug metadata.
// TODO: check that the non-ODR-type scope operand is valid.
verifyODRTypeAsScopeOperand<DIType>(MD);
verifyODRTypeAsScopeOperand<DILocalScope>(MD);
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);
AssertDI(!isa<DILocation>(Op) || AllowLocs == AreDebugLocsAllowed::Yes,
"DILocation not allowed within this metadata node", &MD, Op);
if (auto *N = dyn_cast<MDNode>(Op)) {
visitMDNode(*N, AllowLocs);
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, AreDebugLocsAllowed::No);
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);
bool HasAssumedSizedArraySupport = dwarf::isFortran(CurrentSourceLang);
AssertDI(HasAssumedSizedArraySupport || N.getRawCountNode() ||
N.getRawUpperBound(),
"Subrange must contain count or upperBound", &N);
AssertDI(!N.getRawCountNode() || !N.getRawUpperBound(),
"Subrange can have any one of count or upperBound", &N);
auto *CBound = N.getRawCountNode();
AssertDI(!CBound || isa<ConstantAsMetadata>(CBound) ||
isa<DIVariable>(CBound) || isa<DIExpression>(CBound),
"Count must be signed constant or DIVariable or DIExpression", &N);
auto Count = N.getCount();
AssertDI(!Count || !Count.is<ConstantInt *>() ||
Count.get<ConstantInt *>()->getSExtValue() >= -1,
"invalid subrange count", &N);
auto *LBound = N.getRawLowerBound();
AssertDI(!LBound || isa<ConstantAsMetadata>(LBound) ||
isa<DIVariable>(LBound) || isa<DIExpression>(LBound),
"LowerBound must be signed constant or DIVariable or DIExpression",
&N);
auto *UBound = N.getRawUpperBound();
AssertDI(!UBound || isa<ConstantAsMetadata>(UBound) ||
isa<DIVariable>(UBound) || isa<DIExpression>(UBound),
"UpperBound must be signed constant or DIVariable or DIExpression",
&N);
auto *Stride = N.getRawStride();
AssertDI(!Stride || isa<ConstantAsMetadata>(Stride) ||
isa<DIVariable>(Stride) || isa<DIExpression>(Stride),
"Stride must be signed constant or DIVariable or DIExpression", &N);
}
void Verifier::visitDIGenericSubrange(const DIGenericSubrange &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_generic_subrange, "invalid tag", &N);
AssertDI(N.getRawCountNode() || N.getRawUpperBound(),
"GenericSubrange must contain count or upperBound", &N);
AssertDI(!N.getRawCountNode() || !N.getRawUpperBound(),
"GenericSubrange can have any one of count or upperBound", &N);
auto *CBound = N.getRawCountNode();
AssertDI(!CBound || isa<DIVariable>(CBound) || isa<DIExpression>(CBound),
"Count must be signed constant or DIVariable or DIExpression", &N);
auto *LBound = N.getRawLowerBound();
AssertDI(LBound, "GenericSubrange must contain lowerBound", &N);
AssertDI(isa<DIVariable>(LBound) || isa<DIExpression>(LBound),
"LowerBound must be signed constant or DIVariable or DIExpression",
&N);
auto *UBound = N.getRawUpperBound();
AssertDI(!UBound || isa<DIVariable>(UBound) || isa<DIExpression>(UBound),
"UpperBound must be signed constant or DIVariable or DIExpression",
&N);
auto *Stride = N.getRawStride();
AssertDI(Stride, "GenericSubrange must contain stride", &N);
AssertDI(isa<DIVariable>(Stride) || isa<DIExpression>(Stride),
"Stride must be signed constant or DIVariable or DIExpression", &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 ||
N.getTag() == dwarf::DW_TAG_string_type,
"invalid tag", &N);
}
void Verifier::visitDIStringType(const DIStringType &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_string_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 ||
N.getTag() == dwarf::DW_TAG_set_type,
"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());
}
if (N.getTag() == dwarf::DW_TAG_set_type) {
if (auto *T = N.getRawBaseType()) {
auto *Enum = dyn_cast_or_null<DICompositeType>(T);
auto *Basic = dyn_cast_or_null<DIBasicType>(T);
AssertDI(
(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type) ||
(Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned ||
Basic->getEncoding() == dwarf::DW_ATE_signed ||
Basic->getEncoding() == dwarf::DW_ATE_unsigned_char ||
Basic->getEncoding() == dwarf::DW_ATE_signed_char ||
Basic->getEncoding() == dwarf::DW_ATE_boolean)),
"invalid set base type", &N, T);
}
}
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 ||
N.getTag() == dwarf::DW_TAG_namelist,
"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 (auto *D = N.getRawDiscriminator()) {
AssertDI(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part,
"discriminator can only appear on variant part");
}
if (N.getRawDataLocation()) {
AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
"dataLocation can only appear in array type");
}
if (N.getRawAssociated()) {
AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
"associated can only appear in array type");
}
if (N.getRawAllocated()) {
AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
"allocated can only appear in array type");
}
if (N.getRawRank()) {
AssertDI(N.getTag() == dwarf::DW_TAG_array_type,
"rank can only appear in array type");
}
}
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;
case DIFile::CSK_SHA256:
Size = 64;
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());
CurrentSourceLang = (dwarf::SourceLanguage)N.getSourceLanguage();
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::visitDIArgList(const DIArgList &N) {
AssertDI(!N.getNumOperands(),
"DIArgList should have no operands other than a list of "
"ValueAsMetadata",
&N);
}
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());
// Assert only if the global variable is not an extern
if (N.isDefinition())
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 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 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 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));
// 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() == "SemanticInterposition") {
ConstantInt *Value =
mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2));
Assert(Value,
"SemanticInterposition metadata requires constant integer argument");
}
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()->stripPointerCasts()),
"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));
}
void Verifier::verifyAttributeTypes(AttributeSet Attrs, const Value *V) {
for (Attribute A : Attrs) {
if (A.isStringAttribute()) {
#define GET_ATTR_NAMES
#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)
#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
if (A.getKindAsString() == #DISPLAY_NAME) { \
auto V = A.getValueAsString(); \
if (!(V.empty() || V == "true" || V == "false")) \
CheckFailed("invalid value for '" #DISPLAY_NAME "' attribute: " + V + \
""); \
}
#include "llvm/IR/Attributes.inc"
continue;
}
if (A.isIntAttribute() != Attribute::isIntAttrKind(A.getKindAsEnum())) {
CheckFailed("Attribute '" + A.getAsString() + "' should have an Argument",
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, V);
for (Attribute Attr : Attrs)
Assert(Attr.isStringAttribute() ||
Attribute::canUseAsParamAttr(Attr.getKindAsEnum()),
"Attribute '" + Attr.getAsString() +
"' does not apply to parameters",
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::Preallocated);
AttrCount += Attrs.hasAttribute(Attribute::StructRet) ||
Attrs.hasAttribute(Attribute::InReg);
AttrCount += Attrs.hasAttribute(Attribute::Nest);
AttrCount += Attrs.hasAttribute(Attribute::ByRef);
Assert(AttrCount <= 1,
"Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', "
"'byref', 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);
AttrBuilder IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty);
for (Attribute Attr : Attrs) {
if (!Attr.isStringAttribute() &&
IncompatibleAttrs.contains(Attr.getKindAsEnum())) {
CheckFailed("Attribute '" + Attr.getAsString() +
"' applied to incompatible type!", V);
return;
}
}
if (PointerType *PTy = dyn_cast<PointerType>(Ty)) {
if (Attrs.hasAttribute(Attribute::ByVal)) {
SmallPtrSet<Type *, 4> Visited;
Assert(Attrs.getByValType()->isSized(&Visited),
"Attribute 'byval' does not support unsized types!", V);
}
if (Attrs.hasAttribute(Attribute::ByRef)) {
SmallPtrSet<Type *, 4> Visited;
Assert(Attrs.getByRefType()->isSized(&Visited),
"Attribute 'byref' does not support unsized types!", V);
}
if (Attrs.hasAttribute(Attribute::InAlloca)) {
SmallPtrSet<Type *, 4> Visited;
Assert(Attrs.getInAllocaType()->isSized(&Visited),
"Attribute 'inalloca' does not support unsized types!", V);
}
if (Attrs.hasAttribute(Attribute::Preallocated)) {
SmallPtrSet<Type *, 4> Visited;
Assert(Attrs.getPreallocatedType()->isSized(&Visited),
"Attribute 'preallocated' does not support unsized types!", V);
}
if (!PTy->isOpaque()) {
if (!isa<PointerType>(PTy->getElementType()))
Assert(!Attrs.hasAttribute(Attribute::SwiftError),
"Attribute 'swifterror' only applies to parameters "
"with pointer to pointer type!",
V);
if (Attrs.hasAttribute(Attribute::ByRef)) {
Assert(Attrs.getByRefType() == PTy->getElementType(),
"Attribute 'byref' type does not match parameter!", V);
}
if (Attrs.hasAttribute(Attribute::ByVal) && Attrs.getByValType()) {
Assert(Attrs.getByValType() == PTy->getElementType(),
"Attribute 'byval' type does not match parameter!", V);
}
if (Attrs.hasAttribute(Attribute::Preallocated)) {
Assert(Attrs.getPreallocatedType() == PTy->getElementType(),
"Attribute 'preallocated' type does not match parameter!", V);
}
if (Attrs.hasAttribute(Attribute::InAlloca)) {
Assert(Attrs.getInAllocaType() == PTy->getElementType(),
"Attribute 'inalloca' type does not match parameter!", V);
}
if (Attrs.hasAttribute(Attribute::ElementType)) {
Assert(Attrs.getElementType() == PTy->getElementType(),
"Attribute 'elementtype' type does not match parameter!", V);
}
}
}
}
void Verifier::checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr,
const Value *V) {
if (Attrs.hasFnAttr(Attr)) {
StringRef S = Attrs.getFnAttr(Attr).getValueAsString();
unsigned N;
if (S.getAsInteger(10, N))
CheckFailed("\"" + Attr + "\" takes an unsigned integer: " + S, 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;
if (AttributeListsVisited.insert(Attrs.getRawPointer()).second) {
Assert(Attrs.hasParentContext(Context),
"Attribute list does not match Module context!", &Attrs, V);
for (const auto &AttrSet : Attrs) {
Assert(!AttrSet.hasAttributes() || AttrSet.hasParentContext(Context),
"Attribute set does not match Module context!", &AttrSet, V);
for (const auto &A : AttrSet) {
Assert(A.hasParentContext(Context),
"Attribute does not match Module context!", &A, V);
}
}
}
bool SawNest = false;
bool SawReturned = false;
bool SawSRet = false;
bool SawSwiftSelf = false;
bool SawSwiftAsync = false;
bool SawSwiftError = false;
// Verify return value attributes.
AttributeSet RetAttrs = Attrs.getRetAttrs();
for (Attribute RetAttr : RetAttrs)
Assert(RetAttr.isStringAttribute() ||
Attribute::canUseAsRetAttr(RetAttr.getKindAsEnum()),
"Attribute '" + RetAttr.getAsString() +
"' does not apply to function return values",
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.getParamAttrs(i);
if (!IsIntrinsic) {
Assert(!ArgAttrs.hasAttribute(Attribute::ImmArg),
"immarg attribute only applies to intrinsics",V);
Assert(!ArgAttrs.hasAttribute(Attribute::ElementType),
"Attribute 'elementtype' can only be applied 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::SwiftAsync)) {
Assert(!SawSwiftAsync, "Cannot have multiple 'swiftasync' parameters!", V);
SawSwiftAsync = 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.hasFnAttrs())
return;
verifyAttributeTypes(Attrs.getFnAttrs(), V);
for (Attribute FnAttr : Attrs.getFnAttrs())
Assert(FnAttr.isStringAttribute() ||
Attribute::canUseAsFnAttr(FnAttr.getKindAsEnum()),
"Attribute '" + FnAttr.getAsString() +
"' does not apply to functions!",
V);
Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) &&
Attrs.hasFnAttr(Attribute::ReadOnly)),
"Attributes 'readnone and readonly' are incompatible!", V);
Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) &&
Attrs.hasFnAttr(Attribute::WriteOnly)),
"Attributes 'readnone and writeonly' are incompatible!", V);
Assert(!(Attrs.hasFnAttr(Attribute::ReadOnly) &&
Attrs.hasFnAttr(Attribute::WriteOnly)),
"Attributes 'readonly and writeonly' are incompatible!", V);
Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) &&
Attrs.hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly)),
"Attributes 'readnone and inaccessiblemem_or_argmemonly' are "
"incompatible!",
V);
Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) &&
Attrs.hasFnAttr(Attribute::InaccessibleMemOnly)),
"Attributes 'readnone and inaccessiblememonly' are incompatible!", V);
Assert(!(Attrs.hasFnAttr(Attribute::NoInline) &&
Attrs.hasFnAttr(Attribute::AlwaysInline)),
"Attributes 'noinline and alwaysinline' are incompatible!", V);
if (Attrs.hasFnAttr(Attribute::OptimizeNone)) {
Assert(Attrs.hasFnAttr(Attribute::NoInline),
"Attribute 'optnone' requires 'noinline'!", V);
Assert(!Attrs.hasFnAttr(Attribute::OptimizeForSize),
"Attributes 'optsize and optnone' are incompatible!", V);
Assert(!Attrs.hasFnAttr(Attribute::MinSize),
"Attributes 'minsize and optnone' are incompatible!", V);
}
if (Attrs.hasFnAttr(Attribute::JumpTable)) {
const GlobalValue *GV = cast<GlobalValue>(V);
Assert(GV->hasGlobalUnnamedAddr(),
"Attribute 'jumptable' requires 'unnamed_addr'", V);
}
if (Attrs.hasFnAttr(Attribute::AllocSize)) {
std::pair<unsigned, Optional<unsigned>> Args =
Attrs.getFnAttrs().getAllocSizeArgs();
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.hasFnAttr(Attribute::VScaleRange)) {
std::pair<unsigned, unsigned> Args =
Attrs.getFnAttrs().getVScaleRangeArgs();
if (Args.first > Args.second && Args.second != 0)
CheckFailed("'vscale_range' minimum cannot be greater than maximum", V);
}
if (Attrs.hasFnAttr("frame-pointer")) {
StringRef FP = Attrs.getFnAttr("frame-pointer").getValueAsString();
if (FP != "all" && FP != "non-leaf" && FP != "none")
CheckFailed("invalid value for 'frame-pointer' attribute: " + FP, V);
}
checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-prefix", V);
checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-entry", V);
checkUnsignedBaseTenFuncAttr(Attrs, "warn-stack-size", 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);
}
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.getParamAttrs(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 w/inline transition bundle is deprecated", 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 w/inline deopt operands is deprecated", Call);
const int ExpectedNumArgs = 7 + NumCallArgs;
Assert(ExpectedNumArgs == (int)Call.arg_size(),
"gc.statepoint too many arguments", 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 IsIntrinsic = F.isIntrinsic();
// Check function attributes.
verifyFunctionAttrs(FT, Attrs, &F, IsIntrinsic);
// 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.hasFnAttr(Attribute::Builtin),
"Attribute 'builtin' can only be applied to a callsite.", &F);
Assert(!Attrs.hasAttrSomewhere(Attribute::ElementType),
"Attribute 'elementtype' 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::X86_INTR: {
Assert(F.arg_empty() || Attrs.hasParamAttr(0, Attribute::ByVal),
"Calling convention parameter requires byval", &F);
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);
if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
const unsigned StackAS = DL.getAllocaAddrSpace();
unsigned i = 0;
for (const Argument &Arg : F.args()) {
Assert(!Attrs.hasParamAttr(i, Attribute::ByVal),
"Calling convention disallows byval", &F);
Assert(!Attrs.hasParamAttr(i, Attribute::Preallocated),
"Calling convention disallows preallocated", &F);
Assert(!Attrs.hasParamAttr(i, Attribute::InAlloca),
"Calling convention disallows inalloca", &F);
if (Attrs.hasParamAttr(i, Attribute::ByRef)) {
// FIXME: Should also disallow LDS and GDS, but we don't have the enum
// value here.
Assert(Arg.getType()->getPointerAddressSpace() != StackAS,
"Calling convention disallows stack byref", &F);
}
++i;
}
}
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 (!IsIntrinsic) {
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);
Assert(!Arg.getType()->isX86_AMXTy(),
"Function takes x86_amx but isn't an intrinsic", &Arg, &F);
}
// Check that swifterror argument is only used by loads and stores.
if (Attrs.hasParamAttr(i, Attribute::SwiftError)) {
verifySwiftErrorValue(&Arg);
}
++i;
}
if (!IsIntrinsic) {
Assert(!F.getReturnType()->isTokenTy(),
"Function returns a token but isn't an intrinsic", &F);
Assert(!F.getReturnType()->isX86_AMXTy(),
"Function returns a x86_amx 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, AreDebugLocsAllowed::Yes);
}
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(!IsIntrinsic, "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.
auto AllowLocs = AreDebugLocsAllowed::No;
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);
AssertDI(cast<DISubprogram>(I.second)->isDistinct(),
"function definition may only have a distinct !dbg attachment",
&F);
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;
AllowLocs = AreDebugLocsAllowed::Yes;
break;
}
case LLVMContext::MD_prof:
++NumProfAttachments;
Assert(NumProfAttachments == 1,
"function must have a single !prof attachment", &F, I.second);
break;
}