X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FVerifier.cpp;h=7ec0cf3a4582c7330fc2006289aa5d6d48fc76a5;hb=0c78ac11dd1a2cb4012df6ae5b875d70d34e780b;hp=3442149401c75ee040b3b657cf46fde2a2154c00;hpb=2099ff065d5256883d278acb70a44e36b62a6436;p=oota-llvm.git diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 3442149401c..7ec0cf3a458 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,19 +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" @@ -67,6 +67,35 @@ 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 { @@ -89,16 +118,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 ) {} @@ -157,6 +186,7 @@ namespace { // Anonymous namespace for class virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); + AU.addRequiredID(PreVerifyID); if (RealPass) AU.addRequired(); } @@ -213,6 +243,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); @@ -224,8 +255,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 PAListPtr &Attrs, + const Value *V); void WriteValue(const Value *V) { if (!V) return; @@ -309,10 +348,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); } @@ -333,45 +377,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) { } +// 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 " + 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); + } + + 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); + } + + ParameterAttributes TypeI = Attrs & ParamAttr::typeIncompatible(Ty); + Assert1(!TypeI, "Wrong type for attribute " + + ParamAttr::getAsString(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 PAListPtr &Attrs, + const Value *V) { + if (Attrs.isEmpty()) + return; + + bool SawNest = false; + + for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) { + const ParamAttrsWithIndex &Attr = Attrs.getSlot(i); + + 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); + + if (Attr.Attrs & ParamAttr::Nest) { + Assert1(!SawNest, "More than one parameter has attribute nest!", V); + SawNest = true; + } + + if (Attr.Attrs & ParamAttr::StructRet) + Assert1(Attr.Index == 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))), - "Invalid struct-return function!", &F); - - if (const ParamAttrsList *Attrs = FT->getParamAttrs()) { - unsigned Idx = 1; - for (FunctionType::param_iterator I = FT->param_begin(), - E = FT->param_end(); I != E; ++I, ++Idx) { - if (Attrs->paramHasAttr(Idx, ParamAttr::ZExt) || - Attrs->paramHasAttr(Idx, ParamAttr::SExt)) - Assert1(FT->getParamType(Idx-1)->isInteger(), - "Attribute ZExt should only apply to Integer type!", &F); - if (Attrs->paramHasAttr(Idx, ParamAttr::NoAlias)) - Assert1(isa(FT->getParamType(Idx-1)), - "Attribute NoAlias should only apply to Pointer type!", &F); - } - } + Assert1(!F.hasStructRetAttr() || F.getReturnType() == Type::VoidTy, + "Invalid struct return type!", &F); + + const PAListPtr &Attrs = F.getParamAttrs(); + + Assert1(Attrs.isEmpty() || + Attrs.getSlot(Attrs.getNumSlots()-1).Index <= 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()) { @@ -399,7 +503,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) @@ -422,6 +530,12 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { // Ensure that basic blocks have terminators! Assert1(BB.getTerminator(), "Basic Block does not have terminator!", &BB); + // Ensure that the BB doesn't point out of its Function for unwinding. + Assert2(!BB.getUnwindDest() || + BB.getUnwindDest()->getParent() == BB.getParent(), + "Basic Block unwinds to block in different function!", + &BB, BB.getUnwindDest()); + // Check constraints that this basic block imposes on all of the PHI nodes in // it. if (isa(BB.front())) { @@ -477,15 +591,24 @@ 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 (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 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 + Assert1(0, "Invalid return type!", &RI); + // Check to make sure that the return value has necessary properties for // terminators... visitTerminatorInst(RI); @@ -604,8 +727,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); } @@ -615,8 +750,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); } @@ -626,8 +773,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); } @@ -637,8 +795,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); } @@ -706,34 +876,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); - if (Function *F = CI.getCalledFunction()) + 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); + + 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 @@ -844,7 +1046,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, @@ -868,6 +1070,22 @@ 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(GRI.isValidOperands(GRI.getAggregateValue(), GRI.getIndex()), + "Invalid GetResultInst operands!", &GRI); + visitInstruction(GRI); +} + /// verifyInstruction - Verify that an instruction is well formed. /// @@ -882,6 +1100,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(), @@ -889,7 +1112,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 @@ -909,9 +1134,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. @@ -984,7 +1223,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 { @@ -996,7 +1235,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); } } @@ -1013,14 +1252,66 @@ 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( + 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(); @@ -1029,97 +1320,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::part_set: - case Intrinsic::part_select: - if (ArgNo == 1) { - unsigned ResultBits = - cast(FTy->getReturnType())->getBitWidth(); - if (GotBits != ResultBits) - CheckFailed("Intrinsic requires the bit widths of the first " - "parameter and the result 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); } }