X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FVerifier.cpp;h=cf812a8fffefe30f8622cc965e540d1db7b6c580;hb=e81561909d128c6e2d8033cb5465a49b2596b26a;hp=8a4cf2c0d5b73a683faba35dd47c7a327bff793f;hpb=80105ddf5148711b8de8b7869a19649286482f16;p=oota-llvm.git diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 8a4cf2c0d5b..cf812a8fffe 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -55,17 +55,18 @@ #include "llvm/Analysis/Dominators.h" #include "llvm/Support/CFG.h" #include "llvm/Support/InstVisitor.h" +#include "llvm/Support/Streams.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Compiler.h" #include -#include -#include #include using namespace llvm; namespace { // Anonymous namespace for class - struct Verifier : public FunctionPass, InstVisitor { + struct VISIBILITY_HIDDEN + Verifier : public FunctionPass, InstVisitor { bool Broken; // Is this module found to be broken? bool RealPass; // Are we not being run by a PassManager? VerifierFailureAction action; @@ -103,7 +104,7 @@ namespace { // Anonymous namespace for class // returning back to the pass manager, or else the pass manager may try to // run other passes on the broken module. if (RealPass) - abortIfBroken(); + return abortIfBroken(); return false; } @@ -117,7 +118,7 @@ namespace { // Anonymous namespace for class // returning back to the pass manager, or else the pass manager may try to // run other passes on the broken module. if (RealPass) - abortIfBroken(); + return abortIfBroken(); return false; } @@ -136,8 +137,7 @@ namespace { // Anonymous namespace for class visitGlobalVariable(*I); // If the module is broken, abort at this time. - abortIfBroken(); - return false; + return abortIfBroken(); } virtual void getAnalysisUsage(AnalysisUsage &AU) const { @@ -149,27 +149,24 @@ namespace { // Anonymous namespace for class /// abortIfBroken - If the module is broken and we are supposed to abort on /// this condition, do so. /// - void abortIfBroken() { - if (Broken) - { + bool abortIfBroken() { + if (Broken) { msgs << "Broken module found, "; - switch (action) - { + switch (action) { case AbortProcessAction: msgs << "compilation aborted!\n"; - std::cerr << msgs.str(); + cerr << msgs.str(); abort(); - case ThrowExceptionAction: - msgs << "verification terminated.\n"; - throw msgs.str(); case PrintMessageAction: msgs << "verification continues.\n"; - std::cerr << msgs.str(); - break; + cerr << msgs.str(); + return false; case ReturnStatusAction: - break; + msgs << "compilation terminated.\n"; + return Broken; } } + return false; } @@ -179,8 +176,22 @@ namespace { // Anonymous namespace for class void visitGlobalVariable(GlobalVariable &GV); void visitFunction(Function &F); void visitBasicBlock(BasicBlock &BB); + void visitTruncInst(TruncInst &I); + void visitZExtInst(ZExtInst &I); + void visitSExtInst(SExtInst &I); + void visitFPTruncInst(FPTruncInst &I); + void visitFPExtInst(FPExtInst &I); + void visitFPToUIInst(FPToUIInst &I); + void visitFPToSIInst(FPToSIInst &I); + void visitUIToFPInst(UIToFPInst &I); + void visitSIToFPInst(SIToFPInst &I); + void visitIntToPtrInst(IntToPtrInst &I); + void visitPtrToIntInst(PtrToIntInst &I); + void visitBitCastInst(BitCastInst &I); void visitPHINode(PHINode &PN); void visitBinaryOperator(BinaryOperator &B); + void visitICmpInst(ICmpInst &IC); + void visitFCmpInst(FCmpInst &FC); void visitShiftInst(ShiftInst &SI); void visitExtractElementInst(ExtractElementInst &EI); void visitInsertElementInst(InsertElementInst &EI); @@ -206,7 +217,7 @@ namespace { // Anonymous namespace for class if (isa(V)) { msgs << *V; } else { - WriteAsOperand (msgs, V, true, true, Mod); + WriteAsOperand(msgs, V, true, Mod); msgs << "\n"; } } @@ -241,7 +252,7 @@ namespace { // Anonymous namespace for class } }; - RegisterOpt X("verify", "Module Verifier"); + RegisterPass X("verify", "Module Verifier"); } // End anonymous namespace @@ -259,8 +270,16 @@ namespace { // Anonymous namespace for class void Verifier::visitGlobalValue(GlobalValue &GV) { - Assert1(!GV.isExternal() || GV.hasExternalLinkage(), - "Global is external, but doesn't have external linkage!", &GV); + Assert1(!GV.isExternal() || + GV.hasExternalLinkage() || + GV.hasDLLImportLinkage() || + GV.hasExternalWeakLinkage(), + "Global is external, but doesn't have external or dllimport or weak linkage!", + &GV); + + Assert1(!GV.hasDLLImportLinkage() || GV.isExternal(), + "Global is marked as dllimport, but not external", &GV); + Assert1(!GV.hasAppendingLinkage() || isa(GV), "Only global variables can have appending linkage!", &GV); @@ -326,6 +345,7 @@ void Verifier::visitFunction(Function &F) { break; case CallingConv::Fast: case CallingConv::Cold: + case CallingConv::X86_FastCall: Assert1(!F.isVarArg(), "Varargs functions must have C calling conventions!", &F); break; @@ -458,6 +478,169 @@ void Verifier::visitUserOp1(Instruction &I) { Assert1(0, "User-defined operators should not live outside of a pass!", &I); } +void Verifier::visitTruncInst(TruncInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + // Get the size of the types in bits, we'll need this later + unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits(); + unsigned DestBitSize = DestTy->getPrimitiveSizeInBits(); + + Assert1(SrcTy->isIntegral(), "Trunc only operates on integer", &I); + Assert1(DestTy->isIntegral(),"Trunc only produces integral", &I); + Assert1(SrcBitSize > DestBitSize,"DestTy too big for Trunc", &I); + + visitInstruction(I); +} + +void Verifier::visitZExtInst(ZExtInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + // Get the size of the types in bits, we'll need this later + unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits(); + unsigned DestBitSize = DestTy->getPrimitiveSizeInBits(); + + Assert1(SrcTy->isIntegral(),"ZExt only operates on integral", &I); + Assert1(DestTy->isInteger(),"ZExt only produces an integer", &I); + Assert1(SrcBitSize < DestBitSize,"Type too small for ZExt", &I); + + visitInstruction(I); +} + +void Verifier::visitSExtInst(SExtInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + // Get the size of the types in bits, we'll need this later + unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits(); + unsigned DestBitSize = DestTy->getPrimitiveSizeInBits(); + + Assert1(SrcTy->isIntegral(),"SExt only operates on integral", &I); + Assert1(DestTy->isInteger(),"SExt only produces an integer", &I); + Assert1(SrcBitSize < DestBitSize,"Type too small for SExt", &I); + + visitInstruction(I); +} + +void Verifier::visitFPTruncInst(FPTruncInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + // Get the size of the types in bits, we'll need this later + unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits(); + unsigned DestBitSize = DestTy->getPrimitiveSizeInBits(); + + Assert1(SrcTy->isFloatingPoint(),"FPTrunc only operates on FP", &I); + Assert1(DestTy->isFloatingPoint(),"FPTrunc only produces an FP", &I); + Assert1(SrcBitSize > DestBitSize,"DestTy too big for FPTrunc", &I); + + visitInstruction(I); +} + +void Verifier::visitFPExtInst(FPExtInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + // Get the size of the types in bits, we'll need this later + unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits(); + unsigned DestBitSize = DestTy->getPrimitiveSizeInBits(); + + Assert1(SrcTy->isFloatingPoint(),"FPExt only operates on FP", &I); + Assert1(DestTy->isFloatingPoint(),"FPExt only produces an FP", &I); + Assert1(SrcBitSize < DestBitSize,"DestTy too small for FPExt", &I); + + visitInstruction(I); +} + +void Verifier::visitUIToFPInst(UIToFPInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + Assert1(SrcTy->isIntegral(),"UInt2FP source must be integral", &I); + Assert1(DestTy->isFloatingPoint(),"UInt2FP result must be FP", &I); + + visitInstruction(I); +} + +void Verifier::visitSIToFPInst(SIToFPInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + Assert1(SrcTy->isIntegral(),"SInt2FP source must be integral", &I); + Assert1(DestTy->isFloatingPoint(),"SInt2FP result must be FP", &I); + + visitInstruction(I); +} + +void Verifier::visitFPToUIInst(FPToUIInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + Assert1(SrcTy->isFloatingPoint(),"FP2UInt source must be FP", &I); + Assert1(DestTy->isIntegral(),"FP2UInt result must be integral", &I); + + visitInstruction(I); +} + +void Verifier::visitFPToSIInst(FPToSIInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + Assert1(SrcTy->isFloatingPoint(),"FPToSI source must be FP", &I); + Assert1(DestTy->isIntegral(),"FP2ToI result must be integral", &I); + + visitInstruction(I); +} + +void Verifier::visitPtrToIntInst(PtrToIntInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + Assert1(isa(SrcTy), "PtrToInt source must be pointer", &I); + Assert1(DestTy->isIntegral(), "PtrToInt result must be integral", &I); + + visitInstruction(I); +} + +void Verifier::visitIntToPtrInst(IntToPtrInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + Assert1(SrcTy->isIntegral(), "IntToPtr source must be an integral", &I); + Assert1(isa(DestTy), "IntToPtr result must be a pointer",&I); + + visitInstruction(I); +} + +void Verifier::visitBitCastInst(BitCastInst &I) { + // Get the source and destination types + const Type *SrcTy = I.getOperand(0)->getType(); + const Type *DestTy = I.getType(); + + // Get the size of the types in bits, we'll need this later + unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits(); + unsigned DestBitSize = DestTy->getPrimitiveSizeInBits(); + + // BitCast implies a no-op cast of type only. No bits change. + // However, you can't cast pointers to anything but pointers. + Assert1(isa(DestTy) == isa(DestTy), + "Bitcast requires both operands to be pointer or neither", &I); + Assert1(SrcBitSize == DestBitSize, "Bitcast requies types of same width", &I); + + visitInstruction(I); +} + /// visitPHINode - Ensure that a PHI node is well formed. /// void Verifier::visitPHINode(PHINode &PN) { @@ -544,6 +727,33 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) { visitInstruction(B); } +void Verifier::visitICmpInst(ICmpInst& IC) { + // Check that the operands are the same type + const Type* Op0Ty = IC.getOperand(0)->getType(); + const Type* Op1Ty = IC.getOperand(1)->getType(); + Assert1(Op0Ty == Op1Ty, + "Both operands to ICmp instruction are not of the same type!", &IC); + // Check that the operands are the right type + Assert1(Op0Ty->isIntegral() || Op0Ty->getTypeID() == Type::PointerTyID || + (isa(Op0Ty) && + cast(Op0Ty)->getElementType()->isIntegral()), + "Invalid operand types for ICmp instruction", &IC); + visitInstruction(IC); +} + +void Verifier::visitFCmpInst(FCmpInst& FC) { + // Check that the operands are the same type + const Type* Op0Ty = FC.getOperand(0)->getType(); + const Type* Op1Ty = FC.getOperand(1)->getType(); + Assert1(Op0Ty == Op1Ty, + "Both operands to FCmp instruction are not of the same type!", &FC); + // Check that the operands are the right type + Assert1(Op0Ty->isFloatingPoint() || (isa(Op0Ty) && + cast(Op0Ty)->getElementType()->isFloatingPoint()), + "Invalid operand types for FCmp instruction", &FC); + visitInstruction(FC); +} + void Verifier::visitShiftInst(ShiftInst &SI) { Assert1(SI.getType()->isInteger(), "Shift must return an integer result!", &SI); @@ -579,7 +789,7 @@ void Verifier::visitShuffleVectorInst(ShuffleVectorInst &SV) { // Check to see if Mask is valid. if (const ConstantPacked *MV = dyn_cast(SV.getOperand(2))) { for (unsigned i = 0, e = MV->getNumOperands(); i != e; ++i) { - Assert1(isa(MV->getOperand(i)) || + Assert1(isa(MV->getOperand(i)) || isa(MV->getOperand(i)), "Invalid shufflevector shuffle mask!", &SV); } @@ -655,10 +865,16 @@ void Verifier::visitInstruction(Instruction &I) { } for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { - // Check to make sure that the "address of" an intrinsic function is never - // taken. Assert1(I.getOperand(i) != 0, "Instruction has null operand!", &I); + + // Check to make sure that only first-class-values are operands to + // instructions. + Assert1(I.getOperand(i)->getType()->isFirstClassType(), + "Instruction operands must be first-class values!", &I); + if (Function *F = dyn_cast(I.getOperand(i))) { + // Check to make sure that the "address of" an intrinsic function is never + // taken. Assert1(!F->isIntrinsic() || (i == 0 && isa(I)), "Cannot take the address of an intrinsic!", &I); } else if (BasicBlock *OpBB = dyn_cast(I.getOperand(i))) { @@ -797,11 +1013,15 @@ bool llvm::verifyFunction(const Function &f, VerifierFailureAction action) { /// verifyModule - Check a module for errors, printing messages on stderr. /// Return true if the module is corrupt. /// -bool llvm::verifyModule(const Module &M, VerifierFailureAction action) { +bool llvm::verifyModule(const Module &M, VerifierFailureAction action, + std::string *ErrorInfo) { PassManager PM; Verifier *V = new Verifier(action); PM.add(V); PM.run((Module&)M); + + if (ErrorInfo && V->Broken) + *ErrorInfo = V->msgs.str(); return V->Broken; }