summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/Verifier.h45
-rw-r--r--llvm/include/llvm/InitializePasses.h2
-rw-r--r--llvm/lib/Analysis/Analysis.cpp25
-rw-r--r--llvm/lib/IR/Core.cpp2
-rw-r--r--llvm/lib/IR/Verifier.cpp299
-rw-r--r--llvm/test/Verifier/2010-08-07-PointerIntrinsic.ll5
-rw-r--r--llvm/tools/llvm-as/llvm-as.cpp7
-rw-r--r--llvm/unittests/IR/VerifierTest.cpp15
8 files changed, 201 insertions, 199 deletions
diff --git a/llvm/include/llvm/IR/Verifier.h b/llvm/include/llvm/IR/Verifier.h
index 9f6cb42e11f..f5d8945ea06 100644
--- a/llvm/include/llvm/IR/Verifier.h
+++ b/llvm/include/llvm/IR/Verifier.h
@@ -28,44 +28,31 @@ namespace llvm {
class FunctionPass;
class Module;
class Function;
-
-/// \brief An enumeration to specify the action to be taken if errors found.
-///
-/// This enumeration is used in the functions below to indicate what should
-/// happen if the verifier finds errors. Each of the functions that uses
-/// this enumeration as an argument provides a default value for it. The
-/// actions are listed below.
-enum VerifierFailureAction {
- AbortProcessAction, ///< verifyModule will print to stderr and abort()
- PrintMessageAction, ///< verifyModule will print to stderr and return true
- ReturnStatusAction ///< verifyModule will just return true
-};
-
-/// \brief Create a verifier pass.
-///
-/// Check a module or function for validity. When the pass is used, the
-/// action indicated by the \p action argument will be used if errors are
-/// found.
-FunctionPass *
-createVerifierPass(VerifierFailureAction action = AbortProcessAction);
+class raw_ostream;
/// \brief Check a function for errors, useful for use when debugging a
/// pass.
///
/// If there are no errors, the function returns false. If an error is found,
-/// the action taken depends on the \p action parameter.
-bool verifyFunction(const Function &F,
- VerifierFailureAction action = AbortProcessAction);
+/// a message describing the error is written to OS (if non-null) and false is
+/// returned.
+bool verifyFunction(const Function &F, raw_ostream *OS = 0);
/// \brief Check a module for errors.
///
/// If there are no errors, the function returns false. If an error is found,
-/// the action taken depends on the \p action parameter.
-/// This should only be used for debugging, because it plays games with
-/// PassManagers and stuff.
-bool verifyModule(const Module &M,
- VerifierFailureAction action = AbortProcessAction,
- std::string *ErrorInfo = 0);
+/// a message describing the error is written to OS (if non-null) and false is
+/// returned.
+bool verifyModule(const Module &M, raw_ostream *OS = 0);
+
+/// \brief Create a verifier pass.
+///
+/// Check a module or function for validity. This is essentially a pass wrapped
+/// around the above verifyFunction and verifyModule routines and
+/// functionality. When the pass detects a verification error it is always
+/// printed to stderr, and by default they are fatal. You can override that by
+/// passing \c false to \p FatalErrors.
+FunctionPass *createVerifierPass(bool FatalErrors = true);
} // End llvm namespace
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index a88d94945a8..e08e0c4baf2 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -256,7 +256,7 @@ void initializeTypeBasedAliasAnalysisPass(PassRegistry&);
void initializeUnifyFunctionExitNodesPass(PassRegistry&);
void initializeUnreachableBlockElimPass(PassRegistry&);
void initializeUnreachableMachineBlockElimPass(PassRegistry&);
-void initializeVerifierPass(PassRegistry&);
+void initializeVerifierPassPass(PassRegistry&);
void initializeVirtRegMapPass(PassRegistry&);
void initializeVirtRegRewriterPass(PassRegistry&);
void initializeInstSimplifierPass(PassRegistry&);
diff --git a/llvm/lib/Analysis/Analysis.cpp b/llvm/lib/Analysis/Analysis.cpp
index ef99e35ffda..c9ce1643c3d 100644
--- a/llvm/lib/Analysis/Analysis.cpp
+++ b/llvm/lib/Analysis/Analysis.cpp
@@ -11,6 +11,7 @@
#include "llvm-c/Initialization.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/InitializePasses.h"
#include "llvm/PassRegistry.h"
#include <cstring>
@@ -72,21 +73,33 @@ void LLVMInitializeAnalysis(LLVMPassRegistryRef R) {
LLVMBool LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action,
char **OutMessages) {
+ raw_ostream *DebugOS = Action != LLVMReturnStatusAction ? &errs() : 0;
std::string Messages;
+ raw_string_ostream MsgsOS(Messages);
- LLVMBool Result = verifyModule(*unwrap(M),
- static_cast<VerifierFailureAction>(Action),
- OutMessages? &Messages : 0);
+ LLVMBool Result = verifyModule(*unwrap(M), OutMessages ? &MsgsOS : DebugOS);
+
+ // Duplicate the output to stderr.
+ if (DebugOS && OutMessages)
+ *DebugOS << MsgsOS.str();
+
+ if (Action == LLVMAbortProcessAction && Result)
+ report_fatal_error("Broken module found, compilation aborted!");
if (OutMessages)
- *OutMessages = strdup(Messages.c_str());
+ *OutMessages = strdup(MsgsOS.str().c_str());
return Result;
}
LLVMBool LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action) {
- return verifyFunction(*unwrap<Function>(Fn),
- static_cast<VerifierFailureAction>(Action));
+ LLVMBool Result = verifyFunction(
+ *unwrap<Function>(Fn), Action != LLVMReturnStatusAction ? &errs() : 0);
+
+ if (Action == LLVMAbortProcessAction && Result)
+ report_fatal_error("Broken function found, compilation aborted!");
+
+ return Result;
}
void LLVMViewFunctionCFG(LLVMValueRef Fn) {
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 1417e5dc4fd..cd7cb9ed147 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -44,7 +44,7 @@ void llvm::initializeCore(PassRegistry &Registry) {
initializePrintModulePassWrapperPass(Registry);
initializePrintFunctionPassWrapperPass(Registry);
initializePrintBasicBlockPassPass(Registry);
- initializeVerifierPass(Registry);
+ initializeVerifierPassPass(Registry);
}
void LLVMInitializeCore(LLVMPassRegistryRef R) {
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index a004955e807..feea4850195 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -80,21 +80,15 @@ static cl::opt<bool> DisableDebugInfoVerifier("disable-debug-info-verifier",
cl::init(true));
namespace {
-struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
- static char ID;
-
- // What to do if verification fails.
- VerifierFailureAction Action;
+class Verifier : public InstVisitor<Verifier> {
+ friend class InstVisitor<Verifier>;
- Module *M;
+ raw_ostream &OS;
+ const Module *M;
LLVMContext *Context;
const DataLayout *DL;
DominatorTree DT;
- bool Broken;
- std::string Messages;
- raw_string_ostream MessagesStr;
-
/// \brief When verifying a basic block, keep track of all of the
/// instructions we have seen so far.
///
@@ -113,57 +107,45 @@ struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
/// \brief Finder keeps track of all debug info MDNodes in a Module.
DebugInfoFinder Finder;
- Verifier()
- : FunctionPass(ID), Action(AbortProcessAction), M(0), Context(0), DL(0),
- Broken(false), MessagesStr(Messages), PersonalityFn(0) {
- initializeVerifierPass(*PassRegistry::getPassRegistry());
- }
- explicit Verifier(VerifierFailureAction Action)
- : FunctionPass(ID), Action(Action), M(0), Context(0), DL(0),
- Broken(false), MessagesStr(Messages), PersonalityFn(0) {
- initializeVerifierPass(*PassRegistry::getPassRegistry());
- }
-
- bool doInitialization(Module &M) {
- this->M = &M;
- Context = &M.getContext();
-
- DL = getAnalysisIfAvailable<DataLayout>();
+ /// \brief Track the brokenness of the module while recursively visiting.
+ bool Broken;
- // We must abort before returning back to the pass manager, or else the
- // pass manager may try to run other passes on the broken module.
- return abortIfBroken();
- }
+public:
+ explicit Verifier(raw_ostream &OS = dbgs())
+ : OS(OS), M(0), Context(0), DL(0), PersonalityFn(0), Broken(false) {}
- bool runOnFunction(Function &F) {
- Broken = false;
+ bool verify(const Function &F) {
+ M = F.getParent();
+ Context = &M->getContext();
// First ensure the function is well-enough formed to compute dominance
// information.
- for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
+ if (F.empty()) {
+ OS << "Function '" << F.getName()
+ << "' does not contain an entry block!\n";
+ return false;
+ }
+ for (Function::const_iterator I = F.begin(), E = F.end(); I != E; ++I) {
if (I->empty() || !I->back().isTerminator()) {
- dbgs() << "Basic Block in function '" << F.getName()
- << "' does not have terminator!\n";
- I->printAsOperand(dbgs(), true);
- dbgs() << "\n";
- Broken = true;
+ OS << "Basic Block in function '" << F.getName()
+ << "' does not have terminator!\n";
+ I->printAsOperand(OS, true);
+ OS << "\n";
+ return false;
}
}
- if (Broken)
- return abortIfBroken();
// Now 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.
- DT.recalculate(F);
-
- M = F.getParent();
- if (!Context)
- Context = &F.getContext();
+ // FIXME: It's really gross that we have to cast away constness here.
+ DT.recalculate(const_cast<Function &>(F));
Finder.reset();
- visit(F);
+ Broken = false;
+ // FIXME: We strip const here because the inst visitor strips const.
+ visit(const_cast<Function &>(F));
InstsInThisBlock.clear();
PersonalityFn = 0;
@@ -171,14 +153,17 @@ struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
// Verify Debug Info.
verifyDebugInfo();
- // We must abort before returning back to the pass manager, or else the
- // pass manager may try to run other passes on the broken module.
- return abortIfBroken();
+ return !Broken;
}
- bool doFinalization(Module &M) {
+ bool verify(const Module &M) {
+ this->M = &M;
+ Context = &M.getContext();
+ Finder.reset();
+ Broken = false;
+
// Scan through, checking all of the external function's linkage now...
- for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
visitGlobalValue(*I);
// Check to make sure function prototypes are okay.
@@ -186,16 +171,16 @@ struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
visitFunction(*I);
}
- for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+ for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I)
visitGlobalVariable(*I);
- for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E;
- ++I)
+ for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
+ I != E; ++I)
visitGlobalAlias(*I);
- for (Module::named_metadata_iterator I = M.named_metadata_begin(),
- E = M.named_metadata_end();
+ for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
+ E = M.named_metadata_end();
I != E; ++I)
visitNamedMDNode(*I);
@@ -209,52 +194,26 @@ struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
verifyDebugInfo();
}
- // If the module is broken, abort at this time.
- return abortIfBroken();
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- }
-
- /// abortIfBroken - If the module is broken and we are supposed to abort on
- /// this condition, do so.
- ///
- bool abortIfBroken() {
- if (!Broken)
- return false;
- MessagesStr << "Broken module found, ";
- switch (Action) {
- case AbortProcessAction:
- MessagesStr << "compilation aborted!\n";
- dbgs() << MessagesStr.str();
- // Client should choose different reaction if abort is not desired
- abort();
- case PrintMessageAction:
- MessagesStr << "verification continues.\n";
- dbgs() << MessagesStr.str();
- return false;
- case ReturnStatusAction:
- MessagesStr << "compilation terminated.\n";
- return true;
- }
- llvm_unreachable("Invalid action");
+ return !Broken;
}
+private:
// Verification methods...
- void visitGlobalValue(GlobalValue &GV);
- void visitGlobalVariable(GlobalVariable &GV);
- void visitGlobalAlias(GlobalAlias &GA);
- void visitNamedMDNode(NamedMDNode &NMD);
+ void visitGlobalValue(const GlobalValue &GV);
+ void visitGlobalVariable(const GlobalVariable &GV);
+ void visitGlobalAlias(const GlobalAlias &GA);
+ void visitNamedMDNode(const NamedMDNode &NMD);
void visitMDNode(MDNode &MD, Function *F);
- void visitModuleIdents(Module &M);
- void visitModuleFlags(Module &M);
- void visitModuleFlag(MDNode *Op, DenseMap<MDString *, MDNode *> &SeenIDs,
- SmallVectorImpl<MDNode *> &Requirements);
- void visitFunction(Function &F);
+ void visitModuleIdents(const Module &M);
+ void visitModuleFlags(const Module &M);
+ void visitModuleFlag(const MDNode *Op,
+ DenseMap<const MDString *, const MDNode *> &SeenIDs,
+ SmallVectorImpl<const MDNode *> &Requirements);
+ void visitFunction(const Function &F);
void visitBasicBlock(BasicBlock &BB);
- using InstVisitor<Verifier>::visit;
+ // InstVisitor overrides...
+ using InstVisitor<Verifier>::visit;
void visit(Instruction &I);
void visitTruncInst(TruncInst &I);
@@ -326,17 +285,17 @@ struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
if (!V)
return;
if (isa<Instruction>(V)) {
- MessagesStr << *V << '\n';
+ OS << *V << '\n';
} else {
- V->printAsOperand(MessagesStr, true, M);
- MessagesStr << '\n';
+ V->printAsOperand(OS, true, M);
+ OS << '\n';
}
}
void WriteType(Type *T) {
if (!T)
return;
- MessagesStr << ' ' << *T;
+ OS << ' ' << *T;
}
// CheckFailed - A check failed, so print out the condition and the message
@@ -345,7 +304,7 @@ struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
void CheckFailed(const Twine &Message, const Value *V1 = 0,
const Value *V2 = 0, const Value *V3 = 0,
const Value *V4 = 0) {
- MessagesStr << Message.str() << "\n";
+ OS << Message.str() << "\n";
WriteValue(V1);
WriteValue(V2);
WriteValue(V3);
@@ -355,7 +314,7 @@ struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
void CheckFailed(const Twine &Message, const Value *V1, Type *T2,
const Value *V3 = 0) {
- MessagesStr << Message.str() << "\n";
+ OS << Message.str() << "\n";
WriteValue(V1);
WriteType(T2);
WriteValue(V3);
@@ -363,7 +322,7 @@ struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
}
void CheckFailed(const Twine &Message, Type *T1, Type *T2 = 0, Type *T3 = 0) {
- MessagesStr << Message.str() << "\n";
+ OS << Message.str() << "\n";
WriteType(T1);
WriteType(T2);
WriteType(T3);
@@ -372,9 +331,6 @@ struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
};
} // End anonymous namespace
-char Verifier::ID = 0;
-INITIALIZE_PASS(Verifier, "verify", "Module Verifier", false, false)
-
// Assert - We know that cond should be true, if not print an error message.
#define Assert(C, M) \
do { if (!(C)) { CheckFailed(M); return; } } while (0)
@@ -394,7 +350,7 @@ void Verifier::visit(Instruction &I) {
}
-void Verifier::visitGlobalValue(GlobalValue &GV) {
+void Verifier::visitGlobalValue(const GlobalValue &GV) {
Assert1(!GV.isDeclaration() ||
GV.isMaterializable() ||
GV.hasExternalLinkage() ||
@@ -408,13 +364,13 @@ void Verifier::visitGlobalValue(GlobalValue &GV) {
"Only global variables can have appending linkage!", &GV);
if (GV.hasAppendingLinkage()) {
- GlobalVariable *GVar = dyn_cast<GlobalVariable>(&GV);
+ const GlobalVariable *GVar = dyn_cast<GlobalVariable>(&GV);
Assert1(GVar && GVar->getType()->getElementType()->isArrayTy(),
"Only global arrays can have appending linkage!", GVar);
}
}
-void Verifier::visitGlobalVariable(GlobalVariable &GV) {
+void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
if (GV.hasInitializer()) {
Assert1(GV.getInitializer()->getType() == GV.getType()->getElementType(),
"Global variable initializer type does not match global "
@@ -459,8 +415,8 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType());
Assert1(PTy, "wrong type for intrinsic global variable", &GV);
if (GV.hasInitializer()) {
- Constant *Init = GV.getInitializer();
- ConstantArray *InitArray = dyn_cast<ConstantArray>(Init);
+ const Constant *Init = GV.getInitializer();
+ const ConstantArray *InitArray = dyn_cast<ConstantArray>(Init);
Assert1(InitArray, "wrong initalizer for intrinsic global variable",
Init);
for (unsigned i = 0, e = InitArray->getNumOperands(); i != e; ++i) {
@@ -509,7 +465,7 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
visitGlobalValue(GV);
}
-void Verifier::visitGlobalAlias(GlobalAlias &GA) {
+void Verifier::visitGlobalAlias(const GlobalAlias &GA) {
Assert1(!GA.getName().empty(),
"Alias name cannot be empty!", &GA);
Assert1(GlobalAlias::isValidLinkage(GA.getLinkage()),
@@ -520,10 +476,10 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) {
"Alias and aliasee types should match!", &GA);
Assert1(!GA.hasUnnamedAddr(), "Alias cannot have unnamed_addr!", &GA);
- Constant *Aliasee = GA.getAliasee();
+ const Constant *Aliasee = GA.getAliasee();
if (!isa<GlobalValue>(Aliasee)) {
- ConstantExpr *CE = dyn_cast<ConstantExpr>(Aliasee);
+ const ConstantExpr *CE = dyn_cast<ConstantExpr>(Aliasee);
Assert1(CE &&
(CE->getOpcode() == Instruction::BitCast ||
CE->getOpcode() == Instruction::AddrSpaceCast ||
@@ -550,7 +506,7 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) {
visitGlobalValue(GA);
}
-void Verifier::visitNamedMDNode(NamedMDNode &NMD) {
+void Verifier::visitNamedMDNode(const NamedMDNode &NMD) {
for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i) {
MDNode *MD = NMD.getOperand(i);
if (!MD)
@@ -598,7 +554,7 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) {
}
}
-void Verifier::visitModuleIdents(Module &M) {
+void Verifier::visitModuleIdents(const Module &M) {
const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident");
if (!Idents)
return;
@@ -616,24 +572,24 @@ void Verifier::visitModuleIdents(Module &M) {
}
}
-void Verifier::visitModuleFlags(Module &M) {
+void Verifier::visitModuleFlags(const Module &M) {
const NamedMDNode *Flags = M.getModuleFlagsMetadata();
if (!Flags) return;
// Scan each flag, and track the flags and requirements.
- DenseMap<MDString*, MDNode*> SeenIDs;
- SmallVector<MDNode*, 16> Requirements;
+ DenseMap<const MDString*, const MDNode*> SeenIDs;
+ SmallVector<const MDNode*, 16> Requirements;
for (unsigned I = 0, E = Flags->getNumOperands(); I != E; ++I) {
visitModuleFlag(Flags->getOperand(I), SeenIDs, Requirements);
}
// Validate that the requirements in the module are valid.
for (unsigned I = 0, E = Requirements.size(); I != E; ++I) {
- MDNode *Requirement = Requirements[I];
- MDString *Flag = cast<MDString>(Requirement->getOperand(0));
- Value *ReqValue = Requirement->getOperand(1);
+ const MDNode *Requirement = Requirements[I];
+ const MDString *Flag = cast<MDString>(Requirement->getOperand(0));
+ const Value *ReqValue = Requirement->getOperand(1);
- MDNode *Op = SeenIDs.lookup(Flag);
+ const MDNode *Op = SeenIDs.lookup(Flag);
if (!Op) {
CheckFailed("invalid requirement on flag, flag is not present in module",
Flag);
@@ -649,8 +605,10 @@ void Verifier::visitModuleFlags(Module &M) {
}
}
-void Verifier::visitModuleFlag(MDNode *Op, DenseMap<MDString*, MDNode*>&SeenIDs,
- SmallVectorImpl<MDNode*> &Requirements) {
+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.
Assert1(Op->getNumOperands() == 3,
@@ -987,7 +945,7 @@ bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) {
// visitFunction - Verify that a function is ok.
//
-void Verifier::visitFunction(Function &F) {
+void Verifier::visitFunction(const Function &F) {
// Check function arguments.
FunctionType *FT = F.getFunctionType();
unsigned NumArgs = F.arg_size();
@@ -1045,8 +1003,8 @@ void Verifier::visitFunction(Function &F) {
// Check that the argument values match the function type for this function...
unsigned i = 0;
- for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
- I != E; ++I, ++i) {
+ for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E;
+ ++I, ++i) {
Assert2(I->getType() == FT->getParamType(i),
"Argument value does not match function argument type!",
I, FT->getParamType(i));
@@ -1068,13 +1026,13 @@ void Verifier::visitFunction(Function &F) {
Assert1(!isLLVMdotName, "llvm intrinsics cannot be defined!", &F);
// Check the entry node
- BasicBlock *Entry = &F.getEntryBlock();
+ const BasicBlock *Entry = &F.getEntryBlock();
Assert1(pred_begin(Entry) == pred_end(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()) {
- Assert1(!BlockAddress::get(Entry)->isConstantUsed(),
+ Assert1(!BlockAddress::lookup(Entry)->isConstantUsed(),
"blockaddress may not be used with the entry block!", Entry);
}
}
@@ -2402,30 +2360,71 @@ void Verifier::verifyDebugInfo() {
// Implement the public interfaces to this file...
//===----------------------------------------------------------------------===//
-FunctionPass *llvm::createVerifierPass(VerifierFailureAction action) {
- return new Verifier(action);
-}
-
-bool llvm::verifyFunction(const Function &f, VerifierFailureAction action) {
+bool llvm::verifyFunction(const Function &f, raw_ostream *OS) {
Function &F = const_cast<Function &>(f);
assert(!F.isDeclaration() && "Cannot verify external functions");
- FunctionPassManager FPM(F.getParent());
- Verifier *V = new Verifier(action);
- FPM.add(V);
- FPM.doInitialization();
- FPM.run(F);
- return V->Broken;
+ raw_null_ostream NullStr;
+ Verifier V(OS ? *OS : NullStr);
+
+ // Note that this function's return value is inverted from what you would
+ // expect of a function called "verify".
+ return !V.verify(F);
+}
+
+bool llvm::verifyModule(const Module &M, raw_ostream *OS) {
+ raw_null_ostream NullStr;
+ Verifier V(OS ? *OS : NullStr);
+
+ bool Broken = false;
+ for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
+ if (!I->isDeclaration())
+ Broken |= !V.verify(*I);
+
+ // Note that this function's return value is inverted from what you would
+ // expect of a function called "verify".
+ return !V.verify(M) || Broken;
+}
+
+namespace {
+struct VerifierPass : public FunctionPass {
+ static char ID;
+
+ Verifier V;
+ bool FatalErrors;
+
+ VerifierPass() : FunctionPass(ID), FatalErrors(true) {
+ initializeVerifierPassPass(*PassRegistry::getPassRegistry());
+ }
+ explicit VerifierPass(bool FatalErrors)
+ : FunctionPass(ID), V(dbgs()), FatalErrors(FatalErrors) {
+ initializeVerifierPassPass(*PassRegistry::getPassRegistry());
+ }
+
+ bool runOnFunction(Function &F) {
+ if (!V.verify(F) && FatalErrors)
+ report_fatal_error("Broken function found, compilation aborted!");
+
+ return false;
+ }
+
+ bool doFinalization(Module &M) {
+ if (!V.verify(M) && FatalErrors)
+ report_fatal_error("Broken module found, compilation aborted!");
+
+ return false;
+ }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
+};
}
-bool llvm::verifyModule(const Module &M, VerifierFailureAction action,
- std::string *ErrorInfo) {
- PassManager PM;
- Verifier *V = new Verifier(action);
- PM.add(V);
- PM.run(const_cast<Module &>(M));
+char VerifierPass::ID = 0;
+INITIALIZE_PASS(VerifierPass, "verify", "Module Verifier", false, false)
- if (ErrorInfo && V->Broken)
- *ErrorInfo = V->MessagesStr.str();
- return V->Broken;
+FunctionPass *llvm::createVerifierPass(bool FatalErrors) {
+ return new VerifierPass(FatalErrors);
}
+
diff --git a/llvm/test/Verifier/2010-08-07-PointerIntrinsic.ll b/llvm/test/Verifier/2010-08-07-PointerIntrinsic.ll
index a668d04213f..427eb66aa7b 100644
--- a/llvm/test/Verifier/2010-08-07-PointerIntrinsic.ll
+++ b/llvm/test/Verifier/2010-08-07-PointerIntrinsic.ll
@@ -1,6 +1,5 @@
-; RUN: not llvm-as < %s 2> %t
-; RUN: FileCheck %s --input-file=%t
-; CHECK: Broken module
+; RUN: not llvm-as < %s 2>&1 | FileCheck %s
+; CHECK: assembly parsed, but does not verify as correct
; PR7316
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32"
diff --git a/llvm/tools/llvm-as/llvm-as.cpp b/llvm/tools/llvm-as/llvm-as.cpp
index 97e7d160983..d13caf1955e 100644
--- a/llvm/tools/llvm-as/llvm-as.cpp
+++ b/llvm/tools/llvm-as/llvm-as.cpp
@@ -100,11 +100,12 @@ int main(int argc, char **argv) {
}
if (!DisableVerify) {
- std::string Err;
- if (verifyModule(*M.get(), ReturnStatusAction, &Err)) {
+ std::string ErrorStr;
+ raw_string_ostream OS(ErrorStr);
+ if (verifyModule(*M.get(), &OS)) {
errs() << argv[0]
<< ": assembly parsed, but does not verify as correct!\n";
- errs() << Err;
+ errs() << OS.str();
return 1;
}
}
diff --git a/llvm/unittests/IR/VerifierTest.cpp b/llvm/unittests/IR/VerifierTest.cpp
index 8e21fb80fe9..a5ce5fc9d30 100644
--- a/llvm/unittests/IR/VerifierTest.cpp
+++ b/llvm/unittests/IR/VerifierTest.cpp
@@ -42,7 +42,7 @@ TEST(VerifierTest, Branch_i1) {
Constant *Zero32 = ConstantInt::get(IntegerType::get(C, 32), 0);
BI->setOperand(0, Zero32);
- EXPECT_TRUE(verifyFunction(*F, ReturnStatusAction));
+ EXPECT_TRUE(verifyFunction(*F));
}
TEST(VerifierTest, AliasUnnamedAddr) {
@@ -58,8 +58,10 @@ TEST(VerifierTest, AliasUnnamedAddr) {
"bar", Aliasee, &M);
GA->setUnnamedAddr(true);
std::string Error;
- EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error));
- EXPECT_TRUE(StringRef(Error).startswith("Alias cannot have unnamed_addr"));
+ raw_string_ostream ErrorOS(Error);
+ EXPECT_TRUE(verifyModule(M, &ErrorOS));
+ EXPECT_TRUE(
+ StringRef(ErrorOS.str()).startswith("Alias cannot have unnamed_addr"));
}
TEST(VerifierTest, InvalidRetAttribute) {
@@ -72,9 +74,10 @@ TEST(VerifierTest, InvalidRetAttribute) {
Attribute::UWTable));
std::string Error;
- EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error));
- EXPECT_TRUE(StringRef(Error).
- startswith("Attribute 'uwtable' only applies to functions!"));
+ raw_string_ostream ErrorOS(Error);
+ EXPECT_TRUE(verifyModule(M, &ErrorOS));
+ EXPECT_TRUE(StringRef(ErrorOS.str()).startswith(
+ "Attribute 'uwtable' only applies to functions!"));
}
}
OpenPOWER on IntegriCloud