#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/DebugInfo.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
-#include "llvm/InstVisitor.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include <cstdarg>
using namespace llvm;
-static cl::opt<bool> DisableDebugInfoVerifier("disable-debug-info-verifier",
- cl::init(true));
+static cl::opt<bool> VerifyDebugInfo("verify-debug-info", cl::init(false));
namespace {
class Verifier : public InstVisitor<Verifier> {
InstsInThisBlock.clear();
PersonalityFn = 0;
- if (!DisableDebugInfoVerifier)
+ if (VerifyDebugInfo)
// Verify Debug Info.
verifyDebugInfo();
visitModuleFlags(M);
visitModuleIdents(M);
- if (!DisableDebugInfoVerifier) {
+ if (VerifyDebugInfo) {
Finder.reset();
Finder.processModule(M);
// Verify Debug Info.
Assert1(!GA.getAlignment(), "Alias connot have an alignment", &GA);
const Constant *Aliasee = GA.getAliasee();
+ const GlobalValue *GV = dyn_cast<GlobalValue>(Aliasee);
- if (!isa<GlobalValue>(Aliasee)) {
+ if (!GV) {
const ConstantExpr *CE = dyn_cast<ConstantExpr>(Aliasee);
- Assert1(CE &&
- (CE->getOpcode() == Instruction::BitCast ||
- CE->getOpcode() == Instruction::AddrSpaceCast ||
- CE->getOpcode() == Instruction::GetElementPtr) &&
- isa<GlobalValue>(CE->getOperand(0)),
- "Aliasee should be either GlobalValue, bitcast or "
- "addrspacecast of GlobalValue",
+ if (CE && (CE->getOpcode() == Instruction::BitCast ||
+ CE->getOpcode() == Instruction::AddrSpaceCast ||
+ CE->getOpcode() == Instruction::GetElementPtr))
+ GV = dyn_cast<GlobalValue>(CE->getOperand(0));
+
+ Assert1(GV, "Aliasee should be either GlobalValue, bitcast or "
+ "addrspacecast of GlobalValue",
&GA);
if (CE->getOpcode() == Instruction::BitCast) {
- unsigned SrcAS = CE->getOperand(0)->getType()->getPointerAddressSpace();
+ unsigned SrcAS = GV->getType()->getPointerAddressSpace();
unsigned DstAS = CE->getType()->getPointerAddressSpace();
Assert1(SrcAS == DstAS,
&GA);
}
}
+ Assert1(!GV->isDeclaration(), "Alias must point to a definition", &GA);
+ if (const GlobalAlias *GAAliasee = dyn_cast<GlobalAlias>(GV)) {
+ Assert1(!GAAliasee->mayBeOverridden(), "Alias cannot point to a weak alias",
+ &GA);
+ }
- const GlobalValue* Resolved = GA.resolveAliasedGlobal(/*stopOnWeak*/ false);
- Assert1(Resolved,
- "Aliasing chain should end with function or global variable", &GA);
+ const GlobalValue *AG = GA.getAliasedGlobal();
+ Assert1(AG, "Aliasing chain should end with function or global variable",
+ &GA);
visitGlobalValue(GA);
}
}
void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) {
- Assert1(CXI.getOrdering() != NotAtomic,
+
+ // FIXME: more conditions???
+ Assert1(CXI.getSuccessOrdering() != NotAtomic,
"cmpxchg instructions must be atomic.", &CXI);
- Assert1(CXI.getOrdering() != Unordered,
+ Assert1(CXI.getFailureOrdering() != NotAtomic,
+ "cmpxchg instructions must be atomic.", &CXI);
+ Assert1(CXI.getSuccessOrdering() != Unordered,
+ "cmpxchg instructions cannot be unordered.", &CXI);
+ Assert1(CXI.getFailureOrdering() != Unordered,
"cmpxchg instructions cannot be unordered.", &CXI);
+ Assert1(CXI.getSuccessOrdering() >= CXI.getFailureOrdering(),
+ "cmpxchg instructions be at least as constrained on success as fail",
+ &CXI);
+ Assert1(CXI.getFailureOrdering() != Release &&
+ CXI.getFailureOrdering() != AcquireRelease,
+ "cmpxchg failure ordering cannot include release semantics", &CXI);
+
PointerType *PTy = dyn_cast<PointerType>(CXI.getOperand(0)->getType());
Assert1(PTy, "First cmpxchg operand must be a pointer.", &CXI);
Type *ElTy = PTy->getElementType();
Assert1(BB, "Instruction not embedded in basic block!", &I);
if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential
- for (Value::use_iterator UI = I.use_begin(), UE = I.use_end();
- UI != UE; ++UI)
- Assert1(*UI != (User*)&I || !DT.isReachableFromEntry(BB),
+ for (User *U : I.users()) {
+ Assert1(U != (User*)&I || !DT.isReachableFromEntry(BB),
"Only PHI nodes may reference their own value!", &I);
+ }
}
// Check that void typed values don't have names
// Check that all uses of the instruction, if they are instructions
// themselves, actually have parent basic blocks. If the use is not an
// instruction, it is an error!
- for (User::use_iterator UI = I.use_begin(), UE = I.use_end();
- UI != UE; ++UI) {
- if (Instruction *Used = dyn_cast<Instruction>(*UI))
+ for (Use &U : I.uses()) {
+ if (Instruction *Used = dyn_cast<Instruction>(U.getUser()))
Assert2(Used->getParent() != 0, "Instruction referencing instruction not"
" embedded in a basic block!", &I, Used);
else {
- CheckFailed("Use of instruction is not an instruction!", *UI);
+ CheckFailed("Use of instruction is not an instruction!", U);
return;
}
}
MDNode *MD = I.getMetadata(LLVMContext::MD_range);
Assert1(!MD || isa<LoadInst>(I), "Ranges are only for loads!", &I);
- if (!DisableDebugInfoVerifier) {
+ if (VerifyDebugInfo) {
MD = I.getMetadata(LLVMContext::MD_dbg);
Finder.processLocation(*M, DILocation(MD));
}
}
llvm_unreachable("all argument kinds not covered");
- case IITDescriptor::ExtendVecArgument:
+ case IITDescriptor::ExtendArgument: {
// This may only be used when referring to a previous vector argument.
- return D.getArgumentNumber() >= ArgTys.size() ||
- !isa<VectorType>(ArgTys[D.getArgumentNumber()]) ||
- VectorType::getExtendedElementVectorType(
- cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty;
+ if (D.getArgumentNumber() >= ArgTys.size())
+ return true;
+
+ Type *NewTy = ArgTys[D.getArgumentNumber()];
+ if (VectorType *VTy = dyn_cast<VectorType>(NewTy))
+ NewTy = VectorType::getExtendedElementVectorType(VTy);
+ else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy))
+ NewTy = IntegerType::get(ITy->getContext(), 2 * ITy->getBitWidth());
+ else
+ return true;
- case IITDescriptor::TruncVecArgument:
+ return Ty != NewTy;
+ }
+ case IITDescriptor::TruncArgument: {
+ // This may only be used when referring to a previous vector argument.
+ if (D.getArgumentNumber() >= ArgTys.size())
+ return true;
+
+ Type *NewTy = ArgTys[D.getArgumentNumber()];
+ if (VectorType *VTy = dyn_cast<VectorType>(NewTy))
+ NewTy = VectorType::getTruncatedElementVectorType(VTy);
+ else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy))
+ NewTy = IntegerType::get(ITy->getContext(), ITy->getBitWidth() / 2);
+ else
+ return true;
+
+ return Ty != NewTy;
+ }
+ case IITDescriptor::HalfVecArgument:
// This may only be used when referring to a previous vector argument.
return D.getArgumentNumber() >= ArgTys.size() ||
!isa<VectorType>(ArgTys[D.getArgumentNumber()]) ||
- VectorType::getTruncatedElementVectorType(
+ VectorType::getHalfElementsVectorType(
cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty;
}
llvm_unreachable("unhandled");
// know they are legal for the intrinsic!) get the intrinsic name through the
// usual means. This allows us to verify the mangling of argument types into
// the name.
- Assert1(Intrinsic::getName(ID, ArgTys) == IF->getName(),
- "Intrinsic name not mangled correctly for type arguments!", IF);
+ const std::string ExpectedName = Intrinsic::getName(ID, ArgTys);
+ Assert1(ExpectedName == IF->getName(),
+ "Intrinsic name not mangled correctly for type arguments! "
+ "Should be: " + ExpectedName, IF);
// If the intrinsic takes MDNode arguments, verify that they are either global
// or are local to *this* function.
MDNode *MD = cast<MDNode>(CI.getArgOperand(0));
Assert1(MD->getNumOperands() == 1,
"invalid llvm.dbg.declare intrinsic call 2", &CI);
- if (!DisableDebugInfoVerifier)
+ if (VerifyDebugInfo)
Finder.processDeclare(*M, cast<DbgDeclareInst>(&CI));
} break;
case Intrinsic::dbg_value: { //llvm.dbg.value
- if (!DisableDebugInfoVerifier) {
+ if (VerifyDebugInfo) {
Assert1(CI.getArgOperand(0) && isa<MDNode>(CI.getArgOperand(0)),
"invalid llvm.dbg.value intrinsic call 1", &CI);
Finder.processValue(*M, cast<DbgValueInst>(&CI));
void Verifier::verifyDebugInfo() {
// Verify Debug Info.
- if (!DisableDebugInfoVerifier) {
- for (DebugInfoFinder::iterator I = Finder.compile_unit_begin(),
- E = Finder.compile_unit_end(); I != E; ++I)
- Assert1(DICompileUnit(*I).Verify(), "DICompileUnit does not Verify!", *I);
- for (DebugInfoFinder::iterator I = Finder.subprogram_begin(),
- E = Finder.subprogram_end(); I != E; ++I)
- Assert1(DISubprogram(*I).Verify(), "DISubprogram does not Verify!", *I);
- for (DebugInfoFinder::iterator I = Finder.global_variable_begin(),
- E = Finder.global_variable_end(); I != E; ++I)
- Assert1(DIGlobalVariable(*I).Verify(),
- "DIGlobalVariable does not Verify!", *I);
- for (DebugInfoFinder::iterator I = Finder.type_begin(),
- E = Finder.type_end(); I != E; ++I)
- Assert1(DIType(*I).Verify(), "DIType does not Verify!", *I);
- for (DebugInfoFinder::iterator I = Finder.scope_begin(),
- E = Finder.scope_end(); I != E; ++I)
- Assert1(DIScope(*I).Verify(), "DIScope does not Verify!", *I);
+ if (VerifyDebugInfo) {
+ for (DICompileUnit CU : Finder.compile_units()) {
+ Assert1(CU.Verify(), "DICompileUnit does not Verify!", CU);
+ }
+ for (DISubprogram S : Finder.subprograms()) {
+ Assert1(S.Verify(), "DISubprogram does not Verify!", S);
+ }
+ for (DIGlobalVariable GV : Finder.global_variables()) {
+ Assert1(GV.Verify(), "DIGlobalVariable does not Verify!", GV);
+ }
+ for (DIType T : Finder.types()) {
+ Assert1(T.Verify(), "DIType does not Verify!", T);
+ }
+ for (DIScope S : Finder.scopes()) {
+ Assert1(S.Verify(), "DIScope does not Verify!", S);
+ }
}
}
initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
}
- bool runOnFunction(Function &F) {
+ bool runOnFunction(Function &F) override {
if (!V.verify(F) && FatalErrors)
report_fatal_error("Broken function found, compilation aborted!");
return false;
}
- bool doFinalization(Module &M) {
+ bool doFinalization(Module &M) override {
if (!V.verify(M) && FatalErrors)
report_fatal_error("Broken module found, compilation aborted!");
return false;
}
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};