Make the verifier API more complete and useful.

Patch contributed by Reid Spencer


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12609 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2004-04-02 15:45:08 +00:00
parent 0e4271f8b2
commit fdc38c4ad3

View File

@ -55,6 +55,7 @@
#include "llvm/Support/InstVisitor.h" #include "llvm/Support/InstVisitor.h"
#include "Support/STLExtras.h" #include "Support/STLExtras.h"
#include <algorithm> #include <algorithm>
#include <sstream>
using namespace llvm; using namespace llvm;
namespace { // Anonymous namespace for class namespace { // Anonymous namespace for class
@ -62,14 +63,25 @@ namespace { // Anonymous namespace for class
struct Verifier : public FunctionPass, InstVisitor<Verifier> { struct Verifier : public FunctionPass, InstVisitor<Verifier> {
bool Broken; // Is this module found to be broken? bool Broken; // Is this module found to be broken?
bool RealPass; // Are we not being run by a PassManager? bool RealPass; // Are we not being run by a PassManager?
bool AbortBroken; // If broken, should it or should it not abort? VerifierFailureAction action;
// What to do if verification fails.
Module *Mod; // Module we are verifying right now Module *Mod; // Module we are verifying right now
DominatorSet *DS; // Dominator set, caution can be null! DominatorSet *DS; // Dominator set, caution can be null!
std::stringstream msgs; // A stringstream to collect messages
Verifier() : Broken(false), RealPass(true), AbortBroken(true), DS(0) {} Verifier()
Verifier(bool AB) : Broken(false), RealPass(true), AbortBroken(AB), DS(0) {} : Broken(false), RealPass(true), action(AbortProcessAction),
DS(0), msgs( std::ios_base::app | std::ios_base::out ) {}
Verifier( VerifierFailureAction ctn )
: Broken(false), RealPass(true), action(ctn), DS(0),
msgs( std::ios_base::app | std::ios_base::out ) {}
Verifier(bool AB )
: Broken(false), RealPass(true),
action( AB ? AbortProcessAction : PrintMessageAction), DS(0),
msgs( std::ios_base::app | std::ios_base::out ) {}
Verifier(DominatorSet &ds) Verifier(DominatorSet &ds)
: Broken(false), RealPass(false), AbortBroken(false), DS(&ds) {} : Broken(false), RealPass(false), action(PrintMessageAction),
DS(&ds), msgs( std::ios_base::app | std::ios_base::out ) {}
bool doInitialization(Module &M) { bool doInitialization(Module &M) {
@ -120,10 +132,26 @@ namespace { // Anonymous namespace for class
/// abortIfBroken - If the module is broken and we are supposed to abort on /// abortIfBroken - If the module is broken and we are supposed to abort on
/// this condition, do so. /// this condition, do so.
/// ///
void abortIfBroken() const { void abortIfBroken() {
if (Broken && AbortBroken) { if (Broken)
std::cerr << "Broken module found, compilation aborted!\n"; {
abort(); msgs << "Broken module found, ";
switch (action)
{
case AbortProcessAction:
msgs << "compilation aborted!\n";
std::cerr << msgs.str();
abort();
case ThrowExceptionAction:
msgs << "verification terminated.\n";
throw msgs.str();
case PrintMessageAction:
msgs << "verification continues.\n";
std::cerr << msgs.str();
break;
case ReturnStatusAction:
break;
}
} }
} }
@ -154,12 +182,12 @@ namespace { // Anonymous namespace for class
void WriteValue(const Value *V) { void WriteValue(const Value *V) {
if (!V) return; if (!V) return;
if (isa<Instruction>(V)) { if (isa<Instruction>(V)) {
std::cerr << *V; msgs << *V;
} else if (const Type *Ty = dyn_cast<Type>(V)) { } else if (const Type *Ty = dyn_cast<Type>(V)) {
WriteTypeSymbolic(std::cerr, Ty, Mod); WriteTypeSymbolic(msgs, Ty, Mod);
} else { } else {
WriteAsOperand (std::cerr, V, true, true, Mod); WriteAsOperand (msgs, V, true, true, Mod);
std::cerr << "\n"; msgs << "\n";
} }
} }
@ -170,7 +198,7 @@ namespace { // Anonymous namespace for class
void CheckFailed(const std::string &Message, void CheckFailed(const std::string &Message,
const Value *V1 = 0, const Value *V2 = 0, const Value *V1 = 0, const Value *V2 = 0,
const Value *V3 = 0, const Value *V4 = 0) { const Value *V3 = 0, const Value *V4 = 0) {
std::cerr << Message << "\n"; msgs << Message << "\n";
WriteValue(V1); WriteValue(V1);
WriteValue(V2); WriteValue(V2);
WriteValue(V3); WriteValue(V3);
@ -623,18 +651,18 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
// Implement the public interfaces to this file... // Implement the public interfaces to this file...
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
FunctionPass *llvm::createVerifierPass() { FunctionPass *llvm::createVerifierPass(VerifierFailureAction action) {
return new Verifier(); return new Verifier(action);
} }
// verifyFunction - Create // verifyFunction - Create
bool llvm::verifyFunction(const Function &f) { bool llvm::verifyFunction(const Function &f, VerifierFailureAction action) {
Function &F = const_cast<Function&>(f); Function &F = const_cast<Function&>(f);
assert(!F.isExternal() && "Cannot verify external functions"); assert(!F.isExternal() && "Cannot verify external functions");
FunctionPassManager FPM(new ExistingModuleProvider(F.getParent())); FunctionPassManager FPM(new ExistingModuleProvider(F.getParent()));
Verifier *V = new Verifier(); Verifier *V = new Verifier(action);
FPM.add(V); FPM.add(V);
FPM.run(F); FPM.run(F);
return V->Broken; return V->Broken;
@ -643,9 +671,9 @@ bool llvm::verifyFunction(const Function &f) {
/// verifyModule - Check a module for errors, printing messages on stderr. /// verifyModule - Check a module for errors, printing messages on stderr.
/// Return true if the module is corrupt. /// Return true if the module is corrupt.
/// ///
bool llvm::verifyModule(const Module &M) { bool llvm::verifyModule(const Module &M, VerifierFailureAction action) {
PassManager PM; PassManager PM;
Verifier *V = new Verifier(); Verifier *V = new Verifier(action);
PM.add(V); PM.add(V);
PM.run((Module&)M); PM.run((Module&)M);
return V->Broken; return V->Broken;