namespace {
struct VerifierSupport {
raw_ostream *OS;
- const Module *M = nullptr;
- Optional<ModuleSlotTracker> MST;
+ const Module &M;
+ ModuleSlotTracker MST;
+ const DataLayout &DL;
+ LLVMContext &Context;
/// Track the brokenness of the module while recursively visiting.
bool Broken = false;
/// Whether to treat broken debug info as an error.
bool TreatBrokenDebugInfoAsError = true;
- explicit VerifierSupport(raw_ostream *OS) : OS(OS) {}
+ explicit VerifierSupport(raw_ostream *OS, const Module &M)
+ : OS(OS), M(M), MST(&M), DL(M.getDataLayout()), Context(M.getContext()) {}
private:
template <class NodeTy> void Write(const ilist_iterator<NodeTy> &I) {
}
void Write(const Module *M) {
- if (!M)
- return;
*OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n";
}
if (!V)
return;
if (isa<Instruction>(V)) {
- V->print(*OS, *MST);
+ V->print(*OS, MST);
*OS << '\n';
} else {
- V->printAsOperand(*OS, true, *MST);
+ V->printAsOperand(*OS, true, MST);
*OS << '\n';
}
}
void Write(const Metadata *MD) {
if (!MD)
return;
- MD->print(*OS, *MST, M);
+ MD->print(*OS, MST, &M);
*OS << '\n';
}
void Write(const NamedMDNode *NMD) {
if (!NMD)
return;
- NMD->print(*OS, *MST);
+ NMD->print(*OS, MST);
*OS << '\n';
}
class Verifier : public InstVisitor<Verifier>, VerifierSupport {
friend class InstVisitor<Verifier>;
- LLVMContext *Context;
DominatorTree DT;
/// \brief When verifying a basic block, keep track of all of the
// constant expressions, we can arrive at a particular user many times.
SmallPtrSet<const Value *, 32> GlobalValueVisited;
- void checkAtomicMemAccessSize(const Module *M, Type *Ty,
- const Instruction *I);
-
- void updateModule(const Module *NewM) {
- if (M == NewM)
- return;
- MST.emplace(NewM);
- M = NewM;
- }
+ void checkAtomicMemAccessSize(Type *Ty, const Instruction *I);
public:
- explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError)
- : VerifierSupport(OS), Context(nullptr), LandingPadResultTy(nullptr),
+ explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError,
+ const Module &M)
+ : VerifierSupport(OS, M), LandingPadResultTy(nullptr),
SawFrameEscape(false) {
TreatBrokenDebugInfoAsError = ShouldTreatBrokenDebugInfoAsError;
}
bool hasBrokenDebugInfo() const { return BrokenDebugInfo; }
bool verify(const Function &F) {
- updateModule(F.getParent());
- Context = &M->getContext();
+ assert(F.getParent() == &M &&
+ "An instance of this class only works with a specific module!");
// First ensure the function is well-enough formed to compute dominance
// information, and directly compute a dominance tree. We don't rely on the
if (OS) {
*OS << "Basic Block in function '" << F.getName()
<< "' does not have terminator!\n";
- BB.printAsOperand(*OS, true, *MST);
+ BB.printAsOperand(*OS, true, MST);
*OS << "\n";
}
return false;
return !Broken;
}
- bool verify(const Module &M) {
- updateModule(&M);
- Context = &M.getContext();
+ /// Verify the module that this instance of \c Verifier was initialized with.
+ bool verify() {
Broken = false;
// Collect all declarations of the llvm.experimental.deoptimize intrinsic.
forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool {
if (const Instruction *I = dyn_cast<Instruction>(V)) {
if (!I->getParent() || !I->getParent()->getParent())
- CheckFailed("Global is referenced by parentless instruction!", &GV,
- M, I);
- else if (I->getParent()->getParent()->getParent() != M)
- CheckFailed("Global is referenced in a different module!", &GV,
- M, I, I->getParent()->getParent(),
+ CheckFailed("Global is referenced by parentless instruction!", &GV, &M,
+ I);
+ else if (I->getParent()->getParent()->getParent() != &M)
+ CheckFailed("Global is referenced in a different module!", &GV, &M, I,
+ I->getParent()->getParent(),
I->getParent()->getParent()->getParent());
return false;
} else if (const Function *F = dyn_cast<Function>(V)) {
- if (F->getParent() != M)
- CheckFailed("Global is used by function in a different module", &GV,
- M, F, F->getParent());
+ if (F->getParent() != &M)
+ CheckFailed("Global is used by function in a different module", &GV, &M,
+ F, F->getParent());
return false;
}
return true;
if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) {
StructType *STy = dyn_cast<StructType>(ATy->getElementType());
PointerType *FuncPtrTy =
- FunctionType::get(Type::getVoidTy(*Context), false)->getPointerTo();
+ FunctionType::get(Type::getVoidTy(Context), false)->getPointerTo();
// FIXME: Reject the 2-field form in LLVM 4.0.
Assert(STy &&
(STy->getNumElements() == 2 || STy->getNumElements() == 3) &&
void Verifier::visitComdat(const Comdat &C) {
// The Module is invalid if the GlobalValue has private linkage. Entities
// with private linkage don't have entries in the symbol table.
- if (const GlobalValue *GV = M->getNamedValue(C.getName()))
+ if (const GlobalValue *GV = M.getNamedValue(C.getName()))
Assert(!GV->hasPrivateLinkage(), "comdat global value has private linkage",
GV);
}
"'noinline and alwaysinline' are incompatible!",
V);
- Assert(!AttrBuilder(Attrs, Idx)
- .overlaps(AttributeFuncs::typeIncompatible(Ty)),
- "Wrong types for attribute: " +
- AttributeSet::get(*Context, Idx,
- AttributeFuncs::typeIncompatible(Ty)).getAsString(Idx),
- V);
+ Assert(
+ !AttrBuilder(Attrs, Idx).overlaps(AttributeFuncs::typeIncompatible(Ty)),
+ "Wrong types for attribute: " +
+ AttributeSet::get(Context, Idx, AttributeFuncs::typeIncompatible(Ty))
+ .getAsString(Idx),
+ V);
if (PointerType *PTy = dyn_cast<PointerType>(Ty)) {
SmallPtrSet<Type*, 4> Visited;
if (const auto *GV = dyn_cast<GlobalValue>(C)) {
// Global Values get visited separately, but we do need to make sure
// that the global value is in the correct module
- Assert(GV->getParent() == M, "Referencing global in another module!",
- EntryC, M, GV, GV->getParent());
+ Assert(GV->getParent() == &M, "Referencing global in another module!",
+ EntryC, &M, GV, GV->getParent());
continue;
}
FunctionType *FT = F.getFunctionType();
unsigned NumArgs = F.arg_size();
- Assert(Context == &F.getContext(),
+ Assert(&Context == &F.getContext(),
"Function context does not match Module context!", &F);
Assert(!F.hasCommonLinkage(), "Functions may not have common linkage", &F);
"PtrToInt source must be pointer", &I);
if (auto *PTy = dyn_cast<PointerType>(SrcTy->getScalarType()))
- Assert(!M->getDataLayout().isNonIntegralPointerType(PTy),
+ Assert(!DL.isNonIntegralPointerType(PTy),
"ptrtoint not supported for non-integral pointers");
Assert(DestTy->getScalarType()->isIntegerTy(),
"IntToPtr result must be a pointer", &I);
if (auto *PTy = dyn_cast<PointerType>(DestTy->getScalarType()))
- Assert(!M->getDataLayout().isNonIntegralPointerType(PTy),
+ Assert(!DL.isNonIntegralPointerType(PTy),
"inttoptr not supported for non-integral pointers");
Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "IntToPtr type mismatch",
}
}
-void Verifier::checkAtomicMemAccessSize(const Module *M, Type *Ty,
- const Instruction *I) {
- unsigned Size = M->getDataLayout().getTypeSizeInBits(Ty);
+void Verifier::checkAtomicMemAccessSize(Type *Ty, const Instruction *I) {
+ unsigned Size = DL.getTypeSizeInBits(Ty);
Assert(Size >= 8, "atomic memory access' size must be byte-sized", Ty, I);
Assert(!(Size & (Size - 1)),
"atomic memory access' operand must have a power-of-two size", Ty, I);
"atomic load operand must have integer, pointer, or floating point "
"type!",
ElTy, &LI);
- checkAtomicMemAccessSize(M, ElTy, &LI);
+ checkAtomicMemAccessSize(ElTy, &LI);
} else {
Assert(LI.getSynchScope() == CrossThread,
"Non-atomic load cannot have SynchronizationScope specified", &LI);
"atomic store operand must have integer, pointer, or floating point "
"type!",
ElTy, &SI);
- checkAtomicMemAccessSize(M, ElTy, &SI);
+ checkAtomicMemAccessSize(ElTy, &SI);
} else {
Assert(SI.getSynchScope() == CrossThread,
"Non-atomic store cannot have SynchronizationScope specified", &SI);
Assert(ElTy->isIntegerTy() || ElTy->isPointerTy(),
"cmpxchg operand must have integer or pointer type",
ElTy, &CXI);
- checkAtomicMemAccessSize(M, ElTy, &CXI);
+ checkAtomicMemAccessSize(ElTy, &CXI);
Assert(ElTy == CXI.getOperand(1)->getType(),
"Expected value type does not match pointer operand type!", &CXI,
ElTy);
Type *ElTy = PTy->getElementType();
Assert(ElTy->isIntegerTy(), "atomicrmw operand must have integer type!",
&RMWI, ElTy);
- checkAtomicMemAccessSize(M, ElTy, &RMWI);
+ checkAtomicMemAccessSize(ElTy, &RMWI);
Assert(ElTy == RMWI.getOperand(1)->getType(),
"Argument value type does not match pointer operand type!", &RMWI,
ElTy);
"Cannot invoke an intrinsic other than donothing, patchpoint or "
"statepoint",
&I);
- Assert(F->getParent() == M, "Referencing function in another module!",
- &I, M, F, F->getParent());
+ Assert(F->getParent() == &M, "Referencing function in another module!",
+ &I, &M, F, F->getParent());
} else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) {
Assert(OpBB->getParent() == BB->getParent(),
"Referring to a basic block in another function!", &I);
Assert(OpArg->getParent() == BB->getParent(),
"Referring to an argument in another function!", &I);
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(I.getOperand(i))) {
- Assert(GV->getParent() == M, "Referencing global in another module!", &I, M, GV, GV->getParent());
+ Assert(GV->getParent() == &M, "Referencing global in another module!", &I,
+ &M, GV, GV->getParent());
} else if (isa<Instruction>(I.getOperand(i))) {
verifyDominatesUse(I, i);
} else if (isa<InlineAsm>(I.getOperand(i))) {
}
void Verifier::verifyCompileUnits() {
- auto *CUs = M->getNamedMetadata("llvm.dbg.cu");
+ auto *CUs = M.getNamedMetadata("llvm.dbg.cu");
SmallPtrSet<const Metadata *, 2> Listed;
if (CUs)
Listed.insert(CUs->op_begin(), CUs->op_end());
Function &F = const_cast<Function &>(f);
// Don't use a raw_null_ostream. Printing IR is expensive.
- Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true);
+ Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true, *f.getParent());
// Note that this function's return value is inverted from what you would
// expect of a function called "verify".
bool llvm::verifyModule(const Module &M, raw_ostream *OS,
bool *BrokenDebugInfo) {
// Don't use a raw_null_ostream. Printing IR is expensive.
- Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/!BrokenDebugInfo);
+ Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/!BrokenDebugInfo, M);
bool Broken = false;
for (const Function &F : M)
Broken |= !V.verify(F);
- Broken |= !V.verify(M);
+ Broken |= !V.verify();
if (BrokenDebugInfo)
*BrokenDebugInfo = V.hasBrokenDebugInfo();
// Note that this function's return value is inverted from what you would
struct VerifierLegacyPass : public FunctionPass {
static char ID;
- Verifier V;
+ std::unique_ptr<Verifier> V;
bool FatalErrors = true;
- VerifierLegacyPass()
- : FunctionPass(ID),
- V(&dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false) {
+ VerifierLegacyPass() : FunctionPass(ID) {
initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
}
explicit VerifierLegacyPass(bool FatalErrors)
: FunctionPass(ID),
- V(&dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false),
FatalErrors(FatalErrors) {
initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
}
+ bool doInitialization(Module &M) override {
+ V = llvm::make_unique<Verifier>(
+ &dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false, M);
+ return false;
+ }
+
bool runOnFunction(Function &F) override {
- if (!V.verify(F) && FatalErrors)
+ if (!V->verify(F) && FatalErrors)
report_fatal_error("Broken function found, compilation aborted!");
return false;
bool HasErrors = false;
for (Function &F : M)
if (F.isDeclaration())
- HasErrors |= !V.verify(F);
+ HasErrors |= !V->verify(F);
- HasErrors |= !V.verify(M);
+ HasErrors |= !V->verify();
if (FatalErrors) {
if (HasErrors)
report_fatal_error("Broken module found, compilation aborted!");
- assert(!V.hasBrokenDebugInfo() && "Module contains invalid debug info");
+ assert(!V->hasBrokenDebugInfo() && "Module contains invalid debug info");
}
// Strip broken debug info.
- if (V.hasBrokenDebugInfo()) {
+ if (V->hasBrokenDebugInfo()) {
DiagnosticInfoIgnoringInvalidDebugMetadata DiagInvalid(M);
M.getContext().diagnose(DiagInvalid);
if (!StripDebugInfo(M))