//
// 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.
//
//===----------------------------------------------------------------------===//
//
// * 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 ; <int>:0' is bad
+// * Only phi nodes can be self referential: 'add i32 %0, %0 ; <int>: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
//===----------------------------------------------------------------------===//
#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/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"
return false;
}
};
+}
- char PreVerifier::ID = 0;
- RegisterPass<PreVerifier> PreVer("preverify", "Preliminary module verification");
- const PassInfo *PreVerifyID = PreVer.getPassInfo();
+char PreVerifier::ID = 0;
+static RegisterPass<PreVerifier>
+PreVer("preverify", "Preliminary module verification");
+static const PassInfo *const PreVerifyID = &PreVer;
+namespace {
struct VISIBILITY_HIDDEN
Verifier : public FunctionPass, InstVisitor<Verifier> {
static char ID; // Pass ID, replacement for typeid
: 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 ) {}
void visitUserOp2(Instruction &I) { visitUserOp1(I); }
void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI);
void visitAllocationInst(AllocationInst &AI);
+ void visitExtractValueInst(ExtractValueInst &EVI);
+ void visitInsertValueInst(InsertValueInst &IVI);
void VerifyCallSite(CallSite CS);
void VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F,
unsigned Count, ...);
- void VerifyParamAttrs(const FunctionType *FT, const ParamAttrsList *Attrs,
- const Value *V);
+ 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;
Broken = true;
}
};
-
- char Verifier::ID = 0;
- RegisterPass<Verifier> X("verify", "Module Verifier");
} // End anonymous namespace
+char Verifier::ID = 0;
+static RegisterPass<Verifier> X("verify", "Module Verifier");
// Assert - We know that cond should be true, if not print an error message.
#define Assert(C, M) \
GV.hasExternalLinkage() ||
GV.hasDLLImportLinkage() ||
GV.hasExternalWeakLinkage() ||
+ GV.hasGhostLinkage() ||
(isa<GlobalAlias>(GV) &&
(GV.hasInternalLinkage() || GV.hasWeakLinkage())),
"Global is external, but doesn't have external or dllimport or weak linkage!",
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<GlobalValue>(GA.getAliasee())) {
const ConstantExpr *CE = dyn_cast<ConstantExpr>(GA.getAliasee());
Assert1(CE && CE->getOpcode() == Instruction::BitCast &&
"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) {
}
-// VerifyParamAttrs - Check parameter attributes against a function type.
-// The value V is printed in error messages.
-void Verifier::VerifyParamAttrs(const FunctionType *FT,
- const ParamAttrsList *Attrs,
- const Value *V) {
- if (!Attrs)
+// 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;
- // Note that when calling a varargs function, the following test disallows
- // parameter attributes for the arguments corresponding to the varargs part.
- Assert1(Attrs->size() &&
- Attrs->getParamIndex(Attrs->size()-1) <= FT->getNumParams(),
- "Attributes after end of type!", V);
+ 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);
+ }
- bool SawNest = false;
+ 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);
+ }
- for (unsigned Idx = 0; Idx <= FT->getNumParams(); ++Idx) {
- uint16_t Attr = Attrs->getParamAttrs(Idx);
-
- if (!Idx) {
- uint16_t RetI = Attr & ParamAttr::ParameterOnly;
- Assert1(!RetI, "Attribute " + Attrs->getParamAttrsText(RetI) +
- "does not apply to return values!", V);
- } else {
- uint16_t ParmI = Attr & ParamAttr::ReturnOnly;
- Assert1(!ParmI, "Attribute " + Attrs->getParamAttrsText(ParmI) +
- "only applies to return values!", V);
- }
+ ParameterAttributes TypeI = Attrs & ParamAttr::typeIncompatible(Ty);
+ Assert1(!TypeI, "Wrong type for attribute " +
+ ParamAttr::getAsString(TypeI), V);
+}
- for (unsigned i = 0;
- i < array_lengthof(ParamAttr::MutuallyIncompatible); ++i) {
- uint16_t MutI = Attr & ParamAttr::MutuallyIncompatible[i];
- Assert1(!(MutI & (MutI - 1)), "Attributes " +
- Attrs->getParamAttrsText(MutI) + "are incompatible!", 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;
- uint16_t IType = Attr & ParamAttr::IntegerTypeOnly;
- Assert1(!IType || FT->getParamType(Idx-1)->isInteger(),
- "Attribute " + Attrs->getParamAttrsText(IType) +
- "should only apply to Integer type!", V);
-
- uint16_t PType = Attr & ParamAttr::PointerTypeOnly;
- Assert1(!PType || isa<PointerType>(FT->getParamType(Idx-1)),
- "Attribute " + Attrs->getParamAttrsText(PType) +
- "should only apply to Pointer type!", V);
-
- if (Attr & ParamAttr::ByVal) {
- const PointerType *Ty =
- dyn_cast<PointerType>(FT->getParamType(Idx-1));
- Assert1(!Ty || isa<StructType>(Ty->getElementType()),
- "Attribute byval should only apply to pointer to structs!", V);
- }
+ 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 & ParamAttr::Nest) {
+ if (Attr.Attrs & 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);
- }
+ if (Attr.Attrs & ParamAttr::StructRet)
+ Assert1(Attr.Index == 1, "Attribute sret not on first parameter!", V);
}
}
"# formal arguments must match # of arguments for function type!",
&F, FT);
Assert1(F.getReturnType()->isFirstClassType() ||
- F.getReturnType() == Type::VoidTy,
+ F.getReturnType() == Type::VoidTy ||
+ isa<StructType>(F.getReturnType()),
"Functions cannot return aggregate values!", &F);
- Assert1(!F.isStructReturn() || FT->getReturnType() == Type::VoidTy,
- "Invalid struct-return function!", &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.
- VerifyParamAttrs(FT, F.getParamAttrs(), &F);
+ VerifyFunctionAttrs(FT, Attrs, &F);
// Check that this function meets the restrictions on this calling convention.
switch (F.getCallingConv()) {
if (F.isDeclaration()) {
Assert1(F.hasExternalLinkage() || F.hasDLLImportLinkage() ||
- F.hasExternalWeakLinkage(),
+ F.hasExternalWeakLinkage() || F.hasGhostLinkage(),
"invalid linkage type for function declaration", &F);
} else {
// Verify that this function (which has a body) is not named "llvm.*". It
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<StructType>(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<ArrayType>(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);
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
- bool SrcVec = SrcTy->getTypeID() == Type::VectorTyID;
- bool DstVec = DestTy->getTypeID() == Type::VectorTyID;
+ bool SrcVec = isa<VectorType>(SrcTy);
+ bool DstVec = isa<VectorType>(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);
+ 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<VectorType>(SrcTy)->getNumElements() == cast<VectorType>(DestTy)->getNumElements(),
+ Assert1(cast<VectorType>(SrcTy)->getNumElements() ==
+ cast<VectorType>(DestTy)->getNumElements(),
"UIToFP source and dest vector length mismatch", &I);
visitInstruction(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);
+ 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<VectorType>(SrcTy)->getNumElements() == cast<VectorType>(DestTy)->getNumElements(),
+ Assert1(cast<VectorType>(SrcTy)->getNumElements() ==
+ cast<VectorType>(DestTy)->getNumElements(),
"SIToFP source and dest vector length mismatch", &I);
visitInstruction(I);
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
- bool SrcVec = SrcTy->getTypeID() == Type::VectorTyID;
- bool DstVec = DestTy->getTypeID() == Type::VectorTyID;
+ bool SrcVec = isa<VectorType>(SrcTy);
+ bool DstVec = isa<VectorType>(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);
+ 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<VectorType>(SrcTy)->getNumElements() == cast<VectorType>(DestTy)->getNumElements(),
+ Assert1(cast<VectorType>(SrcTy)->getNumElements() ==
+ cast<VectorType>(DestTy)->getNumElements(),
"FPToUI source and dest vector length mismatch", &I);
visitInstruction(I);
const Type *SrcTy = I.getOperand(0)->getType();
const Type *DestTy = I.getType();
- bool SrcVec = SrcTy->getTypeID() == Type::VectorTyID;
- bool DstVec = DestTy->getTypeID() == Type::VectorTyID;
+ bool SrcVec = isa<VectorType>(SrcTy);
+ bool DstVec = isa<VectorType>(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);
+ 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<VectorType>(SrcTy)->getNumElements() == cast<VectorType>(DestTy)->getNumElements(),
+ Assert1(cast<VectorType>(SrcTy)->getNumElements() ==
+ cast<VectorType>(DestTy)->getNumElements(),
"FPToSI source and dest vector length mismatch", &I);
visitInstruction(I);
"Call parameter type does not match function signature!",
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.
- VerifyParamAttrs(FTy, CS.getParamAttrs(), I);
+ 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);
}
case Instruction::Shl:
case Instruction::LShr:
case Instruction::AShr:
- Assert1(B.getType()->isInteger(),
- "Shift must return an integer result!", &B);
+ Assert1(B.getType()->isInteger() ||
+ (isa<VectorType>(B.getType()) &&
+ cast<VectorType>(B.getType())->getElementType()->isInteger()),
+ "Shifts only work with integral types!", &B);
Assert1(B.getType() == B.getOperand(0)->getType(),
"Shift return type must be same as operands!", &B);
/* FALL THROUGH */
// Check to see if Mask is valid.
if (const ConstantVector *MV = dyn_cast<ConstantVector>(SV.getOperand(2))) {
for (unsigned i = 0, e = MV->getNumOperands(); i != e; ++i) {
- Assert1(isa<ConstantInt>(MV->getOperand(i)) ||
- isa<UndefValue>(MV->getOperand(i)),
- "Invalid shufflevector shuffle mask!", &SV);
+ if (ConstantInt* CI = dyn_cast<ConstantInt>(MV->getOperand(i))) {
+ Assert1(!CI->uge(MV->getNumOperands()*2),
+ "Invalid shufflevector shuffle mask!", &SV);
+ } else {
+ Assert1(isa<UndefValue>(MV->getOperand(i)),
+ "Invalid shufflevector shuffle mask!", &SV);
+ }
}
} else {
Assert1(isa<UndefValue>(SV.getOperand(2)) ||
SmallVector<Value*, 16> Idxs(GEP.idx_begin(), GEP.idx_end());
const Type *ElTy =
GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(),
- Idxs.begin(), Idxs.end(), true);
+ Idxs.begin(), Idxs.end());
Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP);
Assert2(isa<PointerType>(GEP.getType()) &&
cast<PointerType>(GEP.getType())->getElementType() == ElTy,
}
void Verifier::visitAllocationInst(AllocationInst &AI) {
- const PointerType *Ptr = AI.getType();
- Assert(Ptr->getAddressSpace() == 0,
- "Allocation instruction pointer not in the generic address space!");
+ 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::visitExtractValueInst(ExtractValueInst &EVI) {
+ Assert1(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(),
+ EVI.idx_begin(), EVI.idx_end()) ==
+ EVI.getType(),
+ "Invalid ExtractValueInst operands!", &EVI);
+
+ visitInstruction(EVI);
+}
+
+void Verifier::visitInsertValueInst(InsertValueInst &IVI) {
+ Assert1(ExtractValueInst::getIndexedType(IVI.getAggregateOperand()->getType(),
+ IVI.idx_begin(), IVI.idx_end()) ==
+ IVI.getOperand(1)->getType(),
+ "Invalid InsertValueInst operands!", &IVI);
+
+ visitInstruction(IVI);
+}
/// verifyInstruction - Verify that an instruction is well formed.
///
!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<TerminatorInst>(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(),
// 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<CallInst>(I) || isa<InvokeInst>(I))
+ && isa<StructType>(I.getType())),
"Instruction returns a non-scalar type!", &I);
// Check that all uses of the instruction, if they are instructions
// 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()) {
+ Assert1(0, "Instruction operands must be first-class values!", &I);
+ }
+
if (Function *F = dyn_cast<Function>(I.getOperand(i))) {
// Check to make sure that the "address of" an intrinsic function is never
// taken.
}
// Definition must dominate use unless use is unreachable!
- Assert2(DT->dominates(OpBlock, BB) ||
+ Assert2(InstsInThisBlock.count(Op) || DT->dominates(Op, &I) ||
!DT->dominates(&BB->getParent()->getEntryBlock(), BB),
"Instruction does not dominate all uses!", Op, &I);
} else {
InstsInThisBlock.insert(&I);
}
-static bool HasPtrPtrType(Value *Val) {
- if (const PointerType *PtrTy = dyn_cast<PointerType>(Val->getType()))
- return isa<PointerType>(PtrTy->getElementType());
- return false;
-}
-
/// visitIntrinsicFunction - Allow intrinsics to be verified in different ways.
///
void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
default:
break;
case Intrinsic::gcroot:
- Assert1(HasPtrPtrType(CI.getOperand(1)),
- "llvm.gcroot parameter #1 must be a pointer to a pointer.", &CI);
- Assert1(isa<AllocaInst>(IntrinsicInst::StripPointerCasts(CI.getOperand(1))),
- "llvm.gcroot parameter #1 must be an alloca (or a bitcast of one).",
- &CI);
- Assert1(isa<Constant>(CI.getOperand(2)),
- "llvm.gcroot parameter #2 must be a constant.", &CI);
- break;
case Intrinsic::gcwrite:
- Assert1(CI.getOperand(3)->getType()
- == PointerType::getUnqual(CI.getOperand(1)->getType()),
- "Call to llvm.gcwrite must be with type 'void (%ty*, %ty2*, %ty**)'.",
- &CI);
- break;
- case Intrinsic::gcread:
- Assert1(CI.getOperand(2)->getType() == PointerType::getUnqual(CI.getType()),
- "Call to llvm.gcread must be with type '%ty* (%ty2*, %ty**).'",
- &CI);
- break;
+ 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<AllocaInst>(CI.getOperand(1)->stripPointerCasts()),
+ "llvm.gcroot parameter #1 must be an alloca.", &CI);
+ Assert1(isa<Constant>(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<Function>(IntrinsicInst::StripPointerCasts(CI.getOperand(2))),
+ Assert1(isa<Function>(CI.getOperand(2)->stripPointerCasts()),
"llvm.init_trampoline parameter #2 must resolve to a function.",
&CI);
+ break;
}
}
unsigned Count, ...) {
va_list VA;
va_start(VA, Count);
-
const FunctionType *FTy = F->getFunctionType();
// For overloaded intrinsics, the Suffix of the function name must match the
// 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())
EltTy = VTy->getElementType();
NumElts = VTy->getNumElements();
}
-
- if ((int)VT < 0) {
+
+ if (VT < 0) {
int Match = ~VT;
if (Match == 0) {
if (Ty != FTy->getReturnType()) {
Suffix += ".";
if (EltTy != Ty)
Suffix += "v" + utostr(NumElts);
- Suffix += MVT::getValueTypeString(MVT::getValueType(EltTy));
+ Suffix += MVT::getMVT(EltTy).getMVTString();
} else if (VT == MVT::iPTR) {
if (!isa<PointerType>(Ty)) {
if (ArgNo == 0)
else
CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " is not a "
"pointer and a pointer is required.", F);
+ }
+ } else if (VT == MVT::iPTRAny) {
+ // Outside of TableGen, we don't distinguish iPTRAny (to any address
+ // space) and iPTR. In the verifier, we can not distinguish which case
+ // we have so allow either case to be legal.
+ if (const PointerType* PTyp = dyn_cast<PointerType>(Ty)) {
+ Suffix += ".p" + utostr(PTyp->getAddressSpace()) +
+ MVT::getMVT(PTyp->getElementType()).getMVTString();
+ } else {
+ 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
va_end(VA);
- // If we computed a Suffix then the intrinsic is overloaded and we need to
- // make sure that the name of the function is correct. We add the suffix to
- // the name of the intrinsic and compare against the given function name. If
- // they are not the same, the function name is invalid. This ensures that
- // overloading of intrinsics uses a sane and consistent naming convention.
+ // For intrinsics without pointer arguments, if we computed a Suffix then the
+ // intrinsic is overloaded and we need to make sure that the name of the
+ // function is correct. We add the suffix to the name of the intrinsic and
+ // compare against the given function name. If they are not the same, the
+ // function name is invalid. This ensures that overloading of intrinsics
+ // uses a sane and consistent naming convention. Note that intrinsics with
+ // pointer argument may or may not be overloaded so we will check assuming it
+ // has a suffix and not.
if (!Suffix.empty()) {
std::string Name(Intrinsic::getName(ID));
- if (Name + Suffix != F->getName())
+ if (Name + Suffix != F->getName()) {
CheckFailed("Overloaded intrinsic has incorrect suffix: '" +
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);
}
PassManager PM;
Verifier *V = new Verifier(action);
PM.add(V);
- PM.run((Module&)M);
+ PM.run(const_cast<Module&>(M));
if (ErrorInfo && V->Broken)
*ErrorInfo = V->msgs.str();