summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/IR/Verifier.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/IR/Verifier.cpp')
-rw-r--r--contrib/llvm/lib/IR/Verifier.cpp711
1 files changed, 566 insertions, 145 deletions
diff --git a/contrib/llvm/lib/IR/Verifier.cpp b/contrib/llvm/lib/IR/Verifier.cpp
index 682e934..5855059 100644
--- a/contrib/llvm/lib/IR/Verifier.cpp
+++ b/contrib/llvm/lib/IR/Verifier.cpp
@@ -45,48 +45,86 @@
//===----------------------------------------------------------------------===//
#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/ilist.h"
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SetVector.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/IR/Argument.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/CallSite.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/DiagnosticInfo.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/InstIterator.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.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/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/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
-#include <cstdarg>
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <utility>
+
using namespace llvm;
static cl::opt<bool> VerifyDebugInfo("verify-debug-info", cl::init(true));
-namespace {
+namespace llvm {
+
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;
@@ -95,16 +133,11 @@ struct VerifierSupport {
/// 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) {
- Write(&*I);
- }
-
void Write(const Module *M) {
- if (!M)
- return;
*OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n";
}
@@ -112,13 +145,14 @@ private:
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(ImmutableCallSite CS) {
Write(CS.getInstruction());
}
@@ -126,7 +160,7 @@ private:
void Write(const Metadata *MD) {
if (!MD)
return;
- MD->print(*OS, *MST, M);
+ MD->print(*OS, MST, &M);
*OS << '\n';
}
@@ -137,7 +171,7 @@ private:
void Write(const NamedMDNode *NMD) {
if (!NMD)
return;
- NMD->print(*OS, *MST);
+ NMD->print(*OS, MST);
*OS << '\n';
}
@@ -153,6 +187,14 @@ private:
*OS << *C;
}
+ void Write(const APInt *AI) {
+ if (!AI)
+ return;
+ *OS << *AI << '\n';
+ }
+
+ void Write(const unsigned i) { *OS << i << '\n'; }
+
template <typename T> void Write(ArrayRef<T> Vs) {
for (const T &V : Vs)
Write(V);
@@ -206,10 +248,13 @@ public:
}
};
+} // namespace llvm
+
+namespace {
+
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
@@ -252,28 +297,23 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
// 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);
+ TBAAVerifier TBAAVerifyHelper;
- 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),
- SawFrameEscape(false) {
+ 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) {
- 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
@@ -291,7 +331,7 @@ public:
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;
@@ -309,9 +349,8 @@ public:
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.
@@ -364,8 +403,8 @@ private:
SmallVectorImpl<const MDNode *> &Requirements);
void visitFunction(const Function &F);
void visitBasicBlock(BasicBlock &BB);
- void visitRangeMetadata(Instruction& I, MDNode* Range, Type* Ty);
- void visitDereferenceableMetadata(Instruction& I, MDNode* MD);
+ void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty);
+ void visitDereferenceableMetadata(Instruction &I, MDNode *MD);
template <class Ty> bool isValidMetadataArray(const MDTuple &N);
#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N);
@@ -428,6 +467,7 @@ private:
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);
@@ -456,7 +496,7 @@ private:
void verifyFrameRecoverIndices();
void verifySiblingFuncletUnwinds();
- void verifyBitPieceExpression(const DbgInfoIntrinsic &I);
+ void verifyFragmentExpression(const DbgInfoIntrinsic &I);
/// Module-level debug info verification...
void verifyCompileUnits();
@@ -465,17 +505,17 @@ private:
/// declarations share the same calling convention.
void verifyDeoptimizeCallingConvs();
};
-} // End anonymous namespace
+
+} // 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 (0)
+ 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 (0)
-
+ do { if (!(C)) { DebugInfoCheckFailed(__VA_ARGS__); return; } } while (false)
void Verifier::visit(Instruction &I) {
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
@@ -517,17 +557,17 @@ void Verifier::visitGlobalValue(const GlobalValue &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(),
+ 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;
@@ -540,7 +580,6 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
"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()) {
@@ -561,7 +600,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
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) &&
@@ -606,6 +645,16 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
GV.hasAvailableExternallyLinkage(),
"Global is marked as dllimport, but not external", &GV);
+ // 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");
+ }
+
if (!GV.hasInitializer()) {
visitGlobalValue(GV);
return;
@@ -672,10 +721,15 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) {
}
void Verifier::visitNamedMDNode(const NamedMDNode &NMD) {
+ // There used to be various other llvm.dbg.* nodes, but we don't support
+ // upgrading them and we want to reserve the namespace for future uses.
+ if (NMD.getName().startswith("llvm.dbg."))
+ AssertDI(NMD.getName() == "llvm.dbg.cu",
+ "unrecognized named metadata node in the llvm.dbg namespace",
+ &NMD);
for (const MDNode *MD : NMD.operands()) {
- if (NMD.getName() == "llvm.dbg.cu") {
+ if (NMD.getName() == "llvm.dbg.cu")
AssertDI(MD && isa<DICompileUnit>(MD), "invalid compile unit", &NMD, MD);
- }
if (!MD)
continue;
@@ -769,7 +823,7 @@ static bool isScope(const Metadata *MD) { return !MD || isa<DIScope>(MD); }
static bool isDINode(const Metadata *MD) { return !MD || isa<DINode>(MD); }
template <class Ty>
-bool isValidMetadataArrayImpl(const MDTuple &N, bool AllowNull) {
+static bool isValidMetadataArrayImpl(const MDTuple &N, bool AllowNull) {
for (Metadata *MD : N.operands()) {
if (MD) {
if (!isa<Ty>(MD))
@@ -782,13 +836,11 @@ bool isValidMetadataArrayImpl(const MDTuple &N, bool AllowNull) {
return true;
}
-template <class Ty>
-bool isValidMetadataArray(const MDTuple &N) {
+template <class Ty> static bool isValidMetadataArray(const MDTuple &N) {
return isValidMetadataArrayImpl<Ty>(N, /* AllowNull */ false);
}
-template <class Ty>
-bool isValidMetadataNullArray(const MDTuple &N) {
+template <class Ty> static bool isValidMetadataNullArray(const MDTuple &N) {
return isValidMetadataArrayImpl<Ty>(N, /* AllowNull */ true);
}
@@ -835,6 +887,7 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
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,
@@ -908,6 +961,8 @@ void Verifier::visitDISubroutineType(const DISubroutineType &N) {
void Verifier::visitDIFile(const DIFile &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N);
+ AssertDI((N.getChecksumKind() != DIFile::CSK_None ||
+ N.getChecksum().empty()), "invalid checksum kind", &N);
}
void Verifier::visitDICompileUnit(const DICompileUnit &N) {
@@ -937,15 +992,15 @@ void Verifier::visitDICompileUnit(const DICompileUnit &N) {
for (Metadata *Op : N.getRetainedTypes()->operands()) {
AssertDI(Op && (isa<DIType>(Op) ||
(isa<DISubprogram>(Op) &&
- cast<DISubprogram>(Op)->isDefinition() == false)),
+ !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<DIGlobalVariable>(Op), "invalid global variable ref",
- &N, Op);
+ AssertDI(Op && (isa<DIGlobalVariableExpression>(Op)),
+ "invalid global variable ref", &N, Op);
}
}
if (auto *Array = N.getRawImportedEntities()) {
@@ -1088,12 +1143,6 @@ void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N);
AssertDI(!N.getName().empty(), "missing global variable name", &N);
- if (auto *V = N.getRawVariable()) {
- AssertDI(isa<ConstantAsMetadata>(V) &&
- !isa<Function>(cast<ConstantAsMetadata>(V)->getValue()),
- "invalid global varaible ref", &N, V);
- visitConstantExprsRecursively(cast<ConstantAsMetadata>(V)->getValue());
- }
if (auto *Member = N.getRawStaticDataMemberDeclaration()) {
AssertDI(isa<DIDerivedType>(Member),
"invalid static data member declaration", &N, Member);
@@ -1113,6 +1162,15 @@ 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);
+}
+
void Verifier::visitDIObjCProperty(const DIObjCProperty &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_APPLE_property, "invalid tag", &N);
if (auto *T = N.getRawType())
@@ -1134,7 +1192,7 @@ void Verifier::visitDIImportedEntity(const DIImportedEntity &N) {
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);
}
@@ -1401,12 +1459,12 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
"'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;
@@ -1630,8 +1688,8 @@ void Verifier::visitConstantExprsRecursively(const Constant *EntryC) {
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;
}
@@ -1648,12 +1706,23 @@ void Verifier::visitConstantExprsRecursively(const Constant *EntryC) {
}
void Verifier::visitConstantExpr(const ConstantExpr *CE) {
- if (CE->getOpcode() != Instruction::BitCast)
- return;
-
- Assert(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0),
- CE->getType()),
- "Invalid bitcast", CE);
+ if (CE->getOpcode() == Instruction::BitCast)
+ Assert(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0),
+ CE->getType()),
+ "Invalid bitcast", CE);
+
+ if (CE->getOpcode() == Instruction::IntToPtr ||
+ CE->getOpcode() == Instruction::PtrToInt) {
+ auto *PtrTy = CE->getOpcode() == Instruction::IntToPtr
+ ? CE->getType()
+ : CE->getOperand(0)->getType();
+ StringRef Msg = CE->getOpcode() == Instruction::IntToPtr
+ ? "inttoptr not supported for non-integral pointers"
+ : "ptrtoint not supported for non-integral pointers";
+ Assert(
+ !DL.isNonIntegralPointerType(cast<PointerType>(PtrTy->getScalarType())),
+ Msg);
+ }
}
bool Verifier::verifyAttributeCount(AttributeSet Attrs, unsigned Params) {
@@ -1783,7 +1852,7 @@ void Verifier::verifyStatepoint(ImmutableCallSite CS) {
Assert(Call, "illegal use of statepoint token", &CI, U);
if (!Call) continue;
Assert(isa<GCRelocateInst>(Call) || isa<GCResultInst>(Call),
- "gc.result or gc.relocate are the only value uses"
+ "gc.result or gc.relocate are the only value uses "
"of a gc.statepoint",
&CI, U);
if (isa<GCResultInst>(Call)) {
@@ -1880,7 +1949,7 @@ void Verifier::visitFunction(const Function &F) {
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);
@@ -2035,7 +2104,7 @@ void Verifier::visitFunction(const Function &F) {
if (F.getIntrinsicID() && F.getParent()->isMaterialized()) {
const User *U;
if (F.hasAddressTaken(&U))
- Assert(0, "Invalid user of intrinsic instruction!", U);
+ Assert(false, "Invalid user of intrinsic instruction!", U);
}
Assert(!F.hasDLLImportStorageClass() ||
@@ -2078,9 +2147,9 @@ void Verifier::visitFunction(const Function &F) {
continue;
// FIXME: Once N is canonical, check "SP == &N".
- Assert(SP->describes(&F),
- "!dbg attachment points at wrong subprogram for function", N, &F,
- &I, DL, Scope, SP);
+ AssertDI(SP->describes(&F),
+ "!dbg attachment points at wrong subprogram for function", N, &F,
+ &I, DL, Scope, SP);
}
}
@@ -2218,7 +2287,7 @@ void Verifier::visitSelectInst(SelectInst &SI) {
/// a pass, if any exist, it's an error.
///
void Verifier::visitUserOp1(Instruction &I) {
- Assert(0, "User-defined operators should not live outside of a pass!", &I);
+ Assert(false, "User-defined operators should not live outside of a pass!", &I);
}
void Verifier::visitTruncInst(TruncInst &I) {
@@ -2409,6 +2478,11 @@ void Verifier::visitPtrToIntInst(PtrToIntInst &I) {
Assert(SrcTy->getScalarType()->isPointerTy(),
"PtrToInt source must be pointer", &I);
+
+ if (auto *PTy = dyn_cast<PointerType>(SrcTy->getScalarType()))
+ Assert(!DL.isNonIntegralPointerType(PTy),
+ "ptrtoint not supported for non-integral pointers");
+
Assert(DestTy->getScalarType()->isIntegerTy(),
"PtrToInt result must be integral", &I);
Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToInt type mismatch",
@@ -2433,6 +2507,11 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) {
"IntToPtr source must be an integral", &I);
Assert(DestTy->getScalarType()->isPointerTy(),
"IntToPtr result must be a pointer", &I);
+
+ if (auto *PTy = dyn_cast<PointerType>(DestTy->getScalarType()))
+ Assert(!DL.isNonIntegralPointerType(PTy),
+ "inttoptr not supported for non-integral pointers");
+
Assert(SrcTy->isVectorTy() == DestTy->isVectorTy(), "IntToPtr type mismatch",
&I);
if (SrcTy->isVectorTy()) {
@@ -2541,15 +2620,20 @@ void Verifier::verifyCallSite(CallSite CS) {
}
// For each argument of the callsite, if it has the swifterror argument,
- // make sure the underlying alloca has swifterror as well.
+ // make sure the underlying alloca/parameter it comes from has a swifterror as
+ // well.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
if (CS.paramHasAttr(i+1, Attribute::SwiftError)) {
Value *SwiftErrorArg = CS.getArgument(i);
- auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets());
- Assert(AI, "swifterror argument should come from alloca", AI, I);
- if (AI)
+ if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) {
Assert(AI->isSwiftError(),
"swifterror argument for call has mismatched alloca", AI, I);
+ continue;
+ }
+ auto ArgI = dyn_cast<Argument>(SwiftErrorArg);
+ Assert(ArgI, "swifterror argument should come from an alloca or parameter", SwiftErrorArg, I);
+ Assert(ArgI->hasSwiftErrorAttr(),
+ "swifterror argument for call has mismatched parameter", ArgI, I);
}
if (FTy->isVarArg()) {
@@ -2915,10 +2999,8 @@ static bool isContiguous(const ConstantRange &A, const ConstantRange &B) {
return A.getUpper() == B.getLower() || A.getLower() == B.getUpper();
}
-void Verifier::visitRangeMetadata(Instruction& I,
- MDNode* Range, Type* Ty) {
- assert(Range &&
- Range == I.getMetadata(LLVMContext::MD_range) &&
+void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) {
+ assert(Range && Range == I.getMetadata(LLVMContext::MD_range) &&
"precondition violation");
unsigned NumOperands = Range->getNumOperands();
@@ -2965,9 +3047,8 @@ void Verifier::visitRangeMetadata(Instruction& I,
}
}
-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);
@@ -2991,7 +3072,7 @@ void Verifier::visitLoadInst(LoadInst &LI) {
"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);
@@ -3020,7 +3101,7 @@ void Verifier::visitStoreInst(StoreInst &SI) {
"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);
@@ -3109,7 +3190,7 @@ void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) {
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);
@@ -3128,7 +3209,7 @@ void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) {
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);
@@ -3288,6 +3369,21 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) {
visitInstruction(LPI);
}
+void Verifier::visitResumeInst(ResumeInst &RI) {
+ Assert(RI.getFunction()->hasPersonalityFn(),
+ "ResumeInst needs to be in a function with a personality.", &RI);
+
+ if (!LandingPadResultTy)
+ LandingPadResultTy = RI.getValue()->getType();
+ else
+ Assert(LandingPadResultTy == RI.getValue()->getType(),
+ "The resume instruction should have a consistent result type "
+ "inside a function.",
+ &RI);
+
+ visitTerminatorInst(RI);
+}
+
void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
BasicBlock *BB = CPI.getParent();
@@ -3640,7 +3736,7 @@ void Verifier::visitInstruction(Instruction &I) {
// Check to make sure that only first-class-values are operands to
// instructions.
if (!I.getOperand(i)->getType()->isFirstClassType()) {
- Assert(0, "Instruction operands must be first-class values!", &I);
+ Assert(false, "Instruction operands must be first-class values!", &I);
}
if (Function *F = dyn_cast<Function>(I.getOperand(i))) {
@@ -3653,14 +3749,16 @@ void Verifier::visitInstruction(Instruction &I) {
Assert(
!F->isIntrinsic() || isa<CallInst>(I) ||
F->getIntrinsicID() == Intrinsic::donothing ||
+ F->getIntrinsicID() == Intrinsic::coro_resume ||
+ F->getIntrinsicID() == Intrinsic::coro_destroy ||
F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void ||
F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 ||
F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint,
- "Cannot invoke an intrinsic other than donothing, patchpoint or "
- "statepoint",
+ "Cannot invoke an intrinsic other than donothing, patchpoint, "
+ "statepoint, coro_resume or coro_destroy",
&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);
@@ -3668,7 +3766,8 @@ void Verifier::visitInstruction(Instruction &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))) {
@@ -3676,9 +3775,12 @@ void Verifier::visitInstruction(Instruction &I) {
(i + 3 == e && isa<InvokeInst>(I)),
"Cannot take the address of an inline asm!", &I);
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(i))) {
- if (CE->getType()->isPtrOrPtrVectorTy()) {
+ if (CE->getType()->isPtrOrPtrVectorTy() ||
+ !DL.getNonIntegralAddressSpaces().empty()) {
// If we have a ConstantExpr pointer, we need to see if it came from an
- // illegal bitcast (inttoptr <constant int> )
+ // illegal bitcast. If the datalayout string specifies non-integral
+ // address spaces then we also need to check for illegal ptrtoint and
+ // inttoptr expressions.
visitConstantExprsRecursively(CE);
}
}
@@ -3691,7 +3793,7 @@ void Verifier::visitInstruction(Instruction &I) {
if (ConstantFP *CFP0 =
mdconst::dyn_extract_or_null<ConstantFP>(MD->getOperand(0))) {
const APFloat &Accuracy = CFP0->getValueAPF();
- Assert(&Accuracy.getSemantics() == &APFloat::IEEEsingle,
+ Assert(&Accuracy.getSemantics() == &APFloat::IEEEsingle(),
"fpmath accuracy must have float type", &I);
Assert(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(),
"fpmath accuracy not a positive number!", &I);
@@ -3721,6 +3823,9 @@ void Verifier::visitInstruction(Instruction &I) {
if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null))
visitDereferenceableMetadata(I, MD);
+ if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa))
+ TBAAVerifyHelper.visitTBAAMetadata(I, TBAA);
+
if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) {
Assert(I.getType()->isPointerTy(), "align applies only to pointer types",
&I);
@@ -3743,7 +3848,7 @@ void Verifier::visitInstruction(Instruction &I) {
}
if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I))
- verifyBitPieceExpression(*DII);
+ verifyFragmentExpression(*DII);
InstsInThisBlock.insert(&I);
}
@@ -3803,6 +3908,20 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
switch (ID) {
default:
break;
+ case Intrinsic::coro_id: {
+ auto *InfoArg = CS.getArgOperand(3)->stripPointerCasts();
+ if (isa<ConstantPointerNull>(InfoArg))
+ break;
+ auto *GV = dyn_cast<GlobalVariable>(InfoArg);
+ Assert(GV && GV->isConstant() && GV->hasDefinitiveInitializer(),
+ "info argument of llvm.coro.begin must refer to an initialized "
+ "constant");
+ Constant *Init = GV->getInitializer();
+ Assert(isa<ConstantStruct>(Init) || isa<ConstantArray>(Init),
+ "info argument of llvm.coro.begin must refer to either a struct or "
+ "an array");
+ break;
+ }
case Intrinsic::ctlz: // llvm.ctlz
case Intrinsic::cttz: // llvm.cttz
Assert(isa<ConstantInt>(CS.getArgOperand(1)),
@@ -3833,6 +3952,32 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
CS);
break;
}
+ case Intrinsic::memcpy_element_atomic: {
+ ConstantInt *ElementSizeCI = dyn_cast<ConstantInt>(CS.getArgOperand(3));
+ Assert(ElementSizeCI, "element size of the element-wise atomic memory "
+ "intrinsic must be a constant int",
+ CS);
+ const APInt &ElementSizeVal = ElementSizeCI->getValue();
+ Assert(ElementSizeVal.isPowerOf2(),
+ "element size of the element-wise atomic memory intrinsic "
+ "must be a power of 2",
+ CS);
+
+ auto IsValidAlignment = [&](uint64_t Alignment) {
+ return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment);
+ };
+
+ uint64_t DstAlignment = CS.getParamAlignment(1),
+ SrcAlignment = CS.getParamAlignment(2);
+
+ Assert(IsValidAlignment(DstAlignment),
+ "incorrect alignment of the destination argument",
+ CS);
+ Assert(IsValidAlignment(SrcAlignment),
+ "incorrect alignment of the source argument",
+ CS);
+ break;
+ }
case Intrinsic::gcroot:
case Intrinsic::gcwrite:
case Intrinsic::gcread:
@@ -4181,10 +4326,10 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) {
if (!VarSP || !LocSP)
return; // Broken scope chains are checked elsewhere.
- Assert(VarSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind +
- " variable and !dbg attachment",
- &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc,
- Loc->getScope()->getSubprogram());
+ AssertDI(VarSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind +
+ " variable and !dbg attachment",
+ &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc,
+ Loc->getScope()->getSubprogram());
}
static uint64_t getVariableSize(const DILocalVariable &V) {
@@ -4210,7 +4355,7 @@ static uint64_t getVariableSize(const DILocalVariable &V) {
return 0;
}
-void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I) {
+void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) {
DILocalVariable *V;
DIExpression *E;
if (auto *DVI = dyn_cast<DbgValueInst>(&I)) {
@@ -4227,7 +4372,8 @@ void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I) {
return;
// Nothing to do if this isn't a bit piece expression.
- if (!E->isBitPiece())
+ auto Fragment = E->getFragmentInfo();
+ if (!Fragment)
return;
// The frontend helps out GDB by emitting the members of local anonymous
@@ -4245,21 +4391,21 @@ void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I) {
if (!VarSize)
return;
- unsigned PieceSize = E->getBitPieceSize();
- unsigned PieceOffset = E->getBitPieceOffset();
- Assert(PieceSize + PieceOffset <= VarSize,
- "piece is larger than or outside of variable", &I, V, E);
- Assert(PieceSize != VarSize, "piece covers entire variable", &I, V, E);
+ unsigned FragSize = Fragment->SizeInBits;
+ unsigned FragOffset = Fragment->OffsetInBits;
+ AssertDI(FragSize + FragOffset <= VarSize,
+ "fragment is larger than or outside of variable", &I, V, E);
+ AssertDI(FragSize != VarSize, "fragment covers entire variable", &I, V, E);
}
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());
- Assert(
- std::all_of(CUVisited.begin(), CUVisited.end(),
- [&Listed](const Metadata *CU) { return Listed.count(CU); }),
+ AssertDI(
+ all_of(CUVisited,
+ [&Listed](const Metadata *CU) { return Listed.count(CU); }),
"All DICompileUnits must be listed in llvm.dbg.cu");
CUVisited.clear();
}
@@ -4285,7 +4431,7 @@ bool llvm::verifyFunction(const Function &f, raw_ostream *OS) {
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".
@@ -4295,13 +4441,13 @@ bool llvm::verifyFunction(const Function &f, raw_ostream *OS) {
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
@@ -4310,26 +4456,30 @@ bool llvm::verifyModule(const Module &M, raw_ostream *OS,
}
namespace {
+
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;
@@ -4339,17 +4489,17 @@ struct VerifierLegacyPass : public FunctionPass {
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))
@@ -4362,6 +4512,277 @@ struct VerifierLegacyPass : public FunctionPass {
AU.setPreservesAll();
}
};
+
+} // end anonymous namespace
+
+/// Helper to issue failure from the TBAA verification
+template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&... Args) {
+ if (Diagnostic)
+ return Diagnostic->CheckFailed(Args...);
+}
+
+#define AssertTBAA(C, ...) \
+ do { \
+ if (!(C)) { \
+ CheckFailed(__VA_ARGS__); \
+ return false; \
+ } \
+ } while (false)
+
+/// Verify that \p BaseNode can be used as the "base type" in the struct-path
+/// TBAA scheme. This means \p BaseNode is either a scalar node, or a
+/// struct-type node describing an aggregate data structure (like a struct).
+TBAAVerifier::TBAABaseNodeSummary
+TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode) {
+ if (BaseNode->getNumOperands() < 2) {
+ CheckFailed("Base nodes must have at least two operands", &I, BaseNode);
+ return {true, ~0u};
+ }
+
+ auto Itr = TBAABaseNodes.find(BaseNode);
+ if (Itr != TBAABaseNodes.end())
+ return Itr->second;
+
+ auto Result = verifyTBAABaseNodeImpl(I, BaseNode);
+ auto InsertResult = TBAABaseNodes.insert({BaseNode, Result});
+ (void)InsertResult;
+ assert(InsertResult.second && "We just checked!");
+ return Result;
+}
+
+TBAAVerifier::TBAABaseNodeSummary
+TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode) {
+ const TBAAVerifier::TBAABaseNodeSummary InvalidNode = {true, ~0u};
+
+ if (BaseNode->getNumOperands() == 2) {
+ // Scalar nodes can only be accessed at offset 0.
+ return isValidScalarTBAANode(BaseNode)
+ ? TBAAVerifier::TBAABaseNodeSummary({false, 0})
+ : InvalidNode;
+ }
+
+ if (BaseNode->getNumOperands() % 2 != 1) {
+ CheckFailed("Struct tag nodes must have an odd number of operands!",
+ BaseNode);
+ return InvalidNode;
+ }
+
+ if (!isa<MDString>(BaseNode->getOperand(0))) {
+ CheckFailed("Struct tag nodes have a string as their first operand",
+ BaseNode);
+ return InvalidNode;
+ }
+
+ bool Failed = false;
+
+ Optional<APInt> PrevOffset;
+ unsigned BitWidth = ~0u;
+
+ // We've already checked that BaseNode is not a degenerate root node with one
+ // operand in \c verifyTBAABaseNode, so this loop should run at least once.
+ for (unsigned Idx = 1; Idx < BaseNode->getNumOperands(); Idx += 2) {
+ const MDOperand &FieldTy = BaseNode->getOperand(Idx);
+ const MDOperand &FieldOffset = BaseNode->getOperand(Idx + 1);
+ if (!isa<MDNode>(FieldTy)) {
+ CheckFailed("Incorrect field entry in struct type node!", &I, BaseNode);
+ Failed = true;
+ continue;
+ }
+
+ auto *OffsetEntryCI =
+ mdconst::dyn_extract_or_null<ConstantInt>(FieldOffset);
+ if (!OffsetEntryCI) {
+ CheckFailed("Offset entries must be constants!", &I, BaseNode);
+ Failed = true;
+ continue;
+ }
+
+ if (BitWidth == ~0u)
+ BitWidth = OffsetEntryCI->getBitWidth();
+
+ if (OffsetEntryCI->getBitWidth() != BitWidth) {
+ CheckFailed(
+ "Bitwidth between the offsets and struct type entries must match", &I,
+ BaseNode);
+ Failed = true;
+ continue;
+ }
+
+ // NB! As far as I can tell, we generate a non-strictly increasing offset
+ // sequence only from structs that have zero size bit fields. When
+ // recursing into a contained struct in \c getFieldNodeFromTBAABaseNode we
+ // pick the field lexically the latest in struct type metadata node. This
+ // mirrors the actual behavior of the alias analysis implementation.
+ bool IsAscending =
+ !PrevOffset || PrevOffset->ule(OffsetEntryCI->getValue());
+
+ if (!IsAscending) {
+ CheckFailed("Offsets must be increasing!", &I, BaseNode);
+ Failed = true;
+ }
+
+ PrevOffset = OffsetEntryCI->getValue();
+ }
+
+ return Failed ? InvalidNode
+ : TBAAVerifier::TBAABaseNodeSummary(false, BitWidth);
+}
+
+static bool IsRootTBAANode(const MDNode *MD) {
+ return MD->getNumOperands() < 2;
+}
+
+static bool IsScalarTBAANodeImpl(const MDNode *MD,
+ SmallPtrSetImpl<const MDNode *> &Visited) {
+ if (MD->getNumOperands() != 2 && MD->getNumOperands() != 3)
+ return false;
+
+ if (!isa<MDString>(MD->getOperand(0)))
+ return false;
+
+ if (MD->getNumOperands() == 3) {
+ auto *Offset = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2));
+ if (!(Offset && Offset->isZero() && isa<MDString>(MD->getOperand(0))))
+ return false;
+ }
+
+ auto *Parent = dyn_cast_or_null<MDNode>(MD->getOperand(1));
+ return Parent && Visited.insert(Parent).second &&
+ (IsRootTBAANode(Parent) || IsScalarTBAANodeImpl(Parent, Visited));
+}
+
+bool TBAAVerifier::isValidScalarTBAANode(const MDNode *MD) {
+ auto ResultIt = TBAAScalarNodes.find(MD);
+ if (ResultIt != TBAAScalarNodes.end())
+ return ResultIt->second;
+
+ SmallPtrSet<const MDNode *, 4> Visited;
+ bool Result = IsScalarTBAANodeImpl(MD, Visited);
+ auto InsertResult = TBAAScalarNodes.insert({MD, Result});
+ (void)InsertResult;
+ assert(InsertResult.second && "Just checked!");
+
+ return Result;
+}
+
+/// Returns the field node at the offset \p Offset in \p BaseNode. Update \p
+/// Offset in place to be the offset within the field node returned.
+///
+/// We assume we've okayed \p BaseNode via \c verifyTBAABaseNode.
+MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I,
+ const MDNode *BaseNode,
+ APInt &Offset) {
+ assert(BaseNode->getNumOperands() >= 2 && "Invalid base node!");
+
+ // Scalar nodes have only one possible "field" -- their parent in the access
+ // hierarchy. Offset must be zero at this point, but our caller is supposed
+ // to Assert that.
+ if (BaseNode->getNumOperands() == 2)
+ return cast<MDNode>(BaseNode->getOperand(1));
+
+ for (unsigned Idx = 1; Idx < BaseNode->getNumOperands(); Idx += 2) {
+ auto *OffsetEntryCI =
+ mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx + 1));
+ if (OffsetEntryCI->getValue().ugt(Offset)) {
+ if (Idx == 1) {
+ CheckFailed("Could not find TBAA parent in struct type node", &I,
+ BaseNode, &Offset);
+ return nullptr;
+ }
+
+ auto *PrevOffsetEntryCI =
+ mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx - 1));
+ Offset -= PrevOffsetEntryCI->getValue();
+ return cast<MDNode>(BaseNode->getOperand(Idx - 2));
+ }
+ }
+
+ auto *LastOffsetEntryCI = mdconst::extract<ConstantInt>(
+ BaseNode->getOperand(BaseNode->getNumOperands() - 1));
+
+ Offset -= LastOffsetEntryCI->getValue();
+ return cast<MDNode>(BaseNode->getOperand(BaseNode->getNumOperands() - 2));
+}
+
+bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
+ AssertTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) ||
+ isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) ||
+ isa<AtomicCmpXchgInst>(I),
+ "TBAA is only for loads, stores and calls!", &I);
+
+ bool IsStructPathTBAA =
+ isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3;
+
+ AssertTBAA(
+ IsStructPathTBAA,
+ "Old-style TBAA is no longer allowed, use struct-path TBAA instead", &I);
+
+ AssertTBAA(MD->getNumOperands() < 5,
+ "Struct tag metadata must have either 3 or 4 operands", &I, MD);
+
+ MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0));
+ MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1));
+
+ if (MD->getNumOperands() == 4) {
+ auto *IsImmutableCI =
+ mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(3));
+ AssertTBAA(IsImmutableCI,
+ "Immutability tag on struct tag metadata must be a constant", &I,
+ MD);
+ AssertTBAA(
+ IsImmutableCI->isZero() || IsImmutableCI->isOne(),
+ "Immutability part of the struct tag metadata must be either 0 or 1",
+ &I, MD);
+ }
+
+ AssertTBAA(BaseNode && AccessType,
+ "Malformed struct tag metadata: base and access-type "
+ "should be non-null and point to Metadata nodes",
+ &I, MD, BaseNode, AccessType);
+
+ AssertTBAA(isValidScalarTBAANode(AccessType),
+ "Access type node must be a valid scalar type", &I, MD,
+ AccessType);
+
+ auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2));
+ AssertTBAA(OffsetCI, "Offset must be constant integer", &I, MD);
+
+ APInt Offset = OffsetCI->getValue();
+ bool SeenAccessTypeInPath = false;
+
+ SmallPtrSet<MDNode *, 4> StructPath;
+
+ for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode);
+ BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset)) {
+ if (!StructPath.insert(BaseNode).second) {
+ CheckFailed("Cycle detected in struct path", &I, MD);
+ return false;
+ }
+
+ bool Invalid;
+ unsigned BaseNodeBitWidth;
+ std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode);
+
+ // If the base node is invalid in itself, then we've already printed all the
+ // errors we wanted to print.
+ if (Invalid)
+ return false;
+
+ SeenAccessTypeInPath |= BaseNode == AccessType;
+
+ if (isValidScalarTBAANode(BaseNode) || BaseNode == AccessType)
+ AssertTBAA(Offset == 0, "Offset not zero at the point of scalar access",
+ &I, MD, &Offset);
+
+ AssertTBAA(BaseNodeBitWidth == Offset.getBitWidth() ||
+ (BaseNodeBitWidth == 0 && Offset == 0),
+ "Access bit-width not the same as description bit-width", &I, MD,
+ BaseNodeBitWidth, Offset.getBitWidth());
+ }
+
+ AssertTBAA(SeenAccessTypeInPath, "Did not see access type in access path!",
+ &I, MD);
+ return true;
}
char VerifierLegacyPass::ID = 0;
@@ -4371,7 +4792,7 @@ FunctionPass *llvm::createVerifierPass(bool FatalErrors) {
return new VerifierLegacyPass(FatalErrors);
}
-char VerifierAnalysis::PassID;
+AnalysisKey VerifierAnalysis::Key;
VerifierAnalysis::Result VerifierAnalysis::run(Module &M,
ModuleAnalysisManager &) {
Result Res;
OpenPOWER on IntegriCloud