X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FVerifier.cpp;h=0ce7d4c27ce921395c97491ae6f23f28ad33a560;hb=719de53742167ca3f0e6b2efafb6eac18bd90452;hp=c01f0fe9cc18982507d9383b13a66ce8e8b45311;hpb=181b6c9cb5def44658d15848e34c5c45d973f065;p=oota-llvm.git diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index c01f0fe9cc1..0ce7d4c27ce 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -21,7 +21,7 @@ // * The code is in valid SSA form // * It should be illegal to put a label into any other type (like a structure) // or to return one. [except constant arrays!] -// * Only phi nodes can be self referential: 'add int %0, %0 ; :0' is bad +// * Only phi nodes can be self referential: 'add i32 %0, %0 ; :0' is bad // * PHI nodes must have an entry for each predecessor, with no extras. // * PHI nodes must be the first thing in a basic block, all grouped together // * PHI nodes must have at least one entry @@ -40,20 +40,19 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/Verifier.h" -#include "llvm/Assembly/Writer.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" -#include "llvm/Pass.h" -#include "llvm/Module.h" -#include "llvm/ModuleProvider.h" -#include "llvm/ParameterAttributes.h" #include "llvm/DerivedTypes.h" #include "llvm/InlineAsm.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/ModuleProvider.h" +#include "llvm/Pass.h" #include "llvm/PassManager.h" #include "llvm/Analysis/Dominators.h" +#include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/CallSite.h" #include "llvm/Support/CFG.h" #include "llvm/Support/InstVisitor.h" #include "llvm/Support/Streams.h" @@ -68,7 +67,39 @@ using namespace llvm; namespace { // Anonymous namespace for class + struct VISIBILITY_HIDDEN PreVerifier : public FunctionPass { + static char ID; // Pass ID, replacement for typeid + PreVerifier() : FunctionPass((intptr_t)&ID) { } + + // Check that the prerequisites for successful DominatorTree construction + // are satisfied. + bool runOnFunction(Function &F) { + bool Broken = false; + + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { + if (I->empty() || !I->back().isTerminator()) { + cerr << "Basic Block does not have terminator!\n"; + WriteAsOperand(*cerr, I, true); + cerr << "\n"; + Broken = true; + } + } + + if (Broken) + abort(); + + return false; + } + }; +} + +char PreVerifier::ID = 0; +static RegisterPass +PreVer("preverify", "Preliminary module verification"); +static const PassInfo *const PreVerifyID = &PreVer; + +namespace { struct VISIBILITY_HIDDEN Verifier : public FunctionPass, InstVisitor { static char ID; // Pass ID, replacement for typeid @@ -90,16 +121,16 @@ namespace { // Anonymous namespace for class : FunctionPass((intptr_t)&ID), Broken(false), RealPass(true), action(AbortProcessAction), DT(0), msgs( std::ios::app | std::ios::out ) {} - Verifier( VerifierFailureAction ctn ) + explicit Verifier(VerifierFailureAction ctn) : FunctionPass((intptr_t)&ID), Broken(false), RealPass(true), action(ctn), DT(0), msgs( std::ios::app | std::ios::out ) {} - Verifier(bool AB ) + explicit Verifier(bool AB) : FunctionPass((intptr_t)&ID), Broken(false), RealPass(true), action( AB ? AbortProcessAction : PrintMessageAction), DT(0), msgs( std::ios::app | std::ios::out ) {} - Verifier(DominatorTree &dt) + explicit Verifier(DominatorTree &dt) : FunctionPass((intptr_t)&ID), Broken(false), RealPass(false), action(PrintMessageAction), DT(&dt), msgs( std::ios::app | std::ios::out ) {} @@ -158,6 +189,7 @@ namespace { // Anonymous namespace for class virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); + AU.addRequiredID(PreVerifyID); if (RealPass) AU.addRequired(); } @@ -214,6 +246,7 @@ namespace { // Anonymous namespace for class void visitShuffleVectorInst(ShuffleVectorInst &EI); void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); } void visitCallInst(CallInst &CI); + void visitInvokeInst(InvokeInst &II); void visitGetElementPtrInst(GetElementPtrInst &GEP); void visitLoadInst(LoadInst &LI); void visitStoreInst(StoreInst &SI); @@ -225,9 +258,16 @@ namespace { // Anonymous namespace for class void visitUserOp1(Instruction &I); void visitUserOp2(Instruction &I) { visitUserOp1(I); } void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI); + void visitAllocationInst(AllocationInst &AI); + void visitGetResultInst(GetResultInst &GRI); + void VerifyCallSite(CallSite CS); void VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, unsigned Count, ...); + void VerifyAttrs(ParameterAttributes Attrs, const Type *Ty, + bool isReturnValue, const Value *V); + void VerifyFunctionAttrs(const FunctionType *FT, const PAListPtr &Attrs, + const Value *V); void WriteValue(const Value *V) { if (!V) return; @@ -268,11 +308,10 @@ namespace { // Anonymous namespace for class Broken = true; } }; - - char Verifier::ID = 0; - RegisterPass X("verify", "Module Verifier"); } // End anonymous namespace +char Verifier::ID = 0; +static RegisterPass X("verify", "Module Verifier"); // Assert - We know that cond should be true, if not print an error message. #define Assert(C, M) \ @@ -311,10 +350,15 @@ void Verifier::visitGlobalValue(GlobalValue &GV) { } void Verifier::visitGlobalVariable(GlobalVariable &GV) { - if (GV.hasInitializer()) + if (GV.hasInitializer()) { Assert1(GV.getInitializer()->getType() == GV.getType()->getElementType(), "Global variable initializer type does not match global " "variable type!", &GV); + } else { + Assert1(GV.hasExternalLinkage() || GV.hasDLLImportLinkage() || + GV.hasExternalWeakLinkage(), + "invalid linkage type for global declaration", &GV); + } visitGlobalValue(GV); } @@ -325,9 +369,11 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) { Assert1(GA.hasExternalLinkage() || GA.hasInternalLinkage() || GA.hasWeakLinkage(), "Alias should have external or external weak linkage!", &GA); + Assert1(GA.getAliasee(), + "Aliasee cannot be NULL!", &GA); Assert1(GA.getType() == GA.getAliasee()->getType(), "Alias and aliasee types should match!", &GA); - + if (!isa(GA.getAliasee())) { const ConstantExpr *CE = dyn_cast(GA.getAliasee()); Assert1(CE && CE->getOpcode() == Instruction::BitCast && @@ -335,112 +381,105 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) { "Aliasee should be either GlobalValue or bitcast of GlobalValue", &GA); } - + + const GlobalValue* Aliasee = GA.resolveAliasedGlobal(); + Assert1(Aliasee, + "Aliasing chain should end with function or global variable", &GA); + visitGlobalValue(GA); } void Verifier::verifyTypeSymbolTable(TypeSymbolTable &ST) { } -// visitFunction - Verify that a function is ok. -// -void Verifier::visitFunction(Function &F) { - // Check function arguments. - const FunctionType *FT = F.getFunctionType(); - unsigned NumArgs = F.getArgumentList().size(); - - Assert2(FT->getNumParams() == NumArgs, - "# formal arguments must match # of arguments for function type!", - &F, FT); - Assert1(F.getReturnType()->isFirstClassType() || - F.getReturnType() == Type::VoidTy, - "Functions cannot return aggregate values!", &F); - - Assert1(!FT->isStructReturn() || FT->getReturnType() == Type::VoidTy, - "Invalid struct-return function!", &F); - - const uint16_t ReturnIncompatible = - ParamAttr::ByVal | ParamAttr::InReg | - ParamAttr::Nest | ParamAttr::StructRet; - - const uint16_t ParameterIncompatible = - ParamAttr::NoReturn | ParamAttr::NoUnwind; - - const uint16_t MutuallyIncompatible = - ParamAttr::ByVal | ParamAttr::InReg | - ParamAttr::Nest | ParamAttr::StructRet; +// VerifyAttrs - Check the given parameter attributes for an argument or return +// value of the specified type. The value V is printed in error messages. +void Verifier::VerifyAttrs(ParameterAttributes Attrs, const Type *Ty, + bool isReturnValue, const Value *V) { + if (Attrs == ParamAttr::None) + return; - const uint16_t MutuallyIncompatible2 = - ParamAttr::ZExt | ParamAttr::SExt; + if (isReturnValue) { + ParameterAttributes RetI = Attrs & ParamAttr::ParameterOnly; + Assert1(!RetI, "Attribute " + ParamAttr::getAsString(RetI) + + "does not apply to return values!", V); + } else { + ParameterAttributes ParmI = Attrs & ParamAttr::ReturnOnly; + Assert1(!ParmI, "Attribute " + ParamAttr::getAsString(ParmI) + + "only applies to return values!", V); + } - const uint16_t IntegerTypeOnly = - ParamAttr::SExt | ParamAttr::ZExt; + for (unsigned i = 0; + i < array_lengthof(ParamAttr::MutuallyIncompatible); ++i) { + ParameterAttributes MutI = Attrs & ParamAttr::MutuallyIncompatible[i]; + Assert1(!(MutI & (MutI - 1)), "Attributes " + + ParamAttr::getAsString(MutI) + "are incompatible!", V); + } - const uint16_t PointerTypeOnly = - ParamAttr::ByVal | ParamAttr::Nest | - ParamAttr::NoAlias | ParamAttr::StructRet; + ParameterAttributes TypeI = Attrs & ParamAttr::typeIncompatible(Ty); + Assert1(!TypeI, "Wrong type for attribute " + + ParamAttr::getAsString(TypeI), V); +} - bool SawSRet = false; +// VerifyFunctionAttrs - Check parameter attributes against a function type. +// The value V is printed in error messages. +void Verifier::VerifyFunctionAttrs(const FunctionType *FT, + const PAListPtr &Attrs, + const Value *V) { + if (Attrs.isEmpty()) + return; - if (const ParamAttrsList *Attrs = FT->getParamAttrs()) { - unsigned Idx = 1; - bool SawNest = false; + bool SawNest = false; - uint16_t RetI = Attrs->getParamAttrs(0) & ReturnIncompatible; - Assert1(!RetI, "Attribute " + Attrs->getParamAttrsText(RetI) + - "should not apply to functions!", &F); - uint16_t MutI = Attrs->getParamAttrs(0) & MutuallyIncompatible2; - Assert1(MutI != MutuallyIncompatible2, "Attributes" + - Attrs->getParamAttrsText(MutI) + "are incompatible!", &F); + for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) { + const ParamAttrsWithIndex &Attr = Attrs.getSlot(i); - for (FunctionType::param_iterator I = FT->param_begin(), - E = FT->param_end(); I != E; ++I, ++Idx) { + const Type *Ty; + if (Attr.Index == 0) + Ty = FT->getReturnType(); + else if (Attr.Index-1 < FT->getNumParams()) + Ty = FT->getParamType(Attr.Index-1); + else + break; // VarArgs attributes, don't verify. + + VerifyAttrs(Attr.Attrs, Ty, Attr.Index == 0, V); - uint16_t Attr = Attrs->getParamAttrs(Idx); + if (Attr.Attrs & ParamAttr::Nest) { + Assert1(!SawNest, "More than one parameter has attribute nest!", V); + SawNest = true; + } - uint16_t ParmI = Attr & ParameterIncompatible; - Assert1(!ParmI, "Attribute " + Attrs->getParamAttrsText(ParmI) + - "should only be applied to function!", &F); + if (Attr.Attrs & ParamAttr::StructRet) + Assert1(Attr.Index == 1, "Attribute sret not on first parameter!", V); + } +} - uint16_t MutI = Attr & MutuallyIncompatible; - Assert1(!(MutI & (MutI - 1)), "Attributes " + - Attrs->getParamAttrsText(MutI) + "are incompatible!", &F); +// visitFunction - Verify that a function is ok. +// +void Verifier::visitFunction(Function &F) { + // Check function arguments. + const FunctionType *FT = F.getFunctionType(); + unsigned NumArgs = F.arg_size(); - uint16_t MutI2 = Attr & MutuallyIncompatible2; - Assert1(MutI2 != MutuallyIncompatible2, "Attributes" + - Attrs->getParamAttrsText(MutI2) + "are incompatible!", &F); + Assert2(FT->getNumParams() == NumArgs, + "# formal arguments must match # of arguments for function type!", + &F, FT); + Assert1(F.getReturnType()->isFirstClassType() || + F.getReturnType() == Type::VoidTy || + isa(F.getReturnType()), + "Functions cannot return aggregate values!", &F); - uint16_t IType = Attr & IntegerTypeOnly; - Assert1(!IType || FT->getParamType(Idx-1)->isInteger(), - "Attribute " + Attrs->getParamAttrsText(IType) + - "should only apply to Integer type!", &F); + Assert1(!F.hasStructRetAttr() || F.getReturnType() == Type::VoidTy, + "Invalid struct return type!", &F); - uint16_t PType = Attr & PointerTypeOnly; - Assert1(!PType || isa(FT->getParamType(Idx-1)), - "Attribute " + Attrs->getParamAttrsText(PType) + - "should only apply to Pointer type!", &F); + const PAListPtr &Attrs = F.getParamAttrs(); - if (Attrs->paramHasAttr(Idx, ParamAttr::ByVal)) { - const PointerType *Ty = - dyn_cast(FT->getParamType(Idx-1)); - Assert1(!Ty || isa(Ty->getElementType()), - "Attribute byval should only apply to pointer to structs!", &F); - } + Assert1(Attrs.isEmpty() || + Attrs.getSlot(Attrs.getNumSlots()-1).Index <= FT->getNumParams(), + "Attributes after last parameter!", &F); - if (Attrs->paramHasAttr(Idx, ParamAttr::Nest)) { - Assert1(!SawNest, "More than one parameter has attribute nest!", &F); - SawNest = true; - } - - if (Attrs->paramHasAttr(Idx, ParamAttr::StructRet)) { - SawSRet = true; - Assert1(Idx == 1, "Attribute sret not on first parameter!", &F); - } - } - } - - Assert1(SawSRet == FT->isStructReturn(), - "StructReturn function with no sret attribute!", &F); + // Check function attributes. + VerifyFunctionAttrs(FT, Attrs, &F); // Check that this function meets the restrictions on this calling convention. switch (F.getCallingConv()) { @@ -468,7 +507,11 @@ void Verifier::visitFunction(Function &F) { "Functions cannot take aggregates as arguments by value!", I); } - if (!F.isDeclaration()) { + if (F.isDeclaration()) { + Assert1(F.hasExternalLinkage() || F.hasDLLImportLinkage() || + F.hasExternalWeakLinkage(), + "invalid linkage type for function declaration", &F); + } else { // Verify that this function (which has a body) is not named "llvm.*". It // is not legal to define intrinsics. if (F.getName().size() >= 5) @@ -546,15 +589,36 @@ void Verifier::visitTerminatorInst(TerminatorInst &I) { void Verifier::visitReturnInst(ReturnInst &RI) { Function *F = RI.getParent()->getParent(); - if (RI.getNumOperands() == 0) - Assert2(F->getReturnType() == Type::VoidTy, + unsigned N = RI.getNumOperands(); + if (F->getReturnType() == Type::VoidTy) + Assert2(N == 0, "Found return instr that returns void in Function of non-void " "return type!", &RI, F->getReturnType()); - else - Assert2(F->getReturnType() == RI.getOperand(0)->getType(), - "Function return type does not match operand " - "type of return inst!", &RI, F->getReturnType()); - + else if (N == 1 && F->getReturnType() == RI.getOperand(0)->getType()) { + // Exactly one return value and it matches the return type. Good. + } else if (const StructType *STy = dyn_cast(F->getReturnType())) { + // The return type is a struct; check for multiple return values. + Assert2(STy->getNumElements() == N, + "Incorrect number of return values in ret instruction!", + &RI, F->getReturnType()); + for (unsigned i = 0; i != N; ++i) + Assert2(STy->getElementType(i) == RI.getOperand(i)->getType(), + "Function return type does not match operand " + "type of return inst!", &RI, F->getReturnType()); + } else if (const ArrayType *ATy = dyn_cast(F->getReturnType())) { + // The return type is an array; check for multiple return values. + Assert2(ATy->getNumElements() == N, + "Incorrect number of return values in ret instruction!", + &RI, F->getReturnType()); + for (unsigned i = 0; i != N; ++i) + Assert2(ATy->getElementType() == RI.getOperand(i)->getType(), + "Function return type does not match operand " + "type of return inst!", &RI, F->getReturnType()); + } else { + CheckFailed("Function return type does not match operand " + "type of return inst!", &RI, F->getReturnType()); + } + // Check to make sure that the return value has necessary properties for // terminators... visitTerminatorInst(RI); @@ -673,8 +737,20 @@ void Verifier::visitUIToFPInst(UIToFPInst &I) { const Type *SrcTy = I.getOperand(0)->getType(); const Type *DestTy = I.getType(); - Assert1(SrcTy->isInteger(),"UInt2FP source must be integral", &I); - Assert1(DestTy->isFloatingPoint(),"UInt2FP result must be FP", &I); + bool SrcVec = isa(SrcTy); + bool DstVec = isa(DestTy); + + Assert1(SrcVec == DstVec, + "UIToFP source and dest must both be vector or scalar", &I); + Assert1(SrcTy->isIntOrIntVector(), + "UIToFP source must be integer or integer vector", &I); + Assert1(DestTy->isFPOrFPVector(), + "UIToFP result must be FP or FP vector", &I); + + if (SrcVec && DstVec) + Assert1(cast(SrcTy)->getNumElements() == + cast(DestTy)->getNumElements(), + "UIToFP source and dest vector length mismatch", &I); visitInstruction(I); } @@ -684,8 +760,20 @@ void Verifier::visitSIToFPInst(SIToFPInst &I) { const Type *SrcTy = I.getOperand(0)->getType(); const Type *DestTy = I.getType(); - Assert1(SrcTy->isInteger(),"SInt2FP source must be integral", &I); - Assert1(DestTy->isFloatingPoint(),"SInt2FP result must be FP", &I); + bool SrcVec = SrcTy->getTypeID() == Type::VectorTyID; + bool DstVec = DestTy->getTypeID() == Type::VectorTyID; + + Assert1(SrcVec == DstVec, + "SIToFP source and dest must both be vector or scalar", &I); + Assert1(SrcTy->isIntOrIntVector(), + "SIToFP source must be integer or integer vector", &I); + Assert1(DestTy->isFPOrFPVector(), + "SIToFP result must be FP or FP vector", &I); + + if (SrcVec && DstVec) + Assert1(cast(SrcTy)->getNumElements() == + cast(DestTy)->getNumElements(), + "SIToFP source and dest vector length mismatch", &I); visitInstruction(I); } @@ -695,8 +783,19 @@ void Verifier::visitFPToUIInst(FPToUIInst &I) { const Type *SrcTy = I.getOperand(0)->getType(); const Type *DestTy = I.getType(); - Assert1(SrcTy->isFloatingPoint(),"FP2UInt source must be FP", &I); - Assert1(DestTy->isInteger(),"FP2UInt result must be integral", &I); + bool SrcVec = isa(SrcTy); + bool DstVec = isa(DestTy); + + Assert1(SrcVec == DstVec, + "FPToUI source and dest must both be vector or scalar", &I); + Assert1(SrcTy->isFPOrFPVector(), "FPToUI source must be FP or FP vector", &I); + Assert1(DestTy->isIntOrIntVector(), + "FPToUI result must be integer or integer vector", &I); + + if (SrcVec && DstVec) + Assert1(cast(SrcTy)->getNumElements() == + cast(DestTy)->getNumElements(), + "FPToUI source and dest vector length mismatch", &I); visitInstruction(I); } @@ -706,8 +805,20 @@ void Verifier::visitFPToSIInst(FPToSIInst &I) { const Type *SrcTy = I.getOperand(0)->getType(); const Type *DestTy = I.getType(); - Assert1(SrcTy->isFloatingPoint(),"FPToSI source must be FP", &I); - Assert1(DestTy->isInteger(),"FP2ToI result must be integral", &I); + bool SrcVec = isa(SrcTy); + bool DstVec = isa(DestTy); + + Assert1(SrcVec == DstVec, + "FPToSI source and dest must both be vector or scalar", &I); + Assert1(SrcTy->isFPOrFPVector(), + "FPToSI source must be FP or FP vector", &I); + Assert1(DestTy->isIntOrIntVector(), + "FPToSI result must be integer or integer vector", &I); + + if (SrcVec && DstVec) + Assert1(cast(SrcTy)->getNumElements() == + cast(DestTy)->getNumElements(), + "FPToSI source and dest vector length mismatch", &I); visitInstruction(I); } @@ -775,34 +886,66 @@ void Verifier::visitPHINode(PHINode &PN) { visitInstruction(PN); } -void Verifier::visitCallInst(CallInst &CI) { - Assert1(isa(CI.getOperand(0)->getType()), - "Called function must be a pointer!", &CI); - const PointerType *FPTy = cast(CI.getOperand(0)->getType()); +void Verifier::VerifyCallSite(CallSite CS) { + Instruction *I = CS.getInstruction(); + + Assert1(isa(CS.getCalledValue()->getType()), + "Called function must be a pointer!", I); + const PointerType *FPTy = cast(CS.getCalledValue()->getType()); Assert1(isa(FPTy->getElementType()), - "Called function is not pointer to function type!", &CI); + "Called function is not pointer to function type!", I); const FunctionType *FTy = cast(FPTy->getElementType()); // Verify that the correct number of arguments are being passed if (FTy->isVarArg()) - Assert1(CI.getNumOperands()-1 >= FTy->getNumParams(), - "Called function requires more parameters than were provided!",&CI); + Assert1(CS.arg_size() >= FTy->getNumParams(), + "Called function requires more parameters than were provided!",I); else - Assert1(CI.getNumOperands()-1 == FTy->getNumParams(), - "Incorrect number of arguments passed to called function!", &CI); + Assert1(CS.arg_size() == FTy->getNumParams(), + "Incorrect number of arguments passed to called function!", I); // Verify that all arguments to the call match the function type... for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) - Assert3(CI.getOperand(i+1)->getType() == FTy->getParamType(i), + Assert3(CS.getArgument(i)->getType() == FTy->getParamType(i), "Call parameter type does not match function signature!", - CI.getOperand(i+1), FTy->getParamType(i), &CI); + CS.getArgument(i), FTy->getParamType(i), I); + + const PAListPtr &Attrs = CS.getParamAttrs(); + + Assert1(Attrs.isEmpty() || + Attrs.getSlot(Attrs.getNumSlots()-1).Index <= CS.arg_size(), + "Attributes after last parameter!", I); + + // Verify call attributes. + VerifyFunctionAttrs(FTy, Attrs, I); + + if (FTy->isVarArg()) + // Check attributes on the varargs part. + for (unsigned Idx = 1 + FTy->getNumParams(); Idx <= CS.arg_size(); ++Idx) { + ParameterAttributes Attr = Attrs.getParamAttrs(Idx); + + VerifyAttrs(Attr, CS.getArgument(Idx-1)->getType(), false, I); - if (Function *F = CI.getCalledFunction()) + ParameterAttributes VArgI = Attr & ParamAttr::VarArgsIncompatible; + Assert1(!VArgI, "Attribute " + ParamAttr::getAsString(VArgI) + + "cannot be used for vararg call arguments!", I); + } + + visitInstruction(*I); +} + +void Verifier::visitCallInst(CallInst &CI) { + VerifyCallSite(&CI); + + if (Function *F = CI.getCalledFunction()) { if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) visitIntrinsicFunctionCall(ID, CI); + } +} - visitInstruction(CI); +void Verifier::visitInvokeInst(InvokeInst &II) { + VerifyCallSite(&II); } /// visitBinaryOperator - Check that both arguments to the binary operator are @@ -913,7 +1056,7 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { SmallVector Idxs(GEP.idx_begin(), GEP.idx_end()); const Type *ElTy = GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(), - &Idxs[0], Idxs.size(), true); + Idxs.begin(), Idxs.end()); Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP); Assert2(isa(GEP.getType()) && cast(GEP.getType())->getElementType() == ElTy, @@ -937,6 +1080,28 @@ void Verifier::visitStoreInst(StoreInst &SI) { visitInstruction(SI); } +void Verifier::visitAllocationInst(AllocationInst &AI) { + const PointerType *PTy = AI.getType(); + Assert1(PTy->getAddressSpace() == 0, + "Allocation instruction pointer not in the generic address space!", + &AI); + Assert1(PTy->getElementType()->isSized(), "Cannot allocate unsized type", + &AI); + visitInstruction(AI); +} + +void Verifier::visitGetResultInst(GetResultInst &GRI) { + Assert1(GetResultInst::isValidOperands(GRI.getAggregateValue(), + GRI.getIndex()), + "Invalid GetResultInst operands!", &GRI); + Assert1(isa(GRI.getAggregateValue()) || + isa(GRI.getAggregateValue()) || + isa(GRI.getAggregateValue()), + "GetResultInst operand must be a call/invoke/undef!", &GRI); + + visitInstruction(GRI); +} + /// verifyInstruction - Verify that an instruction is well formed. /// @@ -951,6 +1116,11 @@ void Verifier::visitInstruction(Instruction &I) { !DT->dominates(&BB->getParent()->getEntryBlock(), BB), "Only PHI nodes may reference their own value!", &I); } + + // Verify that if this is a terminator that it is at the end of the block. + if (isa(I)) + Assert1(BB->getTerminator() == &I, "Terminator not at end of block!", &I); + // Check that void typed values don't have names Assert1(I.getType() != Type::VoidTy || !I.hasName(), @@ -958,7 +1128,9 @@ void Verifier::visitInstruction(Instruction &I) { // Check that the return value of the instruction is either void or a legal // value type. - Assert1(I.getType() == Type::VoidTy || I.getType()->isFirstClassType(), + Assert1(I.getType() == Type::VoidTy || I.getType()->isFirstClassType() + || ((isa(I) || isa(I)) + && isa(I.getType())), "Instruction returns a non-scalar type!", &I); // Check that all uses of the instruction, if they are instructions @@ -978,9 +1150,23 @@ void Verifier::visitInstruction(Instruction &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 (!I.getOperand(i)->getType()->isFirstClassType()) { + if (isa(I) || isa(I)) + Assert1(isa(I.getOperand(i)->getType()), + "Invalid ReturnInst operands!", &I); + else if (isa(I) || isa(I)) { + if (const PointerType *PT = dyn_cast + (I.getOperand(i)->getType())) { + const Type *ETy = PT->getElementType(); + Assert1(isa(ETy), "Invalid CallInst operands!", &I); + } + else + Assert1(0, "Invalid CallInst operands!", &I); + } + else + Assert1(0, "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. @@ -1053,7 +1239,7 @@ void Verifier::visitInstruction(Instruction &I) { } // Definition must dominate use unless use is unreachable! - Assert2(DT->dominates(OpBlock, BB) || + Assert2(DT->dominates(Op, &I) || !DT->dominates(&BB->getParent()->getEntryBlock(), BB), "Instruction does not dominate all uses!", Op, &I); } else { @@ -1065,7 +1251,7 @@ void Verifier::visitInstruction(Instruction &I) { "Instruction does not dominate all uses!", Op, &I); } } else if (isa(I.getOperand(i))) { - Assert1(i == 0 && isa(I), + Assert1(i == 0 && (isa(I) || isa(I)), "Cannot take the address of an inline asm!", &I); } } @@ -1082,6 +1268,55 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { #define GET_INTRINSIC_VERIFIER #include "llvm/Intrinsics.gen" #undef GET_INTRINSIC_VERIFIER + + switch (ID) { + default: + break; + case Intrinsic::gcroot: + case Intrinsic::gcwrite: + case Intrinsic::gcread: { + Type *PtrTy = PointerType::getUnqual(Type::Int8Ty), + *PtrPtrTy = PointerType::getUnqual(PtrTy); + + switch (ID) { + default: + break; + case Intrinsic::gcroot: + Assert1(CI.getOperand(1)->getType() == PtrPtrTy, + "Intrinsic parameter #1 is not i8**.", &CI); + Assert1(CI.getOperand(2)->getType() == PtrTy, + "Intrinsic parameter #2 is not i8*.", &CI); + Assert1(isa(CI.getOperand(1)->stripPointerCasts()), + "llvm.gcroot parameter #1 must be an alloca.", &CI); + Assert1(isa(CI.getOperand(2)), + "llvm.gcroot parameter #2 must be a constant.", &CI); + break; + case Intrinsic::gcwrite: + Assert1(CI.getOperand(1)->getType() == PtrTy, + "Intrinsic parameter #1 is not a i8*.", &CI); + Assert1(CI.getOperand(2)->getType() == PtrTy, + "Intrinsic parameter #2 is not a i8*.", &CI); + Assert1(CI.getOperand(3)->getType() == PtrPtrTy, + "Intrinsic parameter #3 is not a i8**.", &CI); + break; + case Intrinsic::gcread: + Assert1(CI.getOperand(1)->getType() == PtrTy, + "Intrinsic parameter #1 is not a i8*.", &CI); + Assert1(CI.getOperand(2)->getType() == PtrPtrTy, + "Intrinsic parameter #2 is not a i8**.", &CI); + break; + } + + Assert1(CI.getParent()->getParent()->hasCollector(), + "Enclosing function does not specify a collector algorithm.", + &CI); + } break; + case Intrinsic::init_trampoline: + Assert1(isa(CI.getOperand(2)->stripPointerCasts()), + "llvm.init_trampoline parameter #2 must resolve to a function.", + &CI); + break; + } } /// VerifyIntrinsicPrototype - TableGen emits calls to this function into @@ -1107,7 +1342,7 @@ void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, // Note that "arg#0" is the return type. for (unsigned ArgNo = 0; ArgNo < Count; ++ArgNo) { - MVT::ValueType VT = va_arg(VA, MVT::ValueType); + int VT = va_arg(VA, int); // An MVT::SimpleValueType when non-negative. if (VT == MVT::isVoid && ArgNo > 0) { if (!FTy->isVarArg()) @@ -1127,8 +1362,8 @@ void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, EltTy = VTy->getElementType(); NumElts = VTy->getNumElements(); } - - if ((int)VT < 0) { + + if (VT < 0) { int Match = ~VT; if (Match == 0) { if (Ty != FTy->getReturnType()) { @@ -1144,6 +1379,15 @@ void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, } } } else if (VT == MVT::iAny) { + if (!EltTy->isInteger()) { + if (ArgNo == 0) + CheckFailed("Intrinsic result type is not " + "an integer type.", F); + else + CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " is not " + "an integer type.", F); + break; + } unsigned GotBits = cast(EltTy)->getBitWidth(); Suffix += "."; if (EltTy != Ty) @@ -1157,25 +1401,44 @@ void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, CheckFailed("Intrinsic requires even byte width argument", F); break; } + } else if (VT == MVT::fAny) { + if (!EltTy->isFloatingPoint()) { + if (ArgNo == 0) + CheckFailed("Intrinsic result type is not " + "a floating-point type.", F); + else + CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " is not " + "a floating-point type.", F); + break; + } + Suffix += "."; + if (EltTy != Ty) + Suffix += "v" + utostr(NumElts); + Suffix += MVT::getMVT(EltTy).getMVTString(); } else if (VT == MVT::iPTR) { if (!isa(Ty)) { - CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " is not a " - "pointer and a pointer is required.", F); + if (ArgNo == 0) + CheckFailed("Intrinsic result type is not a " + "pointer and a pointer is required.", F); + else + CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " is not a " + "pointer and a pointer is required.", F); break; } - } else if (MVT::isVector(VT)) { + } else if (MVT((MVT::SimpleValueType)VT).isVector()) { + MVT VVT = MVT((MVT::SimpleValueType)VT); // If this is a vector argument, verify the number and type of elements. - if (MVT::getVectorElementType(VT) != MVT::getValueType(EltTy)) { + if (VVT.getVectorElementType() != MVT::getMVT(EltTy)) { CheckFailed("Intrinsic prototype has incorrect vector element type!", F); break; } - if (MVT::getVectorNumElements(VT) != NumElts) { + if (VVT.getVectorNumElements() != NumElts) { CheckFailed("Intrinsic prototype has incorrect number of " "vector elements!",F); break; } - } else if (MVT::getTypeForValueType(VT) != EltTy) { + } else if (MVT((MVT::SimpleValueType)VT).getTypeForMVT() != EltTy) { if (ArgNo == 0) CheckFailed("Intrinsic prototype has incorrect result type!", F); else @@ -1205,6 +1468,10 @@ void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, F->getName().substr(Name.length()) + "'. It should be '" + Suffix + "'", F); } + + // Check parameter attributes. + Assert1(F->getParamAttrs() == Intrinsic::getParamAttrs(ID), + "Intrinsic has wrong parameter attributes!", F); }