summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/IR/Verifier.h18
-rw-r--r--include/llvm/InitializePasses.h2
-rw-r--r--lib/IR/Core.cpp2
-rw-r--r--lib/IR/Verifier.cpp31
-rw-r--r--test/Other/new-pass-manager.ll30
-rw-r--r--tools/opt/NewPMDriver.cpp12
-rw-r--r--tools/opt/NewPMDriver.h7
-rw-r--r--tools/opt/Passes.cpp32
-rw-r--r--tools/opt/Passes.h3
-rw-r--r--tools/opt/opt.cpp8
10 files changed, 118 insertions, 27 deletions
diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h
index 0f146e6936..9a2f402ac8 100644
--- a/include/llvm/IR/Verifier.h
+++ b/include/llvm/IR/Verifier.h
@@ -21,13 +21,15 @@
#ifndef LLVM_IR_VERIFIER_H
#define LLVM_IR_VERIFIER_H
+#include "llvm/ADT/StringRef.h"
#include <string>
namespace llvm {
+class Function;
class FunctionPass;
class Module;
-class Function;
+class PreservedAnalyses;
class raw_ostream;
/// \brief Check a function for errors, useful for use when debugging a
@@ -52,8 +54,22 @@ bool verifyModule(const Module &M, raw_ostream *OS = 0);
/// 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.
+///
+/// Note that this creates a pass suitable for the legacy pass manager. It has nothing to do with \c VerifierPass.
FunctionPass *createVerifierPass(bool FatalErrors = true);
+class VerifierPass {
+ bool FatalErrors;
+
+public:
+ explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {}
+
+ PreservedAnalyses run(Module *M);
+ PreservedAnalyses run(Function *F);
+
+ static StringRef name() { return "VerifierPass"; }
+};
+
} // End llvm namespace
#endif
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index e08e0c4baf..36efee570b 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -256,7 +256,7 @@ void initializeTypeBasedAliasAnalysisPass(PassRegistry&);
void initializeUnifyFunctionExitNodesPass(PassRegistry&);
void initializeUnreachableBlockElimPass(PassRegistry&);
void initializeUnreachableMachineBlockElimPass(PassRegistry&);
-void initializeVerifierPassPass(PassRegistry&);
+void initializeVerifierLegacyPassPass(PassRegistry&);
void initializeVirtRegMapPass(PassRegistry&);
void initializeVirtRegRewriterPass(PassRegistry&);
void initializeInstSimplifierPass(PassRegistry&);
diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp
index cd7cb9ed14..3a6a0b0b44 100644
--- a/lib/IR/Core.cpp
+++ b/lib/IR/Core.cpp
@@ -44,7 +44,7 @@ void llvm::initializeCore(PassRegistry &Registry) {
initializePrintModulePassWrapperPass(Registry);
initializePrintFunctionPassWrapperPass(Registry);
initializePrintBasicBlockPassPass(Registry);
- initializeVerifierPassPass(Registry);
+ initializeVerifierLegacyPassPass(Registry);
}
void LLVMInitializeCore(LLVMPassRegistryRef R) {
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index feea485019..f81260960e 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -62,9 +62,9 @@
#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/PassManager.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/CommandLine.h"
@@ -2387,18 +2387,18 @@ bool llvm::verifyModule(const Module &M, raw_ostream *OS) {
}
namespace {
-struct VerifierPass : public FunctionPass {
+struct VerifierLegacyPass : public FunctionPass {
static char ID;
Verifier V;
bool FatalErrors;
- VerifierPass() : FunctionPass(ID), FatalErrors(true) {
- initializeVerifierPassPass(*PassRegistry::getPassRegistry());
+ VerifierLegacyPass() : FunctionPass(ID), FatalErrors(true) {
+ initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
}
- explicit VerifierPass(bool FatalErrors)
+ explicit VerifierLegacyPass(bool FatalErrors)
: FunctionPass(ID), V(dbgs()), FatalErrors(FatalErrors) {
- initializeVerifierPassPass(*PassRegistry::getPassRegistry());
+ initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) {
@@ -2421,10 +2421,23 @@ struct VerifierPass : public FunctionPass {
};
}
-char VerifierPass::ID = 0;
-INITIALIZE_PASS(VerifierPass, "verify", "Module Verifier", false, false)
+char VerifierLegacyPass::ID = 0;
+INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false)
FunctionPass *llvm::createVerifierPass(bool FatalErrors) {
- return new VerifierPass(FatalErrors);
+ return new VerifierLegacyPass(FatalErrors);
}
+PreservedAnalyses VerifierPass::run(Module *M) {
+ if (verifyModule(*M, &dbgs()) && FatalErrors)
+ report_fatal_error("Broken module found, compilation aborted!");
+
+ return PreservedAnalyses::all();
+}
+
+PreservedAnalyses VerifierPass::run(Function *F) {
+ if (verifyFunction(*F, &dbgs()) && FatalErrors)
+ report_fatal_error("Broken function found, compilation aborted!");
+
+ return PreservedAnalyses::all();
+}
diff --git a/test/Other/new-pass-manager.ll b/test/Other/new-pass-manager.ll
index 376bb2625e..cec01b54ff 100644
--- a/test/Other/new-pass-manager.ll
+++ b/test/Other/new-pass-manager.ll
@@ -8,19 +8,23 @@
; RUN: opt -disable-output -debug-pass-manager -passes=print %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-MODULE-PRINT
; CHECK-MODULE-PRINT: Starting module pass manager
+; CHECK-MODULE-PRINT: Running module pass: VerifierPass
; CHECK-MODULE-PRINT: Running module pass: PrintModulePass
; CHECK-MODULE-PRINT: ModuleID
; CHECK-MODULE-PRINT: define void @foo()
+; CHECK-MODULE-PRINT: Running module pass: VerifierPass
; CHECK-MODULE-PRINT: Finished module pass manager
; RUN: opt -disable-output -debug-pass-manager -passes='function(print)' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PRINT
; CHECK-FUNCTION-PRINT: Starting module pass manager
+; CHECK-FUNCTION-PRINT: Running module pass: VerifierPass
; CHECK-FUNCTION-PRINT: Starting function pass manager
; CHECK-FUNCTION-PRINT: Running function pass: PrintFunctionPass
; CHECK-FUNCTION-PRINT-NOT: ModuleID
; CHECK-FUNCTION-PRINT: define void @foo()
; CHECK-FUNCTION-PRINT: Finished function pass manager
+; CHECK-FUNCTION-PRINT: Running module pass: VerifierPass
; CHECK-FUNCTION-PRINT: Finished module pass manager
; RUN: opt -S -o - -passes='no-op-module,no-op-module' %s \
@@ -34,6 +38,32 @@
; RUN: | llvm-dis \
; RUN: | FileCheck %s --check-prefix=CHECK-NOOP
+; RUN: opt -disable-output -debug-pass-manager -verify-each -passes='no-op-module,function(no-op-function)' %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-VERIFY-EACH
+; CHECK-VERIFY-EACH: Starting module pass manager
+; CHECK-VERIFY-EACH: Running module pass: VerifierPass
+; CHECK-VERIFY-EACH: Running module pass: NoOpModulePass
+; CHECK-VERIFY-EACH: Running module pass: VerifierPass
+; CHECK-VERIFY-EACH: Starting function pass manager
+; CHECK-VERIFY-EACH: Running function pass: NoOpFunctionPass
+; CHECK-VERIFY-EACH: Running function pass: VerifierPass
+; CHECK-VERIFY-EACH: Finished function pass manager
+; CHECK-VERIFY-EACH: Running module pass: VerifierPass
+; CHECK-VERIFY-EACH: Finished module pass manager
+
+; RUN: opt -disable-output -debug-pass-manager -disable-verify -passes='no-op-module,function(no-op-function)' %s 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-NO-VERIFY
+; CHECK-NO-VERIFY: Starting module pass manager
+; CHECK-NO-VERIFY-NOT: VerifierPass
+; CHECK-NO-VERIFY: Running module pass: NoOpModulePass
+; CHECK-NO-VERIFY-NOT: VerifierPass
+; CHECK-NO-VERIFY: Starting function pass manager
+; CHECK-NO-VERIFY: Running function pass: NoOpFunctionPass
+; CHECK-NO-VERIFY-NOT: VerifierPass
+; CHECK-NO-VERIFY: Finished function pass manager
+; CHECK-NO-VERIFY-NOT: VerifierPass
+; CHECK-NO-VERIFY: Finished module pass manager
+
define void @foo() {
ret void
}
diff --git a/tools/opt/NewPMDriver.cpp b/tools/opt/NewPMDriver.cpp
index 2d210387f8..f21a68fc8a 100644
--- a/tools/opt/NewPMDriver.cpp
+++ b/tools/opt/NewPMDriver.cpp
@@ -21,6 +21,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ToolOutputFile.h"
@@ -30,13 +31,20 @@ using namespace opt_tool;
bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
tool_output_file *Out, StringRef PassPipeline,
- OutputKind OK) {
+ OutputKind OK, VerifierKind VK) {
ModulePassManager MPM;
- if (!parsePassPipeline(MPM, PassPipeline)) {
+
+ if (VK > VK_NoVerifier)
+ MPM.addPass(VerifierPass());
+
+ if (!parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass)) {
errs() << Arg0 << ": unable to parse pass pipeline description.\n";
return false;
}
+ if (VK > VK_NoVerifier)
+ MPM.addPass(VerifierPass());
+
// Add any relevant output pass at the end of the pipeline.
switch (OK) {
case OK_NoOutput:
diff --git a/tools/opt/NewPMDriver.h b/tools/opt/NewPMDriver.h
index 2ae1ad5d83..3661d3e677 100644
--- a/tools/opt/NewPMDriver.h
+++ b/tools/opt/NewPMDriver.h
@@ -34,6 +34,11 @@ enum OutputKind {
OK_OutputAssembly,
OK_OutputBitcode
};
+enum VerifierKind {
+ VK_NoVerifier,
+ VK_VerifyInAndOut,
+ VK_VerifyEachPass
+};
}
/// \brief Driver function to run the new pass manager over a module.
@@ -44,7 +49,7 @@ enum OutputKind {
/// when the transition finishes.
bool runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
tool_output_file *Out, StringRef PassPipeline,
- opt_tool::OutputKind OK);
+ opt_tool::OutputKind OK, opt_tool::VerifierKind VK);
}
#endif
diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp
index e79ac422eb..36fe6ad126 100644
--- a/tools/opt/Passes.cpp
+++ b/tools/opt/Passes.cpp
@@ -17,6 +17,7 @@
#include "Passes.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
@@ -78,7 +79,8 @@ static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) {
}
static bool parseFunctionPassPipeline(FunctionPassManager &FPM,
- StringRef &PipelineText) {
+ StringRef &PipelineText,
+ bool VerifyEachPass) {
for (;;) {
// Parse nested pass managers by recursing.
if (PipelineText.startswith("function(")) {
@@ -86,7 +88,7 @@ static bool parseFunctionPassPipeline(FunctionPassManager &FPM,
// Parse the inner pipeline inte the nested manager.
PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText) ||
+ if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
PipelineText.empty())
return false;
assert(PipelineText[0] == ')');
@@ -99,6 +101,8 @@ static bool parseFunctionPassPipeline(FunctionPassManager &FPM,
size_t End = PipelineText.find_first_of(",)");
if (!parseFunctionPassName(FPM, PipelineText.substr(0, End)))
return false;
+ if (VerifyEachPass)
+ FPM.addPass(VerifierPass());
PipelineText = PipelineText.substr(End);
}
@@ -112,7 +116,8 @@ static bool parseFunctionPassPipeline(FunctionPassManager &FPM,
}
static bool parseModulePassPipeline(ModulePassManager &MPM,
- StringRef &PipelineText) {
+ StringRef &PipelineText,
+ bool VerifyEachPass) {
for (;;) {
// Parse nested pass managers by recursing.
if (PipelineText.startswith("module(")) {
@@ -120,7 +125,7 @@ static bool parseModulePassPipeline(ModulePassManager &MPM,
// Parse the inner pipeline into the nested manager.
PipelineText = PipelineText.substr(strlen("module("));
- if (!parseModulePassPipeline(NestedMPM, PipelineText) ||
+ if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass) ||
PipelineText.empty())
return false;
assert(PipelineText[0] == ')');
@@ -133,7 +138,7 @@ static bool parseModulePassPipeline(ModulePassManager &MPM,
// Parse the inner pipeline inte the nested manager.
PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText) ||
+ if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
PipelineText.empty())
return false;
assert(PipelineText[0] == ')');
@@ -146,6 +151,8 @@ static bool parseModulePassPipeline(ModulePassManager &MPM,
size_t End = PipelineText.find_first_of(",)");
if (!parseModulePassName(MPM, PipelineText.substr(0, End)))
return false;
+ if (VerifyEachPass)
+ MPM.addPass(VerifierPass());
PipelineText = PipelineText.substr(End);
}
@@ -161,13 +168,16 @@ static bool parseModulePassPipeline(ModulePassManager &MPM,
// Primary pass pipeline description parsing routine.
// FIXME: Should this routine accept a TargetMachine or require the caller to
// pre-populate the analysis managers with target-specific stuff?
-bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText) {
+bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
+ bool VerifyEachPass) {
// Look at the first entry to figure out which layer to start parsing at.
if (PipelineText.startswith("module("))
- return parseModulePassPipeline(MPM, PipelineText) && PipelineText.empty();
+ return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) &&
+ PipelineText.empty();
if (PipelineText.startswith("function(")) {
FunctionPassManager FPM;
- if (!parseFunctionPassPipeline(FPM, PipelineText) || !PipelineText.empty())
+ if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||
+ !PipelineText.empty())
return false;
MPM.addPass(createModuleToFunctionPassAdaptor(FPM));
return true;
@@ -177,11 +187,13 @@ bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText) {
StringRef FirstName =
PipelineText.substr(0, PipelineText.find_first_of(",)"));
if (isModulePassName(FirstName))
- return parseModulePassPipeline(MPM, PipelineText) && PipelineText.empty();
+ return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) &&
+ PipelineText.empty();
if (isFunctionPassName(FirstName)) {
FunctionPassManager FPM;
- if (!parseFunctionPassPipeline(FPM, PipelineText) || !PipelineText.empty())
+ if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||
+ !PipelineText.empty())
return false;
MPM.addPass(createModuleToFunctionPassAdaptor(FPM));
return true;
diff --git a/tools/opt/Passes.h b/tools/opt/Passes.h
index 6016b74c80..3bd6752692 100644
--- a/tools/opt/Passes.h
+++ b/tools/opt/Passes.h
@@ -49,7 +49,8 @@ class ModulePassManager;
/// the sequence of passes aren't all the exact same kind of pass, it will be
/// an error. You cannot mix different levels implicitly, you must explicitly
/// form a pass manager in which to nest passes.
-bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText);
+bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
+ bool VerifyEachPass = true);
}
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index ef8c504d0f..782cac213f 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -676,11 +676,17 @@ int main(int argc, char **argv) {
if (!NoOutput)
OK = OutputAssembly ? OK_OutputAssembly : OK_OutputBitcode;
+ VerifierKind VK = VK_VerifyInAndOut;
+ if (NoVerify)
+ VK = VK_NoVerifier;
+ else if (VerifyEach)
+ VK = VK_VerifyEachPass;
+
// The user has asked to use the new pass manager and provided a pipeline
// string. Hand off the rest of the functionality to the new code for that
// layer.
return runPassPipeline(argv[0], Context, *M.get(), Out.get(), PassPipeline,
- OK)
+ OK, VK)
? 0
: 1;
}