Write(&*I);
}
+ void Write(const Module *M) {
+ if (!M)
+ return;
+ OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n";
+ }
+
void Write(const Value *V) {
if (!V)
return;
/// given function and the largest index passed to llvm.localrecover.
DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo;
+ /// Cache of constants visited in search of ConstantExprs.
+ SmallPtrSet<const Constant *, 32> ConstantExprVisited;
+
public:
explicit Verifier(raw_ostream &OS)
: VerifierSupport(OS), Context(nullptr), LandingPadResultTy(nullptr),
void VerifyFunctionMetadata(
const SmallVector<std::pair<unsigned, MDNode *>, 4> MDs);
- void VerifyConstantExprBitcastType(const ConstantExpr *CE);
+ void visitConstantExprsRecursively(const Constant *EntryC);
+ void visitConstantExpr(const ConstantExpr *CE);
void VerifyStatepoint(ImmutableCallSite CS);
void verifyFrameRecoverIndices();
}
// Walk any aggregate initializers looking for bitcasts between address spaces
- SmallPtrSet<const Value *, 4> Visited;
- SmallVector<const Value *, 4> WorkStack;
- WorkStack.push_back(cast<Value>(GV.getInitializer()));
-
- while (!WorkStack.empty()) {
- const Value *V = WorkStack.pop_back_val();
- if (!Visited.insert(V).second)
- continue;
-
- if (const User *U = dyn_cast<User>(V)) {
- WorkStack.append(U->op_begin(), U->op_end());
- }
-
- if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
- VerifyConstantExprBitcastType(CE);
- if (Broken)
- return;
- }
- }
+ visitConstantExprsRecursively(GV.getInitializer());
visitGlobalValue(GV);
}
void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited,
const GlobalAlias &GA, const Constant &C) {
if (const auto *GV = dyn_cast<GlobalValue>(&C)) {
- Assert(!GV->isDeclaration(), "Alias must point to a definition", &GA);
+ 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);
}
if (const auto *CE = dyn_cast<ConstantExpr>(&C))
- VerifyConstantExprBitcastType(CE);
+ visitConstantExprsRecursively(CE);
for (const Use &U : C.operands()) {
Value *V = &*U;
"invalid composite elements", &N, N.getRawElements());
Assert(isTypeRef(N, N.getRawVTableHolder()), "invalid vtable holder", &N,
N.getRawVTableHolder());
- Assert(!N.getRawElements() || isa<MDTuple>(N.getRawElements()),
- "invalid composite elements", &N, N.getRawElements());
Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags",
&N);
if (auto *Params = N.getRawTemplateParams())
Op);
}
}
+ if (auto *Array = N.getRawMacros()) {
+ Assert(isa<MDTuple>(Array), "invalid macro list", &N, Array);
+ for (Metadata *Op : N.getMacros()->operands()) {
+ Assert(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op);
+ }
+ }
}
void Verifier::visitDISubprogram(const DISubprogram &N) {
Assert(isa<DIScope>(S), "invalid scope ref", &N, S);
}
+void Verifier::visitDIMacro(const DIMacro &N) {
+ Assert(N.getMacinfoType() == dwarf::DW_MACINFO_define ||
+ N.getMacinfoType() == dwarf::DW_MACINFO_undef,
+ "invalid macinfo type", &N);
+ Assert(!N.getName().empty(), "anonymous macro", &N);
+}
+
+void Verifier::visitDIMacroFile(const DIMacroFile &N) {
+ Assert(N.getMacinfoType() == dwarf::DW_MACINFO_start_file,
+ "invalid macinfo type", &N);
+ if (auto *F = N.getRawFile())
+ Assert(isa<DIFile>(F), "invalid file", &N, F);
+
+ if (auto *Array = N.getRawElements()) {
+ Assert(isa<MDTuple>(Array), "invalid macro list", &N, Array);
+ for (Metadata *Op : N.getElements()->operands()) {
+ Assert(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op);
+ }
+ }
+}
+
void Verifier::visitDIModule(const DIModule &N) {
Assert(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N);
Assert(!N.getName().empty(), "anonymous module", &N);
}
}
-void Verifier::VerifyConstantExprBitcastType(const ConstantExpr *CE) {
+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);
+
+ // Visit all sub-expressions.
+ for (const Use &U : C->operands()) {
+ const auto *OpC = dyn_cast<Constant>(U);
+ if (!OpC)
+ continue;
+ if (isa<GlobalValue>(OpC))
+ continue; // Global values get visited separately.
+ if (!ConstantExprVisited.insert(OpC).second)
+ continue;
+ Stack.push_back(OpC);
+ }
+ }
+}
+
+void Verifier::visitConstantExpr(const ConstantExpr *CE) {
if (CE->getOpcode() != Instruction::BitCast)
return;
auto *Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
if (Per)
Assert(Per->getParent() == F.getParent(),
- "Referencing personality function in another module!", &F, Per);
+ "Referencing personality function in another module!",
+ &F, F.getParent(), Per, Per->getParent());
}
if (F.isMaterializable()) {
continue;
DISubprogram *SP = Scope ? Scope->getSubprogram() : nullptr;
- if (SP && !Seen.insert(SP).second)
+
+ // Scope and SP could be the same MDNode and we don't want to skip
+ // validation in that case
+ if (SP && ((Scope != SP) && !Seen.insert(SP).second))
continue;
// FIXME: Once N is canonical, check "SP == &N".
" donothing or patchpoint",
&I);
Assert(F->getParent() == M, "Referencing function in another module!",
- &I);
+ &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);
+ 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))) {
if (CE->getType()->isPtrOrPtrVectorTy()) {
// If we have a ConstantExpr pointer, we need to see if it came from an
// illegal bitcast (inttoptr <constant int> )
- SmallVector<const ConstantExpr *, 4> Stack;
- SmallPtrSet<const ConstantExpr *, 4> Visited;
- Stack.push_back(CE);
-
- while (!Stack.empty()) {
- const ConstantExpr *V = Stack.pop_back_val();
- if (!Visited.insert(V).second)
- continue;
-
- VerifyConstantExprBitcastType(V);
-
- for (unsigned I = 0, N = V->getNumOperands(); I != N; ++I) {
- if (ConstantExpr *Op = dyn_cast<ConstantExpr>(V->getOperand(I)))
- Stack.push_back(Op);
- }
- }
+ visitConstantExprsRecursively(CE);
}
}
}