#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/PassManager.h"
#include "llvm/Analysis/Dominators.h"
+#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/Streams.h"
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<PreVerifier> PreVer("preverify", "Preliminary module verification");
+ const PassInfo *PreVerifyID = PreVer.getPassInfo();
struct VISIBILITY_HIDDEN
Verifier : public FunctionPass, InstVisitor<Verifier> {
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
+ AU.addRequiredID(PreVerifyID);
if (RealPass)
AU.addRequired<DominatorTree>();
}
void visitUserOp2(Instruction &I) { visitUserOp1(I); }
void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI);
- void VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, ...);
+ void VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F,
+ unsigned Count, ...);
void WriteValue(const Value *V) {
if (!V) return;
}
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::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.getReturnType() == Type::VoidTy,
"Functions cannot return aggregate values!", &F);
- Assert1(!FT->isStructReturn() ||
- (FT->getReturnType() == Type::VoidTy &&
- FT->getNumParams() > 0 && isa<PointerType>(FT->getParamType(0))),
+ Assert1(!F.isStructReturn() || FT->getReturnType() == Type::VoidTy,
"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<PointerType>(FT->getParamType(Idx-1)),
- "Attribute NoAlias should only apply to Pointer type!", &F);
- if (Attrs->paramHasAttr(Idx, ParamAttr::ByVal))
- Assert1(isa<PointerType>(FT->getParamType(Idx-1)),
- "Attribute ByVal should only apply to Pointer type!", &F);
+ bool SawSRet = false;
+
+ if (const ParamAttrsList *Attrs = F.getParamAttrs()) {
+ Assert1(Attrs->size() &&
+ Attrs->getParamIndex(Attrs->size()-1) <= FT->getNumParams(),
+ "Function has excess attributes!", &F);
+
+ bool SawNest = false;
+
+ 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) +
+ "should not apply to functions!", &F);
+ } else {
+ uint16_t ParmI = Attr & ParamAttr::ReturnOnly;
+ Assert1(!ParmI, "Attribute " + Attrs->getParamAttrsText(ParmI) +
+ "should only be applied to function!", &F);
+
+ }
+
+ 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!", &F);
+ }
+
+ uint16_t IType = Attr & ParamAttr::IntegerTypeOnly;
+ Assert1(!IType || FT->getParamType(Idx-1)->isInteger(),
+ "Attribute " + Attrs->getParamAttrsText(IType) +
+ "should only apply to Integer type!", &F);
+
+ uint16_t PType = Attr & ParamAttr::PointerTypeOnly;
+ Assert1(!PType || isa<PointerType>(FT->getParamType(Idx-1)),
+ "Attribute " + Attrs->getParamAttrsText(PType) +
+ "should only apply to Pointer type!", &F);
+
+ 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!", &F);
+ }
+
+ if (Attr & ParamAttr::Nest) {
+ Assert1(!SawNest, "More than one parameter has attribute nest!", &F);
+ SawNest = true;
+ }
+
+ if (Attr & ParamAttr::StructRet) {
+ SawSRet = true;
+ Assert1(Idx == 1, "Attribute sret not on first parameter!", &F);
+ }
}
}
+ Assert1(SawSRet == F.isStructReturn(),
+ "StructReturn function with no sret attribute!", &F);
+
// Check that this function meets the restrictions on this calling convention.
switch (F.getCallingConv()) {
default:
"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)
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<VectorType>(SrcTy)->getNumElements() == cast<VectorType>(DestTy)->getNumElements(),
+ "UIToFP source and dest vector length mismatch", &I);
visitInstruction(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<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();
- 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<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();
- 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<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!",
CI.getOperand(i+1), FTy->getParamType(i), &CI);
- if (Function *F = CI.getCalledFunction())
+ if (Function *F = CI.getCalledFunction()) {
if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
visitIntrinsicFunctionCall(ID, CI);
-
+ }
+
visitInstruction(CI);
}
SmallVector<Value*, 16> 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<PointerType>(GEP.getType()) &&
cast<PointerType>(GEP.getType())->getElementType() == ElTy,
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) {
#define GET_INTRINSIC_VERIFIER
#include "llvm/Intrinsics.gen"
#undef GET_INTRINSIC_VERIFIER
+
+ switch (ID) {
+ 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::get(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::get(CI.getType()),
+ "Call to llvm.gcread must be with type '%ty* (%ty2*, %ty**).'",
+ &CI);
+ break;
+ case Intrinsic::init_trampoline:
+ Assert1(isa<Function>(IntrinsicInst::StripPointerCasts(CI.getOperand(2))),
+ "llvm.init_trampoline parameter #2 must resolve to a function.",
+ &CI);
+ }
}
/// 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();
// 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<IntegerType>(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<VectorType>(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<IntegerType>(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<IntegerType>(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<VectorType>(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<PointerType>(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<IntegerType>(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);
}
}