aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/LangRef.html141
-rw-r--r--include/llvm-c/Core.h10
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h3
-rw-r--r--include/llvm/Constants.h45
-rw-r--r--include/llvm/DerivedTypes.h61
-rw-r--r--include/llvm/Type.h14
-rw-r--r--include/llvm/Value.h1
-rw-r--r--lib/AsmParser/LLLexer.cpp1
-rw-r--r--lib/AsmParser/LLParser.cpp80
-rw-r--r--lib/AsmParser/LLParser.h4
-rw-r--r--lib/AsmParser/LLToken.h1
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp7
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp21
-rw-r--r--lib/Target/X86/X86InstrInfo.td2
-rw-r--r--lib/VMCore/AsmWriter.cpp13
-rw-r--r--lib/VMCore/ConstantFold.cpp6
-rw-r--r--lib/VMCore/Constants.cpp33
-rw-r--r--lib/VMCore/ConstantsContext.h15
-rw-r--r--lib/VMCore/Core.cpp31
-rw-r--r--lib/VMCore/LLVMContextImpl.h5
-rw-r--r--lib/VMCore/Type.cpp136
-rw-r--r--lib/VMCore/TypesContext.h26
-rw-r--r--test/Assembler/2010-01-06-UnionType.ll3
-rw-r--r--test/Feature/unions.ll12
24 files changed, 612 insertions, 59 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 9590609a87..b337b6a857 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -66,12 +66,17 @@
</li>
<li><a href="#t_derived">Derived Types</a>
<ol>
- <li><a href="#t_array">Array Type</a></li>
+ <li><a href="#t_aggregate">Aggregate Types</a>
+ <ol>
+ <li><a href="#t_array">Array Type</a></li>
+ <li><a href="#t_struct">Structure Type</a></li>
+ <li><a href="#t_pstruct">Packed Structure Type</a></li>
+ <li><a href="#t_union">Union Type</a></li>
+ <li><a href="#t_vector">Vector Type</a></li>
+ </ol>
+ </li>
<li><a href="#t_function">Function Type</a></li>
<li><a href="#t_pointer">Pointer Type</a></li>
- <li><a href="#t_struct">Structure Type</a></li>
- <li><a href="#t_pstruct">Packed Structure Type</a></li>
- <li><a href="#t_vector">Vector Type</a></li>
<li><a href="#t_opaque">Opaque Type</a></li>
</ol>
</li>
@@ -1404,6 +1409,7 @@ Classifications</a> </div>
<a href="#t_pointer">pointer</a>,
<a href="#t_vector">vector</a>,
<a href="#t_struct">structure</a>,
+ <a href="#t_union">union</a>,
<a href="#t_array">array</a>,
<a href="#t_label">label</a>,
<a href="#t_metadata">metadata</a>.
@@ -1418,12 +1424,12 @@ Classifications</a> </div>
</tr>
<tr>
<td><a href="#t_derived">derived</a></td>
- <td><a href="#t_integer">integer</a>,
- <a href="#t_array">array</a>,
+ <td><a href="#t_array">array</a>,
<a href="#t_function">function</a>,
<a href="#t_pointer">pointer</a>,
<a href="#t_struct">structure</a>,
<a href="#t_pstruct">packed structure</a>,
+ <a href="#t_union">union</a>,
<a href="#t_vector">vector</a>,
<a href="#t_opaque">opaque</a>.
</td>
@@ -1561,6 +1567,21 @@ Classifications</a> </div>
possible to have a two dimensional array, using an array as the element type
of another array.</p>
+
+</div>
+
+<!-- _______________________________________________________________________ -->
+<div class="doc_subsubsection"> <a name="t_aggregate">Aggregate Types</a> </div>
+
+<div class="doc_text">
+
+<p>Aggregate Types are a subset of derived types that can contain multiple
+ member types. <a href="#t_array">Arrays</a>,
+ <a href="#t_struct">structs</a>, <a href="#t_vector">vectors</a> and
+ <a href="#t_union">unions</a> are aggregate types.</p>
+
+</div>
+
</div>
<!-- _______________________________________________________________________ -->
@@ -1629,9 +1650,9 @@ Classifications</a> </div>
<h5>Overview:</h5>
<p>The function type can be thought of as a function signature. It consists of
a return type and a list of formal parameter types. The return type of a
- function type is a scalar type, a void type, or a struct type. If the return
- type is a struct type then all struct elements must be of first class types,
- and the struct must have at least one element.</p>
+ function type is a scalar type, a void type, a struct type, or a union
+ type. If the return type is a struct type then all struct elements must be
+ of first class types, and the struct must have at least one element.</p>
<h5>Syntax:</h5>
<pre>
@@ -1754,6 +1775,53 @@ Classifications</a> </div>
</div>
<!-- _______________________________________________________________________ -->
+<div class="doc_subsubsection"> <a name="t_union">Union Type</a> </div>
+
+<div class="doc_text">
+
+<h5>Overview:</h5>
+<p>A union type describes an object with size and alignment suitable for
+ an object of any one of a given set of types (also known as an "untagged"
+ union). It is similar in concept and usage to a
+ <a href="#t_struct">struct</a>, except that all members of the union
+ have an offset of zero. The elements of a union may be any type that has a
+ size. Unions must have at least one member - empty unions are not allowed.
+ </p>
+
+<p>The size of the union as a whole will be the size of its largest member,
+ and the alignment requirements of the union as a whole will be the largest
+ alignment requirement of any member.</p>
+
+<p>Unions members are accessed using '<tt><a href="#i_load">load</a></tt> and
+ '<tt><a href="#i_store">store</a></tt>' by getting a pointer to a field with
+ the '<tt><a href="#i_getelementptr">getelementptr</a></tt>' instruction.
+ Since all members are at offset zero, the getelementptr instruction does
+ not affect the address, only the type of the resulting pointer.</p>
+
+<h5>Syntax:</h5>
+<pre>
+ union { &lt;type list&gt; }
+</pre>
+
+<h5>Examples:</h5>
+<table class="layout">
+ <tr class="layout">
+ <td class="left"><tt>union { i32, i32*, float }</tt></td>
+ <td class="left">A union of three types: an <tt>i32</tt>, a pointer to
+ an <tt>i32</tt>, and a <tt>float</tt>.</td>
+ </tr><tr class="layout">
+ <td class="left">
+ <tt>union {&nbsp;float,&nbsp;i32&nbsp;(i32)&nbsp;*&nbsp;}</tt></td>
+ <td class="left">A union, where the first element is a <tt>float</tt> and the
+ second element is a <a href="#t_pointer">pointer</a> to a
+ <a href="#t_function">function</a> that takes an <tt>i32</tt>, returning
+ an <tt>i32</tt>.</td>
+ </tr>
+</table>
+
+</div>
+
+<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection"> <a name="t_pointer">Pointer Type</a> </div>
<div class="doc_text">
@@ -1991,6 +2059,14 @@ Classifications</a> </div>
the number and types of elements must match those specified by the
type.</dd>
+ <dt><b>Union constants</b></dt>
+ <dd>Union constants are represented with notation similar to a structure with
+ a single element - that is, a single typed element surrounded
+ by braces (<tt>{}</tt>)). For example: "<tt>{ i32 4 }</tt>". The
+ <a href="#t_union">union type</a> can be initialized with a single-element
+ struct as long as the type of the struct element matches the type of
+ one of the union members.</dd>
+
<dt><b>Array constants</b></dt>
<dd>Array constants are represented with notation similar to array type
definitions (a comma separated list of elements, surrounded by square
@@ -2009,7 +2085,8 @@ Classifications</a> </div>
<dt><b>Zero initialization</b></dt>
<dd>The string '<tt>zeroinitializer</tt>' can be used to zero initialize a
- value to zero of <em>any</em> type, including scalar and aggregate types.
+ value to zero of <em>any</em> type, including scalar and
+ <a href="#t_aggregate">aggregate</a> types.
This is often used to avoid having to print large zero initializers
(e.g. for large arrays) and is always exactly equivalent to using explicit
zero initializers.</dd>
@@ -3845,7 +3922,8 @@ Instruction</a> </div>
<div class="doc_text">
-<p>LLVM supports several instructions for working with aggregate values.</p>
+<p>LLVM supports several instructions for working with
+ <a href="#t_aggregate">aggregate</a> values.</p>
</div>
@@ -3862,14 +3940,14 @@ Instruction</a> </div>
</pre>
<h5>Overview:</h5>
-<p>The '<tt>extractvalue</tt>' instruction extracts the value of a struct field
- or array element from an aggregate value.</p>
+<p>The '<tt>extractvalue</tt>' instruction extracts the value of a member field
+ from an <a href="#t_aggregate">aggregate</a> value.</p>
<h5>Arguments:</h5>
<p>The first operand of an '<tt>extractvalue</tt>' instruction is a value
- of <a href="#t_struct">struct</a> or <a href="#t_array">array</a> type. The
- operands are constant indices to specify which value to extract in a similar
- manner as indices in a
+ of <a href="#t_struct">struct</a>, <a href="#t_union">union</a> or
+ <a href="#t_array">array</a> type. The operands are constant indices to
+ specify which value to extract in a similar manner as indices in a
'<tt><a href="#i_getelementptr">getelementptr</a></tt>' instruction.</p>
<h5>Semantics:</h5>
@@ -3896,16 +3974,15 @@ Instruction</a> </div>
</pre>
<h5>Overview:</h5>
-<p>The '<tt>insertvalue</tt>' instruction inserts a value into a struct field or
- array element in an aggregate.</p>
-
+<p>The '<tt>insertvalue</tt>' instruction inserts a value into a member field
+ in an <a href="#t_aggregate">aggregate</a> value.</p>
<h5>Arguments:</h5>
<p>The first operand of an '<tt>insertvalue</tt>' instruction is a value
- of <a href="#t_struct">struct</a> or <a href="#t_array">array</a> type. The
- second operand is a first-class value to insert. The following operands are
- constant indices indicating the position at which to insert the value in a
- similar manner as indices in a
+ of <a href="#t_struct">struct</a>, <a href="#t_union">union</a> or
+ <a href="#t_array">array</a> type. The second operand is a first-class
+ value to insert. The following operands are constant indices indicating
+ the position at which to insert the value in a similar manner as indices in a
'<tt><a href="#i_getelementptr">getelementptr</a></tt>' instruction. The
value to insert must have the same type as the value identified by the
indices.</p>
@@ -4107,8 +4184,8 @@ Instruction</a> </div>
<h5>Overview:</h5>
<p>The '<tt>getelementptr</tt>' instruction is used to get the address of a
- subelement of an aggregate data structure. It performs address calculation
- only and does not access memory.</p>
+ subelement of an <a href="#t_aggregate">aggregate</a> data structure.
+ It performs address calculation only and does not access memory.</p>
<h5>Arguments:</h5>
<p>The first argument is always a pointer, and forms the basis of the
@@ -4118,15 +4195,15 @@ Instruction</a> </div>
indexes the pointer value given as the first argument, the second index
indexes a value of the type pointed to (not necessarily the value directly
pointed to, since the first index can be non-zero), etc. The first type
- indexed into must be a pointer value, subsequent types can be arrays, vectors
- and structs. Note that subsequent types being indexed into can never be
- pointers, since that would require loading the pointer before continuing
- calculation.</p>
+ indexed into must be a pointer value, subsequent types can be arrays,
+ vectors, structs and unions. Note that subsequent types being indexed into
+ can never be pointers, since that would require loading the pointer before
+ continuing calculation.</p>
<p>The type of each index argument depends on the type it is indexing into.
- When indexing into a (optionally packed) structure, only <tt>i32</tt> integer
- <b>constants</b> are allowed. When indexing into an array, pointer or
- vector, integers of any width are allowed, and they are not required to be
+ When indexing into a (optionally packed) structure or union, only <tt>i32</tt>
+ integer <b>constants</b> are allowed. When indexing into an array, pointer
+ or vector, integers of any width are allowed, and they are not required to be
constant.</p>
<p>For example, let's consider a C code fragment and how it gets compiled to
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h
index 98358fe380..4500fccb65 100644
--- a/include/llvm-c/Core.h
+++ b/include/llvm-c/Core.h
@@ -193,7 +193,8 @@ typedef enum {
LLVMPointerTypeKind, /**< Pointers */
LLVMOpaqueTypeKind, /**< Opaque: type with unknown structure */
LLVMVectorTypeKind, /**< SIMD 'packed' format, or other vector type */
- LLVMMetadataTypeKind /**< Metadata */
+ LLVMMetadataTypeKind, /**< Metadata */
+ LLVMUnionTypeKind /**< Unions */
} LLVMTypeKind;
typedef enum {
@@ -372,6 +373,13 @@ unsigned LLVMCountStructElementTypes(LLVMTypeRef StructTy);
void LLVMGetStructElementTypes(LLVMTypeRef StructTy, LLVMTypeRef *Dest);
LLVMBool LLVMIsPackedStruct(LLVMTypeRef StructTy);
+/* Operations on union types */
+LLVMTypeRef LLVMUnionTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes,
+ unsigned ElementCount);
+LLVMTypeRef LLVMUnionType(LLVMTypeRef *ElementTypes, unsigned ElementCount);
+unsigned LLVMCountUnionElementTypes(LLVMTypeRef UnionTy);
+void LLVMGetUnionElementTypes(LLVMTypeRef UnionTy, LLVMTypeRef *Dest);
+
/* Operations on array, pointer, and vector types (sequence types) */
LLVMTypeRef LLVMArrayType(LLVMTypeRef ElementType, unsigned ElementCount);
LLVMTypeRef LLVMPointerType(LLVMTypeRef ElementType, unsigned AddressSpace);
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index 9bb50d4b3b..a980df8110 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -94,7 +94,8 @@ namespace bitc {
TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa)
TYPE_CODE_PPC_FP128= 15, // PPC LONG DOUBLE (2 doubles)
- TYPE_CODE_METADATA = 16 // METADATA
+ TYPE_CODE_METADATA = 16, // METADATA
+ TYPE_CODE_UNION = 17 // UNION: [eltty x N]
};
// The type symbol table only has one code (TST_ENTRY_CODE).
diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h
index ff1be051bc..bd14303d67 100644
--- a/include/llvm/Constants.h
+++ b/include/llvm/Constants.h
@@ -33,6 +33,7 @@ namespace llvm {
class ArrayType;
class IntegerType;
class StructType;
+class UnionType;
class PointerType;
class VectorType;
@@ -453,6 +454,50 @@ struct OperandTraits<ConstantStruct> : public VariadicOperandTraits<> {
DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantStruct, Constant)
//===----------------------------------------------------------------------===//
+// ConstantUnion - Constant Union Declarations
+//
+class ConstantUnion : public Constant {
+ friend struct ConstantCreator<ConstantUnion, UnionType, Constant*>;
+ ConstantUnion(const ConstantUnion &); // DO NOT IMPLEMENT
+protected:
+ ConstantUnion(const UnionType *T, Constant* Val);
+public:
+ // ConstantUnion accessors
+ static Constant *get(const UnionType *T, Constant* V);
+
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
+
+ /// getType() specialization - Reduce amount of casting...
+ ///
+ inline const UnionType *getType() const {
+ return reinterpret_cast<const UnionType*>(Value::getType());
+ }
+
+ /// isNullValue - Return true if this is the value that would be returned by
+ /// getNullValue. This always returns false because zero structs are always
+ /// created as ConstantAggregateZero objects.
+ virtual bool isNullValue() const {
+ return false;
+ }
+
+ virtual void destroyConstant();
+ virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const ConstantUnion *) { return true; }
+ static bool classof(const Value *V) {
+ return V->getValueID() == ConstantUnionVal;
+ }
+};
+
+template <>
+struct OperandTraits<ConstantUnion> : public FixedNumOperandTraits<1> {
+};
+
+DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantUnion, Constant)
+
+//===----------------------------------------------------------------------===//
/// ConstantVector - Constant Vector Declarations
///
class ConstantVector : public Constant {
diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h
index 881fbc81e5..912bb6d882 100644
--- a/include/llvm/DerivedTypes.h
+++ b/include/llvm/DerivedTypes.h
@@ -27,6 +27,7 @@ template<class ValType, class TypeClass> class TypeMap;
class FunctionValType;
class ArrayValType;
class StructValType;
+class UnionValType;
class PointerValType;
class VectorValType;
class IntegerValType;
@@ -229,7 +230,8 @@ public:
return T->getTypeID() == ArrayTyID ||
T->getTypeID() == StructTyID ||
T->getTypeID() == PointerTyID ||
- T->getTypeID() == VectorTyID;
+ T->getTypeID() == VectorTyID ||
+ T->getTypeID() == UnionTyID;
}
};
@@ -301,6 +303,63 @@ public:
};
+/// UnionType - Class to represent union types. A union type is similar to
+/// a structure, except that all member fields begin at offset 0.
+///
+class UnionType : public CompositeType {
+ friend class TypeMap<UnionValType, UnionType>;
+ UnionType(const UnionType &); // Do not implement
+ const UnionType &operator=(const UnionType &); // Do not implement
+ UnionType(LLVMContext &C, const Type* const* Types, unsigned NumTypes);
+public:
+ /// UnionType::get - This static method is the primary way to create a
+ /// UnionType.
+ static UnionType *get(const Type* const* Types, unsigned NumTypes);
+
+ /// UnionType::get - This static method is a convenience method for
+ /// creating union types by specifying the elements as arguments.
+ static UnionType *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);
+
+ /// Given an element type, return the member index of that type, or -1
+ /// if there is no such member type.
+ int getElementTypeIndex(const Type *ElemTy) const;
+
+ // Iterator access to the elements
+ typedef Type::subtype_iterator element_iterator;
+ element_iterator element_begin() const { return ContainedTys; }
+ element_iterator element_end() const { return &ContainedTys[NumContainedTys];}
+
+ // Random access to the elements
+ unsigned getNumElements() const { return NumContainedTys; }
+ const Type *getElementType(unsigned N) const {
+ assert(N < NumContainedTys && "Element number out of range!");
+ return ContainedTys[N];
+ }
+
+ /// getTypeAtIndex - Given an index value into the type, return the type of
+ /// the element. For a union type, this must be a constant value...
+ ///
+ virtual const Type *getTypeAtIndex(const Value *V) const;
+ virtual const Type *getTypeAtIndex(unsigned Idx) const;
+ virtual bool indexValid(const Value *V) const;
+ virtual bool indexValid(unsigned Idx) const;
+
+ // Implement the AbstractTypeUser interface.
+ virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
+ virtual void typeBecameConcrete(const DerivedType *AbsTy);
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const UnionType *) { return true; }
+ static inline bool classof(const Type *T) {
+ return T->getTypeID() == UnionTyID;
+ }
+};
+
+
/// SequentialType - This is the superclass of the array, pointer and vector
/// type classes. All of these represent "arrays" in memory. The array type
/// represents a specifically sized array, pointer types are unsized/unknown
diff --git a/include/llvm/Type.h b/include/llvm/Type.h
index bc319c6537..52b2c845d8 100644
--- a/include/llvm/Type.h
+++ b/include/llvm/Type.h
@@ -82,10 +82,11 @@ public:
IntegerTyID, ///< 8: Arbitrary bit width integers
FunctionTyID, ///< 9: Functions
StructTyID, ///< 10: Structures
- ArrayTyID, ///< 11: Arrays
- PointerTyID, ///< 12: Pointers
- OpaqueTyID, ///< 13: Opaque: type with unknown structure
- VectorTyID, ///< 14: SIMD 'packed' format, or other vector type
+ UnionTyID, ///< 11: Unions
+ ArrayTyID, ///< 12: Arrays
+ PointerTyID, ///< 13: Pointers
+ OpaqueTyID, ///< 14: Opaque: type with unknown structure
+ VectorTyID, ///< 15: SIMD 'packed' format, or other vector type
NumTypeIDs, // Must remain as last defined ID
LastPrimitiveTyID = LabelTyID,
@@ -297,7 +298,7 @@ public:
/// does not include vector types.
///
inline bool isAggregateType() const {
- return ID == StructTyID || ID == ArrayTyID;
+ return ID == StructTyID || ID == ArrayTyID || ID == UnionTyID;
}
/// isSized - Return true if it makes sense to take the size of this type. To
@@ -310,7 +311,8 @@ public:
return true;
// If it is not something that can have a size (e.g. a function or label),
// it doesn't have a size.
- if (ID != StructTyID && ID != ArrayTyID && ID != VectorTyID)
+ if (ID != StructTyID && ID != ArrayTyID && ID != VectorTyID &&
+ ID != UnionTyID)
return false;
// If it is something that can have a size and it's concrete, it definitely
// has a size, otherwise we have to try harder to decide.
diff --git a/include/llvm/Value.h b/include/llvm/Value.h
index 9045906e7b..d06cbc05c6 100644
--- a/include/llvm/Value.h
+++ b/include/llvm/Value.h
@@ -215,6 +215,7 @@ public:
ConstantFPVal, // This is an instance of ConstantFP
ConstantArrayVal, // This is an instance of ConstantArray
ConstantStructVal, // This is an instance of ConstantStruct
+ ConstantUnionVal, // This is an instance of ConstantUnion
ConstantVectorVal, // This is an instance of ConstantVector
ConstantPointerNullVal, // This is an instance of ConstantPointerNull
MDNodeVal, // This is an instance of MDNode
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 8ad658d858..46f3cbcfa3 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/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/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 4dab11826b..5cff310c7e 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/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/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index ed7a1d7117..9abe404273 100644
--- a/lib/AsmParser/LLParser.h
+++ b/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/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index 7f1807c7d0..3ac9169006 100644
--- a/lib/AsmParser/LLToken.h
+++ b/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/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 4dfc6cef5a..a0402caa90 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/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;
+