forked from OSchip/llvm-project
Packed types, brought to you by Brad Jones
llvm-svn: 15938
This commit is contained in:
parent
2b4b4a577a
commit
0220904e7a
|
@ -888,6 +888,27 @@ missing otherwise.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<h3>Packed Types</h3>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th><b>Type</b></th>
|
||||||
|
<th class="td_left"><b>Description</b></th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="#uint24_vbr">uint24_vbr</a></td>
|
||||||
|
<td class="td_left">Type ID for Packed Types (18)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="#uint24_vbr">uint24_vbr</a></td>
|
||||||
|
<td class="td_left">Slot number of packed vector's element type.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="#uint32_vbr">uint32_vbr</a></td>
|
||||||
|
<td class="td_left">The number of elements in the packed vector.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<!-- _______________________________________________________________________ -->
|
<!-- _______________________________________________________________________ -->
|
||||||
<div class="doc_subsection"><a name="globalinfo">Module Global Info</a>
|
<div class="doc_subsection"><a name="globalinfo">Module Global Info</a>
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace llvm {
|
||||||
class ArrayType;
|
class ArrayType;
|
||||||
class StructType;
|
class StructType;
|
||||||
class PointerType;
|
class PointerType;
|
||||||
|
class PackedType;
|
||||||
class ConstantArray;
|
class ConstantArray;
|
||||||
class Module;
|
class Module;
|
||||||
|
|
||||||
|
@ -250,6 +251,14 @@ public:
|
||||||
Constant* Val ///< The constant value
|
Constant* Val ///< The constant value
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
/// @brief Handle a constant packed
|
||||||
|
virtual void handleConstantPacked(
|
||||||
|
const PackedType* PT, ///< Type of the array
|
||||||
|
std::vector<Constant*>& ElementSlots,///< Slot nums for packed values
|
||||||
|
unsigned TypeSlot, ///< Slot # of type
|
||||||
|
Constant* Val ///< The constant value
|
||||||
|
) {}
|
||||||
|
|
||||||
/// @brief Handle a constant pointer
|
/// @brief Handle a constant pointer
|
||||||
virtual void handleConstantPointer(
|
virtual void handleConstantPointer(
|
||||||
const PointerType* PT, ///< Type of the pointer
|
const PointerType* PT, ///< Type of the pointer
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace llvm {
|
||||||
class ArrayType;
|
class ArrayType;
|
||||||
class StructType;
|
class StructType;
|
||||||
class PointerType;
|
class PointerType;
|
||||||
|
class PackedType;
|
||||||
|
|
||||||
template<class ConstantClass, class TypeClass, class ValType>
|
template<class ConstantClass, class TypeClass, class ValType>
|
||||||
struct ConstantCreator;
|
struct ConstantCreator;
|
||||||
|
@ -425,6 +426,44 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//===---------------------------------------------------------------------------
|
||||||
|
/// ConstantPacked - Constant Packed Declarations
|
||||||
|
///
|
||||||
|
class ConstantPacked : public Constant {
|
||||||
|
friend struct ConstantCreator<ConstantPacked, PackedType,
|
||||||
|
std::vector<Constant*> >;
|
||||||
|
ConstantPacked(const ConstantPacked &); // DO NOT IMPLEMENT
|
||||||
|
protected:
|
||||||
|
ConstantPacked(const PackedType *T, const std::vector<Constant*> &Val);
|
||||||
|
public:
|
||||||
|
/// get() - Static factory methods - Return objects of the specified value
|
||||||
|
static Constant *get(const PackedType *T, const std::vector<Constant*> &);
|
||||||
|
static Constant *get(const std::vector<Constant*> &V);
|
||||||
|
|
||||||
|
/// getType - Specialize the getType() method to always return an PackedType,
|
||||||
|
/// which reduces the amount of casting needed in parts of the compiler.
|
||||||
|
///
|
||||||
|
inline const PackedType *getType() const {
|
||||||
|
return reinterpret_cast<const PackedType*>(Value::getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// isNullValue - Return true if this is the value that would be returned by
|
||||||
|
/// getNullValue. This always returns false because zero arrays are always
|
||||||
|
/// created as ConstantAggregateZero objects.
|
||||||
|
virtual bool isNullValue() const { return false; }
|
||||||
|
|
||||||
|
virtual void destroyConstant();
|
||||||
|
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To,
|
||||||
|
bool DisableChecking = false);
|
||||||
|
|
||||||
|
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||||
|
static inline bool classof(const ConstantPacked *) { return true; }
|
||||||
|
static bool classof(const Value *V) {
|
||||||
|
return V->getValueType() == SimpleConstantVal &&
|
||||||
|
V->getType()->getTypeID() == Type::PackedTyID;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//===---------------------------------------------------------------------------
|
//===---------------------------------------------------------------------------
|
||||||
/// ConstantPointerNull - a constant pointer value that points to null
|
/// ConstantPointerNull - a constant pointer value that points to null
|
||||||
///
|
///
|
||||||
|
|
|
@ -28,6 +28,7 @@ class FunctionValType;
|
||||||
class ArrayValType;
|
class ArrayValType;
|
||||||
class StructValType;
|
class StructValType;
|
||||||
class PointerValType;
|
class PointerValType;
|
||||||
|
class PackedValType;
|
||||||
|
|
||||||
class DerivedType : public Type, public AbstractTypeUser {
|
class DerivedType : public Type, public AbstractTypeUser {
|
||||||
// AbstractTypeUsers - Implement a list of the users that need to be notified
|
// AbstractTypeUsers - Implement a list of the users that need to be notified
|
||||||
|
@ -152,8 +153,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// CompositeType - Common super class of ArrayType, StructType, and PointerType
|
/// CompositeType - Common super class of ArrayType, StructType, PointerType
|
||||||
///
|
/// and PackedType
|
||||||
class CompositeType : public DerivedType {
|
class CompositeType : public DerivedType {
|
||||||
protected:
|
protected:
|
||||||
inline CompositeType(TypeID id) : DerivedType(id) { }
|
inline CompositeType(TypeID id) : DerivedType(id) { }
|
||||||
|
@ -170,7 +171,8 @@ public:
|
||||||
static inline bool classof(const Type *T) {
|
static inline bool classof(const Type *T) {
|
||||||
return T->getTypeID() == ArrayTyID ||
|
return T->getTypeID() == ArrayTyID ||
|
||||||
T->getTypeID() == StructTyID ||
|
T->getTypeID() == StructTyID ||
|
||||||
T->getTypeID() == PointerTyID;
|
T->getTypeID() == PointerTyID ||
|
||||||
|
T->getTypeID() == PackedTyID;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -227,11 +229,13 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// SequentialType - This is the superclass of the array and pointer type
|
/// SequentialType - This is the superclass of the array, pointer and packed
|
||||||
/// classes. Both of these represent "arrays" in memory. The array type
|
/// type classes. All of these represent "arrays" in memory. The array type
|
||||||
/// represents a specifically sized array, pointer types are unsized/unknown
|
/// represents a specifically sized array, pointer types are unsized/unknown
|
||||||
/// size arrays. SequentialType holds the common features of both, which stem
|
/// size arrays, packed types represent specifically sized arrays that
|
||||||
/// from the fact that both lay their components out in memory identically.
|
/// allow for use of SIMD instructions. SequentialType holds the common
|
||||||
|
/// features of all, which stem from the fact that all three lay their
|
||||||
|
/// components out in memory identically.
|
||||||
///
|
///
|
||||||
class SequentialType : public CompositeType {
|
class SequentialType : public CompositeType {
|
||||||
SequentialType(const SequentialType &); // Do not implement!
|
SequentialType(const SequentialType &); // Do not implement!
|
||||||
|
@ -258,7 +262,8 @@ public:
|
||||||
static inline bool classof(const SequentialType *T) { return true; }
|
static inline bool classof(const SequentialType *T) { return true; }
|
||||||
static inline bool classof(const Type *T) {
|
static inline bool classof(const Type *T) {
|
||||||
return T->getTypeID() == ArrayTyID ||
|
return T->getTypeID() == ArrayTyID ||
|
||||||
T->getTypeID() == PointerTyID;
|
T->getTypeID() == PointerTyID ||
|
||||||
|
T->getTypeID() == PackedTyID;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -299,6 +304,42 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// PackedType - Class to represent packed types
|
||||||
|
///
|
||||||
|
class PackedType : public SequentialType {
|
||||||
|
friend class TypeMap<PackedValType, PackedType>;
|
||||||
|
unsigned NumElements;
|
||||||
|
|
||||||
|
PackedType(const PackedType &); // Do not implement
|
||||||
|
const PackedType &operator=(const PackedType &); // Do not implement
|
||||||
|
protected:
|
||||||
|
/// This should really be private, but it squelches a bogus warning
|
||||||
|
/// from GCC to make them protected: warning: `class PackedType' only
|
||||||
|
/// defines private constructors and has no friends
|
||||||
|
///
|
||||||
|
/// Private ctor - Only can be created by a static member...
|
||||||
|
///
|
||||||
|
PackedType(const Type *ElType, unsigned NumEl);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// PackedType::get - This static method is the primary way to construct an
|
||||||
|
/// PackedType
|
||||||
|
///
|
||||||
|
static PackedType *get(const Type *ElementType, unsigned NumElements);
|
||||||
|
|
||||||
|
inline unsigned getNumElements() const { return NumElements; }
|
||||||
|
|
||||||
|
// 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 PackedType *T) { return true; }
|
||||||
|
static inline bool classof(const Type *T) {
|
||||||
|
return T->getTypeID() == PackedTyID;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// PointerType - Class to represent pointers
|
/// PointerType - Class to represent pointers
|
||||||
///
|
///
|
||||||
|
|
|
@ -58,6 +58,7 @@ HANDLE_DERV_TYPE(Array , ArrayType)
|
||||||
HANDLE_DERV_TYPE(Pointer , PointerType)
|
HANDLE_DERV_TYPE(Pointer , PointerType)
|
||||||
HANDLE_DERV_TYPE(Struct , StructType)
|
HANDLE_DERV_TYPE(Struct , StructType)
|
||||||
HANDLE_DERV_TYPE(Opaque , OpaqueType)
|
HANDLE_DERV_TYPE(Opaque , OpaqueType)
|
||||||
|
HANDLE_DERV_TYPE(Packed , PackedType)
|
||||||
|
|
||||||
// Kill the macros on exit...
|
// Kill the macros on exit...
|
||||||
#undef HANDLE_PRIM_TYPE
|
#undef HANDLE_PRIM_TYPE
|
||||||
|
|
|
@ -48,6 +48,7 @@ class FunctionType;
|
||||||
class OpaqueType;
|
class OpaqueType;
|
||||||
class PointerType;
|
class PointerType;
|
||||||
class StructType;
|
class StructType;
|
||||||
|
class PackedType;
|
||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
///===-------------------------------------------------------------------===//
|
///===-------------------------------------------------------------------===//
|
||||||
|
@ -71,7 +72,7 @@ struct Type {
|
||||||
FunctionTyID , StructTyID, // Functions... Structs...
|
FunctionTyID , StructTyID, // Functions... Structs...
|
||||||
ArrayTyID , PointerTyID, // Array... pointer...
|
ArrayTyID , PointerTyID, // Array... pointer...
|
||||||
OpaqueTyID, // Opaque type instances...
|
OpaqueTyID, // Opaque type instances...
|
||||||
//PackedTyID , // SIMD 'packed' format... TODO
|
PackedTyID, // SIMD 'packed' format...
|
||||||
//...
|
//...
|
||||||
|
|
||||||
NumTypeIDs, // Must remain as last defined ID
|
NumTypeIDs, // Must remain as last defined ID
|
||||||
|
@ -189,7 +190,8 @@ public:
|
||||||
|
|
||||||
/// isFirstClassType - Return true if the value is holdable in a register.
|
/// isFirstClassType - Return true if the value is holdable in a register.
|
||||||
inline bool isFirstClassType() const {
|
inline bool isFirstClassType() const {
|
||||||
return (ID != VoidTyID && ID <= LastPrimitiveTyID) || ID == PointerTyID;
|
return (ID != VoidTyID && ID <= LastPrimitiveTyID) ||
|
||||||
|
ID == PointerTyID || ID == PackedTyID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isSized - Return true if it makes sense to take the size of this type. To
|
/// isSized - Return true if it makes sense to take the size of this type. To
|
||||||
|
@ -197,7 +199,7 @@ public:
|
||||||
/// TargetData subsystem to do this.
|
/// TargetData subsystem to do this.
|
||||||
///
|
///
|
||||||
bool isSized() const {
|
bool isSized() const {
|
||||||
return (ID >= BoolTyID && ID <= DoubleTyID) || ID == PointerTyID ||
|
return (ID >= BoolTyID && ID <= DoubleTyID) || ID == PointerTyID ||
|
||||||
isSizedDerivedType();
|
isSizedDerivedType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1033,6 +1033,17 @@ UpRTypes : '\\' EUINT64VAL { // Type UpReference
|
||||||
$$ = new PATypeHolder(HandleUpRefs(ArrayType::get(*$4, (unsigned)$2)));
|
$$ = new PATypeHolder(HandleUpRefs(ArrayType::get(*$4, (unsigned)$2)));
|
||||||
delete $4;
|
delete $4;
|
||||||
}
|
}
|
||||||
|
| '<' EUINT64VAL 'x' UpRTypes '>' { // Packed array type?
|
||||||
|
const llvm::Type* ElemTy = $4->get();
|
||||||
|
if ((unsigned)$2 != $2) {
|
||||||
|
ThrowException("Unsigned result not equal to signed result");
|
||||||
|
}
|
||||||
|
if(!ElemTy->isPrimitiveType()) {
|
||||||
|
ThrowException("Elemental type of a PackedType must be primitive");
|
||||||
|
}
|
||||||
|
$$ = new PATypeHolder(HandleUpRefs(PackedType::get(*$4, (unsigned)$2)));
|
||||||
|
delete $4;
|
||||||
|
}
|
||||||
| '{' TypeListI '}' { // Structure type?
|
| '{' TypeListI '}' { // Structure type?
|
||||||
std::vector<const Type*> Elements;
|
std::vector<const Type*> Elements;
|
||||||
mapto($2->begin(), $2->end(), std::back_inserter(Elements),
|
mapto($2->begin(), $2->end(), std::back_inserter(Elements),
|
||||||
|
@ -1144,6 +1155,31 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
|
||||||
$$ = ConstantArray::get(ATy, Vals);
|
$$ = ConstantArray::get(ATy, Vals);
|
||||||
delete $1;
|
delete $1;
|
||||||
}
|
}
|
||||||
|
| Types '<' ConstVector '>' { // Nonempty unsized arr
|
||||||
|
const PackedType *PTy = dyn_cast<PackedType>($1->get());
|
||||||
|
if (PTy == 0)
|
||||||
|
ThrowException("Cannot make packed constant with type: '" +
|
||||||
|
(*$1)->getDescription() + "'!");
|
||||||
|
const Type *ETy = PTy->getElementType();
|
||||||
|
int NumElements = PTy->getNumElements();
|
||||||
|
|
||||||
|
// Verify that we have the correct size...
|
||||||
|
if (NumElements != -1 && NumElements != (int)$3->size())
|
||||||
|
ThrowException("Type mismatch: constant sized packed initialized with " +
|
||||||
|
utostr($3->size()) + " arguments, but has size of " +
|
||||||
|
itostr(NumElements) + "!");
|
||||||
|
|
||||||
|
// Verify all elements are correct type!
|
||||||
|
for (unsigned i = 0; i < $3->size(); i++) {
|
||||||
|
if (ETy != (*$3)[i]->getType())
|
||||||
|
ThrowException("Element #" + utostr(i) + " is not of type '" +
|
||||||
|
ETy->getDescription() +"' as required!\nIt is of type '"+
|
||||||
|
(*$3)[i]->getType()->getDescription() + "'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$$ = ConstantPacked::get(PTy, *$3);
|
||||||
|
delete $1; delete $3;
|
||||||
|
}
|
||||||
| Types '{' ConstVector '}' {
|
| Types '{' ConstVector '}' {
|
||||||
const StructType *STy = dyn_cast<StructType>($1->get());
|
const StructType *STy = dyn_cast<StructType>($1->get());
|
||||||
if (STy == 0)
|
if (STy == 0)
|
||||||
|
@ -1651,6 +1687,30 @@ ConstValueRef : ESINT64VAL { // A reference to a direct constant
|
||||||
| NULL_TOK {
|
| NULL_TOK {
|
||||||
$$ = ValID::createNull();
|
$$ = ValID::createNull();
|
||||||
}
|
}
|
||||||
|
| '<' ConstVector '>' { // Nonempty unsized packed vector
|
||||||
|
const Type *ETy = (*$2)[0]->getType();
|
||||||
|
int NumElements = $2->size();
|
||||||
|
|
||||||
|
PackedType* pt = PackedType::get(ETy, NumElements);
|
||||||
|
PATypeHolder* PTy = new PATypeHolder(
|
||||||
|
HandleUpRefs(
|
||||||
|
PackedType::get(
|
||||||
|
ETy,
|
||||||
|
NumElements)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify all elements are correct type!
|
||||||
|
for (unsigned i = 0; i < $2->size(); i++) {
|
||||||
|
if (ETy != (*$2)[i]->getType())
|
||||||
|
ThrowException("Element #" + utostr(i) + " is not of type '" +
|
||||||
|
ETy->getDescription() +"' as required!\nIt is of type '" +
|
||||||
|
(*$2)[i]->getType()->getDescription() + "'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$$ = ValID::create(ConstantPacked::get(pt, *$2));
|
||||||
|
delete PTy; delete $2;
|
||||||
|
}
|
||||||
| ConstExpr {
|
| ConstExpr {
|
||||||
$$ = ValID::create($1);
|
$$ = ValID::create($1);
|
||||||
};
|
};
|
||||||
|
@ -1852,8 +1912,14 @@ ValueRefList : ResolvedVal { // Used for call statements, and memory insts...
|
||||||
ValueRefListE : ValueRefList | /*empty*/ { $$ = 0; };
|
ValueRefListE : ValueRefList | /*empty*/ { $$ = 0; };
|
||||||
|
|
||||||
InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||||
if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint())
|
if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint() &&
|
||||||
ThrowException("Arithmetic operator requires integer or FP operands!");
|
!isa<PackedType>((*$2).get()))
|
||||||
|
ThrowException(
|
||||||
|
"Arithmetic operator requires integer, FP, or packed operands!");
|
||||||
|
if(isa<PackedType>((*$2).get()) && $1 == Instruction::Rem) {
|
||||||
|
ThrowException(
|
||||||
|
"Rem not supported on packed types!");
|
||||||
|
}
|
||||||
$$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5));
|
$$ = BinaryOperator::create($1, getVal(*$2, $3), getVal(*$2, $5));
|
||||||
if ($$ == 0)
|
if ($$ == 0)
|
||||||
ThrowException("binary operator returned null!");
|
ThrowException("binary operator returned null!");
|
||||||
|
|
|
@ -387,6 +387,27 @@ public:
|
||||||
bca.numValues++;
|
bca.numValues++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void handleConstantPacked(
|
||||||
|
const PackedType* PT,
|
||||||
|
std::vector<Constant*>& Elements,
|
||||||
|
unsigned TypeSlot,
|
||||||
|
Constant* PackedVal)
|
||||||
|
{
|
||||||
|
dump << " PACKD: " << PT->getDescription()
|
||||||
|
<< " TypeSlot=" << TypeSlot << "\n";
|
||||||
|
for ( unsigned i = 0; i < Elements.size(); ++i ) {
|
||||||
|
dump << " #" << i;
|
||||||
|
Elements[i]->print(dump);
|
||||||
|
dump << "\n";
|
||||||
|
}
|
||||||
|
dump << " Value=";
|
||||||
|
PackedVal->print(dump);
|
||||||
|
dump << "\n";
|
||||||
|
|
||||||
|
bca.numConstants++;
|
||||||
|
bca.numValues++;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void handleConstantPointer( const PointerType* PT,
|
virtual void handleConstantPointer( const PointerType* PT,
|
||||||
unsigned Slot, GlobalValue* GV ) {
|
unsigned Slot, GlobalValue* GV ) {
|
||||||
dump << " PNTR: " << PT->getDescription()
|
dump << " PNTR: " << PT->getDescription()
|
||||||
|
|
|
@ -1170,6 +1170,12 @@ const Type *BytecodeReader::ParseType() {
|
||||||
Result = ArrayType::get(ElementType, NumElements);
|
Result = ArrayType::get(ElementType, NumElements);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Type::PackedTyID: {
|
||||||
|
const Type *ElementType = readSanitizedType();
|
||||||
|
unsigned NumElements = read_vbr_uint();
|
||||||
|
Result = PackedType::get(ElementType, NumElements);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Type::StructTyID: {
|
case Type::StructTyID: {
|
||||||
std::vector<const Type*> Elements;
|
std::vector<const Type*> Elements;
|
||||||
unsigned Typ = 0;
|
unsigned Typ = 0;
|
||||||
|
@ -1396,6 +1402,20 @@ Constant *BytecodeReader::ParseConstantValue(unsigned TypeID) {
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Type::PackedTyID: {
|
||||||
|
const PackedType *PT = cast<PackedType>(Ty);
|
||||||
|
unsigned NumElements = PT->getNumElements();
|
||||||
|
unsigned TypeSlot = getTypeSlot(PT->getElementType());
|
||||||
|
std::vector<Constant*> Elements;
|
||||||
|
Elements.reserve(NumElements);
|
||||||
|
while (NumElements--) // Read all of the elements of the constant.
|
||||||
|
Elements.push_back(getConstantValue(TypeSlot,
|
||||||
|
read_vbr_uint()));
|
||||||
|
Constant* Result = ConstantPacked::get(PT, Elements);
|
||||||
|
if (Handler) Handler->handleConstantPacked(PT, Elements, TypeSlot, Result);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
case Type::PointerTyID: { // ConstantPointerRef value...
|
case Type::PointerTyID: { // ConstantPointerRef value...
|
||||||
const PointerType *PT = cast<PointerType>(Ty);
|
const PointerType *PT = cast<PointerType>(Ty);
|
||||||
unsigned Slot = read_vbr_uint();
|
unsigned Slot = read_vbr_uint();
|
||||||
|
|
|
@ -243,6 +243,16 @@ void BytecodeWriter::outputType(const Type *T) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Type::PackedTyID: {
|
||||||
|
const PackedType *PT = cast<PackedType>(T);
|
||||||
|
int Slot = Table.getSlot(PT->getElementType());
|
||||||
|
assert(Slot != -1 && "Type used but not available!!");
|
||||||
|
output_typeid((unsigned)Slot);
|
||||||
|
output_vbr(PT->getNumElements());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
case Type::StructTyID: {
|
case Type::StructTyID: {
|
||||||
const StructType *ST = cast<StructType>(T);
|
const StructType *ST = cast<StructType>(T);
|
||||||
|
|
||||||
|
@ -339,6 +349,17 @@ void BytecodeWriter::outputConstant(const Constant *CPV) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Type::PackedTyID: {
|
||||||
|
const ConstantPacked *CP = cast<ConstantPacked>(CPV);
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) {
|
||||||
|
int Slot = Table.getSlot(CP->getOperand(i));
|
||||||
|
assert(Slot != -1 && "Constant used but not available!!");
|
||||||
|
output_vbr((unsigned)Slot);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Type::StructTyID: {
|
case Type::StructTyID: {
|
||||||
const ConstantStruct *CPS = cast<ConstantStruct>(CPV);
|
const ConstantStruct *CPS = cast<ConstantStruct>(CPV);
|
||||||
|
|
||||||
|
|
|
@ -323,6 +323,13 @@ static void calcTypeName(const Type *Ty,
|
||||||
Result += "]";
|
Result += "]";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Type::PackedTyID: {
|
||||||
|
const PackedType *PTy = cast<PackedType>(Ty);
|
||||||
|
Result += "<" + utostr(PTy->getNumElements()) + " x ";
|
||||||
|
calcTypeName(PTy->getElementType(), TypeStack, TypeNames, Result);
|
||||||
|
Result += ">";
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Type::OpaqueTyID:
|
case Type::OpaqueTyID:
|
||||||
Result += "opaque";
|
Result += "opaque";
|
||||||
break;
|
break;
|
||||||
|
@ -492,6 +499,22 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV,
|
||||||
}
|
}
|
||||||
|
|
||||||
Out << " }";
|
Out << " }";
|
||||||
|
} else if (const ConstantPacked *CP = dyn_cast<ConstantPacked>(CV)) {
|
||||||
|
const Type *ETy = CP->getType()->getElementType();
|
||||||
|
assert(CP->getNumOperands() > 0 &&
|
||||||
|
"Number of operands for a PackedConst must be > 0");
|
||||||
|
Out << '<';
|
||||||
|
Out << ' ';
|
||||||
|
printTypeInt(Out, ETy, TypeTable);
|
||||||
|
WriteAsOperandInternal(Out, CP->getOperand(0),
|
||||||
|
PrintName, TypeTable, Machine);
|
||||||
|
for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) {
|
||||||
|
Out << ", ";
|
||||||
|
printTypeInt(Out, ETy, TypeTable);
|
||||||
|
WriteAsOperandInternal(Out, CP->getOperand(i), PrintName,
|
||||||
|
TypeTable, Machine);
|
||||||
|
}
|
||||||
|
Out << " >";
|
||||||
} else if (isa<ConstantPointerNull>(CV)) {
|
} else if (isa<ConstantPointerNull>(CV)) {
|
||||||
Out << "null";
|
Out << "null";
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@ Constant *Constant::getNullValue(const Type *Ty) {
|
||||||
|
|
||||||
case Type::StructTyID:
|
case Type::StructTyID:
|
||||||
case Type::ArrayTyID:
|
case Type::ArrayTyID:
|
||||||
|
case Type::PackedTyID:
|
||||||
return ConstantAggregateZero::get(Ty);
|
return ConstantAggregateZero::get(Ty);
|
||||||
default:
|
default:
|
||||||
// Function, Label, or Opaque type?
|
// Function, Label, or Opaque type?
|
||||||
|
@ -268,6 +269,17 @@ ConstantStruct::ConstantStruct(const StructType *T,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConstantPacked::ConstantPacked(const PackedType *T,
|
||||||
|
const std::vector<Constant*> &V) : Constant(T) {
|
||||||
|
Operands.reserve(V.size());
|
||||||
|
for (unsigned i = 0, e = V.size(); i != e; ++i) {
|
||||||
|
assert(V[i]->getType() == T->getElementType() ||
|
||||||
|
(T->isAbstract() &&
|
||||||
|
V[i]->getType()->getTypeID() == T->getElementType()->getTypeID()));
|
||||||
|
Operands.push_back(Use(V[i], this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ConstantExpr::ConstantExpr(unsigned Opcode, Constant *C, const Type *Ty)
|
ConstantExpr::ConstantExpr(unsigned Opcode, Constant *C, const Type *Ty)
|
||||||
: Constant(Ty, ConstantExprVal), iType(Opcode) {
|
: Constant(Ty, ConstantExprVal), iType(Opcode) {
|
||||||
Operands.reserve(1);
|
Operands.reserve(1);
|
||||||
|
@ -484,6 +496,31 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
|
||||||
destroyConstant();
|
destroyConstant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConstantPacked::replaceUsesOfWithOnConstant(Value *From, Value *To,
|
||||||
|
bool DisableChecking) {
|
||||||
|
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
|
||||||
|
|
||||||
|
std::vector<Constant*> Values;
|
||||||
|
Values.reserve(getNumOperands()); // Build replacement array...
|
||||||
|
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
|
||||||
|
Constant *Val = getOperand(i);
|
||||||
|
if (Val == From) Val = cast<Constant>(To);
|
||||||
|
Values.push_back(Val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Constant *Replacement = ConstantPacked::get(getType(), Values);
|
||||||
|
assert(Replacement != this && "I didn't contain From!");
|
||||||
|
|
||||||
|
// Everyone using this now uses the replacement...
|
||||||
|
if (DisableChecking)
|
||||||
|
uncheckedReplaceAllUsesWith(Replacement);
|
||||||
|
else
|
||||||
|
replaceAllUsesWith(Replacement);
|
||||||
|
|
||||||
|
// Delete the old constant!
|
||||||
|
destroyConstant();
|
||||||
|
}
|
||||||
|
|
||||||
void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
|
void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
|
||||||
bool DisableChecking) {
|
bool DisableChecking) {
|
||||||
assert(isa<Constant>(ToV) && "Cannot make Constant refer to non-constant!");
|
assert(isa<Constant>(ToV) && "Cannot make Constant refer to non-constant!");
|
||||||
|
@ -959,6 +996,61 @@ void ConstantStruct::destroyConstant() {
|
||||||
destroyConstantImpl();
|
destroyConstantImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- ConstantPacked::get() implementation...
|
||||||
|
//
|
||||||
|
namespace llvm {
|
||||||
|
template<>
|
||||||
|
struct ConvertConstantType<ConstantPacked, PackedType> {
|
||||||
|
static void convert(ConstantPacked *OldC, const PackedType *NewTy) {
|
||||||
|
// Make everyone now use a constant of the new type...
|
||||||
|
std::vector<Constant*> C;
|
||||||
|
for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i)
|
||||||
|
C.push_back(cast<Constant>(OldC->getOperand(i)));
|
||||||
|
Constant *New = ConstantPacked::get(NewTy, C);
|
||||||
|
assert(New != OldC && "Didn't replace constant??");
|
||||||
|
OldC->uncheckedReplaceAllUsesWith(New);
|
||||||
|
OldC->destroyConstant(); // This constant is now dead, destroy it.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<Constant*> getValType(ConstantPacked *CP) {
|
||||||
|
std::vector<Constant*> Elements;
|
||||||
|
Elements.reserve(CP->getNumOperands());
|
||||||
|
for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
|
||||||
|
Elements.push_back(CP->getOperand(i));
|
||||||
|
return Elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ValueMap<std::vector<Constant*>, PackedType,
|
||||||
|
ConstantPacked> PackedConstants;
|
||||||
|
|
||||||
|
Constant *ConstantPacked::get(const PackedType *Ty,
|
||||||
|
const std::vector<Constant*> &V) {
|
||||||
|
// If this is an all-zero packed, return a ConstantAggregateZero object
|
||||||
|
if (!V.empty()) {
|
||||||
|
Constant *C = V[0];
|
||||||
|
if (!C->isNullValue())
|
||||||
|
return PackedConstants.getOrCreate(Ty, V);
|
||||||
|
for (unsigned i = 1, e = V.size(); i != e; ++i)
|
||||||
|
if (V[i] != C)
|
||||||
|
return PackedConstants.getOrCreate(Ty, V);
|
||||||
|
}
|
||||||
|
return ConstantAggregateZero::get(Ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
Constant *ConstantPacked::get(const std::vector<Constant*> &V) {
|
||||||
|
assert(!V.empty() && "Cannot infer type if V is empty");
|
||||||
|
return get(PackedType::get(V.front()->getType(),V.size()), V);
|
||||||
|
}
|
||||||
|
|
||||||
|
// destroyConstant - Remove the constant from the constant table...
|
||||||
|
//
|
||||||
|
void ConstantPacked::destroyConstant() {
|
||||||
|
PackedConstants.remove(this);
|
||||||
|
destroyConstantImpl();
|
||||||
|
}
|
||||||
|
|
||||||
//---- ConstantPointerNull::get() implementation...
|
//---- ConstantPointerNull::get() implementation...
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
|
@ -564,8 +564,10 @@ void BinaryOperator::init(BinaryOps iType, Value *S1, Value *S2)
|
||||||
case Rem:
|
case Rem:
|
||||||
assert(getType() == S1->getType() &&
|
assert(getType() == S1->getType() &&
|
||||||
"Arithmetic operation should return same type as operands!");
|
"Arithmetic operation should return same type as operands!");
|
||||||
assert((getType()->isInteger() || getType()->isFloatingPoint()) &&
|
assert((getType()->isInteger() ||
|
||||||
"Tried to create an arithmetic operation on a non-arithmetic type!");
|
getType()->isFloatingPoint() ||
|
||||||
|
isa<PackedType>(getType()) ) &&
|
||||||
|
"Tried to create an arithmetic operation on a non-arithmetic type!");
|
||||||
break;
|
break;
|
||||||
case And: case Or:
|
case And: case Or:
|
||||||
case Xor:
|
case Xor:
|
||||||
|
|
|
@ -261,6 +261,14 @@ static std::string getTypeDescription(const Type *Ty,
|
||||||
Result += getTypeDescription(ATy->getElementType(), TypeStack) + "]";
|
Result += getTypeDescription(ATy->getElementType(), TypeStack) + "]";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Type::PackedTyID: {
|
||||||
|
const PackedType *PTy = cast<PackedType>(Ty);
|
||||||
|
unsigned NumElements = PTy->getNumElements();
|
||||||
|
Result = "<";
|
||||||
|
Result += utostr(NumElements) + " x ";
|
||||||
|
Result += getTypeDescription(PTy->getElementType(), TypeStack) + ">";
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Result = "<error>";
|
Result = "<error>";
|
||||||
assert(0 && "Unhandled type in getTypeDescription!");
|
assert(0 && "Unhandled type in getTypeDescription!");
|
||||||
|
@ -397,6 +405,16 @@ ArrayType::ArrayType(const Type *ElType, unsigned NumEl)
|
||||||
setAbstract(ElType->isAbstract());
|
setAbstract(ElType->isAbstract());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PackedType::PackedType(const Type *ElType, unsigned NumEl)
|
||||||
|
: SequentialType(PackedTyID, ElType) {
|
||||||
|
NumElements = NumEl;
|
||||||
|
|
||||||
|
assert(NumEl > 0 && "NumEl of a PackedType must be greater than 0");
|
||||||
|
assert((ElType->isIntegral() || ElType->isFloatingPoint()) &&
|
||||||
|
"Elements of a PackedType must be a primitive type");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PointerType::PointerType(const Type *E) : SequentialType(PointerTyID, E) {
|
PointerType::PointerType(const Type *E) : SequentialType(PointerTyID, E) {
|
||||||
// Calculate whether or not this type is abstract
|
// Calculate whether or not this type is abstract
|
||||||
setAbstract(E->isAbstract());
|
setAbstract(E->isAbstract());
|
||||||
|
@ -503,6 +521,10 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2,
|
||||||
const ArrayType *ATy2 = cast<ArrayType>(Ty2);
|
const ArrayType *ATy2 = cast<ArrayType>(Ty2);
|
||||||
return ATy->getNumElements() == ATy2->getNumElements() &&
|
return ATy->getNumElements() == ATy2->getNumElements() &&
|
||||||
TypesEqual(ATy->getElementType(), ATy2->getElementType(), EqTypes);
|
TypesEqual(ATy->getElementType(), ATy2->getElementType(), EqTypes);
|
||||||
|
} else if (const PackedType *PTy = dyn_cast<PackedType>(Ty)) {
|
||||||
|
const PackedType *PTy2 = cast<PackedType>(Ty2);
|
||||||
|
return PTy->getNumElements() == PTy2->getNumElements() &&
|
||||||
|
TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes);
|
||||||
} else if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
|
} else if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
|
||||||
const FunctionType *FTy2 = cast<FunctionType>(Ty2);
|
const FunctionType *FTy2 = cast<FunctionType>(Ty2);
|
||||||
if (FTy->isVarArg() != FTy2->isVarArg() ||
|
if (FTy->isVarArg() != FTy2->isVarArg() ||
|
||||||
|
@ -846,6 +868,56 @@ ArrayType *ArrayType::get(const Type *ElementType, unsigned NumElements) {
|
||||||
return AT;
|
return AT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Packed Type Factory...
|
||||||
|
//
|
||||||
|
namespace llvm {
|
||||||
|
class PackedValType {
|
||||||
|
const Type *ValTy;
|
||||||
|
unsigned Size;
|
||||||
|
public:
|
||||||
|
PackedValType(const Type *val, int sz) : ValTy(val), Size(sz) {}
|
||||||
|
|
||||||
|
static PackedValType get(const PackedType *PT) {
|
||||||
|
return PackedValType(PT->getElementType(), PT->getNumElements());
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned hashTypeStructure(const PackedType *PT) {
|
||||||
|
return PT->getNumElements();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subclass should override this... to update self as usual
|
||||||
|
void doRefinement(const DerivedType *OldType, const Type *NewType) {
|
||||||
|
assert(ValTy == OldType);
|
||||||
|
ValTy = NewType;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator<(const PackedValType &MTV) const {
|
||||||
|
if (Size < MTV.Size) return true;
|
||||||
|
return Size == MTV.Size && ValTy < MTV.ValTy;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static TypeMap<PackedValType, PackedType> PackedTypes;
|
||||||
|
|
||||||
|
|
||||||
|
PackedType *PackedType::get(const Type *ElementType, unsigned NumElements) {
|
||||||
|
assert(ElementType && "Can't get packed of null types!");
|
||||||
|
|
||||||
|
PackedValType PVT(ElementType, NumElements);
|
||||||
|
PackedType *PT = PackedTypes.get(PVT);
|
||||||
|
if (PT) return PT; // Found a match, return it!
|
||||||
|
|
||||||
|
// Value not found. Derive a new type!
|
||||||
|
PackedTypes.add(PVT, PT = new PackedType(ElementType, NumElements));
|
||||||
|
|
||||||
|
#ifdef DEBUG_MERGE_TYPES
|
||||||
|
std::cerr << "Derived new type: " << *PT << "\n";
|
||||||
|
#endif
|
||||||
|
return PT;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Struct Type Factory...
|
// Struct Type Factory...
|
||||||
//
|
//
|
||||||
|
@ -1107,6 +1179,18 @@ void ArrayType::typeBecameConcrete(const DerivedType *AbsTy) {
|
||||||
refineAbstractType(AbsTy, AbsTy);
|
refineAbstractType(AbsTy, 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 PackedType::refineAbstractType(const DerivedType *OldType,
|
||||||
|
const Type *NewType) {
|
||||||
|
PackedTypes.finishRefinement(this, OldType, NewType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackedType::typeBecameConcrete(const DerivedType *AbsTy) {
|
||||||
|
refineAbstractType(AbsTy, AbsTy);
|
||||||
|
}
|
||||||
|
|
||||||
// refineAbstractType - Called when a contained type is found to be more
|
// refineAbstractType - Called when a contained type is found to be more
|
||||||
// concrete - this could potentially change us from an abstract type to a
|
// concrete - this could potentially change us from an abstract type to a
|
||||||
|
|
|
@ -488,8 +488,9 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) {
|
||||||
Assert1(B.getType() == B.getOperand(0)->getType(),
|
Assert1(B.getType() == B.getOperand(0)->getType(),
|
||||||
"Arithmetic operators must have same type for operands and result!",
|
"Arithmetic operators must have same type for operands and result!",
|
||||||
&B);
|
&B);
|
||||||
Assert1(B.getType()->isInteger() || B.getType()->isFloatingPoint(),
|
Assert1(B.getType()->isInteger() || B.getType()->isFloatingPoint() ||
|
||||||
"Arithmetic operators must have integer or fp type!", &B);
|
isa<PackedType>(B.getType()),
|
||||||
|
"Arithmetic operators must have integer, fp, or packed type!", &B);
|
||||||
}
|
}
|
||||||
|
|
||||||
visitInstruction(B);
|
visitInstruction(B);
|
||||||
|
|
Loading…
Reference in New Issue