[llvm] r199569 - [PM] Make the verifier work independently of any pass manager.

Chandler Carruth chandlerc at gmail.com
Sat Jan 18 18:22:19 PST 2014


Author: chandlerc
Date: Sat Jan 18 20:22:18 2014
New Revision: 199569

URL: http://llvm.org/viewvc/llvm-project?rev=199569&view=rev
Log:
[PM] Make the verifier work independently of any pass manager.

This makes the 'verifyFunction' and 'verifyModule' functions totally
independent operations on the LLVM IR. It also cleans up their API a bit
by lifting the abort behavior into their clients and just using an
optional raw_ostream parameter to control printing.

The implementation of the verifier is now just an InstVisitor with no
multiple inheritance. It also is significantly more const-correct, and
hides the const violations internally. The two layers that force us to
break const correctness are building a DomTree and dispatching through
the InstVisitor.

A new VerifierPass is used to implement the legacy pass manager
interface in terms of the other pieces.

The error messages produced may be slightly different now, and we may
have slightly different short circuiting behavior with different usage
models of the verifier, but generally everything works equivalently and
this unblocks wiring the verifier up to the new pass manager.

Modified:
    llvm/trunk/include/llvm/IR/Verifier.h
    llvm/trunk/include/llvm/InitializePasses.h
    llvm/trunk/lib/Analysis/Analysis.cpp
    llvm/trunk/lib/IR/Core.cpp
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/test/Verifier/2010-08-07-PointerIntrinsic.ll
    llvm/trunk/tools/llvm-as/llvm-as.cpp
    llvm/trunk/unittests/IR/VerifierTest.cpp

Modified: llvm/trunk/include/llvm/IR/Verifier.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Verifier.h?rev=199569&r1=199568&r2=199569&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Verifier.h (original)
+++ llvm/trunk/include/llvm/IR/Verifier.h Sat Jan 18 20:22:18 2014
@@ -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
 

Modified: llvm/trunk/include/llvm/InitializePasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=199569&r1=199568&r2=199569&view=diff
==============================================================================
--- llvm/trunk/include/llvm/InitializePasses.h (original)
+++ llvm/trunk/include/llvm/InitializePasses.h Sat Jan 18 20:22:18 2014
@@ -256,7 +256,7 @@ void initializeTypeBasedAliasAnalysisPas
 void initializeUnifyFunctionExitNodesPass(PassRegistry&);
 void initializeUnreachableBlockElimPass(PassRegistry&);
 void initializeUnreachableMachineBlockElimPass(PassRegistry&);
-void initializeVerifierPass(PassRegistry&);
+void initializeVerifierPassPass(PassRegistry&);
 void initializeVirtRegMapPass(PassRegistry&);
 void initializeVirtRegRewriterPass(PassRegistry&);
 void initializeInstSimplifierPass(PassRegistry&);

Modified: llvm/trunk/lib/Analysis/Analysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/Analysis.cpp?rev=199569&r1=199568&r2=199569&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/Analysis.cpp (original)
+++ llvm/trunk/lib/Analysis/Analysis.cpp Sat Jan 18 20:22:18 2014
@@ -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(LLVMPassRegi
 
 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) {

Modified: llvm/trunk/lib/IR/Core.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Core.cpp?rev=199569&r1=199568&r2=199569&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Core.cpp (original)
+++ llvm/trunk/lib/IR/Core.cpp Sat Jan 18 20:22:18 2014
@@ -44,7 +44,7 @@ void llvm::initializeCore(PassRegistry &
   initializePrintModulePassWrapperPass(Registry);
   initializePrintFunctionPassWrapperPass(Registry);
   initializePrintBasicBlockPassPass(Registry);
-  initializeVerifierPass(Registry);
+  initializeVerifierPassPass(Registry);
 }
 
 void LLVMInitializeCore(LLVMPassRegistryRef R) {

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=199569&r1=199568&r2=199569&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Sat Jan 18 20:22:18 2014
@@ -80,21 +80,15 @@ static cl::opt<bool> DisableDebugInfoVer
                                               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, p
   /// \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, p
       // 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, p
         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, p
       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, p
     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, p
   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, p
 
   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, p
   }
 
   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, p
 };
 } // 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(GlobalVa
           "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(Globa
       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(Globa
   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(GlobalAl
           "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(GlobalAl
   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, 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
   } 
 }
 
-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 &
   }
 }
 
-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(Attr
 
 // 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;
-}
-
-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));
-
-  if (ErrorInfo && V->Broken)
-    *ErrorInfo = V->MessagesStr.str();
-  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();
+  }
+};
+}
+
+char VerifierPass::ID = 0;
+INITIALIZE_PASS(VerifierPass, "verify", "Module Verifier", false, false)
+
+FunctionPass *llvm::createVerifierPass(bool FatalErrors) {
+  return new VerifierPass(FatalErrors);
+}
+

Modified: llvm/trunk/test/Verifier/2010-08-07-PointerIntrinsic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/2010-08-07-PointerIntrinsic.ll?rev=199569&r1=199568&r2=199569&view=diff
==============================================================================
--- llvm/trunk/test/Verifier/2010-08-07-PointerIntrinsic.ll (original)
+++ llvm/trunk/test/Verifier/2010-08-07-PointerIntrinsic.ll Sat Jan 18 20:22:18 2014
@@ -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"

Modified: llvm/trunk/tools/llvm-as/llvm-as.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-as/llvm-as.cpp?rev=199569&r1=199568&r2=199569&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-as/llvm-as.cpp (original)
+++ llvm/trunk/tools/llvm-as/llvm-as.cpp Sat Jan 18 20:22:18 2014
@@ -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;
     }
   }

Modified: llvm/trunk/unittests/IR/VerifierTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/VerifierTest.cpp?rev=199569&r1=199568&r2=199569&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/VerifierTest.cpp (original)
+++ llvm/trunk/unittests/IR/VerifierTest.cpp Sat Jan 18 20:22:18 2014
@@ -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!"));
 }
 
 }





More information about the llvm-commits mailing list