IR, bitcode reader, bitcode writer, and asmparser changes to

insertvalue and extractvalue to use constant indices instead of
Value* indices. And begin updating LangRef.html.

There's definately more to come here, but I'm checking this 
basic support in now to make it available to people who are
interested.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51806 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2008-05-31 00:58:22 +00:00
parent 652f7ea955
commit 81a0c0b44e
14 changed files with 1424 additions and 1377 deletions

View File

@ -2918,7 +2918,7 @@ or array element from an aggregate value.
The first operand of an '<tt>extractvalue</tt>' instruction is a 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> 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 type. The operands are constant indices to specify which value to extract
in the same manner as indices in a in a similar manner as indices in a
'<tt><a href="#i_getelementptr">getelementptr</a></tt>' instruction. '<tt><a href="#i_getelementptr">getelementptr</a></tt>' instruction.
</p> </p>
@ -2932,7 +2932,7 @@ the index operands.
<h5>Example:</h5> <h5>Example:</h5>
<pre> <pre>
%result = extractvalue {i32, float} %agg, i32 0 <i>; yields i32</i> %result = extractvalue {i32, float} %agg, 0 <i>; yields i32</i>
</pre> </pre>
</div> </div>
@ -2947,7 +2947,7 @@ the index operands.
<h5>Syntax:</h5> <h5>Syntax:</h5>
<pre> <pre>
&lt;result&gt; = insertvalue &lt;aggregate type&gt; &lt;val&gt;, &lt;ty&gt; &lt;val&gt;, i32 &lt;idx&gt; <i>; yields &lt;n x &lt;ty&gt;&gt;</i> &lt;result&gt; = insertvalue &lt;aggregate type&gt; &lt;val&gt;, &lt;ty&gt; &lt;val&gt;, &lt;idx&gt; <i>; yields &lt;n x &lt;ty&gt;&gt;</i>
</pre> </pre>
<h5>Overview:</h5> <h5>Overview:</h5>
@ -2965,7 +2965,7 @@ 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. 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 second operand is a first-class value to insert.
The following operands are constant indices The following operands are constant indices
indicating the position at which to insert the value in the same manner as indicating the position at which to insert the value in a similar manner as
indices in a indices in a
'<tt><a href="#i_getelementptr">getelementptr</a></tt>' instruction. '<tt><a href="#i_getelementptr">getelementptr</a></tt>' instruction.
The value to insert must have the same type as the value identified The value to insert must have the same type as the value identified
@ -2982,7 +2982,7 @@ specified by the indices is that of <tt>elt</tt>.
<h5>Example:</h5> <h5>Example:</h5>
<pre> <pre>
%result = insertvalue {i32, float} %agg, i32 1, i32 0 <i>; yields {i32, float}</i> %result = insertvalue {i32, float} %agg, 1, 0 <i>; yields {i32, float}</i>
</pre> </pre>
</div> </div>

View File

@ -25,6 +25,7 @@
#include "llvm/OperandTraits.h" #include "llvm/OperandTraits.h"
#include "llvm/ADT/APInt.h" #include "llvm/ADT/APInt.h"
#include "llvm/ADT/APFloat.h" #include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallVector.h"
namespace llvm { namespace llvm {
@ -576,10 +577,10 @@ protected:
static Constant *getShuffleVectorTy(const Type *Ty, Constant *V1, static Constant *getShuffleVectorTy(const Type *Ty, Constant *V1,
Constant *V2, Constant *Mask); Constant *V2, Constant *Mask);
static Constant *getExtractValueTy(const Type *Ty, Constant *Agg, static Constant *getExtractValueTy(const Type *Ty, Constant *Agg,
Constant * const *Idxs, unsigned NumIdxs); const unsigned *Idxs, unsigned NumIdxs);
static Constant *getInsertValueTy(const Type *Ty, Constant *Agg, static Constant *getInsertValueTy(const Type *Ty, Constant *Agg,
Constant *Val, Constant *Val,
Constant * const *Idxs, unsigned NumIdxs); const unsigned *Idxs, unsigned NumIdxs);
public: public:
// Static methods to construct a ConstantExpr of different kinds. Note that // Static methods to construct a ConstantExpr of different kinds. Note that
@ -656,6 +657,10 @@ public:
/// @brief Return true if this is a compare constant expression /// @brief Return true if this is a compare constant expression
bool isCompare() const; bool isCompare() const;
/// @brief Return true if this is an insertvalue or extractvalue expression,
/// and the getIndices() method may be used.
bool hasIndices() const;
/// Select constant expr /// Select constant expr
/// ///
static Constant *getSelect(Constant *C, Constant *V1, Constant *V2) { static Constant *getSelect(Constant *C, Constant *V1, Constant *V2) {
@ -712,9 +717,9 @@ public:
static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx); static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx);
static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask); static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask);
static Constant *getExtractValue(Constant *Agg, static Constant *getExtractValue(Constant *Agg,
Constant* const *IdxList, unsigned NumIdx); const unsigned *IdxList, unsigned NumIdx);
static Constant *getInsertValue(Constant *Agg, Constant *Val, static Constant *getInsertValue(Constant *Agg, Constant *Val,
Constant* const *IdxList, unsigned NumIdx); const unsigned *IdxList, unsigned NumIdx);
/// Floating point negation must be implemented with f(x) = -0.0 - x. This /// Floating point negation must be implemented with f(x) = -0.0 - x. This
/// method returns the negative zero constant for floating point or vector /// method returns the negative zero constant for floating point or vector
@ -732,6 +737,10 @@ public:
/// not an ICMP or FCMP constant expression. /// not an ICMP or FCMP constant expression.
unsigned getPredicate() const; unsigned getPredicate() const;
/// getIndices - Assert that this is an insertvalue or exactvalue
/// expression and return the list of indices.
const SmallVector<unsigned, 4> &getIndices() const;
/// getOpcodeName - Return a string representation for an opcode. /// getOpcodeName - Return a string representation for an opcode.
const char *getOpcodeName() const; const char *getOpcodeName() const;

View File

@ -197,7 +197,9 @@ public:
/// the element. /// the element.
/// ///
virtual const Type *getTypeAtIndex(const Value *V) const = 0; virtual const Type *getTypeAtIndex(const Value *V) const = 0;
virtual const Type *getTypeAtIndex(unsigned Idx) const = 0;
virtual bool indexValid(const Value *V) const = 0; virtual bool indexValid(const Value *V) const = 0;
virtual bool indexValid(unsigned Idx) const = 0;
// Methods for support type inquiry through isa, cast, and dyn_cast: // Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const CompositeType *) { return true; } static inline bool classof(const CompositeType *) { return true; }
@ -245,8 +247,10 @@ public:
/// getTypeAtIndex - Given an index value into the type, return the type of /// getTypeAtIndex - Given an index value into the type, return the type of
/// the element. For a structure type, this must be a constant value... /// the element. For a structure type, this must be a constant value...
/// ///
virtual const Type *getTypeAtIndex(const Value *V) const ; 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(const Value *V) const;
virtual bool indexValid(unsigned Idx) const;
// Implement the AbstractTypeUser interface. // Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
@ -288,6 +292,9 @@ public:
inline const Type *getElementType() const { return ContainedTys[0]; } inline const Type *getElementType() const { return ContainedTys[0]; }
virtual bool indexValid(const Value *V) const; virtual bool indexValid(const Value *V) const;
virtual bool indexValid(unsigned Idx) const {
return true;
}
/// getTypeAtIndex - Given an index value into the type, return the type of /// getTypeAtIndex - Given an index value into the type, return the type of
/// the element. For sequential types, there is only one subtype... /// the element. For sequential types, there is only one subtype...
@ -295,6 +302,9 @@ public:
virtual const Type *getTypeAtIndex(const Value *) const { virtual const Type *getTypeAtIndex(const Value *) const {
return ContainedTys[0]; return ContainedTys[0];
} }
virtual const Type *getTypeAtIndex(unsigned Idx) const {
return ContainedTys[0];
}
// Methods for support type inquiry through isa, cast, and dyn_cast: // Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SequentialType *) { return true; } static inline bool classof(const SequentialType *) { return true; }

View File

@ -22,6 +22,7 @@
#include "llvm/DerivedTypes.h" #include "llvm/DerivedTypes.h"
#include "llvm/ParameterAttributes.h" #include "llvm/ParameterAttributes.h"
#include "llvm/BasicBlock.h" #include "llvm/BasicBlock.h"
#include "llvm/ADT/SmallVector.h"
namespace llvm { namespace llvm {
@ -1518,9 +1519,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value)
/// element value from an aggregate value. /// element value from an aggregate value.
/// ///
class ExtractValueInst : public Instruction { class ExtractValueInst : public Instruction {
SmallVector<unsigned, 4> Indices;
ExtractValueInst(const ExtractValueInst &EVI); ExtractValueInst(const ExtractValueInst &EVI);
void init(Value *Agg, Value* const *Idx, unsigned NumIdx); void init(Value *Agg, const unsigned *Idx, unsigned NumIdx);
void init(Value *Agg, Value *Idx); void init(Value *Agg, unsigned Idx);
template<typename InputIterator> template<typename InputIterator>
void init(Value *Agg, InputIterator IdxBegin, InputIterator IdxEnd, void init(Value *Agg, InputIterator IdxBegin, InputIterator IdxEnd,
@ -1530,14 +1533,15 @@ class ExtractValueInst : public Instruction {
std::random_access_iterator_tag) { std::random_access_iterator_tag) {
unsigned NumIdx = static_cast<unsigned>(std::distance(IdxBegin, IdxEnd)); unsigned NumIdx = static_cast<unsigned>(std::distance(IdxBegin, IdxEnd));
if (NumIdx > 0) { // There's no fundamental reason why we require at least one index
// This requires that the iterator points to contiguous memory. // (other than weirdness with &*IdxBegin being invalid; see
init(Agg, &*IdxBegin, NumIdx); // FIXME: for the general case // getelementptr's init routine for example). But there's no
// we have to build an array here // present need to support it.
} assert(NumIdx > 0 && "ExtractValueInst must have at least one index");
else {
init(Agg, 0, NumIdx); // This requires that the iterator points to contiguous memory.
} init(Agg, &*IdxBegin, NumIdx); // FIXME: for the general case
// we have to build an array here
setName(Name); setName(Name);
} }
@ -1549,7 +1553,7 @@ class ExtractValueInst : public Instruction {
/// pointer type. /// pointer type.
/// ///
static const Type *getIndexedType(const Type *Agg, static const Type *getIndexedType(const Type *Agg,
Value* const *Idx, unsigned NumIdx); const unsigned *Idx, unsigned NumIdx);
template<typename InputIterator> template<typename InputIterator>
static const Type *getIndexedType(const Type *Ptr, static const Type *getIndexedType(const Type *Ptr,
@ -1563,9 +1567,9 @@ class ExtractValueInst : public Instruction {
if (NumIdx > 0) if (NumIdx > 0)
// This requires that the iterator points to contiguous memory. // This requires that the iterator points to contiguous memory.
return getIndexedType(Ptr, (Value *const *)&*IdxBegin, NumIdx); return getIndexedType(Ptr, (const unsigned *)&*IdxBegin, NumIdx);
else else
return getIndexedType(Ptr, (Value *const*)0, NumIdx); return getIndexedType(Ptr, (const unsigned *)0, NumIdx);
} }
/// Constructors - Create a extractvalue instruction with a base aggregate /// Constructors - Create a extractvalue instruction with a base aggregate
@ -1575,55 +1579,53 @@ class ExtractValueInst : public Instruction {
template<typename InputIterator> template<typename InputIterator>
inline ExtractValueInst(Value *Agg, InputIterator IdxBegin, inline ExtractValueInst(Value *Agg, InputIterator IdxBegin,
InputIterator IdxEnd, InputIterator IdxEnd,
unsigned Values,
const std::string &Name, const std::string &Name,
Instruction *InsertBefore); Instruction *InsertBefore);
template<typename InputIterator> template<typename InputIterator>
inline ExtractValueInst(Value *Agg, inline ExtractValueInst(Value *Agg,
InputIterator IdxBegin, InputIterator IdxEnd, InputIterator IdxBegin, InputIterator IdxEnd,
unsigned Values,
const std::string &Name, BasicBlock *InsertAtEnd); const std::string &Name, BasicBlock *InsertAtEnd);
/// Constructors - These two constructors are convenience methods because one /// Constructors - These two constructors are convenience methods because one
/// and two index extractvalue instructions are so common. /// and two index extractvalue instructions are so common.
ExtractValueInst(Value *Agg, Value *Idx, const std::string &Name = "", ExtractValueInst(Value *Agg, unsigned Idx, const std::string &Name = "",
Instruction *InsertBefore = 0); Instruction *InsertBefore = 0);
ExtractValueInst(Value *Agg, Value *Idx, ExtractValueInst(Value *Agg, unsigned Idx,
const std::string &Name, BasicBlock *InsertAtEnd); const std::string &Name, BasicBlock *InsertAtEnd);
public: public:
// allocate space for exactly two operands
void *operator new(size_t s) {
return User::operator new(s, 1);
}
template<typename InputIterator> template<typename InputIterator>
static ExtractValueInst *Create(Value *Agg, InputIterator IdxBegin, static ExtractValueInst *Create(Value *Agg, InputIterator IdxBegin,
InputIterator IdxEnd, InputIterator IdxEnd,
const std::string &Name = "", const std::string &Name = "",
Instruction *InsertBefore = 0) { Instruction *InsertBefore = 0) {
typename std::iterator_traits<InputIterator>::difference_type Values = return new
1 + std::distance(IdxBegin, IdxEnd); ExtractValueInst(Agg, IdxBegin, IdxEnd, Name, InsertBefore);
return new(Values)
ExtractValueInst(Agg, IdxBegin, IdxEnd, Values, Name, InsertBefore);
} }
template<typename InputIterator> template<typename InputIterator>
static ExtractValueInst *Create(Value *Agg, static ExtractValueInst *Create(Value *Agg,
InputIterator IdxBegin, InputIterator IdxEnd, InputIterator IdxBegin, InputIterator IdxEnd,
const std::string &Name, const std::string &Name,
BasicBlock *InsertAtEnd) { BasicBlock *InsertAtEnd) {
typename std::iterator_traits<InputIterator>::difference_type Values = return new ExtractValueInst(Agg, IdxBegin, IdxEnd, Name, InsertAtEnd);
1 + std::distance(IdxBegin, IdxEnd);
return new(Values)
ExtractValueInst(Agg, IdxBegin, IdxEnd, Values, Name, InsertAtEnd);
} }
/// Constructors - These two creators are convenience methods because one /// Constructors - These two creators are convenience methods because one
/// index extractvalue instructions are much more common than those with /// index extractvalue instructions are much more common than those with
/// more than one. /// more than one.
static ExtractValueInst *Create(Value *Agg, Value *Idx, static ExtractValueInst *Create(Value *Agg, unsigned Idx,
const std::string &Name = "", const std::string &Name = "",
Instruction *InsertBefore = 0) { Instruction *InsertBefore = 0) {
return new(2) ExtractValueInst(Agg, Idx, Name, InsertBefore); return new ExtractValueInst(Agg, Idx, Name, InsertBefore);
} }
static ExtractValueInst *Create(Value *Agg, Value *Idx, static ExtractValueInst *Create(Value *Agg, unsigned Idx,
const std::string &Name, const std::string &Name,
BasicBlock *InsertAtEnd) { BasicBlock *InsertAtEnd) {
return new(2) ExtractValueInst(Agg, Idx, Name, InsertAtEnd); return new ExtractValueInst(Agg, Idx, Name, InsertAtEnd);
} }
virtual ExtractValueInst *clone() const; virtual ExtractValueInst *clone() const;
@ -1650,7 +1652,7 @@ public:
typename std::iterator_traits<InputIterator>:: typename std::iterator_traits<InputIterator>::
iterator_category()); iterator_category());
} }
static const Type *getIndexedType(const Type *Ptr, Value *Idx); static const Type *getIndexedType(const Type *Ptr, unsigned Idx);
inline op_iterator idx_begin() { return op_begin()+1; } inline op_iterator idx_begin() { return op_begin()+1; }
inline const_op_iterator idx_begin() const { return op_begin()+1; } inline const_op_iterator idx_begin() const { return op_begin()+1; }
@ -1686,20 +1688,19 @@ public:
}; };
template <> template <>
struct OperandTraits<ExtractValueInst> : VariadicOperandTraits<1> { struct OperandTraits<ExtractValueInst> : FixedNumOperandTraits<1> {
}; };
template<typename InputIterator> template<typename InputIterator>
ExtractValueInst::ExtractValueInst(Value *Agg, ExtractValueInst::ExtractValueInst(Value *Agg,
InputIterator IdxBegin, InputIterator IdxBegin,
InputIterator IdxEnd, InputIterator IdxEnd,
unsigned Values,
const std::string &Name, const std::string &Name,
Instruction *InsertBefore) Instruction *InsertBefore)
: Instruction(checkType(getIndexedType(Agg->getType(), IdxBegin, IdxEnd)), : Instruction(checkType(getIndexedType(Agg->getType(), IdxBegin, IdxEnd)),
ExtractValue, ExtractValue,
OperandTraits<ExtractValueInst>::op_end(this) - Values, OperandTraits<ExtractValueInst>::op_begin(this),
Values, InsertBefore) { 1, InsertBefore) {
init(Agg, IdxBegin, IdxEnd, Name, init(Agg, IdxBegin, IdxEnd, Name,
typename std::iterator_traits<InputIterator>::iterator_category()); typename std::iterator_traits<InputIterator>::iterator_category());
} }
@ -1707,17 +1708,12 @@ template<typename InputIterator>
ExtractValueInst::ExtractValueInst(Value *Agg, ExtractValueInst::ExtractValueInst(Value *Agg,
InputIterator IdxBegin, InputIterator IdxBegin,
InputIterator IdxEnd, InputIterator IdxEnd,
unsigned Values,
const std::string &Name, const std::string &Name,
BasicBlock *InsertAtEnd) BasicBlock *InsertAtEnd)
: Instruction(PointerType::get(checkType( : Instruction(checkType(getIndexedType(Agg->getType(), IdxBegin, IdxEnd)),
getIndexedType(Agg->getType(),
IdxBegin, IdxEnd)),
cast<PointerType>(Agg->getType())
->getAddressSpace()),
ExtractValue, ExtractValue,
OperandTraits<ExtractValueInst>::op_end(this) - Values, OperandTraits<ExtractValueInst>::op_begin(this),
Values, InsertAtEnd) { 1, InsertAtEnd) {
init(Agg, IdxBegin, IdxEnd, Name, init(Agg, IdxBegin, IdxEnd, Name,
typename std::iterator_traits<InputIterator>::iterator_category()); typename std::iterator_traits<InputIterator>::iterator_category());
} }
@ -1733,9 +1729,12 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueInst, Value)
/// value into an aggregate value. /// value into an aggregate value.
/// ///
class InsertValueInst : public Instruction { class InsertValueInst : public Instruction {
SmallVector<unsigned, 4> Indices;
void *operator new(size_t, unsigned); // Do not implement
InsertValueInst(const InsertValueInst &IVI); InsertValueInst(const InsertValueInst &IVI);
void init(Value *Agg, Value *Val, Value* const *Idx, unsigned NumIdx); void init(Value *Agg, Value *Val, const unsigned *Idx, unsigned NumIdx);
void init(Value *Agg, Value *Val, Value *Idx); void init(Value *Agg, Value *Val, unsigned Idx);
template<typename InputIterator> template<typename InputIterator>
void init(Value *Agg, Value *Val, void init(Value *Agg, Value *Val,
@ -1746,14 +1745,15 @@ class InsertValueInst : public Instruction {
std::random_access_iterator_tag) { std::random_access_iterator_tag) {
unsigned NumIdx = static_cast<unsigned>(std::distance(IdxBegin, IdxEnd)); unsigned NumIdx = static_cast<unsigned>(std::distance(IdxBegin, IdxEnd));
if (NumIdx > 0) { // There's no fundamental reason why we require at least one index
// This requires that the iterator points to contiguous memory. // (other than weirdness with &*IdxBegin being invalid; see
init(Agg, Val, &*IdxBegin, NumIdx); // FIXME: for the general case // getelementptr's init routine for example). But there's no
// we have to build an array here // present need to support it.
} assert(NumIdx > 0 && "InsertValueInst must have at least one index");
else {
init(Agg, Val, 0, NumIdx); // This requires that the iterator points to contiguous memory.
} init(Agg, Val, &*IdxBegin, NumIdx); // FIXME: for the general case
// we have to build an array here
setName(Name); setName(Name);
} }
@ -1765,56 +1765,55 @@ class InsertValueInst : public Instruction {
template<typename InputIterator> template<typename InputIterator>
inline InsertValueInst(Value *Agg, Value *Val, InputIterator IdxBegin, inline InsertValueInst(Value *Agg, Value *Val, InputIterator IdxBegin,
InputIterator IdxEnd, InputIterator IdxEnd,
unsigned Values,
const std::string &Name, const std::string &Name,
Instruction *InsertBefore); Instruction *InsertBefore);
template<typename InputIterator> template<typename InputIterator>
inline InsertValueInst(Value *Agg, Value *Val, inline InsertValueInst(Value *Agg, Value *Val,
InputIterator IdxBegin, InputIterator IdxEnd, InputIterator IdxBegin, InputIterator IdxEnd,
unsigned Values,
const std::string &Name, BasicBlock *InsertAtEnd); const std::string &Name, BasicBlock *InsertAtEnd);
/// Constructors - These two constructors are convenience methods because one /// Constructors - These two constructors are convenience methods because one
/// and two index insertvalue instructions are so common. /// and two index insertvalue instructions are so common.
InsertValueInst(Value *Agg, Value *Val, InsertValueInst(Value *Agg, Value *Val,
Value *Idx, const std::string &Name = "", unsigned Idx, const std::string &Name = "",
Instruction *InsertBefore = 0); Instruction *InsertBefore = 0);
InsertValueInst(Value *Agg, Value *Val, Value *Idx, InsertValueInst(Value *Agg, Value *Val, unsigned Idx,
const std::string &Name, BasicBlock *InsertAtEnd); const std::string &Name, BasicBlock *InsertAtEnd);
public: public:
// allocate space for exactly two operands
void *operator new(size_t s) {
return User::operator new(s, 2);
}
template<typename InputIterator> template<typename InputIterator>
static InsertValueInst *Create(Value *Agg, Value *Val, InputIterator IdxBegin, static InsertValueInst *Create(Value *Agg, Value *Val, InputIterator IdxBegin,
InputIterator IdxEnd, InputIterator IdxEnd,
const std::string &Name = "", const std::string &Name = "",
Instruction *InsertBefore = 0) { Instruction *InsertBefore = 0) {
typename std::iterator_traits<InputIterator>::difference_type Values = return new InsertValueInst(Agg, Val, IdxBegin, IdxEnd,
1 + std::distance(IdxBegin, IdxEnd); Name, InsertBefore);
return new(Values)
InsertValueInst(Agg, Val, IdxBegin, IdxEnd, Values, Name, InsertBefore);
} }
template<typename InputIterator> template<typename InputIterator>
static InsertValueInst *Create(Value *Agg, Value *Val, static InsertValueInst *Create(Value *Agg, Value *Val,
InputIterator IdxBegin, InputIterator IdxEnd, InputIterator IdxBegin, InputIterator IdxEnd,
const std::string &Name, const std::string &Name,
BasicBlock *InsertAtEnd) { BasicBlock *InsertAtEnd) {
typename std::iterator_traits<InputIterator>::difference_type Values = return new InsertValueInst(Agg, Val, IdxBegin, IdxEnd,
1 + std::distance(IdxBegin, IdxEnd); Name, InsertAtEnd);
return new(Values)
InsertValueInst(Agg, Val, IdxBegin, IdxEnd, Values, Name, InsertAtEnd);
} }
/// Constructors - These two creators are convenience methods because one /// Constructors - These two creators are convenience methods because one
/// index insertvalue instructions are much more common than those with /// index insertvalue instructions are much more common than those with
/// more than one. /// more than one.
static InsertValueInst *Create(Value *Agg, Value *Val, Value *Idx, static InsertValueInst *Create(Value *Agg, Value *Val, unsigned Idx,
const std::string &Name = "", const std::string &Name = "",
Instruction *InsertBefore = 0) { Instruction *InsertBefore = 0) {
return new(3) InsertValueInst(Agg, Val, Idx, Name, InsertBefore); return new InsertValueInst(Agg, Val, Idx, Name, InsertBefore);
} }
static InsertValueInst *Create(Value *Agg, Value *Val, Value *Idx, static InsertValueInst *Create(Value *Agg, Value *Val, unsigned Idx,
const std::string &Name, const std::string &Name,
BasicBlock *InsertAtEnd) { BasicBlock *InsertAtEnd) {
return new(3) InsertValueInst(Agg, Val, Idx, Name, InsertAtEnd); return new InsertValueInst(Agg, Val, Idx, Name, InsertAtEnd);
} }
virtual InsertValueInst *clone() const; virtual InsertValueInst *clone() const;
@ -1827,10 +1826,10 @@ public:
return reinterpret_cast<const PointerType*>(Instruction::getType()); return reinterpret_cast<const PointerType*>(Instruction::getType());
} }
inline op_iterator idx_begin() { return op_begin()+1; } inline unsigned *idx_begin() { return Indices.begin(); }
inline const_op_iterator idx_begin() const { return op_begin()+1; } inline const unsigned *idx_begin() const { return Indices.begin(); }
inline op_iterator idx_end() { return op_end(); } inline unsigned *idx_end() { return Indices.end(); }
inline const_op_iterator idx_end() const { return op_end(); } inline const unsigned *idx_end() const { return Indices.end(); }
Value *getAggregateOperand() { Value *getAggregateOperand() {
return getOperand(0); return getOperand(0);
@ -1871,7 +1870,7 @@ public:
}; };
template <> template <>
struct OperandTraits<InsertValueInst> : VariadicOperandTraits<2> { struct OperandTraits<InsertValueInst> : FixedNumOperandTraits<2> {
}; };
template<typename InputIterator> template<typename InputIterator>
@ -1879,15 +1878,11 @@ InsertValueInst::InsertValueInst(Value *Agg,
Value *Val, Value *Val,
InputIterator IdxBegin, InputIterator IdxBegin,
InputIterator IdxEnd, InputIterator IdxEnd,
unsigned Values,
const std::string &Name, const std::string &Name,
Instruction *InsertBefore) Instruction *InsertBefore)
: Instruction(checkType(ExtractValueInst::getIndexedType( : Instruction(Agg->getType(), InsertValue,
Agg->getType(), OperandTraits<InsertValueInst>::op_begin(this),
IdxBegin, IdxEnd)), 2, InsertBefore) {
InsertValue,
OperandTraits<InsertValueInst>::op_end(this) - Values,
Values, InsertBefore) {
init(Agg, Val, IdxBegin, IdxEnd, Name, init(Agg, Val, IdxBegin, IdxEnd, Name,
typename std::iterator_traits<InputIterator>::iterator_category()); typename std::iterator_traits<InputIterator>::iterator_category());
} }
@ -1896,18 +1891,11 @@ InsertValueInst::InsertValueInst(Value *Agg,
Value *Val, Value *Val,
InputIterator IdxBegin, InputIterator IdxBegin,
InputIterator IdxEnd, InputIterator IdxEnd,
unsigned Values,
const std::string &Name, const std::string &Name,
BasicBlock *InsertAtEnd) BasicBlock *InsertAtEnd)
: Instruction(PointerType::get(checkType( : Instruction(Agg->getType(), InsertValue,
ExtractValueInst::getIndexedType( OperandTraits<InsertValueInst>::op_begin(this),
Val->getType(), 2, InsertAtEnd) {
IdxBegin, IdxEnd)),
cast<PointerType>(Val->getType())
->getAddressSpace()),
InsertValue,
OperandTraits<InsertValueInst>::op_end(this) - Values,
Values, InsertAtEnd) {
init(Agg, Val, IdxBegin, IdxEnd, Name, init(Agg, Val, IdxBegin, IdxEnd, Name,
typename std::iterator_traits<InputIterator>::iterator_category()); typename std::iterator_traits<InputIterator>::iterator_category());
} }

File diff suppressed because it is too large Load Diff

View File

@ -354,7 +354,7 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE typedef union YYSTYPE
#line 949 "/Users/gohman/LLVM/llvm/lib/AsmParser/llvmAsmParser.y" #line 953 "/Users/gohman/LLVM/llvm/lib/AsmParser/llvmAsmParser.y"
{ {
llvm::Module *ModuleVal; llvm::Module *ModuleVal;
llvm::Function *FunctionVal; llvm::Function *FunctionVal;
@ -368,6 +368,7 @@ typedef union YYSTYPE
llvm::PATypeHolder *TypeVal; llvm::PATypeHolder *TypeVal;
llvm::Value *ValueVal; llvm::Value *ValueVal;
std::vector<llvm::Value*> *ValueList; std::vector<llvm::Value*> *ValueList;
std::vector<unsigned> *ConstantList;
llvm::ArgListType *ArgList; llvm::ArgListType *ArgList;
llvm::TypeWithAttrs TypeWithAttrs; llvm::TypeWithAttrs TypeWithAttrs;
llvm::TypeWithAttrsList *TypeWithAttrsList; llvm::TypeWithAttrsList *TypeWithAttrsList;
@ -402,7 +403,7 @@ typedef union YYSTYPE
llvm::FCmpInst::Predicate FPredicate; llvm::FCmpInst::Predicate FPredicate;
} }
/* Line 1529 of yacc.c. */ /* Line 1529 of yacc.c. */
#line 406 "llvmAsmParser.tab.h" #line 407 "llvmAsmParser.tab.h"
YYSTYPE; YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_DECLARED 1

View File

@ -963,6 +963,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
llvm::PATypeHolder *TypeVal; llvm::PATypeHolder *TypeVal;
llvm::Value *ValueVal; llvm::Value *ValueVal;
std::vector<llvm::Value*> *ValueList; std::vector<llvm::Value*> *ValueList;
std::vector<unsigned> *ConstantList;
llvm::ArgListType *ArgList; llvm::ArgListType *ArgList;
llvm::TypeWithAttrs TypeWithAttrs; llvm::TypeWithAttrs TypeWithAttrs;
llvm::TypeWithAttrsList *TypeWithAttrsList; llvm::TypeWithAttrsList *TypeWithAttrsList;
@ -1008,6 +1009,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
%type <PHIList> PHIList %type <PHIList> PHIList
%type <ParamList> ParamList // For call param lists & GEP indices %type <ParamList> ParamList // For call param lists & GEP indices
%type <ValueList> IndexList // For GEP indices %type <ValueList> IndexList // For GEP indices
%type <ConstantList> ConstantIndexList // For insertvalue/extractvalue indices
%type <TypeList> TypeListI %type <TypeList> TypeListI
%type <TypeWithAttrsList> ArgTypeList ArgTypeListI %type <TypeWithAttrsList> ArgTypeList ArgTypeListI
%type <TypeWithAttrs> ArgType %type <TypeWithAttrs> ArgType
@ -1974,46 +1976,20 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
$$ = ConstantExpr::getShuffleVector($3, $5, $7); $$ = ConstantExpr::getShuffleVector($3, $5, $7);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| EXTRACTVALUE '(' ConstVal IndexList ')' { | EXTRACTVALUE '(' ConstVal ConstantIndexList ')' {
if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType())) if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
GEN_ERROR("ExtractValue requires an aggregate operand"); GEN_ERROR("ExtractValue requires an aggregate operand");
const Type *IdxTy = $$ = ConstantExpr::getExtractValue($3, &(*$4)[0], $4->size());
ExtractValueInst::getIndexedType($3->getType(), $4->begin(), $4->end());
if (!IdxTy)
GEN_ERROR("Index list invalid for constant extractvalue");
SmallVector<Constant*, 8> IdxVec;
for (unsigned i = 0, e = $4->size(); i != e; ++i)
if (Constant *C = dyn_cast<Constant>((*$4)[i]))
IdxVec.push_back(C);
else
GEN_ERROR("Indices to constant extractvalue must be constants");
delete $4; delete $4;
$$ = ConstantExpr::getExtractValue($3, &IdxVec[0], IdxVec.size());
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| INSERTVALUE '(' ConstVal ',' ConstVal IndexList ')' { | INSERTVALUE '(' ConstVal ',' ConstVal ConstantIndexList ')' {
if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType())) if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
GEN_ERROR("InsertValue requires an aggregate operand"); GEN_ERROR("InsertValue requires an aggregate operand");
const Type *IdxTy = $$ = ConstantExpr::getInsertValue($3, $5, &(*$6)[0], $6->size());
ExtractValueInst::getIndexedType($3->getType(), $6->begin(), $6->end());
if (IdxTy != $5->getType())
GEN_ERROR("Index list invalid for constant insertvalue");
SmallVector<Constant*, 8> IdxVec;
for (unsigned i = 0, e = $6->size(); i != e; ++i)
if (Constant *C = dyn_cast<Constant>((*$6)[i]))
IdxVec.push_back(C);
else
GEN_ERROR("Indices to constant insertvalue must be constants");
delete $6; delete $6;
$$ = ConstantExpr::getInsertValue($3, $5, &IdxVec[0], IdxVec.size());
CHECK_FOR_ERROR CHECK_FOR_ERROR
}; };
@ -2885,6 +2861,22 @@ IndexList // Used for gep instructions and constant expressions
} }
; ;
ConstantIndexList // Used for insertvalue and extractvalue instructions
: ',' EUINT64VAL {
$$ = new std::vector<unsigned>();
if ((unsigned)$2 != $2)
GEN_ERROR("Index " + utostr($2) + " is not valid for insertvalue or extractvalue.");
$$->push_back($2);
}
| ConstantIndexList ',' EUINT64VAL {
$$ = $1;
if ((unsigned)$3 != $3)
GEN_ERROR("Index " + utostr($3) + " is not valid for insertvalue or extractvalue.");
$$->push_back($3);
CHECK_FOR_ERROR
}
;
OptTailCall : TAIL CALL { OptTailCall : TAIL CALL {
$$ = true; $$ = true;
CHECK_FOR_ERROR CHECK_FOR_ERROR
@ -3245,7 +3237,7 @@ MemoryInst : MALLOC Types OptCAlign {
delete $2; delete $2;
delete $4; delete $4;
} }
| EXTRACTVALUE Types ValueRef IndexList { | EXTRACTVALUE Types ValueRef ConstantIndexList {
if (!UpRefs.empty()) if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription()); GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get())) if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))
@ -3260,7 +3252,7 @@ MemoryInst : MALLOC Types OptCAlign {
delete $2; delete $2;
delete $4; delete $4;
} }
| INSERTVALUE Types ValueRef ',' Types ValueRef IndexList { | INSERTVALUE Types ValueRef ',' Types ValueRef ConstantIndexList {
if (!UpRefs.empty()) if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription()); GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get())) if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))

View File

@ -731,6 +731,10 @@ ParseGlobalVariable(std::string *NameStr,
GenerateError("Cannot declare global vars of function type"); GenerateError("Cannot declare global vars of function type");
return 0; return 0;
} }
if (Ty == Type::LabelTy) {
GenerateError("Cannot declare global vars of label type");
return 0;
}
const PointerType *PTy = PointerType::get(Ty, AddressSpace); const PointerType *PTy = PointerType::get(Ty, AddressSpace);
@ -959,6 +963,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
llvm::PATypeHolder *TypeVal; llvm::PATypeHolder *TypeVal;
llvm::Value *ValueVal; llvm::Value *ValueVal;
std::vector<llvm::Value*> *ValueList; std::vector<llvm::Value*> *ValueList;
std::vector<unsigned> *ConstantList;
llvm::ArgListType *ArgList; llvm::ArgListType *ArgList;
llvm::TypeWithAttrs TypeWithAttrs; llvm::TypeWithAttrs TypeWithAttrs;
llvm::TypeWithAttrsList *TypeWithAttrsList; llvm::TypeWithAttrsList *TypeWithAttrsList;
@ -1004,6 +1009,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
%type <PHIList> PHIList %type <PHIList> PHIList
%type <ParamList> ParamList // For call param lists & GEP indices %type <ParamList> ParamList // For call param lists & GEP indices
%type <ValueList> IndexList // For GEP indices %type <ValueList> IndexList // For GEP indices
%type <ConstantList> ConstantIndexList // For insertvalue/extractvalue indices
%type <TypeList> TypeListI %type <TypeList> TypeListI
%type <TypeWithAttrsList> ArgTypeList ArgTypeListI %type <TypeWithAttrsList> ArgTypeList ArgTypeListI
%type <TypeWithAttrs> ArgType %type <TypeWithAttrs> ArgType
@ -1402,7 +1408,7 @@ Types
} }
| '[' EUINT64VAL 'x' Types ']' { // Sized array type? | '[' EUINT64VAL 'x' Types ']' { // Sized array type?
$$ = new PATypeHolder(HandleUpRefs(ArrayType::get(*$4, (unsigned)$2))); $$ = new PATypeHolder(HandleUpRefs(ArrayType::get(*$4, $2)));
delete $4; delete $4;
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
@ -1850,12 +1856,14 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| INTTYPE TRUETOK { // Boolean constants | INTTYPE TRUETOK { // Boolean constants
assert(cast<IntegerType>($1)->getBitWidth() == 1 && "Not Bool?"); if (cast<IntegerType>($1)->getBitWidth() != 1)
GEN_ERROR("Constant true must have type i1");
$$ = ConstantInt::getTrue(); $$ = ConstantInt::getTrue();
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| INTTYPE FALSETOK { // Boolean constants | INTTYPE FALSETOK { // Boolean constants
assert(cast<IntegerType>($1)->getBitWidth() == 1 && "Not Bool?"); if (cast<IntegerType>($1)->getBitWidth() != 1)
GEN_ERROR("Constant false must have type i1");
$$ = ConstantInt::getFalse(); $$ = ConstantInt::getFalse();
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
@ -1968,46 +1976,20 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
$$ = ConstantExpr::getShuffleVector($3, $5, $7); $$ = ConstantExpr::getShuffleVector($3, $5, $7);
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| EXTRACTVALUE '(' ConstVal IndexList ')' { | EXTRACTVALUE '(' ConstVal ConstantIndexList ')' {
if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType())) if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
GEN_ERROR("ExtractValue requires an aggregate operand"); GEN_ERROR("ExtractValue requires an aggregate operand");
const Type *IdxTy = $$ = ConstantExpr::getExtractValue($3, &(*$4)[0], $4->size());
ExtractValueInst::getIndexedType($3->getType(), $4->begin(), $4->end());
if (!IdxTy)
GEN_ERROR("Index list invalid for constant extractvalue");
SmallVector<Constant*, 8> IdxVec;
for (unsigned i = 0, e = $4->size(); i != e; ++i)
if (Constant *C = dyn_cast<Constant>((*$4)[i]))
IdxVec.push_back(C);
else
GEN_ERROR("Indices to constant extractvalue must be constants");
delete $4; delete $4;
$$ = ConstantExpr::getExtractValue($3, &IdxVec[0], IdxVec.size());
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| INSERTVALUE '(' ConstVal ',' ConstVal IndexList ')' { | INSERTVALUE '(' ConstVal ',' ConstVal ConstantIndexList ')' {
if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType())) if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
GEN_ERROR("InsertValue requires an aggregate operand"); GEN_ERROR("InsertValue requires an aggregate operand");
const Type *IdxTy = $$ = ConstantExpr::getInsertValue($3, $5, &(*$6)[0], $6->size());
ExtractValueInst::getIndexedType($3->getType(), $6->begin(), $6->end());
if (IdxTy != $5->getType())
GEN_ERROR("Index list invalid for constant insertvalue");
SmallVector<Constant*, 8> IdxVec;
for (unsigned i = 0, e = $6->size(); i != e; ++i)
if (Constant *C = dyn_cast<Constant>((*$6)[i]))
IdxVec.push_back(C);
else
GEN_ERROR("Indices to constant insertvalue must be constants");
delete $6; delete $6;
$$ = ConstantExpr::getInsertValue($3, $5, &IdxVec[0], IdxVec.size());
CHECK_FOR_ERROR CHECK_FOR_ERROR
}; };
@ -2250,8 +2232,8 @@ LibList : LibList ',' STRINGCONSTANT {
ArgListH : ArgListH ',' Types OptParamAttrs OptLocalName { ArgListH : ArgListH ',' Types OptParamAttrs OptLocalName {
if (!UpRefs.empty()) if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription()); GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
if (*$3 == Type::VoidTy) if (!(*$3)->isFirstClassType())
GEN_ERROR("void typed arguments are invalid"); GEN_ERROR("Argument types must be first-class");
ArgListEntry E; E.Attrs = $4; E.Ty = $3; E.Name = $5; ArgListEntry E; E.Attrs = $4; E.Ty = $3; E.Name = $5;
$$ = $1; $$ = $1;
$1->push_back(E); $1->push_back(E);
@ -2260,8 +2242,8 @@ ArgListH : ArgListH ',' Types OptParamAttrs OptLocalName {
| Types OptParamAttrs OptLocalName { | Types OptParamAttrs OptLocalName {
if (!UpRefs.empty()) if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription()); GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
if (*$1 == Type::VoidTy) if (!(*$1)->isFirstClassType())
GEN_ERROR("void typed arguments are invalid"); GEN_ERROR("Argument types must be first-class");
ArgListEntry E; E.Attrs = $2; E.Ty = $1; E.Name = $3; ArgListEntry E; E.Attrs = $2; E.Ty = $1; E.Name = $3;
$$ = new ArgListType; $$ = new ArgListType;
$$->push_back(E); $$->push_back(E);
@ -2498,6 +2480,9 @@ ConstValueRef : ESINT64VAL { // A reference to a direct constant
| '<' ConstVector '>' { // Nonempty unsized packed vector | '<' ConstVector '>' { // Nonempty unsized packed vector
const Type *ETy = (*$2)[0]->getType(); const Type *ETy = (*$2)[0]->getType();
int NumElements = $2->size(); int NumElements = $2->size();
if (!ETy->isInteger() && !ETy->isFloatingPoint())
GEN_ERROR("Invalid vector element type: " + ETy->getDescription());
VectorType* pt = VectorType::get(ETy, NumElements); VectorType* pt = VectorType::get(ETy, NumElements);
PATypeHolder* PTy = new PATypeHolder( PATypeHolder* PTy = new PATypeHolder(
@ -2639,7 +2624,8 @@ BBTerminatorInst :
$$ = BranchInst::Create(tmpBB); $$ = BranchInst::Create(tmpBB);
} // Conditional Branch... } // Conditional Branch...
| BR INTTYPE ValueRef ',' LABEL ValueRef ',' LABEL ValueRef { | BR INTTYPE ValueRef ',' LABEL ValueRef ',' LABEL ValueRef {
assert(cast<IntegerType>($2)->getBitWidth() == 1 && "Not Bool?"); if (cast<IntegerType>($2)->getBitWidth() != 1)
GEN_ERROR("Branch condition must have type i1");
BasicBlock* tmpBBA = getBBVal($6); BasicBlock* tmpBBA = getBBVal($6);
CHECK_FOR_ERROR CHECK_FOR_ERROR
BasicBlock* tmpBBB = getBBVal($9); BasicBlock* tmpBBB = getBBVal($9);
@ -2875,6 +2861,22 @@ IndexList // Used for gep instructions and constant expressions
} }
; ;
ConstantIndexList // Used for insertvalue and extractvalue instructions
: ',' EUINT64VAL {
$$ = new std::vector<unsigned>();
if ((unsigned)$2 != $2)
GEN_ERROR("Index " + utostr($2) + " is not valid for insertvalue or extractvalue.");
$$->push_back($2);
}
| ConstantIndexList ',' EUINT64VAL {
$$ = $1;
if ((unsigned)$3 != $3)
GEN_ERROR("Index " + utostr($3) + " is not valid for insertvalue or extractvalue.");
$$->push_back($3);
CHECK_FOR_ERROR
}
;
OptTailCall : TAIL CALL { OptTailCall : TAIL CALL {
$$ = true; $$ = true;
CHECK_FOR_ERROR CHECK_FOR_ERROR
@ -3149,6 +3151,8 @@ MemoryInst : MALLOC Types OptCAlign {
| MALLOC Types ',' INTTYPE ValueRef OptCAlign { | MALLOC Types ',' INTTYPE ValueRef OptCAlign {
if (!UpRefs.empty()) if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription()); GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
if ($4 != Type::Int32Ty)
GEN_ERROR("Malloc array size is not a 32-bit integer!");
Value* tmpVal = getVal($4, $5); Value* tmpVal = getVal($4, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
$$ = new MallocInst(*$2, tmpVal, $6); $$ = new MallocInst(*$2, tmpVal, $6);
@ -3164,6 +3168,8 @@ MemoryInst : MALLOC Types OptCAlign {
| ALLOCA Types ',' INTTYPE ValueRef OptCAlign { | ALLOCA Types ',' INTTYPE ValueRef OptCAlign {
if (!UpRefs.empty()) if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription()); GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
if ($4 != Type::Int32Ty)
GEN_ERROR("Alloca array size is not a 32-bit integer!");
Value* tmpVal = getVal($4, $5); Value* tmpVal = getVal($4, $5);
CHECK_FOR_ERROR CHECK_FOR_ERROR
$$ = new AllocaInst(*$2, tmpVal, $6); $$ = new AllocaInst(*$2, tmpVal, $6);
@ -3231,7 +3237,7 @@ MemoryInst : MALLOC Types OptCAlign {
delete $2; delete $2;
delete $4; delete $4;
} }
| EXTRACTVALUE Types ValueRef IndexList { | EXTRACTVALUE Types ValueRef ConstantIndexList {
if (!UpRefs.empty()) if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription()); GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get())) if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))
@ -3246,7 +3252,7 @@ MemoryInst : MALLOC Types OptCAlign {
delete $2; delete $2;
delete $4; delete $4;
} }
| INSERTVALUE Types ValueRef ',' Types ValueRef IndexList { | INSERTVALUE Types ValueRef ',' Types ValueRef ConstantIndexList {
if (!UpRefs.empty()) if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription()); GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get())) if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))

View File

@ -770,27 +770,45 @@ bool BitcodeReader::ParseConstants() {
V = ConstantExpr::getGetElementPtr(Elts[0], &Elts[1], Elts.size()-1); V = ConstantExpr::getGetElementPtr(Elts[0], &Elts[1], Elts.size()-1);
break; break;
} }
case bitc::CST_CODE_CE_EXTRACTVAL: { // CE_EXTRACTVAL: [n x operands] case bitc::CST_CODE_CE_EXTRACTVAL: {
if (Record.size() & 1) return Error("Invalid CE_EXTRACTVAL record"); // CE_EXTRACTVAL: [opty, opval, n x indices]
SmallVector<Constant*, 16> Elts; const Type *AggTy = getTypeByID(Record[0]);
for (unsigned i = 0, e = Record.size(); i != e; i += 2) { if (!AggTy || !AggTy->isAggregateType())
const Type *ElTy = getTypeByID(Record[i]); return Error("Invalid CE_INSERTVAL record");
if (!ElTy) return Error("Invalid CE_EXTRACTVAL record"); Constant *Agg = ValueList.getConstantFwdRef(Record[1], AggTy);
Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy)); SmallVector<unsigned, 4> Indices;
for (unsigned i = 2, e = Record.size(); i != e; ++i) {
uint64_t Index = Record[i];
if ((unsigned)Index != Index)
return Error("Invalid CE_EXTRACTVAL record");
Indices.push_back((unsigned)Index);
} }
V = ConstantExpr::getExtractValue(Elts[0], &Elts[1], Elts.size()-1); if (!ExtractValueInst::getIndexedType(AggTy,
Indices.begin(), Indices.end()))
return Error("Invalid CE_EXTRACTVAL record");
V = ConstantExpr::getExtractValue(Agg, &Indices[0], Indices.size());
break; break;
} }
case bitc::CST_CODE_CE_INSERTVAL: { // CE_INSERTVAL: [n x operands] case bitc::CST_CODE_CE_INSERTVAL: {
if (Record.size() & 1) return Error("Invalid CE_INSERTVAL record"); // CE_INSERTVAL: [opty, opval, opty, opval, n x indices]
SmallVector<Constant*, 16> Elts; const Type *AggTy = getTypeByID(Record[0]);
for (unsigned i = 0, e = Record.size(); i != e; i += 2) { if (!AggTy || !AggTy->isAggregateType())
const Type *ElTy = getTypeByID(Record[i]); return Error("Invalid CE_INSERTVAL record");
if (!ElTy) return Error("Invalid CE_INSERTVAL record"); Constant *Agg = ValueList.getConstantFwdRef(Record[1], AggTy);
Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy)); const Type *ValTy = getTypeByID(Record[2]);
Constant *Val = ValueList.getConstantFwdRef(Record[2], ValTy);
SmallVector<unsigned, 4> Indices;
for (unsigned i = 4, e = Record.size(); i != e; ++i) {
uint64_t Index = Record[i];
if ((unsigned)Index != Index)
return Error("Invalid CE_INSERTVAL record");
Indices.push_back((unsigned)Index);
} }
V = ConstantExpr::getInsertValue(Elts[0], Elts[1], if (ExtractValueInst::getIndexedType(AggTy,
&Elts[2], Elts.size()-1); Indices.begin(),
Indices.end()) != ValTy)
return Error("Invalid CE_INSERTVAL record");
V = ConstantExpr::getInsertValue(Agg, Val, &Indices[0], Indices.size());
break; break;
} }
case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#] case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#]
@ -1324,18 +1342,20 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
break; break;
} }
case bitc::FUNC_CODE_INST_EXTRACTVAL: { // EXTRACTVAL: [n x operands] case bitc::FUNC_CODE_INST_EXTRACTVAL: {
// EXTRACTVAL: [opty, opval, n x indices]
unsigned OpNum = 0; unsigned OpNum = 0;
Value *Agg; Value *Agg;
if (getValueTypePair(Record, OpNum, NextValueNo, Agg)) if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
return Error("Invalid EXTRACTVAL record"); return Error("Invalid EXTRACTVAL record");
SmallVector<Value*, 16> EXTRACTVALIdx; SmallVector<unsigned, 4> EXTRACTVALIdx;
while (OpNum != Record.size()) { for (unsigned RecSize = Record.size();
Value *Op; OpNum != RecSize; ++OpNum) {
if (getValueTypePair(Record, OpNum, NextValueNo, Op)) uint64_t Index = Record[OpNum];
return Error("Invalid EXTRACTVAL record"); if ((unsigned)Index != Index)
EXTRACTVALIdx.push_back(Op); return Error("Invalid EXTRACTVAL index");
EXTRACTVALIdx.push_back((unsigned)Index);
} }
I = ExtractValueInst::Create(Agg, I = ExtractValueInst::Create(Agg,
@ -1343,7 +1363,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
break; break;
} }
case bitc::FUNC_CODE_INST_INSERTVAL: { // INSERTVAL: [n x operands] case bitc::FUNC_CODE_INST_INSERTVAL: {
// INSERTVAL: [opty, opval, opty, opval, n x indices]
unsigned OpNum = 0; unsigned OpNum = 0;
Value *Agg; Value *Agg;
if (getValueTypePair(Record, OpNum, NextValueNo, Agg)) if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
@ -1352,12 +1373,13 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
if (getValueTypePair(Record, OpNum, NextValueNo, Val)) if (getValueTypePair(Record, OpNum, NextValueNo, Val))
return Error("Invalid INSERTVAL record"); return Error("Invalid INSERTVAL record");
SmallVector<Value*, 16> INSERTVALIdx; SmallVector<unsigned, 4> INSERTVALIdx;
while (OpNum != Record.size()) { for (unsigned RecSize = Record.size();
Value *Op; OpNum != RecSize; ++OpNum) {
if (getValueTypePair(Record, OpNum, NextValueNo, Op)) uint64_t Index = Record[OpNum];
return Error("Invalid INSERTVAL record"); if ((unsigned)Index != Index)
INSERTVALIdx.push_back(Op); return Error("Invalid INSERTVAL index");
INSERTVALIdx.push_back((unsigned)Index);
} }
I = InsertValueInst::Create(Agg, Val, I = InsertValueInst::Create(Agg, Val,

View File

@ -610,20 +610,26 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
Record.push_back(VE.getValueID(C->getOperand(i))); Record.push_back(VE.getValueID(C->getOperand(i)));
} }
break; break;
case Instruction::ExtractValue: case Instruction::ExtractValue: {
Code = bitc::CST_CODE_CE_EXTRACTVAL; Code = bitc::CST_CODE_CE_EXTRACTVAL;
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) { Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
Record.push_back(VE.getTypeID(C->getOperand(i)->getType())); Record.push_back(VE.getValueID(C->getOperand(0)));
Record.push_back(VE.getValueID(C->getOperand(i))); const SmallVector<unsigned, 4> &Indices = CE->getIndices();
} for (unsigned i = 0, e = Indices.size(); i != e; ++i)
Record.push_back(Indices[i]);
break; break;
case Instruction::InsertValue: }
case Instruction::InsertValue: {
Code = bitc::CST_CODE_CE_INSERTVAL; Code = bitc::CST_CODE_CE_INSERTVAL;
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) { Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
Record.push_back(VE.getTypeID(C->getOperand(i)->getType())); Record.push_back(VE.getValueID(C->getOperand(0)));
Record.push_back(VE.getValueID(C->getOperand(i))); Record.push_back(VE.getTypeID(C->getOperand(1)->getType()));
} Record.push_back(VE.getValueID(C->getOperand(1)));
const SmallVector<unsigned, 4> &Indices = CE->getIndices();
for (unsigned i = 0, e = Indices.size(); i != e; ++i)
Record.push_back(Indices[i]);
break; break;
}
case Instruction::Select: case Instruction::Select:
Code = bitc::CST_CODE_CE_SELECT; Code = bitc::CST_CODE_CE_SELECT;
Record.push_back(VE.getValueID(C->getOperand(0))); Record.push_back(VE.getValueID(C->getOperand(0)));

View File

@ -537,15 +537,23 @@ public:
/// Constants.cpp, and is used behind the scenes to implement /// Constants.cpp, and is used behind the scenes to implement
/// extractvalue constant exprs. /// extractvalue constant exprs.
class VISIBILITY_HIDDEN ExtractValueConstantExpr : public ConstantExpr { class VISIBILITY_HIDDEN ExtractValueConstantExpr : public ConstantExpr {
ExtractValueConstantExpr(Constant *Agg, const std::vector<Constant*> &IdxList, void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
const Type *DestTy);
public: public:
static ExtractValueConstantExpr *Create(Constant *Agg, // allocate space for exactly one operand
const std::vector<Constant*> &IdxList, void *operator new(size_t s) {
const Type *DestTy) { return User::operator new(s, 1);
return
new(IdxList.size() + 1) ExtractValueConstantExpr(Agg, IdxList, DestTy);
} }
ExtractValueConstantExpr(Constant *Agg,
const SmallVector<unsigned, 4> &IdxList,
const Type *DestTy)
: ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1),
Indices(IdxList) {
Op<0>() = Agg;
}
/// Indicies - These identify which value to extract.
const SmallVector<unsigned, 4> Indices;
/// Transparently provide more efficient getOperand methods. /// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
}; };
@ -554,17 +562,24 @@ public:
/// Constants.cpp, and is used behind the scenes to implement /// Constants.cpp, and is used behind the scenes to implement
/// insertvalue constant exprs. /// insertvalue constant exprs.
class VISIBILITY_HIDDEN InsertValueConstantExpr : public ConstantExpr { class VISIBILITY_HIDDEN InsertValueConstantExpr : public ConstantExpr {
InsertValueConstantExpr(Constant *Agg, Constant *Val, void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
const std::vector<Constant*> &IdxList,
const Type *DestTy);
public: public:
static InsertValueConstantExpr *Create(Constant *Agg, Constant *Val, // allocate space for exactly one operand
const std::vector<Constant*> &IdxList, void *operator new(size_t s) {
const Type *DestTy) { return User::operator new(s, 2);
return
new(IdxList.size() + 2) InsertValueConstantExpr(Agg, Val,
IdxList, DestTy);
} }
InsertValueConstantExpr(Constant *Agg, Constant *Val,
const SmallVector<unsigned, 4> &IdxList,
const Type *DestTy)
: ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2),
Indices(IdxList) {
Op<0>() = Agg;
Op<1>() = Val;
}
/// Indicies - These identify the position for the insertion.
const SmallVector<unsigned, 4> Indices;
/// Transparently provide more efficient getOperand methods. /// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
}; };
@ -639,45 +654,15 @@ struct OperandTraits<ShuffleVectorConstantExpr> : FixedNumOperandTraits<3> {
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value) DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)
template <> template <>
struct OperandTraits<ExtractValueConstantExpr> : VariadicOperandTraits<1> { struct OperandTraits<ExtractValueConstantExpr> : FixedNumOperandTraits<1> {
}; };
ExtractValueConstantExpr::ExtractValueConstantExpr
(Constant *Agg,
const std::vector<Constant*> &IdxList,
const Type *DestTy)
: ConstantExpr(DestTy, Instruction::ExtractValue,
OperandTraits<ExtractValueConstantExpr>::op_end(this)
- (IdxList.size()+1),
IdxList.size()+1) {
OperandList[0] = Agg;
for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
OperandList[i+1] = IdxList[i];
}
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueConstantExpr, Value) DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueConstantExpr, Value)
template <> template <>
struct OperandTraits<InsertValueConstantExpr> : VariadicOperandTraits<2> { struct OperandTraits<InsertValueConstantExpr> : FixedNumOperandTraits<2> {
}; };
InsertValueConstantExpr::InsertValueConstantExpr
(Constant *Agg, Constant *Val,
const std::vector<Constant*> &IdxList,
const Type *DestTy)
: ConstantExpr(DestTy, Instruction::InsertValue,
OperandTraits<InsertValueConstantExpr>::op_end(this)
- (IdxList.size()+2),
IdxList.size()+2) {
OperandList[0] = Agg;
OperandList[1] = Val;
for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
OperandList[i+2] = IdxList[i];
}
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueConstantExpr, Value) DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueConstantExpr, Value)
template <> template <>
struct OperandTraits<GetElementPtrConstantExpr> : VariadicOperandTraits<1> { struct OperandTraits<GetElementPtrConstantExpr> : VariadicOperandTraits<1> {
}; };
@ -718,6 +703,21 @@ bool ConstantExpr::isCompare() const {
return getOpcode() == Instruction::ICmp || getOpcode() == Instruction::FCmp; return getOpcode() == Instruction::ICmp || getOpcode() == Instruction::FCmp;
} }
bool ConstantExpr::hasIndices() const {
return getOpcode() == Instruction::ExtractValue ||
getOpcode() == Instruction::InsertValue;
}
const SmallVector<unsigned, 4> &ConstantExpr::getIndices() const {
if (const ExtractValueConstantExpr *EVCE =
dyn_cast<ExtractValueConstantExpr>(this))
return EVCE->Indices;
if (const InsertValueConstantExpr *IVCE =
dyn_cast<InsertValueConstantExpr>(this))
return IVCE->Indices;
assert(0 && "ConstantExpr does not have indices!");
}
/// ConstantExpr::get* - Return some common constants without having to /// ConstantExpr::get* - Return some common constants without having to
/// specify the full Instruction::OPCODE identifier. /// specify the full Instruction::OPCODE identifier.
/// ///
@ -829,29 +829,17 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
Op2 = (OpNo == 2) ? Op : getOperand(2); Op2 = (OpNo == 2) ? Op : getOperand(2);
return ConstantExpr::getShuffleVector(Op0, Op1, Op2); return ConstantExpr::getShuffleVector(Op0, Op1, Op2);
case Instruction::InsertValue: { case Instruction::InsertValue: {
SmallVector<Constant*, 8> Ops; const SmallVector<unsigned, 4> Indices = getIndices();
Ops.resize(getNumOperands()-2); Op0 = (OpNo == 0) ? Op : getOperand(0);
for (unsigned i = 2, e = getNumOperands(); i != e; ++i) Op1 = (OpNo == 1) ? Op : getOperand(1);
Ops[i-2] = getOperand(i); return ConstantExpr::getInsertValue(Op0, Op1,
if (OpNo == 0) &Indices[0], Indices.size());
return ConstantExpr::getInsertValue(Op, getOperand(1),
&Ops[0], Ops.size());
if (OpNo == 1)
return ConstantExpr::getInsertValue(getOperand(0), Op,
&Ops[0], Ops.size());
Ops[OpNo-2] = Op;
return ConstantExpr::getInsertValue(getOperand(0), getOperand(1),
&Ops[0], Ops.size());
} }
case Instruction::ExtractValue: { case Instruction::ExtractValue: {
SmallVector<Constant*, 8> Ops; assert(OpNo == 0 && "ExtractaValue has only one operand!");
Ops.resize(getNumOperands()-1); const SmallVector<unsigned, 4> Indices = getIndices();
for (unsigned i = 1, e = getNumOperands(); i != e; ++i) return
Ops[i-1] = getOperand(i); ConstantExpr::getExtractValue(Op, &Indices[0], Indices.size());
if (OpNo == 0)
return ConstantExpr::getExtractValue(Op, &Ops[0], Ops.size());
Ops[OpNo-1] = Op;
return ConstantExpr::getExtractValue(getOperand(0), &Ops[0], Ops.size());
} }
case Instruction::GetElementPtr: { case Instruction::GetElementPtr: {
SmallVector<Constant*, 8> Ops; SmallVector<Constant*, 8> Ops;
@ -908,10 +896,16 @@ getWithOperands(const std::vector<Constant*> &Ops) const {
return ConstantExpr::getExtractElement(Ops[0], Ops[1]); return ConstantExpr::getExtractElement(Ops[0], Ops[1]);
case Instruction::ShuffleVector: case Instruction::ShuffleVector:
return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]);
case Instruction::InsertValue: case Instruction::InsertValue: {
return ConstantExpr::getInsertValue(Ops[0], Ops[1], &Ops[2], Ops.size()-2); const SmallVector<unsigned, 4> Indices = getIndices();
case Instruction::ExtractValue: return ConstantExpr::getInsertValue(Ops[0], Ops[1],
return ConstantExpr::getExtractValue(Ops[0], &Ops[1], Ops.size()-1); &Indices[0], Indices.size());
}
case Instruction::ExtractValue: {
const SmallVector<unsigned, 4> Indices = getIndices();
return ConstantExpr::getExtractValue(Ops[0],
&Indices[0], Indices.size());
}
case Instruction::GetElementPtr: case Instruction::GetElementPtr:
return ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], Ops.size()-1); return ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], Ops.size()-1);
case Instruction::ICmp: case Instruction::ICmp:
@ -1624,21 +1618,30 @@ void UndefValue::destroyConstant() {
namespace { namespace {
struct ExprMapKeyType { struct ExprMapKeyType {
explicit ExprMapKeyType(unsigned opc, std::vector<Constant*> ops, typedef SmallVector<unsigned, 4> IndexList;
unsigned short pred = 0) : opcode(opc), predicate(pred), operands(ops) { }
ExprMapKeyType(unsigned opc,
const std::vector<Constant*> &ops,
unsigned short pred = 0,
const IndexList &inds = IndexList())
: opcode(opc), predicate(pred), operands(ops), indices(inds) {}
uint16_t opcode; uint16_t opcode;
uint16_t predicate; uint16_t predicate;
std::vector<Constant*> operands; std::vector<Constant*> operands;
IndexList indices;
bool operator==(const ExprMapKeyType& that) const { bool operator==(const ExprMapKeyType& that) const {
return this->opcode == that.opcode && return this->opcode == that.opcode &&
this->predicate == that.predicate && this->predicate == that.predicate &&
this->operands == that.operands; this->operands == that.operands;
this->indices == that.indices;
} }
bool operator<(const ExprMapKeyType & that) const { bool operator<(const ExprMapKeyType & that) const {
return this->opcode < that.opcode || return this->opcode < that.opcode ||
(this->opcode == that.opcode && this->predicate < that.predicate) || (this->opcode == that.opcode && this->predicate < that.predicate) ||
(this->opcode == that.opcode && this->predicate == that.predicate && (this->opcode == that.opcode && this->predicate == that.predicate &&
this->operands < that.operands); this->operands < that.operands) ||
(this->opcode == that.opcode && this->predicate == that.predicate &&
this->operands == that.operands && this->indices < that.indices);
} }
bool operator!=(const ExprMapKeyType& that) const { bool operator!=(const ExprMapKeyType& that) const {
@ -1669,15 +1672,11 @@ namespace llvm {
if (V.opcode == Instruction::ShuffleVector) if (V.opcode == Instruction::ShuffleVector)
return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1], return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1],
V.operands[2]); V.operands[2]);
if (V.opcode == Instruction::InsertValue) { if (V.opcode == Instruction::InsertValue)
std::vector<Constant*> IdxList(V.operands.begin()+2, V.operands.end()); return new InsertValueConstantExpr(V.operands[0], V.operands[1],
return InsertValueConstantExpr::Create(V.operands[0], V.operands[1], V.indices, Ty);
IdxList, Ty); if (V.opcode == Instruction::ExtractValue)
} return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty);
if (V.opcode == Instruction::ExtractValue) {
std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
return ExtractValueConstantExpr::Create(V.operands[0], IdxList, Ty);
}
if (V.opcode == Instruction::GetElementPtr) { if (V.opcode == Instruction::GetElementPtr) {
std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end()); std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty); return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty);
@ -1756,7 +1755,9 @@ static ExprMapKeyType getValType(ConstantExpr *CE) {
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
Operands.push_back(cast<Constant>(CE->getOperand(i))); Operands.push_back(cast<Constant>(CE->getOperand(i)));
return ExprMapKeyType(CE->getOpcode(), Operands, return ExprMapKeyType(CE->getOpcode(), Operands,
CE->isCompare() ? CE->getPredicate() : 0); CE->isCompare() ? CE->getPredicate() : 0,
CE->hasIndices() ?
CE->getIndices() : SmallVector<unsigned, 4>());
} }
static ManagedStatic<ValueMap<ExprMapKeyType, Type, static ManagedStatic<ValueMap<ExprMapKeyType, Type,
@ -2298,31 +2299,26 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2,
Constant *ConstantExpr::getInsertValueTy(const Type *ReqTy, Constant *Agg, Constant *ConstantExpr::getInsertValueTy(const Type *ReqTy, Constant *Agg,
Constant *Val, Constant *Val,
Constant *const *Idxs, unsigned NumIdx) { const unsigned *Idxs, unsigned NumIdx) {
assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs, assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs,
Idxs+NumIdx) == Val->getType() && Idxs+NumIdx) == Val->getType() &&
"insertvalue indices invalid!"); "insertvalue indices invalid!");
assert(Agg->getType() == ReqTy && assert(Agg->getType() == ReqTy &&
"insertvalue type invalid!"); "insertvalue type invalid!");
if (Constant *FC = ConstantFoldInsertValue(Agg, Val, Idxs, NumIdx))
return FC; // Fold a few common cases...
assert(Agg->getType()->isFirstClassType() && assert(Agg->getType()->isFirstClassType() &&
"Non-first-class type for constant InsertValue expression"); "Non-first-class type for constant InsertValue expression");
// Look up the constant in the table first to ensure uniqueness // Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> ArgVec; std::vector<Constant*> ArgVec;
ArgVec.reserve(NumIdx+2);
ArgVec.push_back(Agg); ArgVec.push_back(Agg);
ArgVec.push_back(Val); ArgVec.push_back(Val);
for (unsigned i = 0; i != NumIdx; ++i) SmallVector<unsigned, 4> Indices(Idxs, Idxs + NumIdx);
ArgVec.push_back(cast<Constant>(Idxs[i])); const ExprMapKeyType Key(Instruction::InsertValue, ArgVec, 0, Indices);
const ExprMapKeyType Key(Instruction::InsertValue, ArgVec);
return ExprConstants->getOrCreate(ReqTy, Key); return ExprConstants->getOrCreate(ReqTy, Key);
} }
Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val, Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val,
Constant* const *IdxList, unsigned NumIdx) { const unsigned *IdxList, unsigned NumIdx) {
assert(Agg->getType()->isFirstClassType() && assert(Agg->getType()->isFirstClassType() &&
"Tried to create insertelement operation on non-first-class type!"); "Tried to create insertelement operation on non-first-class type!");
@ -2334,28 +2330,22 @@ Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val,
} }
Constant *ConstantExpr::getExtractValueTy(const Type *ReqTy, Constant *Agg, Constant *ConstantExpr::getExtractValueTy(const Type *ReqTy, Constant *Agg,
Constant *const *Idxs, unsigned NumIdx) { const unsigned *Idxs, unsigned NumIdx) {
assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs, assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs,
Idxs+NumIdx) == ReqTy && Idxs+NumIdx) == ReqTy &&
"extractvalue indices invalid!"); "extractvalue indices invalid!");
if (Constant *FC = ConstantFoldExtractValue(Agg, Idxs, NumIdx))
return FC; // Fold a few common cases...
assert(Agg->getType()->isFirstClassType() && assert(Agg->getType()->isFirstClassType() &&
"Non-first-class type for constant extractvalue expression"); "Non-first-class type for constant extractvalue expression");
// Look up the constant in the table first to ensure uniqueness // Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> ArgVec; std::vector<Constant*> ArgVec;
ArgVec.reserve(NumIdx+1);
ArgVec.push_back(Agg); ArgVec.push_back(Agg);
for (unsigned i = 0; i != NumIdx; ++i) SmallVector<unsigned, 4> Indices;
ArgVec.push_back(cast<Constant>(Idxs[i])); const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec, 0, Indices);
const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec);
return ExprConstants->getOrCreate(ReqTy, Key); return ExprConstants->getOrCreate(ReqTy, Key);
} }
Constant *ConstantExpr::getExtractValue(Constant *Agg, Constant *ConstantExpr::getExtractValue(Constant *Agg,
Constant* const *IdxList, unsigned NumIdx) { const unsigned *IdxList, unsigned NumIdx) {
assert(Agg->getType()->isFirstClassType() && assert(Agg->getType()->isFirstClassType() &&
"Tried to create extractelement operation on non-first-class type!"); "Tried to create extractelement operation on non-first-class type!");
@ -2591,31 +2581,19 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
Replacement = ConstantExpr::getGetElementPtr(Pointer, Replacement = ConstantExpr::getGetElementPtr(Pointer,
&Indices[0], Indices.size()); &Indices[0], Indices.size());
} else if (getOpcode() == Instruction::ExtractValue) { } else if (getOpcode() == Instruction::ExtractValue) {
SmallVector<Constant*, 8> Indices;
Constant *Agg = getOperand(0); Constant *Agg = getOperand(0);
Indices.reserve(getNumOperands()-1);
if (Agg == From) Agg = To; if (Agg == From) Agg = To;
for (unsigned i = 1, e = getNumOperands(); i != e; ++i) { const SmallVector<unsigned, 4> &Indices = getIndices();
Constant *Val = getOperand(i);
if (Val == From) Val = To;
Indices.push_back(Val);
}
Replacement = ConstantExpr::getExtractValue(Agg, Replacement = ConstantExpr::getExtractValue(Agg,
&Indices[0], Indices.size()); &Indices[0], Indices.size());
} else if (getOpcode() == Instruction::InsertValue) { } else if (getOpcode() == Instruction::InsertValue) {
SmallVector<Constant*, 8> Indices;
Constant *Agg = getOperand(0); Constant *Agg = getOperand(0);
Constant *Val = getOperand(1); Constant *Val = getOperand(1);
Indices.reserve(getNumOperands()-2);
if (Agg == From) Agg = To; if (Agg == From) Agg = To;
if (Val == From) Val = To; if (Val == From) Val = To;
for (unsigned i = 2, e = getNumOperands(); i != e; ++i) { const SmallVector<unsigned, 4> &Indices = getIndices();
Constant *Val = getOperand(i);
if (Val == From) Val = To;
Indices.push_back(Val);
}
Replacement = ConstantExpr::getInsertValue(Agg, Val, Replacement = ConstantExpr::getInsertValue(Agg, Val,
&Indices[0], Indices.size()); &Indices[0], Indices.size());
} else if (isCast()) { } else if (isCast()) {

View File

@ -1058,7 +1058,22 @@ const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
if (NumIdx == 0) if (NumIdx == 0)
return Agg; return Agg;
return ExtractValueInst::getIndexedType(Agg, Idxs+1, Idxs+NumIdx); unsigned CurIdx = 1;
for (; CurIdx != NumIdx; ++CurIdx) {
const CompositeType *CT = dyn_cast<CompositeType>(Agg);
if (!CT || isa<PointerType>(CT)) return 0;
Value *Index = Idxs[CurIdx];
if (!CT->indexValid(Index)) return 0;
Agg = CT->getTypeAtIndex(Index);
// If the new type forwards to another type, then it is in the middle
// of being refined to another type (and hence, may have dropped all
// references to what it was using before). So, use the new forwarded
// type.
if (const Type *Ty = Agg->getForwardedType())
Agg = Ty;
}
return CurIdx == NumIdx ? Agg : 0;
} }
const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) { const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) {
@ -1335,64 +1350,51 @@ int ShuffleVectorInst::getMaskValue(unsigned i) const {
// InsertValueInst Class // InsertValueInst Class
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
void InsertValueInst::init(Value *Agg, Value *Val, Value* const *Idx, unsigned NumIdx) { void InsertValueInst::init(Value *Agg, Value *Val,
assert(NumOperands == 1+NumIdx && "NumOperands not initialized?"); const unsigned *Idx, unsigned NumIdx) {
Use *OL = OperandList; assert(NumOperands == 2 && "NumOperands not initialized?");
OL[0] = Agg; Op<0>() = Agg;
OL[1] = Val; Op<1>() = Val;
for (unsigned i = 0; i != NumIdx; ++i) Indices.insert(Indices.end(), Idx, Idx + NumIdx);
OL[i+2] = Idx[i];
} }
void InsertValueInst::init(Value *Agg, Value *Val, Value *Idx) { void InsertValueInst::init(Value *Agg, Value *Val, unsigned Idx) {
assert(NumOperands == 3 && "NumOperands not initialized?"); assert(NumOperands == 2 && "NumOperands not initialized?");
Use *OL = OperandList; Op<0>() = Agg;
OL[0] = Agg; Op<1>() = Val;
OL[1] = Val;
OL[2] = Idx; Indices.push_back(Idx);
} }
InsertValueInst::InsertValueInst(const InsertValueInst &IVI) InsertValueInst::InsertValueInst(const InsertValueInst &IVI)
: Instruction(IVI.getType(), InsertValue, : Instruction(IVI.getType(), InsertValue,
OperandTraits<InsertValueInst>::op_end(this) OperandTraits<InsertValueInst>::op_begin(this), 2),
- IVI.getNumOperands(), Indices(IVI.Indices) {
IVI.getNumOperands()) {
Use *OL = OperandList;
Use *IVIOL = IVI.OperandList;
for (unsigned i = 0, E = NumOperands; i != E; ++i)
OL[i] = IVIOL[i];
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ExtractValueInst Class // ExtractValueInst Class
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
void ExtractValueInst::init(Value *Agg, Value* const *Idx, unsigned NumIdx) { void ExtractValueInst::init(Value *Agg, const unsigned *Idx, unsigned NumIdx) {
assert(NumOperands == 1+NumIdx && "NumOperands not initialized?"); assert(NumOperands == 1 && "NumOperands not initialized?");
Use *OL = OperandList; Op<0>() = Agg;
OL[0] = Agg;
for (unsigned i = 0; i != NumIdx; ++i) Indices.insert(Indices.end(), Idx, Idx + NumIdx);
OL[i+1] = Idx[i];
} }
void ExtractValueInst::init(Value *Agg, Value *Idx) { void ExtractValueInst::init(Value *Agg, unsigned Idx) {
assert(NumOperands == 2 && "NumOperands not initialized?"); assert(NumOperands == 1 && "NumOperands not initialized?");
Use *OL = OperandList; Op<0>() = Agg;
OL[0] = Agg;
OL[1] = Idx; Indices.push_back(Idx);
} }
ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI) ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
: Instruction(reinterpret_cast<const Type*>(EVI.getType()), ExtractValue, : Instruction(reinterpret_cast<const Type*>(EVI.getType()), ExtractValue,
OperandTraits<ExtractValueInst>::op_end(this) OperandTraits<ExtractValueInst>::op_begin(this), 1),
- EVI.getNumOperands(), Indices(EVI.Indices) {
EVI.getNumOperands()) {
Use *OL = OperandList;
Use *EVIOL = EVI.OperandList;
for (unsigned i = 0, E = NumOperands; i != E; ++i)
OL[i] = EVIOL[i];
} }
// getIndexedType - Returns the type of the element that would be extracted // getIndexedType - Returns the type of the element that would be extracted
@ -1402,13 +1404,13 @@ ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
// pointer type. // pointer type.
// //
const Type* ExtractValueInst::getIndexedType(const Type *Agg, const Type* ExtractValueInst::getIndexedType(const Type *Agg,
Value* const *Idxs, const unsigned *Idxs,
unsigned NumIdx) { unsigned NumIdx) {
unsigned CurIdx = 0; unsigned CurIdx = 0;
for (; CurIdx != NumIdx; ++CurIdx) { for (; CurIdx != NumIdx; ++CurIdx) {
const CompositeType *CT = dyn_cast<CompositeType>(Agg); const CompositeType *CT = dyn_cast<CompositeType>(Agg);
if (!CT || isa<PointerType>(CT)) return 0; if (!CT || isa<PointerType>(CT) || isa<VectorType>(CT)) return 0;
Value *Index = Idxs[CurIdx]; unsigned Index = Idxs[CurIdx];
if (!CT->indexValid(Index)) return 0; if (!CT->indexValid(Index)) return 0;
Agg = CT->getTypeAtIndex(Index); Agg = CT->getTypeAtIndex(Index);
@ -2869,10 +2871,10 @@ VICmpInst* VICmpInst::clone() const {
} }
ExtractValueInst *ExtractValueInst::clone() const { ExtractValueInst *ExtractValueInst::clone() const {
return new(getNumOperands()) ExtractValueInst(*this); return new ExtractValueInst(*this);
} }
InsertValueInst *InsertValueInst::clone() const { InsertValueInst *InsertValueInst::clone() const {
return new(getNumOperands()) InsertValueInst(*this); return new InsertValueInst(*this);
} }

View File

@ -396,16 +396,24 @@ bool StructType::indexValid(const Value *V) const {
// Structure indexes require 32-bit integer constants. // Structure indexes require 32-bit integer constants.
if (V->getType() == Type::Int32Ty) if (V->getType() == Type::Int32Ty)
if (const ConstantInt *CU = dyn_cast<ConstantInt>(V)) if (const ConstantInt *CU = dyn_cast<ConstantInt>(V))
return CU->getZExtValue() < NumContainedTys; return indexValid(CU->getZExtValue());
return false; return false;
} }
bool StructType::indexValid(unsigned V) const {
return V < NumContainedTys;
}
// getTypeAtIndex - Given an index value into the type, return the type of the // getTypeAtIndex - Given an index value into the type, return the type of the
// element. For a structure type, this must be a constant value... // element. For a structure type, this must be a constant value...
// //
const Type *StructType::getTypeAtIndex(const Value *V) const { const Type *StructType::getTypeAtIndex(const Value *V) const {
assert(indexValid(V) && "Invalid structure index!");
unsigned Idx = (unsigned)cast<ConstantInt>(V)->getZExtValue(); unsigned Idx = (unsigned)cast<ConstantInt>(V)->getZExtValue();
return getTypeAtIndex(Idx);
}
const Type *StructType::getTypeAtIndex(unsigned Idx) const {
assert(indexValid(Idx) && "Invalid structure index!");
return ContainedTys[Idx]; return ContainedTys[Idx];
} }

View File

@ -1,13 +1,13 @@
; RUN: llvm-as < %s ; RUN: llvm-as < %s
;define float @foo({{i32},{float, double}}* %p) { define float @foo({{i32},{float, double}}* %p) {
;%t = load {{i32},{float, double}}* %p %t = load {{i32},{float, double}}* %p
;%s = extractvalue {{i32},{float, double}} %t, i32 1, i32 0 %s = extractvalue {{i32},{float, double}} %t, 1, 0
;%r = insertvalue {{i32},{float, double}} %t, double 2.0, i32 1, i32 1 %r = insertvalue {{i32},{float, double}} %t, double 2.0, 1, 1
;store {{i32},{float, double}} %r, {{i32},{float, double}}* %p store {{i32},{float, double}} %r, {{i32},{float, double}}* %p
;ret float %s ret float %s
;} }
define float @bar({{i32},{float, double}}* %p) { define float @bar({{i32},{float, double}}* %p) {
store {{i32},{float, double}} insertvalue ({{i32},{float, double}}{{i32}{i32 4},{float, double}{float 4.0, double 5.0}}, double 20.0, i32 1, i32 1), {{i32},{float, double}}* %p store {{i32},{float, double}} insertvalue ({{i32},{float, double}}{{i32}{i32 4},{float, double}{float 4.0, double 5.0}}, double 20.0, 1, 1), {{i32},{float, double}}* %p
ret float extractvalue ({{i32},{float, double}}{{i32}{i32 3},{float, double}{float 7.0, double 9.0}}, i32 1, i32 0) ret float extractvalue ({{i32},{float, double}}{{i32}{i32 3},{float, double}{float 7.0, double 9.0}}, 1, 0)
} }