X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FVerifier.cpp;h=e86c89bfa82766e6a794d75ec8c98e5ab9a3064f;hb=e6be34a53ecbe8c2ff9f0793b13d847e94c0de91;hp=c2fba2905229670e9208a7726278913f605002a2;hpb=addd11d98ee3a3013c66d3fd25ee2cfb09b3c7bd;p=oota-llvm.git diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index c2fba290522..e86c89bfa82 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. // //===----------------------------------------------------------------------===// // @@ -46,12 +46,14 @@ #include "llvm/Pass.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" +#include "llvm/ParamAttrsList.h" #include "llvm/DerivedTypes.h" #include "llvm/InlineAsm.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" #include "llvm/PassManager.h" #include "llvm/Analysis/Dominators.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" @@ -66,15 +68,45 @@ 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; + RegisterPass PreVer("preverify", "Preliminary module verification"); + const PassInfo *PreVerifyID = PreVer.getPassInfo(); struct VISIBILITY_HIDDEN Verifier : public FunctionPass, InstVisitor { + static char ID; // Pass ID, replacement for typeid bool Broken; // Is this module found to be broken? bool RealPass; // Are we not being run by a PassManager? VerifierFailureAction action; // What to do if verification fails. Module *Mod; // Module we are verifying right now - ETForest *EF; // ET-Forest, caution can be null! + DominatorTree *DT; // Dominator Tree, caution can be null! std::stringstream msgs; // A stringstream to collect messages /// InstInThisBlock - when verifying a basic block, keep track of all of the @@ -84,18 +116,22 @@ namespace { // Anonymous namespace for class SmallPtrSet InstsInThisBlock; Verifier() - : Broken(false), RealPass(true), action(AbortProcessAction), - EF(0), msgs( std::ios::app | std::ios::out ) {} + : FunctionPass((intptr_t)&ID), + Broken(false), RealPass(true), action(AbortProcessAction), + DT(0), msgs( std::ios::app | std::ios::out ) {} Verifier( VerifierFailureAction ctn ) - : Broken(false), RealPass(true), action(ctn), EF(0), - msgs( std::ios::app | std::ios::out ) {} + : FunctionPass((intptr_t)&ID), + Broken(false), RealPass(true), action(ctn), DT(0), + msgs( std::ios::app | std::ios::out ) {} Verifier(bool AB ) - : Broken(false), RealPass(true), - action( AB ? AbortProcessAction : PrintMessageAction), EF(0), - msgs( std::ios::app | std::ios::out ) {} - Verifier(ETForest &ef) - : Broken(false), RealPass(false), action(PrintMessageAction), - EF(&ef), msgs( std::ios::app | std::ios::out ) {} + : FunctionPass((intptr_t)&ID), + Broken(false), RealPass(true), + action( AB ? AbortProcessAction : PrintMessageAction), DT(0), + msgs( std::ios::app | std::ios::out ) {} + Verifier(DominatorTree &dt) + : FunctionPass((intptr_t)&ID), + Broken(false), RealPass(false), action(PrintMessageAction), + DT(&dt), msgs( std::ios::app | std::ios::out ) {} bool doInitialization(Module &M) { @@ -112,8 +148,10 @@ namespace { // Anonymous namespace for class bool runOnFunction(Function &F) { // Get dominator information if we are being run by PassManager - if (RealPass) EF = &getAnalysis(); - + if (RealPass) DT = &getAnalysis(); + + Mod = F.getParent(); + visit(F); InstsInThisBlock.clear(); @@ -139,14 +177,19 @@ namespace { // Anonymous namespace for class I != E; ++I) visitGlobalVariable(*I); + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E; ++I) + visitGlobalAlias(*I); + // If the module is broken, abort at this time. return abortIfBroken(); } virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); + AU.addRequiredID(PreVerifyID); if (RealPass) - AU.addRequired(); + AU.addRequired(); } /// abortIfBroken - If the module is broken and we are supposed to abort on @@ -177,6 +220,7 @@ namespace { // Anonymous namespace for class void verifyTypeSymbolTable(TypeSymbolTable &ST); void visitGlobalValue(GlobalValue &GV); void visitGlobalVariable(GlobalVariable &GV); + void visitGlobalAlias(GlobalAlias &GA); void visitFunction(Function &F); void visitBasicBlock(BasicBlock &BB); void visitTruncInst(TruncInst &I); @@ -200,6 +244,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); @@ -211,8 +256,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 VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, ...); + 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 ParamAttrsList *Attrs, + const Value *V); void WriteValue(const Value *V) { if (!V) return; @@ -254,6 +307,7 @@ namespace { // Anonymous namespace for class } }; + char Verifier::ID = 0; RegisterPass X("verify", "Module Verifier"); } // End anonymous namespace @@ -275,7 +329,9 @@ void Verifier::visitGlobalValue(GlobalValue &GV) { Assert1(!GV.isDeclaration() || GV.hasExternalLinkage() || GV.hasDLLImportLinkage() || - GV.hasExternalWeakLinkage(), + GV.hasExternalWeakLinkage() || + (isa(GV) && + (GV.hasInternalLinkage() || GV.hasWeakLinkage())), "Global is external, but doesn't have external or dllimport or weak linkage!", &GV); @@ -293,36 +349,125 @@ 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); } +void Verifier::visitGlobalAlias(GlobalAlias &GA) { + Assert1(!GA.getName().empty(), + "Alias name cannot be empty!", &GA); + Assert1(GA.hasExternalLinkage() || GA.hasInternalLinkage() || + GA.hasWeakLinkage(), + "Alias should have external or external weak linkage!", &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 && + isa(CE->getOperand(0)), + "Aliasee should be either GlobalValue or bitcast of GlobalValue", + &GA); + } + + visitGlobalValue(GA); +} + void Verifier::verifyTypeSymbolTable(TypeSymbolTable &ST) { } +// 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; + + if (isReturnValue) { + ParameterAttributes RetI = Attrs & ParamAttr::ParameterOnly; + Assert1(!RetI, "Attribute " + ParamAttrsList::getParamAttrsText(RetI) + + "does not apply to return values!", V); + } else { + ParameterAttributes ParmI = Attrs & ParamAttr::ReturnOnly; + Assert1(!ParmI, "Attribute " + ParamAttrsList::getParamAttrsText(ParmI) + + "only applies to return values!", V); + } + + for (unsigned i = 0; + i < array_lengthof(ParamAttr::MutuallyIncompatible); ++i) { + ParameterAttributes MutI = Attrs & ParamAttr::MutuallyIncompatible[i]; + Assert1(!(MutI & (MutI - 1)), "Attributes " + + ParamAttrsList::getParamAttrsText(MutI) + "are incompatible!", V); + } + + ParameterAttributes TypeI = Attrs & ParamAttr::typeIncompatible(Ty); + Assert1(!TypeI, "Wrong type for attribute " + + ParamAttrsList::getParamAttrsText(TypeI), V); +} + +// VerifyFunctionAttrs - Check parameter attributes against a function type. +// The value V is printed in error messages. +void Verifier::VerifyFunctionAttrs(const FunctionType *FT, + const ParamAttrsList *Attrs, + const Value *V) { + if (!Attrs) + return; + + bool SawNest = false; + + for (unsigned Idx = 0; Idx <= FT->getNumParams(); ++Idx) { + ParameterAttributes Attr = Attrs->getParamAttrs(Idx); + + VerifyAttrs(Attr, FT->getParamType(Idx-1), !Idx, V); + + if (Attr & ParamAttr::Nest) { + Assert1(!SawNest, "More than one parameter has attribute nest!", V); + SawNest = true; + } + + if (Attr & ParamAttr::StructRet) { + Assert1(Idx == 1, "Attribute sret not on first parameter!", V); + } + } +} + // 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(); + unsigned NumArgs = F.arg_size(); Assert2(FT->getNumParams() == NumArgs, "# formal arguments must match # of arguments for function type!", &F, FT); Assert1(F.getReturnType()->isFirstClassType() || - F.getReturnType() == Type::VoidTy, + F.getReturnType() == Type::VoidTy || + isa(F.getReturnType()), "Functions cannot return aggregate values!", &F); - Assert1(!FT->isStructReturn() || - (FT->getReturnType() == Type::VoidTy && - FT->getNumParams() > 0 && isa(FT->getParamType(0))), + Assert1(!F.isStructReturn() || FT->getReturnType() == Type::VoidTy, "Invalid struct-return function!", &F); + const ParamAttrsList *Attrs = F.getParamAttrs(); + + Assert1(!Attrs || + (Attrs->size() && + Attrs->getParamIndex(Attrs->size()-1) <= FT->getNumParams()), + "Attributes after last parameter!", &F); + + // Check function attributes. + VerifyFunctionAttrs(FT, Attrs, &F); + // Check that this function meets the restrictions on this calling convention. switch (F.getCallingConv()) { default: @@ -349,7 +494,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) @@ -427,14 +576,22 @@ void Verifier::visitTerminatorInst(TerminatorInst &I) { void Verifier::visitReturnInst(ReturnInst &RI) { Function *F = RI.getParent()->getParent(); - if (RI.getNumOperands() == 0) + unsigned N = RI.getNumOperands(); + if (N == 0) Assert2(F->getReturnType() == Type::VoidTy, "Found return instr that returns void in Function of non-void " "return type!", &RI, F->getReturnType()); - else + else if (N == 1) Assert2(F->getReturnType() == RI.getOperand(0)->getType(), "Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); + else if (const StructType *STy = dyn_cast(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 + Assert1(0, "Invalid return type!", &RI); // Check to make sure that the return value has necessary properties for // terminators... @@ -554,8 +711,16 @@ 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 = SrcTy->getTypeID() == Type::VectorTyID; + bool DstVec = DestTy->getTypeID() == Type::VectorTyID; + + 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); } @@ -565,8 +730,16 @@ 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); } @@ -576,8 +749,16 @@ 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 = SrcTy->getTypeID() == Type::VectorTyID; + bool DstVec = DestTy->getTypeID() == Type::VectorTyID; + + 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); } @@ -587,8 +768,16 @@ 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 = SrcTy->getTypeID() == Type::VectorTyID; + bool DstVec = DestTy->getTypeID() == Type::VectorTyID; + + 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); } @@ -640,7 +829,8 @@ void Verifier::visitPHINode(PHINode &PN) { // This can be tested by checking whether the instruction before this is // either nonexistent (because this is begin()) or is a PHI node. If not, // then there is some other instruction before a PHI. - Assert2(&PN.getParent()->front() == &PN || isa(PN.getPrev()), + Assert2(&PN == &PN.getParent()->front() || + isa(--BasicBlock::iterator(&PN)), "PHI nodes not grouped at top of basic block!", &PN, PN.getParent()); @@ -655,34 +845,67 @@ 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 ParamAttrsList *Attrs = CS.getParamAttrs(); + + Assert1(!Attrs || + (Attrs->size() && + Attrs->getParamIndex(Attrs->size()-1) <= CS.arg_size()), + "Attributes after last argument!", I); - if (Function *F = CI.getCalledFunction()) + // Verify call attributes. + VerifyFunctionAttrs(FTy, Attrs, I); + + if (Attrs && 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); + + ParameterAttributes VArgI = Attr & ParamAttr::VarArgsIncompatible; + Assert1(!VArgI, "Attribute " + ParamAttrsList::getParamAttrsText(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 @@ -793,7 +1016,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(), true); Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP); Assert2(isa(GEP.getType()) && cast(GEP.getType())->getElementType() == ElTy, @@ -817,6 +1040,19 @@ void Verifier::visitStoreInst(StoreInst &SI) { visitInstruction(SI); } +void Verifier::visitAllocationInst(AllocationInst &AI) { + const PointerType *Ptr = AI.getType(); + Assert(Ptr->getAddressSpace() == 0, + "Allocation instruction pointer not in the generic address space!"); + visitInstruction(AI); +} + +void Verifier::visitGetResultInst(GetResultInst &GRI) { + Assert1(GRI.isValidOperands(GRI.getAggregateValue(), GRI.getIndex()), + "Invalid GetResultInst operands!", &GRI); + visitInstruction(GRI); +} + /// verifyInstruction - Verify that an instruction is well formed. /// @@ -828,9 +1064,14 @@ void Verifier::visitInstruction(Instruction &I) { for (Value::use_iterator UI = I.use_begin(), UE = I.use_end(); UI != UE; ++UI) Assert1(*UI != (User*)&I || - !EF->dominates(&BB->getParent()->getEntryBlock(), BB), + !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(), @@ -838,7 +1079,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 @@ -858,20 +1101,39 @@ 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. Assert1(!F->isIntrinsic() || (i == 0 && isa(I)), "Cannot take the address of an intrinsic!", &I); + Assert1(F->getParent() == Mod, "Referencing function in another module!", + &I); } else if (BasicBlock *OpBB = dyn_cast(I.getOperand(i))) { Assert1(OpBB->getParent() == BB->getParent(), "Referring to a basic block in another function!", &I); } else if (Argument *OpArg = dyn_cast(I.getOperand(i))) { Assert1(OpArg->getParent() == BB->getParent(), "Referring to an argument in another function!", &I); + } else if (GlobalValue *GV = dyn_cast(I.getOperand(i))) { + Assert1(GV->getParent() == Mod, "Referencing global in another module!", + &I); } else if (Instruction *Op = dyn_cast(I.getOperand(i))) { BasicBlock *OpBlock = Op->getParent(); @@ -892,7 +1154,7 @@ void Verifier::visitInstruction(Instruction &I) { // dominates all of it's predecessors (other than the invoke) or if // the invoke value is only used by a phi in the successor. if (!OpBlock->getSinglePredecessor() && - EF->dominates(&BB->getParent()->getEntryBlock(), BB)) { + DT->dominates(&BB->getParent()->getEntryBlock(), BB)) { // The first case we allow is if the use is a PHI operand in the // normal block, and if that PHI operand corresponds to the invoke's // block. @@ -909,7 +1171,7 @@ void Verifier::visitInstruction(Instruction &I) { Bad = false; for (pred_iterator PI = pred_begin(OpBlock), E = pred_end(OpBlock); PI != E; ++PI) { - if (*PI != II->getParent() && !EF->dominates(OpBlock, *PI)) { + if (*PI != II->getParent() && !DT->dominates(OpBlock, *PI)) { Bad = true; break; } @@ -923,24 +1185,24 @@ void Verifier::visitInstruction(Instruction &I) { // If they are in the same basic block, make sure that the definition // comes before the use. Assert2(InstsInThisBlock.count(Op) || - !EF->dominates(&BB->getParent()->getEntryBlock(), BB), + !DT->dominates(&BB->getParent()->getEntryBlock(), BB), "Instruction does not dominate all uses!", Op, &I); } // Definition must dominate use unless use is unreachable! - Assert2(EF->dominates(OpBlock, BB) || - !EF->dominates(&BB->getParent()->getEntryBlock(), BB), + Assert2(DT->dominates(OpBlock, BB) || + !DT->dominates(&BB->getParent()->getEntryBlock(), BB), "Instruction does not dominate all uses!", Op, &I); } else { // PHI nodes are more difficult than other nodes because they actually // "use" the value in the predecessor basic blocks they correspond to. BasicBlock *PredBB = cast(I.getOperand(i+1)); - Assert2(EF->dominates(OpBlock, PredBB) || - !EF->dominates(&BB->getParent()->getEntryBlock(), PredBB), + Assert2(DT->dominates(OpBlock, PredBB) || + !DT->dominates(&BB->getParent()->getEntryBlock(), PredBB), "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); } } @@ -951,19 +1213,72 @@ void Verifier::visitInstruction(Instruction &I) { /// void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { Function *IF = CI.getCalledFunction(); - Assert1(IF->isDeclaration(), "Intrinsic functions should never be defined!", IF); + Assert1(IF->isDeclaration(), "Intrinsic functions should never be defined!", + IF); #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( + IntrinsicInst::StripPointerCasts(CI.getOperand(1))), + "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(IntrinsicInst::StripPointerCasts(CI.getOperand(2))), + "llvm.init_trampoline parameter #2 must resolve to a function.", + &CI); + break; + } } /// VerifyIntrinsicPrototype - TableGen emits calls to this function into /// Intrinsics.gen. This implements a little state machine that verifies the /// prototype of intrinsics. -void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, ...) { +void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, + Function *F, + unsigned Count, ...) { va_list VA; - va_start(VA, F); + va_start(VA, Count); const FunctionType *FTy = F->getFunctionType(); @@ -972,96 +1287,121 @@ void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, ...) { // suffix, to be checked at the end. std::string Suffix; - // Note that "arg#0" is the return type. - for (unsigned ArgNo = 0; 1; ++ArgNo) { - int TypeID = va_arg(VA, int); + if (FTy->getNumParams() + FTy->isVarArg() != Count - 1) { + CheckFailed("Intrinsic prototype has incorrect number of arguments!", F); + return; + } - if (TypeID == -2) { - break; - } + // Note that "arg#0" is the return type. + for (unsigned ArgNo = 0; ArgNo < Count; ++ArgNo) { + MVT::ValueType VT = va_arg(VA, MVT::ValueType); - if (TypeID == -1) { - if (ArgNo != FTy->getNumParams()+1) - CheckFailed("Intrinsic prototype has too many arguments!", F); + if (VT == MVT::isVoid && ArgNo > 0) { + if (!FTy->isVarArg()) + CheckFailed("Intrinsic prototype has no '...'!", F); break; } - if (ArgNo == FTy->getNumParams()+1) { - CheckFailed("Intrinsic prototype has too few arguments!", F); - break; - } - const Type *Ty; if (ArgNo == 0) Ty = FTy->getReturnType(); else Ty = FTy->getParamType(ArgNo-1); - - if (TypeID != Ty->getTypeID()) { - if (ArgNo == 0) - CheckFailed("Intrinsic prototype has incorrect result type!", F); - else - CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " is wrong!",F); - break; - } - if (TypeID == Type::IntegerTyID) { - unsigned ExpectedBits = (unsigned) va_arg(VA, int); - unsigned GotBits = cast(Ty)->getBitWidth(); - if (ExpectedBits == 0) { - Suffix += ".i" + utostr(GotBits); - } else if (GotBits != ExpectedBits) { - std::string bitmsg = " Expected " + utostr(ExpectedBits) + " but got "+ - utostr(GotBits) + " bits."; + unsigned NumElts = 0; + const Type *EltTy = Ty; + if (const VectorType *VTy = dyn_cast(Ty)) { + EltTy = VTy->getElementType(); + NumElts = VTy->getNumElements(); + } + + if ((int)VT < 0) { + int Match = ~VT; + if (Match == 0) { + if (Ty != FTy->getReturnType()) { + CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " does not " + "match return type.", F); + break; + } + } else { + if (Ty != FTy->getParamType(Match-1)) { + CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " does not " + "match parameter %" + utostr(Match-1) + ".", F); + break; + } + } + } else if (VT == MVT::iAny) { + if (!EltTy->isInteger()) { if (ArgNo == 0) - CheckFailed("Intrinsic prototype has incorrect integer result width!" - + bitmsg, F); + CheckFailed("Intrinsic result type is not " + "an integer type.", F); else - CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " has " - "incorrect integer width!" + bitmsg, F); + CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " is not " + "an integer type.", F); break; } + unsigned GotBits = cast(EltTy)->getBitWidth(); + Suffix += "."; + if (EltTy != Ty) + Suffix += "v" + utostr(NumElts); + Suffix += "i" + utostr(GotBits);; // Check some constraints on various intrinsics. switch (ID) { default: break; // Not everything needs to be checked. case Intrinsic::bswap: if (GotBits < 16 || GotBits % 16 != 0) CheckFailed("Intrinsic requires even byte width argument", F); - /* FALL THROUGH */ - case Intrinsic::bit_part_select: - if (ArgNo == 1) { - unsigned ResultBits = - cast(FTy->getReturnType())->getBitWidth(); - if (GotBits != ResultBits) - CheckFailed("Intrinsic requires parameter and result bit " - "widths to match", F); - } break; } - } else if (TypeID == Type::VectorTyID) { - // If this is a packed argument, verify the number and type of elements. - const VectorType *PTy = cast(Ty); - int ElemTy = va_arg(VA, int); - if (ElemTy != PTy->getElementType()->getTypeID()) { + } 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::getValueTypeString(MVT::getValueType(EltTy)); + } else if (VT == MVT::iPTR) { + if (!isa(Ty)) { + 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)) { + // If this is a vector argument, verify the number and type of elements. + if (MVT::getVectorElementType(VT) != MVT::getValueType(EltTy)) { CheckFailed("Intrinsic prototype has incorrect vector element type!", F); break; } - if (ElemTy == Type::IntegerTyID) { - unsigned NumBits = (unsigned)va_arg(VA, int); - unsigned ExpectedBits = - cast(PTy->getElementType())->getBitWidth(); - if (NumBits != ExpectedBits) { - CheckFailed("Intrinsic prototype has incorrect vector element type!", - F); - break; - } - } - if ((unsigned)va_arg(VA, int) != PTy->getNumElements()) { + if (MVT::getVectorNumElements(VT) != NumElts) { CheckFailed("Intrinsic prototype has incorrect number of " "vector elements!",F); - break; + break; } + } else if (MVT::getTypeForValueType(VT) != EltTy) { + if (ArgNo == 0) + CheckFailed("Intrinsic prototype has incorrect result type!", F); + else + CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " is wrong!",F); + break; + } else if (EltTy != Ty) { + if (ArgNo == 0) + CheckFailed("Intrinsic result type is vector " + "and a scalar is required.", F); + else + CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " is vector " + "and a scalar is required.", F); } }