[PM] Make the verifier work independently of any pass manager.
authorChandler Carruth <chandlerc@gmail.com>
Sun, 19 Jan 2014 02:22:18 +0000 (02:22 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sun, 19 Jan 2014 02:22:18 +0000 (02:22 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199569 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 9f6cb42e11f529bd7b6399fdbb3692ce17b1e06f..f5d8945ea063a5008405e3fdb167b0eb9673480f 100644 (file)
@@ -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
 
index a88d94945a821b9fd5eb976233f1db68be46a050..e08e0c4baf202c64ee40fc1ad97d63a8008034f4 100644 (file)
@@ -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&);
index ef99e35ffdaf950afb7c2c2edced4c84efcb9c80..c9ce1643c3d214d7429bf058d00db2f3931d7c8b 100644 (file)
@@ -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) {
index 1417e5dc4fd960c909b518eea8eda94efc385845..cd7cb9ed147226694cf7fbc931741f6286dd6a37 100644 (file)
@@ -44,7 +44,7 @@ void llvm::initializeCore(PassRegistry &Registry) {
   initializePrintModulePassWrapperPass(Registry);
   initializePrintFunctionPassWrapperPass(Registry);
   initializePrintBasicBlockPassPass(Registry);
-  initializeVerifierPass(Registry);
+  initializeVerifierPassPass(Registry);
 }
 
 void LLVMInitializeCore(LLVMPassRegistryRef R) {
index a004955e807f81f5a4ac1bd4f7e8cfdd284e517e..feea485019593c344e736739a4b4f2254bd143e7 100644 (file)
@@ -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);
 }
+
index a668d04213fa78d2d64562259699c11eb9da098f..427eb66aa7b6a8c68a63aa5908c1165b8b5a29ff 100644 (file)
@@ -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"
index 97e7d160983224cd03690b1ca4bb630934ed693c..d13caf1955e44e05088672143662e1052055503a 100644 (file)
@@ -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;
     }
   }
index 8e21fb80fe9478410ace3a49b6a9a9ab9fe9a5fe..a5ce5fc9d301026c139cab694239a8a88ac23b85 100644 (file)
@@ -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!"));
 }
 
 }