diff options
author | Reid Spencer <rspencer@reidspencer.com> | 2007-01-12 07:05:14 +0000 |
---|---|---|
committer | Reid Spencer <rspencer@reidspencer.com> | 2007-01-12 07:05:14 +0000 |
commit | a54b7cbd452b3adb2f51346140d996b29c2cdb30 (patch) | |
tree | 00514e24a3fab3804f1a99557ebd343382d0dc27 /lib/VMCore | |
parent | ed3098989580ecaee7fc89de548afb4c811bea31 (diff) | |
download | external_llvm-a54b7cbd452b3adb2f51346140d996b29c2cdb30.zip external_llvm-a54b7cbd452b3adb2f51346140d996b29c2cdb30.tar.gz external_llvm-a54b7cbd452b3adb2f51346140d996b29c2cdb30.tar.bz2 |
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33113 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 18 | ||||
-rw-r--r-- | lib/VMCore/ConstantFold.cpp | 16 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 95 | ||||
-rw-r--r-- | lib/VMCore/Instructions.cpp | 8 | ||||
-rw-r--r-- | lib/VMCore/Type.cpp | 149 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 41 |
6 files changed, 199 insertions, 128 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 138ab35..4730c31 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -222,6 +222,7 @@ static void fillTypeNameTable(const Module *M, const Type *Ty = cast<Type>(TI->second); if (!isa<PointerType>(Ty) || !cast<PointerType>(Ty)->getElementType()->isPrimitiveType() || + !cast<PointerType>(Ty)->getElementType()->isIntegral() || isa<OpaqueType>(cast<PointerType>(Ty)->getElementType())) TypeNames.insert(std::make_pair(Ty, getLLVMName(TI->first))); } @@ -233,7 +234,7 @@ static void calcTypeName(const Type *Ty, std::vector<const Type *> &TypeStack, std::map<const Type *, std::string> &TypeNames, std::string & Result){ - if (Ty->isPrimitiveType() && !isa<OpaqueType>(Ty)) { + if (Ty->isIntegral() || (Ty->isPrimitiveType() && !isa<OpaqueType>(Ty))) { Result += Ty->getDescription(); // Base case return; } @@ -265,6 +266,15 @@ static void calcTypeName(const Type *Ty, TypeStack.push_back(Ty); // Recursive case: Add us to the stack.. switch (Ty->getTypeID()) { + case Type::IntegerTyID: { + unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth(); + if (BitWidth == 1) + Result += "bool"; + else { + Result += "i" + utostr(BitWidth); + } + break; + } case Type::FunctionTyID: { const FunctionType *FTy = cast<FunctionType>(Ty); calcTypeName(FTy->getReturnType(), TypeStack, TypeNames, Result); @@ -347,7 +357,7 @@ static std::ostream &printTypeInt(std::ostream &Out, const Type *Ty, // Primitive types always print out their description, regardless of whether // they have been named or not. // - if (Ty->isPrimitiveType() && !isa<OpaqueType>(Ty)) + if (Ty->isIntegral() || (Ty->isPrimitiveType() && !isa<OpaqueType>(Ty))) return Out << Ty->getDescription(); // Check to see if the type is named. @@ -706,7 +716,9 @@ private: /// without considering any symbolic types that we may have equal to it. /// std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) { - if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { + if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty)) + Out << "i" << utostr(ITy->getBitWidth()); + else if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { printType(FTy->getReturnType()); Out << " ("; unsigned Idx = 1; diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 1f5aeb3..8aeca7b 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -1364,22 +1364,6 @@ Constant *llvm::ConstantFoldGetElementPtr(const Constant *C, assert(Ty != 0 && "Invalid indices for GEP!"); return ConstantPointerNull::get(PointerType::get(Ty)); } - - if (IdxList.size() == 1) { - const Type *ElTy = cast<PointerType>(C->getType())->getElementType(); - if (uint32_t ElSize = ElTy->getPrimitiveSize()) { - // gep null, C is equal to C*sizeof(nullty). If nullty is a known llvm - // type, we can statically fold this. - Constant *R = ConstantInt::get(Type::Int32Ty, ElSize); - // We know R is unsigned, Idx0 is signed because it must be an index - // through a sequential type (gep pointer operand) which is always - // signed. - R = ConstantExpr::getSExtOrBitCast(R, Idx0->getType()); - R = ConstantExpr::getMul(R, Idx0); // signed multiply - // R is a signed integer, C is the GEP pointer so -> IntToPtr - return ConstantExpr::getIntToPtr(R, C->getType()); - } - } } if (ConstantExpr *CE = dyn_cast<ConstantExpr>(const_cast<Constant*>(C))) { diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 7349091..c2332c6 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -92,25 +92,32 @@ bool Constant::canTrap() const { // Static constructor to create a '0' constant of arbitrary type... Constant *Constant::getNullValue(const Type *Ty) { switch (Ty->getTypeID()) { - case Type::Int1TyID: { - static Constant *NullBool = ConstantInt::get(Type::Int1Ty, false); - return NullBool; - } - case Type::Int8TyID: { - static Constant *NullInt8 = ConstantInt::get(Type::Int8Ty, 0); - return NullInt8; - } - case Type::Int16TyID: { - static Constant *NullInt16 = ConstantInt::get(Type::Int16Ty, 0); - return NullInt16; - } - case Type::Int32TyID: { - static Constant *NullInt32 = ConstantInt::get(Type::Int32Ty, 0); - return NullInt32; - } - case Type::Int64TyID: { - static Constant *NullInt64 = ConstantInt::get(Type::Int64Ty, 0); - return NullInt64; + case Type::IntegerTyID: { + const IntegerType *ITy = dyn_cast<IntegerType>(Ty); + switch (ITy->getBitWidth()) { + case 1: { + static Constant *NullBool = ConstantInt::get(Ty, false); + return NullBool; + } + case 8: { + static Constant *NullInt8 = ConstantInt::get(Ty, 0); + return NullInt8; + } + case 16: { + static Constant *NullInt16 = ConstantInt::get(Ty, 0); + return NullInt16; + } + case 32: { + static Constant *NullInt32 = ConstantInt::get(Ty, 0); + return NullInt32; + } + case 64: { + static Constant *NullInt64 = ConstantInt::get(Ty, 0); + return NullInt64; + } + default: + return ConstantInt::get(Ty, 0); + } } case Type::FloatTyID: { static Constant *NullFloat = ConstantFP::get(Type::FloatTy, 0); @@ -136,14 +143,12 @@ Constant *Constant::getNullValue(const Type *Ty) { // Static constructor to create an integral constant with all bits set ConstantInt *ConstantInt::getAllOnesValue(const Type *Ty) { - switch (Ty->getTypeID()) { - case Type::Int1TyID: return ConstantInt::getTrue(); - case Type::Int8TyID: - case Type::Int16TyID: - case Type::Int32TyID: - case Type::Int64TyID: return ConstantInt::get(Ty, int64_t(-1)); - default: return 0; - } + if (const IntegerType* ITy = dyn_cast<IntegerType>(Ty)) + if (ITy->getBitWidth() == 1) + return ConstantInt::getTrue(); + else + return ConstantInt::get(Ty, int64_t(-1)); + return 0; } /// @returns the value for an packed integer constant of the given type that @@ -549,25 +554,26 @@ getWithOperands(const std::vector<Constant*> &Ops) const { // isValueValidForType implementations bool ConstantInt::isValueValidForType(const Type *Ty, uint64_t Val) { - switch (Ty->getTypeID()) { - default: return false; // These can't be represented as integers! - case Type::Int1TyID: return Val == 0 || Val == 1; - case Type::Int8TyID: return Val <= UINT8_MAX; - case Type::Int16TyID: return Val <= UINT16_MAX; - case Type::Int32TyID: return Val <= UINT32_MAX; - case Type::Int64TyID: return true; // always true, has to fit in largest type - } + unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); // assert okay + assert(NumBits <= 64 && "Not implemented: integers > 64-bits"); + if (Ty == Type::Int1Ty) + return Val == 0 || Val == 1; + if (NumBits == 64) + return true; // always true, has to fit in largest type + uint64_t Max = (1ll << NumBits) - 1; + return Val <= Max; } bool ConstantInt::isValueValidForType(const Type *Ty, int64_t Val) { - switch (Ty->getTypeID()) { - default: return false; // These can't be represented as integers! - case Type::Int1TyID: return (Val == 0 || Val == 1); - case Type::Int8TyID: return (Val >= INT8_MIN && Val <= INT8_MAX); - case Type::Int16TyID: return (Val >= INT16_MIN && Val <= UINT16_MAX); - case Type::Int32TyID: return (Val >= INT32_MIN && Val <= UINT32_MAX); - case Type::Int64TyID: return true; // always true, has to fit in largest type - } + unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); // assert okay + assert(NumBits <= 64 && "Not implemented: integers > 64-bits"); + if (Ty == Type::Int1Ty) + return Val == 0 || Val == 1; + if (NumBits == 64) + return true; // always true, has to fit in largest type + int64_t Min = -(1ll << (NumBits-1)); + int64_t Max = (1ll << (NumBits-1)) - 1; + return (Val >= Min && Val <= Max); } bool ConstantFP::isValueValidForType(const Type *Ty, double Val) { @@ -1441,8 +1447,7 @@ Constant *ConstantExpr::getTruncOrBitCast(Constant *C, const Type *Ty) { Constant *ConstantExpr::getPointerCast(Constant *S, const Type *Ty) { assert(isa<PointerType>(S->getType()) && "Invalid cast"); - assert((Ty->isIntegral() || Ty->getTypeID() == Type::PointerTyID) && - "Invalid cast"); + assert((Ty->isIntegral() || isa<PointerType>(Ty)) && "Invalid cast"); if (Ty->isIntegral()) return getCast(Instruction::PtrToInt, S, Ty); diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index b9a4770..9486fb8 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -1528,7 +1528,7 @@ CastInst *CastInst::createPointerCast(Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd) { assert(isa<PointerType>(S->getType()) && "Invalid cast"); - assert((Ty->isIntegral() || Ty->getTypeID() == Type::PointerTyID) && + assert((Ty->isIntegral() || isa<PointerType>(Ty)) && "Invalid cast"); if (Ty->isIntegral()) @@ -1541,7 +1541,7 @@ CastInst *CastInst::createPointerCast(Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore) { assert(isa<PointerType>(S->getType()) && "Invalid cast"); - assert((Ty->isIntegral() || Ty->getTypeID() == Type::PointerTyID) && + assert((Ty->isIntegral() || isa<PointerType>(Ty)) && "Invalid cast"); if (Ty->isIntegral()) @@ -1913,7 +1913,7 @@ CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS, assert(Op0Ty == Op1Ty && "Both operands to ICmp instruction are not of the same type!"); // Check that the operands are the right type - assert(Op0Ty->isIntegral() || Op0Ty->getTypeID() == Type::PointerTyID || + assert(Op0Ty->isIntegral() || isa<PointerType>(Op0Ty) || (isa<PackedType>(Op0Ty) && cast<PackedType>(Op0Ty)->getElementType()->isIntegral()) && "Invalid operand types for ICmp instruction"); @@ -1948,7 +1948,7 @@ CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS, assert(Op0Ty == Op1Ty && "Both operands to ICmp instruction are not of the same type!"); // Check that the operands are the right type - assert(Op0Ty->isIntegral() || Op0Ty->getTypeID() == Type::PointerTyID || + assert(Op0Ty->isIntegral() || isa<PointerType>(Op0Ty) || (isa<PackedType>(Op0Ty) && cast<PackedType>(Op0Ty)->getElementType()->isIntegral()) && "Invalid operand types for ICmp instruction"); diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 8ab1afd..b70cd5f 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -64,7 +64,7 @@ static ManagedStatic<std::map<const Type*, std::string> > AbstractTypeDescriptions; Type::Type(const char *Name, TypeID id) - : ID(id), Abstract(false), RefCount(0), ForwardType(0) { + : ID(id), Abstract(false), SubclassData(0), RefCount(0), ForwardType(0) { assert(Name && Name[0] && "Should use other ctor if no name!"); (*ConcreteTypeDescriptions)[this] = Name; } @@ -73,11 +73,6 @@ Type::Type(const char *Name, TypeID id) const Type *Type::getPrimitiveType(TypeID IDNumber) { switch (IDNumber) { case VoidTyID : return VoidTy; - case Int1TyID : return Int1Ty; - case Int8TyID : return Int8Ty; - case Int16TyID : return Int16Ty; - case Int32TyID : return Int32Ty; - case Int64TyID : return Int64Ty; case FloatTyID : return FloatTy; case DoubleTyID: return DoubleTy; case LabelTyID : return LabelTy; @@ -116,41 +111,17 @@ bool Type::canLosslesslyBitCastTo(const Type *Ty) const { // At this point we have only various mismatches of the first class types // remaining and ptr->ptr. Just select the lossless conversions. Everything // else is not lossless. - if (getTypeID() == Type::PointerTyID) + if (isa<PointerType>(this)) return isa<PointerType>(Ty); return false; // Other types have no identity values } -// getPrimitiveSize - Return the basic size of this type if it is a primitive -// type. These are fixed by LLVM and are not target dependent. This will -// return zero if the type does not have a size or is not a primitive type. -// -unsigned Type::getPrimitiveSize() const { - switch (getTypeID()) { - case Type::Int1TyID: - case Type::Int8TyID: return 1; - case Type::Int16TyID: return 2; - case Type::FloatTyID: - case Type::Int32TyID: return 4; - case Type::Int64TyID: - case Type::DoubleTyID: return 8; - default: return 0; - } -} - unsigned Type::getPrimitiveSizeInBits() const { switch (getTypeID()) { - case Type::Int1TyID: return 1; - case Type::Int8TyID: return 8; - case Type::Int16TyID: return 16; - case Type::FloatTyID: - case Type::Int32TyID:return 32; - case Type::Int64TyID: + case Type::FloatTyID: return 32; case Type::DoubleTyID: return 64; - case Type::PackedTyID: { - const PackedType *PTy = cast<PackedType>(this); - return PTy->getBitWidth(); - } + case Type::IntegerTyID: return cast<IntegerType>(this)->getBitWidth(); + case Type::PackedTyID: return cast<PackedType>(this)->getBitWidth(); default: return 0; } } @@ -165,11 +136,13 @@ bool Type::isSizedDerivedType() const { if (const PackedType *PTy = dyn_cast<PackedType>(this)) return PTy->getElementType()->isSized(); - if (!isa<StructType>(this)) return false; + if (!isa<StructType>(this)) + return false; // Okay, our struct is sized if all of the elements are... for (subtype_iterator I = subtype_begin(), E = subtype_end(); I != E; ++I) - if (!(*I)->isSized()) return false; + if (!(*I)->isSized()) + return false; return true; } @@ -243,6 +216,14 @@ static std::string getTypeDescription(const Type *Ty, TypeStack.push_back(Ty); // Add us to the stack.. switch (Ty->getTypeID()) { + case Type::IntegerTyID: { + const IntegerType *ITy = cast<IntegerType>(Ty); + if (ITy->getBitWidth() == 1) + Result = "bool"; // FIXME: eventually this becomes i1 + else + Result = "i" + utostr(ITy->getBitWidth()); + break; + } case Type::FunctionTyID: { const FunctionType *FTy = cast<FunctionType>(Ty); if (!Result.empty()) @@ -267,6 +248,7 @@ static std::string getTypeDescription(const Type *Ty, } break; } + case Type::PackedStructTyID: case Type::StructTyID: { const StructType *STy = cast<StructType>(Ty); if (STy->isPacked()) @@ -353,7 +335,6 @@ const Type *StructType::getTypeAtIndex(const Value *V) const { return ContainedTys[Idx]; } - //===----------------------------------------------------------------------===// // Primitive 'Type' data //===----------------------------------------------------------------------===// @@ -365,17 +346,26 @@ const Type *StructType::getTypeAtIndex(const Value *V) const { }; \ } \ static ManagedStatic<TY##Type> The##TY##Ty; \ - Type *Type::TY##Ty = &*The##TY##Ty + const Type *Type::TY##Ty = &*The##TY##Ty + +#define DeclareIntegerType(TY, BitWidth) \ + namespace { \ + struct VISIBILITY_HIDDEN TY##Type : public IntegerType { \ + TY##Type() : IntegerType(BitWidth) {} \ + }; \ + } \ + static ManagedStatic<TY##Type> The##TY##Ty; \ + const Type *Type::TY##Ty = &*The##TY##Ty DeclarePrimType(Void, "void"); -DeclarePrimType(Int1, "bool"); -DeclarePrimType(Int8, "i8"); -DeclarePrimType(Int16, "i16"); -DeclarePrimType(Int32, "i32"); -DeclarePrimType(Int64, "i64"); DeclarePrimType(Float, "float"); DeclarePrimType(Double, "double"); DeclarePrimType(Label, "label"); +DeclareIntegerType(Int1, 1); +DeclareIntegerType(Int8, 8); +DeclareIntegerType(Int16, 16); +DeclareIntegerType(Int32, 32); +DeclareIntegerType(Int64, 64); #undef DeclarePrimType @@ -584,7 +574,10 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, // algorithm is the fact that arraytypes have sizes that differentiates types, // and that function types can be varargs or not. Consider this now. // - if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) { + if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty)) { + const IntegerType *ITy2 = cast<IntegerType>(Ty2); + return ITy->getBitWidth() == ITy2->getBitWidth(); + } else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) { return TypesEqual(PTy->getElementType(), cast<PointerType>(Ty2)->getElementType(), EqTypes); } else if (const StructType *STy = dyn_cast<StructType>(Ty)) { @@ -695,6 +688,9 @@ static unsigned getSubElementHash(const Type *Ty) { switch (SubTy->getTypeID()) { default: break; case Type::OpaqueTyID: return 0; // Opaque -> hash = 0 no matter what. + case Type::IntegerTyID: + HashVal ^= (cast<IntegerType>(SubTy)->getBitWidth() << 3); + break; case Type::FunctionTyID: HashVal ^= cast<FunctionType>(SubTy)->getNumParams()*2 + cast<FunctionType>(SubTy)->isVarArg(); @@ -928,6 +924,60 @@ public: // Function Type Factory and Value Class... // +//===----------------------------------------------------------------------===// +// Integer Type Factory... +// +namespace llvm { +class IntegerValType { + uint16_t bits; +public: + IntegerValType(uint16_t numbits) : bits(numbits) {} + + static IntegerValType get(const IntegerType *Ty) { + return IntegerValType(Ty->getBitWidth()); + } + + static unsigned hashTypeStructure(const IntegerType *Ty) { + return (unsigned)Ty->getBitWidth(); + } + + inline bool operator<(const IntegerValType &IVT) const { + return bits < IVT.bits; + } +}; +} + +static ManagedStatic<TypeMap<IntegerValType, IntegerType> > IntegerTypes; + +const IntegerType *IntegerType::get(unsigned NumBits) { + assert(NumBits >= MIN_INT_BITS && "bitwidth too small"); + assert(NumBits <= MAX_INT_BITS && "bitwidth too large"); + + // Check for the built-in integer types + switch (NumBits) { + case 1: return cast<IntegerType>(Type::Int1Ty); + case 8: return cast<IntegerType>(Type::Int8Ty); + case 16: return cast<IntegerType>(Type::Int16Ty); + case 32: return cast<IntegerType>(Type::Int32Ty); + case 64: return cast<IntegerType>(Type::Int64Ty); + default: + break; + } + + IntegerValType IVT(NumBits); + IntegerType *ITy = IntegerTypes->get(IVT); + if (ITy) return ITy; // Found a match, return it! + + // Value not found. Derive a new type! + ITy = new IntegerType(NumBits); + IntegerTypes->add(IVT, ITy); + +#ifdef DEBUG_MERGE_TYPES + DOUT << "Derived new type: " << *ITy << "\n"; +#endif + return ITy; +} + // FunctionValType - Define a class to hold the key that goes into the TypeMap // namespace llvm { @@ -1440,14 +1490,9 @@ void PointerType::typeBecameConcrete(const DerivedType *AbsTy) { } bool SequentialType::indexValid(const Value *V) const { - const Type *Ty = V->getType(); - switch (Ty->getTypeID()) { - case Type::Int32TyID: - case Type::Int64TyID: - return true; - default: - return false; - } + if (const IntegerType *IT = dyn_cast<IntegerType>(V->getType())) + return IT->getBitWidth() == 32 || IT->getBitWidth() == 64; + return false; } namespace llvm { diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 4431c81..05b8514 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -743,7 +743,7 @@ void Verifier::visitICmpInst(ICmpInst& IC) { Assert1(Op0Ty == Op1Ty, "Both operands to ICmp instruction are not of the same type!", &IC); // Check that the operands are the right type - Assert1(Op0Ty->isIntegral() || Op0Ty->getTypeID() == Type::PointerTyID, + Assert1(Op0Ty->isIntegral() || isa<PointerType>(Op0Ty), "Invalid operand types for ICmp instruction", &IC); visitInstruction(IC); } @@ -1005,7 +1005,7 @@ void Verifier::VerifyIntrinsicPrototype(Function *F, ...) { else Ty = FTy->getParamType(ArgNo-1); - if (Ty->getTypeID() != TypeID) { + if (TypeID != Ty->getTypeID()) { if (ArgNo == 0) CheckFailed("Intrinsic prototype has incorrect result type!", F); else @@ -1013,18 +1013,43 @@ void Verifier::VerifyIntrinsicPrototype(Function *F, ...) { break; } - // If this is a packed argument, verify the number and type of elements. - if (TypeID == Type::PackedTyID) { + if (TypeID == Type::IntegerTyID) { + unsigned GotBits = (unsigned) va_arg(VA, int); + unsigned ExpectBits = cast<IntegerType>(Ty)->getBitWidth(); + if (GotBits != ExpectBits) { + std::string bitmsg = " Expecting " + utostr(ExpectBits) + " but got " + + utostr(GotBits) + " bits."; + if (ArgNo == 0) + CheckFailed("Intrinsic prototype has incorrect integer result width!" + + bitmsg, F); + else + CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " has " + "incorrect integer width!" + bitmsg, F); + break; + } + } else if (TypeID == Type::PackedTyID) { + // If this is a packed argument, verify the number and type of elements. const PackedType *PTy = cast<PackedType>(Ty); - if (va_arg(VA, int) != PTy->getElementType()->getTypeID()) { - CheckFailed("Intrinsic prototype has incorrect vector element type!",F); + int ElemTy = va_arg(VA, int); + if (ElemTy != PTy->getElementType()->getTypeID()) { + 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()) { CheckFailed("Intrinsic prototype has incorrect number of " "vector elements!",F); - break; + break; } } } |