diff options
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 13 | ||||
-rw-r--r-- | lib/VMCore/ConstantFold.cpp | 6 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 33 | ||||
-rw-r--r-- | lib/VMCore/ConstantsContext.h | 15 | ||||
-rw-r--r-- | lib/VMCore/Core.cpp | 31 | ||||
-rw-r--r-- | lib/VMCore/LLVMContextImpl.h | 5 | ||||
-rw-r--r-- | lib/VMCore/Type.cpp | 136 | ||||
-rw-r--r-- | lib/VMCore/TypesContext.h | 26 |
8 files changed, 258 insertions, 7 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 7d6e0a7..4fe1eee 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -239,6 +239,19 @@ void TypePrinting::CalcTypeName(const Type *Ty, OS << '>'; break; } + case Type::UnionTyID: { + const UnionType *UTy = cast<UnionType>(Ty); + OS << "union { "; + for (StructType::element_iterator I = UTy->element_begin(), + E = UTy->element_end(); I != E; ++I) { + CalcTypeName(*I, TypeStack, OS); + if (next(I) != UTy->element_end()) + OS << ','; + OS << ' '; + } + OS << '}'; + break; + } case Type::PointerTyID: { const PointerType *PTy = cast<PointerType>(Ty); CalcTypeName(PTy->getElementType(), TypeStack, OS); diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 5c117d8..4a245d2 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -885,6 +885,8 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg, unsigned numOps; if (const ArrayType *AR = dyn_cast<ArrayType>(AggTy)) numOps = AR->getNumElements(); + else if (isa<UnionType>(AggTy)) + numOps = 1; else numOps = cast<StructType>(AggTy)->getNumElements(); @@ -901,6 +903,10 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg, if (const StructType* ST = dyn_cast<StructType>(AggTy)) return ConstantStruct::get(ST->getContext(), Ops, ST->isPacked()); + if (const UnionType* UT = dyn_cast<UnionType>(AggTy)) { + assert(Ops.size() == 1 && "Union can only contain a single value!"); + return ConstantUnion::get(UT, Ops[0]); + } return ConstantArray::get(cast<ArrayType>(AggTy), Ops); } diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 2250626..8cc6e94 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -585,6 +585,27 @@ Constant* ConstantStruct::get(LLVMContext &Context, return get(Context, std::vector<Constant*>(Vals, Vals+NumVals), Packed); } +ConstantUnion::ConstantUnion(const UnionType *T, Constant* V) + : Constant(T, ConstantUnionVal, + OperandTraits<ConstantUnion>::op_end(this) - 1, 1) { + Use *OL = OperandList; + assert(T->getElementTypeIndex(V->getType()) >= 0 && + "Initializer for union element isn't a member of union type!"); + *OL = V; +} + +// ConstantUnion accessors. +Constant* ConstantUnion::get(const UnionType* T, Constant* V) { + LLVMContextImpl* pImpl = T->getContext().pImpl; + + // Create a ConstantAggregateZero value if all elements are zeros... + if (!V->isNullValue()) + return pImpl->UnionConstants.getOrCreate(T, V); + + return ConstantAggregateZero::get(T); +} + + ConstantVector::ConstantVector(const VectorType *T, const std::vector<Constant*> &V) : Constant(T, ConstantVectorVal, @@ -1010,6 +1031,13 @@ void ConstantStruct::destroyConstant() { // destroyConstant - Remove the constant from the constant table... // +void ConstantUnion::destroyConstant() { + getType()->getContext().pImpl->UnionConstants.remove(this); + destroyConstantImpl(); +} + +// destroyConstant - Remove the constant from the constant table... +// void ConstantVector::destroyConstant() { getType()->getContext().pImpl->VectorConstants.remove(this); destroyConstantImpl(); @@ -2083,6 +2111,11 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, destroyConstant(); } +void ConstantUnion::replaceUsesOfWithOnConstant(Value *From, Value *To, + Use *U) { + assert(false && "Implement replaceUsesOfWithOnConstant for unions"); +} + void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); diff --git a/lib/VMCore/ConstantsContext.h b/lib/VMCore/ConstantsContext.h index 08224e4..c798ba2 100644 --- a/lib/VMCore/ConstantsContext.h +++ b/lib/VMCore/ConstantsContext.h @@ -341,6 +341,13 @@ struct ConstantTraits< std::vector<T, Alloc> > { } }; +template<> +struct ConstantTraits<Constant *> { + static unsigned uses(Constant * const & v) { + return 1; + } +}; + template<class ConstantClass, class TypeClass, class ValType> struct ConstantCreator { static ConstantClass *create(const TypeClass *Ty, const ValType &V) { @@ -470,6 +477,14 @@ struct ConstantKeyData<ConstantStruct> { } }; +template<> +struct ConstantKeyData<ConstantUnion> { + typedef Constant* ValType; + static ValType getValType(ConstantUnion *CU) { + return cast<Constant>(CU->getOperand(0)); + } +}; + // ConstantPointerNull does not take extra "value" argument... template<class ValType> struct ConstantCreator<ConstantPointerNull, PointerType, ValType> { diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index 1755cd2..a044fc5 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -141,6 +141,8 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) { return LLVMFunctionTypeKind; case Type::StructTyID: return LLVMStructTypeKind; + case Type::UnionTyID: + return LLVMUnionTypeKind; case Type::ArrayTyID: return LLVMArrayTypeKind; case Type::PointerTyID: @@ -299,6 +301,35 @@ LLVMBool LLVMIsPackedStruct(LLVMTypeRef StructTy) { return unwrap<StructType>(StructTy)->isPacked(); } +/*--.. Operations on union types ..........................................--*/ + +LLVMTypeRef LLVMUnionTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes, + unsigned ElementCount) { + SmallVector<const Type*, 8> Tys; + for (LLVMTypeRef *I = ElementTypes, + *E = ElementTypes + ElementCount; I != E; ++I) + Tys.push_back(unwrap(*I)); + + return wrap(UnionType::get(&Tys[0], Tys.size())); +} + +LLVMTypeRef LLVMUnionType(LLVMTypeRef *ElementTypes, + unsigned ElementCount, int Packed) { + return LLVMUnionTypeInContext(LLVMGetGlobalContext(), ElementTypes, + ElementCount); +} + +unsigned LLVMCountUnionElementTypes(LLVMTypeRef UnionTy) { + return unwrap<UnionType>(UnionTy)->getNumElements(); +} + +void LLVMGetUnionElementTypes(LLVMTypeRef UnionTy, LLVMTypeRef *Dest) { + UnionType *Ty = unwrap<UnionType>(UnionTy); + for (FunctionType::param_iterator I = Ty->element_begin(), + E = Ty->element_end(); I != E; ++I) + *Dest++ = wrap(*I); +} + /*--.. Operations on array, pointer, and vector types (sequence types) .....--*/ LLVMTypeRef LLVMArrayType(LLVMTypeRef ElementType, unsigned ElementCount) { diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index f7f4860..62491d8 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -116,6 +116,10 @@ public: ConstantStruct, true /*largekey*/> StructConstantsTy; StructConstantsTy StructConstants; + typedef ConstantUniqueMap<Constant*, UnionType, ConstantUnion> + UnionConstantsTy; + UnionConstantsTy UnionConstants; + typedef ConstantUniqueMap<std::vector<Constant*>, VectorType, ConstantVector> VectorConstantsTy; VectorConstantsTy VectorConstants; @@ -159,6 +163,7 @@ public: TypeMap<PointerValType, PointerType> PointerTypes; TypeMap<FunctionValType, FunctionType> FunctionTypes; TypeMap<StructValType, StructType> StructTypes; + TypeMap<UnionValType, UnionType> UnionTypes; TypeMap<IntegerValType, IntegerType> IntegerTypes; // Opaque types are not structurally uniqued, so don't use TypeMap. diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index cf85198..b1cdad5 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -50,8 +50,8 @@ void AbstractTypeUser::setType(Value *V, const Type *NewTy) { /// Because of the way Type subclasses are allocated, this function is necessary /// to use the correct kind of "delete" operator to deallocate the Type object. -/// Some type objects (FunctionTy, StructTy) allocate additional space after -/// the space for their derived type to hold the contained types array of +/// Some type objects (FunctionTy, StructTy, UnionTy) allocate additional space +/// after the space for their derived type to hold the contained types array of /// PATypeHandles. Using this allocation scheme means all the PATypeHandles are /// allocated with the type object, decreasing allocations and eliminating the /// need for a std::vector to be used in the Type class itself. @@ -61,7 +61,8 @@ void Type::destroy() const { // Structures and Functions allocate their contained types past the end of // the type object itself. These need to be destroyed differently than the // other types. - if (isa<FunctionType>(this) || isa<StructType>(this)) { + if (isa<FunctionType>(this) || isa<StructType>(this) || + isa<UnionType>(this)) { // First, make sure we destruct any PATypeHandles allocated by these // subclasses. They must be manually destructed. for (unsigned i = 0; i < NumContainedTys; ++i) @@ -71,8 +72,10 @@ void Type::destroy() const { // to delete this as an array of char. if (isa<FunctionType>(this)) static_cast<const FunctionType*>(this)->FunctionType::~FunctionType(); - else + else if (isa<StructType>(this)) static_cast<const StructType*>(this)->StructType::~StructType(); + else + static_cast<const UnionType*>(this)->UnionType::~UnionType(); // Finally, remove the memory as an array deallocation of the chars it was // constructed from. @@ -226,7 +229,7 @@ bool Type::isSizedDerivedType() const { if (const VectorType *PTy = dyn_cast<VectorType>(this)) return PTy->getElementType()->isSized(); - if (!isa<StructType>(this)) + if (!isa<StructType>(this) && !isa<UnionType>(this)) return false; // Okay, our struct is sized if all of the elements are... @@ -308,6 +311,32 @@ const Type *StructType::getTypeAtIndex(unsigned Idx) const { return ContainedTys[Idx]; } + +bool UnionType::indexValid(const Value *V) const { + // Union indexes require 32-bit integer constants. + if (V->getType()->isInteger(32)) + if (const ConstantInt *CU = dyn_cast<ConstantInt>(V)) + return indexValid(CU->getZExtValue()); + return false; +} + +bool UnionType::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 *UnionType::getTypeAtIndex(const Value *V) const { + unsigned Idx = (unsigned)cast<ConstantInt>(V)->getZExtValue(); + return getTypeAtIndex(Idx); +} + +const Type *UnionType::getTypeAtIndex(unsigned Idx) const { + assert(indexValid(Idx) && "Invalid structure index!"); + return ContainedTys[Idx]; +} + //===----------------------------------------------------------------------===// // Primitive 'Type' data //===----------------------------------------------------------------------===// @@ -463,6 +492,23 @@ StructType::StructType(LLVMContext &C, setAbstract(isAbstract); } +UnionType::UnionType(LLVMContext &C,const Type* const* Types, unsigned NumTypes) + : CompositeType(C, UnionTyID) { + ContainedTys = reinterpret_cast<PATypeHandle*>(this + 1); + NumContainedTys = NumTypes; + bool isAbstract = false; + for (unsigned i = 0; i < NumTypes; ++i) { + assert(Types[i] && "<null> type for union field!"); + assert(isValidElementType(Types[i]) && + "Invalid type for union element!"); + new (&ContainedTys[i]) PATypeHandle(Types[i], this); + isAbstract |= Types[i]->isAbstract(); + } + + // Calculate whether or not this type is abstract + setAbstract(isAbstract); +} + ArrayType::ArrayType(const Type *ElType, uint64_t NumEl) : SequentialType(ArrayTyID, ElType) { NumElements = NumEl; @@ -644,6 +690,13 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, if (!TypesEqual(STy->getElementType(i), STy2->getElementType(i), EqTypes)) return false; return true; + } else if (const UnionType *UTy = dyn_cast<UnionType>(Ty)) { + const UnionType *UTy2 = cast<UnionType>(Ty2); + if (UTy->getNumElements() != UTy2->getNumElements()) return false; + for (unsigned i = 0, e = UTy2->getNumElements(); i != e; ++i) + if (!TypesEqual(UTy->getElementType(i), UTy2->getElementType(i), EqTypes)) + return false; + return true; } else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { const ArrayType *ATy2 = cast<ArrayType>(Ty2); return ATy->getNumElements() == ATy2->getNumElements() && @@ -901,12 +954,66 @@ StructType *StructType::get(LLVMContext &Context, const Type *type, ...) { } bool StructType::isValidElementType(const Type *ElemTy) { - return ElemTy->getTypeID() != VoidTyID && ElemTy->getTypeID() != LabelTyID && - ElemTy->getTypeID() != MetadataTyID && !isa<FunctionType>(ElemTy); + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy() && !isa<FunctionType>(ElemTy); } //===----------------------------------------------------------------------===// +// Union Type Factory... +// + +UnionType *UnionType::get(const Type* const* Types, unsigned NumTypes) { + assert(NumTypes > 0 && "union must have at least one member type!"); + UnionValType UTV(Types, NumTypes); + UnionType *UT = 0; + + LLVMContextImpl *pImpl = Types[0]->getContext().pImpl; + + UT = pImpl->UnionTypes.get(UTV); + + if (!UT) { + // Value not found. Derive a new type! + UT = (UnionType*) operator new(sizeof(UnionType) + + sizeof(PATypeHandle) * NumTypes); + new (UT) UnionType(Types[0]->getContext(), Types, NumTypes); + pImpl->UnionTypes.add(UTV, UT); + } +#ifdef DEBUG_MERGE_TYPES + DEBUG(dbgs() << "Derived new type: " << *UT << "\n"); +#endif + return UT; +} + +UnionType *UnionType::get(const Type *type, ...) { + va_list ap; + SmallVector<const llvm::Type*, 8> UnionFields; + va_start(ap, type); + while (type) { + UnionFields.push_back(type); + type = va_arg(ap, llvm::Type*); + } + unsigned NumTypes = UnionFields.size(); + assert(NumTypes > 0 && "union must have at least one member type!"); + return llvm::UnionType::get(&UnionFields[0], NumTypes); +} + +bool UnionType::isValidElementType(const Type *ElemTy) { + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy() && !ElemTy->isFunction(); +} + +int UnionType::getElementTypeIndex(const Type *ElemTy) const { + int index = 0; + for (UnionType::element_iterator I = element_begin(), E = element_end(); + I != E; ++I, ++index) { + if (ElemTy == *I) return index; + } + + return -1; +} + +//===----------------------------------------------------------------------===// // Pointer Type Factory... // @@ -1169,6 +1276,21 @@ void StructType::typeBecameConcrete(const DerivedType *AbsTy) { // concrete - this could potentially change us from an abstract type to a // concrete type. // +void UnionType::refineAbstractType(const DerivedType *OldType, + const Type *NewType) { + LLVMContextImpl *pImpl = OldType->getContext().pImpl; + pImpl->UnionTypes.RefineAbstractType(this, OldType, NewType); +} + +void UnionType::typeBecameConcrete(const DerivedType *AbsTy) { + LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; + pImpl->UnionTypes.TypeBecameConcrete(this, AbsTy); +} + +// refineAbstractType - Called when a contained type is found to be more +// concrete - this could potentially change us from an abstract type to a +// concrete type. +// void PointerType::refineAbstractType(const DerivedType *OldType, const Type *NewType) { LLVMContextImpl *pImpl = OldType->getContext().pImpl; diff --git a/lib/VMCore/TypesContext.h b/lib/VMCore/TypesContext.h index 4842845..02ab113 100644 --- a/lib/VMCore/TypesContext.h +++ b/lib/VMCore/TypesContext.h @@ -180,6 +180,32 @@ public: } }; +// UnionValType - Define a class to hold the key that goes into the TypeMap +// +class UnionValType { + std::vector<const Type*> ElTypes; +public: + UnionValType(const Type* const* Types, unsigned NumTypes) + : ElTypes(&Types[0], &Types[NumTypes]) {} + + static UnionValType get(const UnionType *UT) { + std::vector<const Type *> ElTypes; + ElTypes.reserve(UT->getNumElements()); + for (unsigned i = 0, e = UT->getNumElements(); i != e; ++i) + ElTypes.push_back(UT->getElementType(i)); + + return UnionValType(&ElTypes[0], ElTypes.size()); + } + + static unsigned hashTypeStructure(const UnionType *UT) { + return UT->getNumElements(); + } + + inline bool operator<(const UnionValType &UTV) const { + return (ElTypes < UTV.ElTypes); + } +}; + // FunctionValType - Define a class to hold the key that goes into the TypeMap // class FunctionValType { |