From a5f54a06b09acf5c4ed3571039f262128226145b Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sun, 7 Jun 2009 07:26:46 +0000 Subject: [PATCH] Create FunctionType::isValidArgumentType to go along with isValidReturnType. Also create isValidElementType for ArrayType, PointerType, StructType and VectorType. Make LLParser use them. This closes up some holes like an assertion failure on: %x = type {label} but largely doesn't change any semantics. The only thing we accept now which we didn't before is vectors of opaque type such as "<4 x opaque>". The opaque can be resolved to an int or float when linking. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73016 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DerivedTypes.h | 20 +++++++++++ include/llvm/Type.h | 2 +- lib/AsmParser/LLParser.cpp | 16 ++++++--- lib/VMCore/Type.cpp | 88 ++++++++++++++++++++++++++++++++------------- 4 files changed, 95 insertions(+), 31 deletions(-) diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h index dd6d908df41..fa951bf70d0 100644 --- a/include/llvm/DerivedTypes.h +++ b/include/llvm/DerivedTypes.h @@ -159,6 +159,10 @@ public: /// type. static bool isValidReturnType(const Type *RetTy); + /// isValidArgumentType - Return true if the specified type is valid as an + /// argument type. + static bool isValidArgumentType(const Type *ArgTy); + inline bool isVarArg() const { return isVarArgs; } inline const Type *getReturnType() const { return ContainedTys[0]; } @@ -232,6 +236,10 @@ public: /// an empty struct, pass NULL, NULL. static StructType *get(const Type *type, ...) END_WITH_NULL; + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + // Iterator access to the elements typedef Type::subtype_iterator element_iterator; element_iterator element_begin() const { return ContainedTys; } @@ -331,6 +339,10 @@ public: /// static ArrayType *get(const Type *ElementType, uint64_t NumElements); + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + inline uint64_t getNumElements() const { return NumElements; } // Implement the AbstractTypeUser interface. @@ -391,6 +403,10 @@ public: return VectorType::get(EltTy, VTy->getNumElements()); } + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + /// @brief Return the number of elements in the Vector type. inline unsigned getNumElements() const { return NumElements; } @@ -431,6 +447,10 @@ public: return PointerType::get(ElementType, 0); } + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + /// @brief Return the address space of the Pointer type. inline unsigned getAddressSpace() const { return AddressSpace; } diff --git a/include/llvm/Type.h b/include/llvm/Type.h index 5ce23ef4e4b..c1732af09bd 100644 --- a/include/llvm/Type.h +++ b/include/llvm/Type.h @@ -205,7 +205,7 @@ public: inline bool isAbstract() const { return Abstract; } /// canLosslesslyBitCastTo - Return true if this type could be converted - /// with a lossless BitCast to type 'Ty'. For example, uint to int. BitCasts + /// with a lossless BitCast to type 'Ty'. For example, i8* to i32*. BitCasts /// are valid for types of the same size only where no re-interpretation of /// the bits is done. /// @brief Determine if this type could be losslessly bitcast to Ty diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 4759d6f19de..4863f3c5116 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -1043,6 +1043,8 @@ bool LLParser::ParseTypeRec(PATypeHolder &Result) { return TokError("basic block pointers are invalid"); if (Result.get() == Type::VoidTy) return TokError("pointers to void are invalid; use i8* instead"); + if (!PointerType::isValidElementType(Result.get())) + return TokError("pointer to this type is invalid"); Result = HandleUpRefs(PointerType::getUnqual(Result.get())); Lex.Lex(); break; @@ -1053,6 +1055,8 @@ bool LLParser::ParseTypeRec(PATypeHolder &Result) { return TokError("basic block pointers are invalid"); if (Result.get() == Type::VoidTy) return TokError("pointers to void are invalid; use i8* instead"); + if (!PointerType::isValidElementType(Result.get())) + return TokError("pointer to this type is invalid"); unsigned AddrSpace; if (ParseOptionalAddrSpace(AddrSpace) || ParseToken(lltok::star, "expected '*' in address space")) @@ -1149,9 +1153,7 @@ bool LLParser::ParseArgumentList(std::vector &ArgList, Lex.Lex(); } - if ((!ArgTy->isFirstClassType() && !isa(ArgTy)) || - (isa(ArgTy) && - cast(ArgTy)->getElementType() == Type::MetadataTy)) + if (!FunctionType::isValidArgumentType(ArgTy)) return Error(TypeLoc, "invalid type for function argument"); ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attrs, Name)); @@ -1247,6 +1249,8 @@ bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) { if (Result == Type::VoidTy) return Error(EltTyLoc, "struct element can not have void type"); + if (!StructType::isValidElementType(Result)) + return Error(EltTyLoc, "invalid element type for struct"); while (EatIfPresent(lltok::comma)) { EltTyLoc = Lex.getLoc(); @@ -1254,6 +1258,8 @@ bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) { if (Result == Type::VoidTy) return Error(EltTyLoc, "struct element can not have void type"); + if (!StructType::isValidElementType(Result)) + return Error(EltTyLoc, "invalid element type for struct"); ParamsList.push_back(Result); } @@ -1301,11 +1307,11 @@ bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) { return Error(SizeLoc, "zero element vector is illegal"); if ((unsigned)Size != Size) return Error(SizeLoc, "size too large for vector"); - if (!EltTy->isFloatingPoint() && !EltTy->isInteger()) + if (!VectorType::isValidElementType(EltTy)) return Error(TypeLoc, "vector element type must be fp or integer"); Result = VectorType::get(EltTy, unsigned(Size)); } else { - if (!EltTy->isFirstClassType() && !isa(EltTy)) + if (!ArrayType::isValidElementType(EltTy)) return Error(TypeLoc, "invalid array element type"); Result = HandleUpRefs(ArrayType::get(EltTy, Size)); } diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 11b93ffda49..a1e6c42f86f 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -135,8 +135,8 @@ bool Type::isFPOrFPVector() const { return cast(this)->getElementType()->isFloatingPoint(); } -// canLosslesllyBitCastTo - Return true if this type can be converted to -// 'Ty' without any reinterpretation of bits. For example, uint to int. +// canLosslesslyBitCastTo - Return true if this type can be converted to +// 'Ty' without any reinterpretation of bits. For example, i8* to i32*. // bool Type::canLosslesslyBitCastTo(const Type *Ty) const { // Identity cast means no change so return true @@ -318,6 +318,17 @@ bool FunctionType::isValidReturnType(const Type *RetTy) { return true; } +/// isValidArgumentType - Return true if the specified type is valid as an +/// argument type. +bool FunctionType::isValidArgumentType(const Type *ArgTy) { + if ((!ArgTy->isFirstClassType() && !isa(ArgTy)) || + (isa(ArgTy) && + cast(ArgTy)->getElementType() == Type::MetadataTy)) + return false; + + return true; +} + FunctionType::FunctionType(const Type *Result, const std::vector &Params, bool IsVarArgs) @@ -331,11 +342,8 @@ FunctionType::FunctionType(const Type *Result, new (&ContainedTys[0]) PATypeHandle(Result, this); for (unsigned i = 0; i != Params.size(); ++i) { - assert((Params[i]->isFirstClassType() || isa(Params[i])) && - "Function arguments must be value types!"); - assert((!isa(Params[i]) || - cast(Params[i])->getElementType() != Type::MetadataTy) - && "Attempt to use metadata* as function argument type!"); + assert(isValidArgumentType(Params[i]) && + "Not a valid type for function argument!"); new (&ContainedTys[i+1]) PATypeHandle(Params[i], this); isAbstract |= Params[i]->isAbstract(); } @@ -352,12 +360,8 @@ StructType::StructType(const std::vector &Types, bool isPacked) bool isAbstract = false; for (unsigned i = 0; i < Types.size(); ++i) { assert(Types[i] && " type for structure field!"); - assert(Types[i] != Type::VoidTy && "Void type for structure field!"); - assert(Types[i] != Type::LabelTy && "Label type for structure field!"); - assert(Types[i] != Type::MetadataTy && "Metadata type for structure field"); - assert((!isa(Types[i]) || - cast(Types[i])->getElementType() != Type::MetadataTy) - && "Type 'metadata*' is invalid for structure field."); + assert(isValidElementType(Types[i]) && + "Invalid type for structure element!"); new (&ContainedTys[i]) PATypeHandle(Types[i], this); isAbstract |= Types[i]->isAbstract(); } @@ -379,8 +383,7 @@ VectorType::VectorType(const Type *ElType, unsigned NumEl) NumElements = NumEl; setAbstract(ElType->isAbstract()); assert(NumEl > 0 && "NumEl of a VectorType must be greater than 0"); - assert((ElType->isInteger() || ElType->isFloatingPoint() || - isa(ElType)) && + assert(isValidElementType(ElType) && "Elements of a VectorType must be a primitive type"); } @@ -1051,12 +1054,7 @@ static ManagedStatic > ArrayTypes; ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { assert(ElementType && "Can't get array of types!"); - assert(ElementType != Type::VoidTy && "Array of void is not valid!"); - assert(ElementType != Type::LabelTy && "Array of labels is not valid!"); - assert(ElementType != Type::MetadataTy && "Array of metadata is not valid!"); - assert((!isa(ElementType) || - cast(ElementType)->getElementType() != Type::MetadataTy) - && "Array of metadata* is not valid!"); + assert(isValidElementType(ElementType) && "Invalid type for array element!"); ArrayValType AVT(ElementType, NumElements); ArrayType *AT = ArrayTypes->get(AVT); @@ -1071,6 +1069,18 @@ ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { return AT; } +bool ArrayType::isValidElementType(const Type *ElemTy) { + if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy || + ElemTy == Type::MetadataTy) + return false; + + if (const PointerType *PTy = dyn_cast(ElemTy)) + if (PTy->getElementType() == Type::MetadataTy) + return false; + + return true; +} + //===----------------------------------------------------------------------===// // Vector Type Factory... @@ -1115,6 +1125,14 @@ VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { return PT; } +bool VectorType::isValidElementType(const Type *ElemTy) { + if (ElemTy->isInteger() || ElemTy->isFloatingPoint() || + isa(ElemTy)) + return true; + + return false; +} + //===----------------------------------------------------------------------===// // Struct Type Factory... // @@ -1181,6 +1199,17 @@ StructType *StructType::get(const Type *type, ...) { return llvm::StructType::get(StructFields); } +bool StructType::isValidElementType(const Type *ElemTy) { + if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy || + ElemTy == Type::MetadataTy) + return false; + + if (const PointerType *PTy = dyn_cast(ElemTy)) + if (PTy->getElementType() == Type::MetadataTy) + return false; + + return true; +} //===----------------------------------------------------------------------===// @@ -1217,10 +1246,7 @@ PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) { assert(ValueType && "Can't get a pointer to type!"); assert(ValueType != Type::VoidTy && "Pointer to void is not valid, use i8* instead!"); - assert(ValueType != Type::LabelTy && "Pointer to label is not valid!"); - assert((!isa(ValueType) || - cast(ValueType)->getElementType() != Type::MetadataTy) - && "Pointer to metadata* is not valid!"); + assert(isValidElementType(ValueType) && "Invalid type for pointer element!"); PointerValType PVT(ValueType, AddressSpace); PointerType *PT = PointerTypes->get(PVT); @@ -1239,6 +1265,18 @@ PointerType *Type::getPointerTo(unsigned addrs) const { return PointerType::get(this, addrs); } +bool PointerType::isValidElementType(const Type *ElemTy) { + if (ElemTy == Type::VoidTy || ElemTy == Type::LabelTy) + return false; + + if (const PointerType *PTy = dyn_cast(ElemTy)) + if (PTy->getElementType() == Type::MetadataTy) + return false; + + return true; +} + + //===----------------------------------------------------------------------===// // Derived Type Refinement Functions //===----------------------------------------------------------------------===// -- 2.11.0