diff options
-rw-r--r-- | include/llvm/IR/Verifier.h | 18 | ||||
-rw-r--r-- | include/llvm/InitializePasses.h | 2 | ||||
-rw-r--r-- | lib/IR/Core.cpp | 2 | ||||
-rw-r--r-- | lib/IR/Verifier.cpp | 31 | ||||
-rw-r--r-- | test/Other/new-pass-manager.ll | 30 | ||||
-rw-r--r-- | tools/opt/NewPMDriver.cpp | 12 | ||||
-rw-r--r-- | tools/opt/NewPMDriver.h | 7 | ||||
-rw-r--r-- | tools/opt/Passes.cpp | 32 | ||||
-rw-r--r-- | tools/opt/Passes.h | 3 | ||||
-rw-r--r-- | tools/opt/opt.cpp | 8 |
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; } |