X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FType.cpp;h=3a9ea582f112efb088d357bd55f48f55f133986e;hb=ebcba612b537f45a033ccd9a60bee0c45e2e2ded;hp=4bb32bbae8921b24508c2853adbffc315dd8959a;hpb=645fc4edc23930365595e3e4b3314db0433a8182;p=oota-llvm.git diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 4bb32bbae89..3a9ea582f11 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.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. // //===----------------------------------------------------------------------===// // @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/DerivedTypes.h" -#include "llvm/ParameterAttributes.h" #include "llvm/Constants.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/StringExtras.h" @@ -23,6 +22,7 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Debug.h" #include +#include using namespace llvm; // DEBUG_MERGE_TYPES - Enable this #define to see how and when derived types are @@ -105,10 +105,13 @@ void Type::destroy() const { const Type *Type::getPrimitiveType(TypeID IDNumber) { switch (IDNumber) { - case VoidTyID : return VoidTy; - case FloatTyID : return FloatTy; - case DoubleTyID: return DoubleTy; - case LabelTyID : return LabelTy; + case VoidTyID : return VoidTy; + case FloatTyID : return FloatTy; + case DoubleTyID : return DoubleTy; + case X86_FP80TyID : return X86_FP80Ty; + case FP128TyID : return FP128Ty; + case PPC_FP128TyID : return PPC_FP128Ty; + case LabelTyID : return LabelTy; default: return 0; } @@ -123,10 +126,24 @@ const Type *Type::getVAArgsPromotedType() const { return this; } +/// isIntOrIntVector - Return true if this is an integer type or a vector of +/// integer types. +/// +bool Type::isIntOrIntVector() const { + if (isInteger()) + return true; + if (ID != Type::VectorTyID) return false; + + return cast(this)->getElementType()->isInteger(); +} + /// isFPOrFPVector - Return true if this is a FP type or a vector of FP types. /// bool Type::isFPOrFPVector() const { - if (ID == Type::FloatTyID || ID == Type::DoubleTyID) return true; + if (ID == Type::FloatTyID || ID == Type::DoubleTyID || + ID == Type::FP128TyID || ID == Type::X86_FP80TyID || + ID == Type::PPC_FP128TyID) + return true; if (ID != Type::VectorTyID) return false; return cast(this)->getElementType()->isFloatingPoint(); @@ -162,6 +179,9 @@ unsigned Type::getPrimitiveSizeInBits() const { switch (getTypeID()) { case Type::FloatTyID: return 32; case Type::DoubleTyID: return 64; + case Type::X86_FP80TyID: return 80; + case Type::FP128TyID: return 128; + case Type::PPC_FP128TyID: return 128; case Type::IntegerTyID: return cast(this)->getBitWidth(); case Type::VectorTyID: return cast(this)->getBitWidth(); default: return 0; @@ -251,6 +271,11 @@ static std::string getTypeDescription(const Type *Ty, case Type::VoidTyID: return (*ConcreteTypeDescriptions)[Ty] = "void"; case Type::FloatTyID: return (*ConcreteTypeDescriptions)[Ty] = "float"; case Type::DoubleTyID: return (*ConcreteTypeDescriptions)[Ty] = "double"; + case Type::X86_FP80TyID: + return (*ConcreteTypeDescriptions)[Ty] = "x86_fp80"; + case Type::FP128TyID: return (*ConcreteTypeDescriptions)[Ty] = "fp128"; + case Type::PPC_FP128TyID: + return (*ConcreteTypeDescriptions)[Ty] = "ppc_fp128"; case Type::LabelTyID: return (*ConcreteTypeDescriptions)[Ty] = "label"; } } @@ -282,15 +307,10 @@ static std::string getTypeDescription(const Type *Ty, if (!Result.empty()) Result += " "; Result += getTypeDescription(FTy->getReturnType(), TypeStack) + " ("; - unsigned Idx = 1; - const ParamAttrsList *Attrs = FTy->getParamAttrs(); for (FunctionType::param_iterator I = FTy->param_begin(), - E = FTy->param_end(); I != E; ++I) { + E = FTy->param_end(); I != E; ++I) { if (I != FTy->param_begin()) Result += ", "; - if (Attrs && Attrs->getParamAttrs(Idx) != ParamAttr::None) - Result += Attrs->getParamAttrsTextByIndex(Idx); - Idx++; Result += getTypeDescription(*I, TypeStack); } if (FTy->isVarArg()) { @@ -298,12 +318,8 @@ static std::string getTypeDescription(const Type *Ty, Result += "..."; } Result += ")"; - if (Attrs && Attrs->getParamAttrs(0) != ParamAttr::None) { - Result += " " + Attrs->getParamAttrsTextByIndex(0); - } break; } - case Type::PackedStructTyID: case Type::StructTyID: { const StructType *STy = cast(Ty); if (STy->isPacked()) @@ -323,7 +339,10 @@ static std::string getTypeDescription(const Type *Ty, } case Type::PointerTyID: { const PointerType *PTy = cast(Ty); - Result = getTypeDescription(PTy->getElementType(), TypeStack) + " *"; + Result = getTypeDescription(PTy->getElementType(), TypeStack); + if (unsigned AddressSpace = PTy->getAddressSpace()) + Result += " addrspace(" + utostr(AddressSpace) + ")"; + Result += " *"; break; } case Type::ArrayTyID: { @@ -377,16 +396,24 @@ bool StructType::indexValid(const Value *V) const { // Structure indexes require 32-bit integer constants. if (V->getType() == Type::Int32Ty) if (const ConstantInt *CU = dyn_cast(V)) - return CU->getZExtValue() < NumContainedTys; + return indexValid(CU->getZExtValue()); return false; } +bool StructType::indexValid(unsigned V) const { + return V < NumContainedTys; +} + // getTypeAtIndex - Given an index value into the type, return the type of the // element. For a structure type, this must be a constant value... // const Type *StructType::getTypeAtIndex(const Value *V) const { - assert(indexValid(V) && "Invalid structure index!"); unsigned Idx = (unsigned)cast(V)->getZExtValue(); + return getTypeAtIndex(Idx); +} + +const Type *StructType::getTypeAtIndex(unsigned Idx) const { + assert(indexValid(Idx) && "Invalid structure index!"); return ContainedTys[Idx]; } @@ -394,10 +421,13 @@ const Type *StructType::getTypeAtIndex(const Value *V) const { // Primitive 'Type' data //===----------------------------------------------------------------------===// -const Type *Type::VoidTy = new Type(Type::VoidTyID); -const Type *Type::FloatTy = new Type(Type::FloatTyID); -const Type *Type::DoubleTy = new Type(Type::DoubleTyID); -const Type *Type::LabelTy = new Type(Type::LabelTyID); +const Type *Type::VoidTy = new Type(Type::VoidTyID); +const Type *Type::FloatTy = new Type(Type::FloatTyID); +const Type *Type::DoubleTy = new Type(Type::DoubleTyID); +const Type *Type::X86_FP80Ty = new Type(Type::X86_FP80TyID); +const Type *Type::FP128Ty = new Type(Type::FP128TyID); +const Type *Type::PPC_FP128Ty = new Type(Type::PPC_FP128TyID); +const Type *Type::LabelTy = new Type(Type::LabelTyID); namespace { struct BuiltinIntegerType : public IntegerType { @@ -415,15 +445,35 @@ const IntegerType *Type::Int64Ty = new BuiltinIntegerType(64); // Derived Type Constructors //===----------------------------------------------------------------------===// +/// isValidReturnType - Return true if the specified type is valid as a return +/// type. +bool FunctionType::isValidReturnType(const Type *RetTy) { + if (RetTy->isFirstClassType()) + return true; + if (RetTy == Type::VoidTy || isa(RetTy)) + return true; + + // If this is a multiple return case, verify that each return is a first class + // value and that there is at least one value. + const StructType *SRetTy = dyn_cast(RetTy); + if (SRetTy == 0 || SRetTy->getNumElements() == 0) + return false; + + for (unsigned i = 0, e = SRetTy->getNumElements(); i != e; ++i) + if (!SRetTy->getElementType(i)->isFirstClassType()) + return false; + return true; +} + FunctionType::FunctionType(const Type *Result, const std::vector &Params, - bool IsVarArgs, const ParamAttrsList *Attrs) - : DerivedType(FunctionTyID), isVarArgs(IsVarArgs), ParamAttrs(Attrs) { + bool IsVarArgs) + : DerivedType(FunctionTyID), isVarArgs(IsVarArgs) { ContainedTys = reinterpret_cast(this+1); NumContainedTys = Params.size() + 1; // + 1 for result type - assert((Result->isFirstClassType() || Result == Type::VoidTy || - isa(Result)) && - "LLVM functions cannot return aggregates"); + assert(isValidReturnType(Result) && "invalid return type for function"); + + bool isAbstract = Result->isAbstract(); new (&ContainedTys[0]) PATypeHandle(Result, this); @@ -474,7 +524,9 @@ VectorType::VectorType(const Type *ElType, unsigned NumEl) } -PointerType::PointerType(const Type *E) : SequentialType(PointerTyID, E) { +PointerType::PointerType(const Type *E, unsigned AddrSpace) + : SequentialType(PointerTyID, E) { + AddressSpace = AddrSpace; // Calculate whether or not this type is abstract setAbstract(E->isAbstract()); } @@ -506,6 +558,7 @@ void DerivedType::dropAllTypeUses() { } +namespace { /// TypePromotionGraph and graph traits - this is designed to allow us to do /// efficient SCC processing of type graphs. This is the exact same as @@ -516,6 +569,8 @@ struct TypePromotionGraph { TypePromotionGraph(Type *T) : Ty(T) {} }; +} + namespace llvm { template <> struct GraphTraits { typedef Type NodeType; @@ -616,8 +671,9 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, const IntegerType *ITy2 = cast(Ty2); return ITy->getBitWidth() == ITy2->getBitWidth(); } else if (const PointerType *PTy = dyn_cast(Ty)) { - return TypesEqual(PTy->getElementType(), - cast(Ty2)->getElementType(), EqTypes); + const PointerType *PTy2 = cast(Ty2); + return PTy->getAddressSpace() == PTy2->getAddressSpace() && + TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes); } else if (const StructType *STy = dyn_cast(Ty)) { const StructType *STy2 = cast(Ty2); if (STy->getNumElements() != STy2->getNumElements()) return false; @@ -640,16 +696,7 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, FTy->getNumParams() != FTy2->getNumParams() || !TypesEqual(FTy->getReturnType(), FTy2->getReturnType(), EqTypes)) return false; - const ParamAttrsList *Attrs1 = FTy->getParamAttrs(); - const ParamAttrsList *Attrs2 = FTy2->getParamAttrs(); - if ((!Attrs1 && Attrs2) || (!Attrs2 && Attrs1) || - (Attrs1 && Attrs2 && (Attrs1->size() != Attrs2->size() || - (Attrs1->getParamAttrs(0) != Attrs2->getParamAttrs(0))))) - return false; - for (unsigned i = 0, e = FTy2->getNumParams(); i != e; ++i) { - if (Attrs1 && Attrs1->getParamAttrs(i+1) != Attrs2->getParamAttrs(i+1)) - return false; if (!TypesEqual(FTy->getParamType(i), FTy2->getParamType(i), EqTypes)) return false; } @@ -670,11 +717,11 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2) { // ever reach a non-abstract type, we know that we don't need to search the // subgraph. static bool AbstractTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, - std::set &VisitedTypes) { + SmallPtrSet &VisitedTypes) { if (TargetTy == CurTy) return true; if (!CurTy->isAbstract()) return false; - if (!VisitedTypes.insert(CurTy).second) + if (!VisitedTypes.insert(CurTy)) return false; // Already been here. for (Type::subtype_iterator I = CurTy->subtype_begin(), @@ -685,10 +732,10 @@ static bool AbstractTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, } static bool ConcreteTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, - std::set &VisitedTypes) { + SmallPtrSet &VisitedTypes) { if (TargetTy == CurTy) return true; - if (!VisitedTypes.insert(CurTy).second) + if (!VisitedTypes.insert(CurTy)) return false; // Already been here. for (Type::subtype_iterator I = CurTy->subtype_begin(), @@ -701,7 +748,7 @@ static bool ConcreteTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, /// TypeHasCycleThroughItself - Return true if the specified type has a cycle /// back to itself. static bool TypeHasCycleThroughItself(const Type *Ty) { - std::set VisitedTypes; + SmallPtrSet VisitedTypes; if (Ty->isAbstract()) { // Optimized case for abstract types. for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); @@ -747,6 +794,9 @@ static unsigned getSubElementHash(const Type *Ty) { case Type::StructTyID: HashVal ^= cast(SubTy)->getNumElements(); break; + case Type::PointerTyID: + HashVal ^= cast(SubTy)->getAddressSpace(); + break; } } return HashVal ? HashVal : 1; // Do not return zero unless opaque subty. @@ -851,7 +901,7 @@ public: // The old record is now out-of-date, because one of the children has been // updated. Remove the obsolete entry from the map. unsigned NumErased = Map.erase(ValType::get(Ty)); - assert(NumErased && "Element not found!"); + assert(NumErased && "Element not found!"); NumErased = NumErased; // Remember the structural hash for the type before we start hacking on it, // in case we need it later. @@ -1028,22 +1078,15 @@ namespace llvm { class FunctionValType { const Type *RetTy; std::vector ArgTypes; - const ParamAttrsList *ParamAttrs; bool isVarArg; public: FunctionValType(const Type *ret, const std::vector &args, - bool IVA, const ParamAttrsList *attrs) - : RetTy(ret), ParamAttrs(attrs), isVarArg(IVA) { - for (unsigned i = 0; i < args.size(); ++i) - ArgTypes.push_back(args[i]); - } + bool isVA) : RetTy(ret), ArgTypes(args), isVarArg(isVA) {} static FunctionValType get(const FunctionType *FT); static unsigned hashTypeStructure(const FunctionType *FT) { - unsigned Result = FT->getNumParams()*64 + FT->isVarArg(); - if (FT->getParamAttrs()) - Result += FT->getParamAttrs()->size()*2; + unsigned Result = FT->getNumParams()*2 + FT->isVarArg(); return Result; } @@ -1054,13 +1097,6 @@ public: if (isVarArg > MTV.isVarArg) return false; if (ArgTypes < MTV.ArgTypes) return true; if (ArgTypes > MTV.ArgTypes) return false; - if (ParamAttrs) - if (MTV.ParamAttrs) - return *ParamAttrs < *MTV.ParamAttrs; - else - return false; - else if (MTV.ParamAttrs) - return true; return false; } }; @@ -1075,26 +1111,22 @@ FunctionValType FunctionValType::get(const FunctionType *FT) { ParamTypes.reserve(FT->getNumParams()); for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) ParamTypes.push_back(FT->getParamType(i)); - return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg(), - FT->getParamAttrs()); + return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg()); } // FunctionType::get - The factory function for the FunctionType class... FunctionType *FunctionType::get(const Type *ReturnType, const std::vector &Params, - bool isVarArg, - const ParamAttrsList *Attrs) { - - FunctionValType VT(ReturnType, Params, isVarArg, Attrs); + bool isVarArg) { + FunctionValType VT(ReturnType, Params, isVarArg); FunctionType *FT = FunctionTypes->get(VT); - if (FT) { + if (FT) return FT; - } FT = (FunctionType*) new char[sizeof(FunctionType) + sizeof(PATypeHandle)*(Params.size()+1)]; - new (FT) FunctionType(ReturnType, Params, isVarArg, Attrs); + new (FT) FunctionType(ReturnType, Params, isVarArg); FunctionTypes->add(VT, FT); #ifdef DEBUG_MERGE_TYPES @@ -1103,12 +1135,6 @@ FunctionType *FunctionType::get(const Type *ReturnType, return FT; } -bool FunctionType::isStructReturn() const { - if (ParamAttrs) - return ParamAttrs->paramHasAttr(1, ParamAttr::StructRet); - return false; -} - //===----------------------------------------------------------------------===// // Array Type Factory... // @@ -1181,8 +1207,7 @@ static ManagedStatic > VectorTypes; VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { - assert(ElementType && "Can't get packed of null types!"); - assert(isPowerOf2_32(NumElements) && "Vector length should be a power of 2!"); + assert(ElementType && "Can't get vector of null types!"); VectorValType PVT(ElementType, NumElements); VectorType *PT = VectorTypes->get(PVT); @@ -1252,6 +1277,17 @@ StructType *StructType::get(const std::vector &ETypes, return ST; } +StructType *StructType::get(const Type *type, ...) { + va_list ap; + std::vector StructFields; + va_start(ap, type); + while (type) { + StructFields.push_back(type); + type = va_arg(ap, llvm::Type*); + } + return llvm::StructType::get(StructFields); +} + //===----------------------------------------------------------------------===// @@ -1263,11 +1299,12 @@ StructType *StructType::get(const std::vector &ETypes, namespace llvm { class PointerValType { const Type *ValTy; + unsigned AddressSpace; public: - PointerValType(const Type *val) : ValTy(val) {} + PointerValType(const Type *val, unsigned as) : ValTy(val), AddressSpace(as) {} static PointerValType get(const PointerType *PT) { - return PointerValType(PT->getElementType()); + return PointerValType(PT->getElementType(), PT->getAddressSpace()); } static unsigned hashTypeStructure(const PointerType *PT) { @@ -1275,25 +1312,26 @@ public: } bool operator<(const PointerValType &MTV) const { - return ValTy < MTV.ValTy; + if (AddressSpace < MTV.AddressSpace) return true; + return AddressSpace == MTV.AddressSpace && ValTy < MTV.ValTy; } }; } static ManagedStatic > PointerTypes; -PointerType *PointerType::get(const Type *ValueType) { +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 sbyte* instead!"); assert(ValueType != Type::LabelTy && "Pointer to label is not valid!"); - PointerValType PVT(ValueType); + PointerValType PVT(ValueType, AddressSpace); PointerType *PT = PointerTypes->get(PVT); if (PT) return PT; // Value not found. Derive a new type! - PointerTypes->add(PVT, PT = new PointerType(ValueType)); + PointerTypes->add(PVT, PT = new PointerType(ValueType, AddressSpace)); #ifdef DEBUG_MERGE_TYPES DOUT << "Derived new type: " << *PT << "\n"; @@ -1388,7 +1426,7 @@ void DerivedType::refineAbstractTypeTo(const Type *NewType) { while (!AbstractTypeUsers.empty() && NewTy != this) { AbstractTypeUser *User = AbstractTypeUsers.back(); - unsigned OldSize = AbstractTypeUsers.size(); + unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize; #ifdef DEBUG_MERGE_TYPES DOUT << " REFINING user " << OldSize-1 << "[" << (void*)User << "] of abstract type [" << (void*)this << " " @@ -1415,7 +1453,7 @@ void DerivedType::notifyUsesThatTypeBecameConcrete() { DOUT << "typeIsREFINED type: " << (void*)this << " " << *this << "\n"; #endif - unsigned OldSize = AbstractTypeUsers.size(); + unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize; while (!AbstractTypeUsers.empty()) { AbstractTypeUser *ATU = AbstractTypeUsers.back(); ATU->typeBecameConcrete(this);