diff options
author | Chris Lattner <sabre@nondot.org> | 2010-02-12 20:49:41 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-02-12 20:49:41 +0000 |
commit | 392be58cad0f051b4e7e252b44cef14b547f9b81 (patch) | |
tree | 94d1ae41a937c2ba15293075eca262842da5d3fe /llvm/lib | |
parent | bdf1b9520cf4be11020a6d2af5b84b33c12e1514 (diff) | |
download | bcm5719-llvm-392be58cad0f051b4e7e252b44cef14b547f9b81.tar.gz bcm5719-llvm-392be58cad0f051b4e7e252b44cef14b547f9b81.zip |
Add support for a union type in LLVM IR. Patch by Talin!
llvm-svn: 96011
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 80 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.h | 4 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLToken.h | 1 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.td | 2 | ||||
-rw-r--r-- | llvm/lib/VMCore/AsmWriter.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/VMCore/ConstantFold.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/VMCore/Constants.cpp | 33 | ||||
-rw-r--r-- | llvm/lib/VMCore/ConstantsContext.h | 15 | ||||
-rw-r--r-- | llvm/lib/VMCore/Core.cpp | 31 | ||||
-rw-r--r-- | llvm/lib/VMCore/LLVMContextImpl.h | 5 | ||||
-rw-r--r-- | llvm/lib/VMCore/Type.cpp | 136 | ||||
-rw-r--r-- | llvm/lib/VMCore/TypesContext.h | 26 |
15 files changed, 363 insertions, 18 deletions
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 8ad658d858d..46f3cbcfa37 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -570,6 +570,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(type); KEYWORD(opaque); + KEYWORD(union); KEYWORD(eq); KEYWORD(ne); KEYWORD(slt); KEYWORD(sgt); KEYWORD(sle); KEYWORD(sge); KEYWORD(ult); KEYWORD(ugt); KEYWORD(ule); KEYWORD(uge); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 4dab11826bc..5cff310c7e3 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1295,6 +1295,11 @@ bool LLParser::ParseTypeRec(PATypeHolder &Result) { if (ParseStructType(Result, false)) return true; break; + case lltok::kw_union: + // TypeRec ::= 'union' '{' ... '}' + if (ParseUnionType(Result)) + return true; + break; case lltok::lsquare: // TypeRec ::= '[' ... ']' Lex.Lex(); // eat the lsquare. @@ -1604,6 +1609,38 @@ bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) { return false; } +/// ParseUnionType +/// TypeRec +/// ::= 'union' '{' TypeRec (',' TypeRec)* '}' +bool LLParser::ParseUnionType(PATypeHolder &Result) { + assert(Lex.getKind() == lltok::kw_union); + Lex.Lex(); // Consume the 'union' + + if (ParseToken(lltok::lbrace, "'{' expected after 'union'")) return true; + + SmallVector<PATypeHolder, 8> ParamsList; + do { + LocTy EltTyLoc = Lex.getLoc(); + if (ParseTypeRec(Result)) return true; + ParamsList.push_back(Result); + + if (Result->isVoidTy()) + return Error(EltTyLoc, "union element can not have void type"); + if (!UnionType::isValidElementType(Result)) + return Error(EltTyLoc, "invalid element type for union"); + + } while (EatIfPresent(lltok::comma)) ; + + if (ParseToken(lltok::rbrace, "expected '}' at end of union")) + return true; + + SmallVector<const Type*, 8> ParamsListTy; + for (unsigned i = 0, e = ParamsList.size(); i != e; ++i) + ParamsListTy.push_back(ParamsList[i].get()); + Result = HandleUpRefs(UnionType::get(&ParamsListTy[0], ParamsListTy.size())); + return false; +} + /// ParseArrayVectorType - Parse an array or vector type, assuming the first /// token has already been consumed. /// TypeRec @@ -2163,8 +2200,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { ParseToken(lltok::rparen, "expected ')' in extractvalue constantexpr")) return true; - if (!isa<StructType>(Val->getType()) && !isa<ArrayType>(Val->getType())) - return Error(ID.Loc, "extractvalue operand must be array or struct"); + if (!Val->getType()->isAggregateType()) + return Error(ID.Loc, "extractvalue operand must be aggregate type"); if (!ExtractValueInst::getIndexedType(Val->getType(), Indices.begin(), Indices.end())) return Error(ID.Loc, "invalid indices for extractvalue"); @@ -2184,8 +2221,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { ParseIndexList(Indices) || ParseToken(lltok::rparen, "expected ')' in insertvalue constantexpr")) return true; - if (!isa<StructType>(Val0->getType()) && !isa<ArrayType>(Val0->getType())) - return Error(ID.Loc, "extractvalue operand must be array or struct"); + if (!Val0->getType()->isAggregateType()) + return Error(ID.Loc, "insertvalue operand must be aggregate type"); if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices.begin(), Indices.end())) return Error(ID.Loc, "invalid indices for insertvalue"); @@ -2521,8 +2558,17 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, V = Constant::getNullValue(Ty); return false; case ValID::t_Constant: - if (ID.ConstantVal->getType() != Ty) + if (ID.ConstantVal->getType() != Ty) { + // Allow a constant struct with a single member to be converted + // to a union, if the union has a member which is the same type + // as the struct member. + if (const UnionType* utype = dyn_cast<UnionType>(Ty)) { + return ParseUnionValue(utype, ID, V); + } + return Error(ID.Loc, "constant expression type mismatch"); + } + V = ID.ConstantVal; return false; } @@ -2552,6 +2598,22 @@ bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, return false; } +bool LLParser::ParseUnionValue(const UnionType* utype, ValID &ID, Value *&V) { + if (const StructType* stype = dyn_cast<StructType>(ID.ConstantVal->getType())) { + if (stype->getNumContainedTypes() != 1) + return Error(ID.Loc, "constant expression type mismatch"); + int index = utype->getElementTypeIndex(stype->getContainedType(0)); + if (index < 0) + return Error(ID.Loc, "initializer type is not a member of the union"); + + V = ConstantUnion::get( + utype, cast<Constant>(ID.ConstantVal->getOperand(0))); + return false; + } + + return Error(ID.Loc, "constant expression type mismatch"); +} + /// FunctionHeader /// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs @@ -3811,8 +3873,8 @@ int LLParser::ParseExtractValue(Instruction *&Inst, PerFunctionState &PFS) { ParseIndexList(Indices, AteExtraComma)) return true; - if (!isa<StructType>(Val->getType()) && !isa<ArrayType>(Val->getType())) - return Error(Loc, "extractvalue operand must be array or struct"); + if (!Val->getType()->isAggregateType()) + return Error(Loc, "extractvalue operand must be aggregate type"); if (!ExtractValueInst::getIndexedType(Val->getType(), Indices.begin(), Indices.end())) @@ -3833,8 +3895,8 @@ int LLParser::ParseInsertValue(Instruction *&Inst, PerFunctionState &PFS) { ParseIndexList(Indices, AteExtraComma)) return true; - if (!isa<StructType>(Val0->getType()) && !isa<ArrayType>(Val0->getType())) - return Error(Loc0, "extractvalue operand must be array or struct"); + if (!Val0->getType()->isAggregateType()) + return Error(Loc0, "insertvalue operand must be aggregate type"); if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices.begin(), Indices.end())) diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h index ed7a1d71176..9abe4042736 100644 --- a/llvm/lib/AsmParser/LLParser.h +++ b/llvm/lib/AsmParser/LLParser.h @@ -31,6 +31,7 @@ namespace llvm { class GlobalValue; class MDString; class MDNode; + class UnionType; /// ValID - Represents a reference of a definition of some sort with no type. /// There are several cases where we have to parse the value but where the @@ -212,6 +213,7 @@ namespace llvm { } bool ParseTypeRec(PATypeHolder &H); bool ParseStructType(PATypeHolder &H, bool Packed); + bool ParseUnionType(PATypeHolder &H); bool ParseArrayVectorType(PATypeHolder &H, bool isVector); bool ParseFunctionType(PATypeHolder &Result); PATypeHolder HandleUpRefs(const Type *Ty); @@ -280,6 +282,8 @@ namespace llvm { return ParseTypeAndBasicBlock(BB, Loc, PFS); } + bool ParseUnionValue(const UnionType* utype, ValID &ID, Value *&V); + struct ParamInfo { LocTy Loc; Value *V; diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index 7f1807c7d0d..3ac91690067 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -97,6 +97,7 @@ namespace lltok { kw_type, kw_opaque, + kw_union, kw_eq, kw_ne, kw_slt, kw_sgt, kw_sle, kw_sge, kw_ult, kw_ugt, kw_ule, kw_uge, kw_oeq, kw_one, kw_olt, kw_ogt, kw_ole, kw_oge, kw_ord, kw_uno, diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 4dfc6cef5ad..a0402caa905 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -585,6 +585,13 @@ bool BitcodeReader::ParseTypeTable() { ResultTy = StructType::get(Context, EltTys, Record[0]); break; } + case bitc::TYPE_CODE_UNION: { // UNION: [eltty x N] + SmallVector<const Type*, 8> EltTys; + for (unsigned i = 0, e = Record.size(); i != e; ++i) + EltTys.push_back(getTypeByID(Record[i], true)); + ResultTy = UnionType::get(&EltTys[0], EltTys.size()); + break; + } case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty] if (Record.size() < 2) return Error("Invalid ARRAY type record"); diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index ec081d5515c..82e73b5cff2 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -181,6 +181,14 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { Log2_32_Ceil(VE.getTypes().size()+1))); unsigned StructAbbrev = Stream.EmitAbbrev(Abbv); + // Abbrev for TYPE_CODE_UNION. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_UNION)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + unsigned UnionAbbrev = Stream.EmitAbbrev(Abbv); + // Abbrev for TYPE_CODE_ARRAY. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY)); @@ -250,6 +258,17 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { AbbrevToUse = StructAbbrev; break; } + case Type::UnionTyID: { + const UnionType *UT = cast<UnionType>(T); + // UNION: [eltty x N] + Code = bitc::TYPE_CODE_UNION; + // Output all of the element types. + for (UnionType::element_iterator I = UT->element_begin(), + E = UT->element_end(); I != E; ++I) + TypeVals.push_back(VE.getTypeID(*I)); + AbbrevToUse = UnionAbbrev; + break; + } case Type::ArrayTyID: { const ArrayType *AT = cast<ArrayType>(T); // ARRAY: [numelts, eltty] @@ -789,7 +808,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, else if (isCStr7) AbbrevToUse = CString7Abbrev; } else if (isa<ConstantArray>(C) || isa<ConstantStruct>(V) || - isa<ConstantVector>(V)) { + isa<ConstantUnion>(C) || isa<ConstantVector>(V)) { Code = bitc::CST_CODE_AGGREGATE; for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) Record.push_back(VE.getValueID(C->getOperand(i))); diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index d0be4f792c2..de085f522b8 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -4242,7 +4242,7 @@ def INVEPT : I<0x38, RawFrm, (outs), (ins), "invept", []>, OpSize, TB; // 66 0F 38 81 def INVVPID : I<0x38, RawFrm, (outs), (ins), "invvpid", []>, OpSize, TB; // 0F 01 C1 -def VMCALL : I<0x01, RawFrm, (outs), (ins), "vmcall", []>, TB; +def VMCALL : I<0x01, MRM_C1, (outs), (ins), "vmcall", []>, TB; def VMCLEARm : I<0xC7, MRM6m, (outs), (ins i64mem:$vmcs), "vmclear\t$vmcs", []>, OpSize, TB; // 0F 01 C2 diff --git a/llvm/lib/VMCore/AsmWriter.cpp b/llvm/lib/VMCore/AsmWriter.cpp index 7d6e0a7d0bc..4fe1eeeb4ab 100644 --- a/llvm/lib/VMCore/AsmWriter.cpp +++ b/llvm/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/llvm/lib/VMCore/ConstantFold.cpp b/llvm/lib/VMCore/ConstantFold.cpp index 5c117d8a181..4a245d22c3e 100644 --- a/llvm/lib/VMCore/ConstantFold.cpp +++ b/llvm/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/llvm/lib/VMCore/Constants.cpp b/llvm/lib/VMCore/Constants.cpp index 2250626051b..8cc6e94a4e8 100644 --- a/llvm/lib/VMCore/Constants.cpp +++ b/llvm/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/llvm/lib/VMCore/ConstantsContext.h b/llvm/lib/VMCore/ConstantsContext.h index 08224e4488b..c798ba2664c 100644 --- a/llvm/lib/VMCore/ConstantsContext.h +++ b/llvm/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/llvm/lib/VMCore/Core.cpp b/llvm/lib/VMCore/Core.cpp index 1755cd213e2..a044fc5b1a0 100644 --- a/llvm/lib/VMCore/Core.cpp +++ b/llvm/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/llvm/lib/VMCore/LLVMContextImpl.h b/llvm/lib/VMCore/LLVMContextImpl.h index f7f4860614a..62491d838fb 100644 --- a/llvm/lib/VMCore/LLVMContextImpl.h +++ b/llvm/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/llvm/lib/VMCore/Type.cpp b/llvm/lib/VMCore/Type.cpp index cf851987df8..b1cdad577c8 100644 --- a/llvm/lib/VMCore/Type.cpp +++ b/llvm/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/llvm/lib/VMCore/TypesContext.h b/llvm/lib/VMCore/TypesContext.h index 484284551fa..02ab1135b32 100644 --- a/llvm/lib/VMCore/TypesContext.h +++ b/llvm/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 { |