1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

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.

llvm-svn: 51806
This commit is contained in:
Dan Gohman 2008-05-31 00:58:22 +00:00
parent ce2c3b07ba
commit ac5c3382fe
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
value of <a href="#t_struct">struct</a> or <a href="#t_array">array</a>
type. The operands are constant indices to specify which value to extract
in the same manner as indices in a
in a similar manner as indices in a
'<tt><a href="#i_getelementptr">getelementptr</a></tt>' instruction.
</p>
@ -2932,7 +2932,7 @@ the index operands.
<h5>Example:</h5>
<pre>
%result = extractvalue {i32, float} %agg, i32 0 <i>; yields i32</i>
%result = extractvalue {i32, float} %agg, 0 <i>; yields i32</i>
</pre>
</div>
@ -2947,7 +2947,7 @@ the index operands.
<h5>Syntax:</h5>
<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>
<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.
The second operand is a first-class value to insert.
The following operands are constant indices
indicating the position at which to insert the value in the same manner as
indicating the position at which to insert the value in a similar manner as
indices in a
'<tt><a href="#i_getelementptr">getelementptr</a></tt>' instruction.
The value to insert must have the same type as the value identified
@ -2982,7 +2982,7 @@ specified by the indices is that of <tt>elt</tt>.
<h5>Example:</h5>
<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>
</div>

View File

@ -25,6 +25,7 @@
#include "llvm/OperandTraits.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallVector.h"
namespace llvm {
@ -576,10 +577,10 @@ protected:
static Constant *getShuffleVectorTy(const Type *Ty, Constant *V1,
Constant *V2, Constant *Mask);
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,
Constant *Val,
Constant * const *Idxs, unsigned NumIdxs);
const unsigned *Idxs, unsigned NumIdxs);
public:
// 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
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
///
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 *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask);
static Constant *getExtractValue(Constant *Agg,
Constant* const *IdxList, unsigned NumIdx);
const unsigned *IdxList, unsigned NumIdx);
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
/// method returns the negative zero constant for floating point or vector
@ -732,6 +737,10 @@ public:
/// not an ICMP or FCMP constant expression.
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.
const char *getOpcodeName() const;

View File

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

View File

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

View File

@ -963,6 +963,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
llvm::PATypeHolder *TypeVal;
llvm::Value *ValueVal;
std::vector<llvm::Value*> *ValueList;
std::vector<unsigned> *ConstantList;
llvm::ArgListType *ArgList;
llvm::TypeWithAttrs TypeWithAttrs;
llvm::TypeWithAttrsList *TypeWithAttrsList;
@ -1008,6 +1009,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
%type <PHIList> PHIList
%type <ParamList> ParamList // For call param lists & GEP indices
%type <ValueList> IndexList // For GEP indices
%type <ConstantList> ConstantIndexList // For insertvalue/extractvalue indices
%type <TypeList> TypeListI
%type <TypeWithAttrsList> ArgTypeList ArgTypeListI
%type <TypeWithAttrs> ArgType
@ -1974,46 +1976,20 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
$$ = ConstantExpr::getShuffleVector($3, $5, $7);
CHECK_FOR_ERROR
}
| EXTRACTVALUE '(' ConstVal IndexList ')' {
| EXTRACTVALUE '(' ConstVal ConstantIndexList ')' {
if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
GEN_ERROR("ExtractValue requires an aggregate operand");
const Type *IdxTy =
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");
$$ = ConstantExpr::getExtractValue($3, &(*$4)[0], $4->size());
delete $4;
$$ = ConstantExpr::getExtractValue($3, &IdxVec[0], IdxVec.size());
CHECK_FOR_ERROR
}
| INSERTVALUE '(' ConstVal ',' ConstVal IndexList ')' {
| INSERTVALUE '(' ConstVal ',' ConstVal ConstantIndexList ')' {
if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
GEN_ERROR("InsertValue requires an aggregate operand");
const Type *IdxTy =
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");
$$ = ConstantExpr::getInsertValue($3, $5, &(*$6)[0], $6->size());
delete $6;
$$ = ConstantExpr::getInsertValue($3, $5, &IdxVec[0], IdxVec.size());
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 {
$$ = true;
CHECK_FOR_ERROR
@ -3245,7 +3237,7 @@ MemoryInst : MALLOC Types OptCAlign {
delete $2;
delete $4;
}
| EXTRACTVALUE Types ValueRef IndexList {
| EXTRACTVALUE Types ValueRef ConstantIndexList {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))
@ -3260,7 +3252,7 @@ MemoryInst : MALLOC Types OptCAlign {
delete $2;
delete $4;
}
| INSERTVALUE Types ValueRef ',' Types ValueRef IndexList {
| INSERTVALUE Types ValueRef ',' Types ValueRef ConstantIndexList {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
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");
return 0;
}
if (Ty == Type::LabelTy) {
GenerateError("Cannot declare global vars of label type");
return 0;
}
const PointerType *PTy = PointerType::get(Ty, AddressSpace);
@ -959,6 +963,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
llvm::PATypeHolder *TypeVal;
llvm::Value *ValueVal;
std::vector<llvm::Value*> *ValueList;
std::vector<unsigned> *ConstantList;
llvm::ArgListType *ArgList;
llvm::TypeWithAttrs TypeWithAttrs;
llvm::TypeWithAttrsList *TypeWithAttrsList;
@ -1004,6 +1009,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
%type <PHIList> PHIList
%type <ParamList> ParamList // For call param lists & GEP indices
%type <ValueList> IndexList // For GEP indices
%type <ConstantList> ConstantIndexList // For insertvalue/extractvalue indices
%type <TypeList> TypeListI
%type <TypeWithAttrsList> ArgTypeList ArgTypeListI
%type <TypeWithAttrs> ArgType
@ -1402,7 +1408,7 @@ Types
}
| '[' EUINT64VAL 'x' Types ']' { // Sized array type?
$$ = new PATypeHolder(HandleUpRefs(ArrayType::get(*$4, (unsigned)$2)));
$$ = new PATypeHolder(HandleUpRefs(ArrayType::get(*$4, $2)));
delete $4;
CHECK_FOR_ERROR
}
@ -1850,12 +1856,14 @@ ConstVal: Types '[' ConstVector ']' { // Nonempty unsized arr
CHECK_FOR_ERROR
}
| 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();
CHECK_FOR_ERROR
}
| 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();
CHECK_FOR_ERROR
}
@ -1968,46 +1976,20 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
$$ = ConstantExpr::getShuffleVector($3, $5, $7);
CHECK_FOR_ERROR
}
| EXTRACTVALUE '(' ConstVal IndexList ')' {
| EXTRACTVALUE '(' ConstVal ConstantIndexList ')' {
if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
GEN_ERROR("ExtractValue requires an aggregate operand");
const Type *IdxTy =
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");
$$ = ConstantExpr::getExtractValue($3, &(*$4)[0], $4->size());
delete $4;
$$ = ConstantExpr::getExtractValue($3, &IdxVec[0], IdxVec.size());
CHECK_FOR_ERROR
}
| INSERTVALUE '(' ConstVal ',' ConstVal IndexList ')' {
| INSERTVALUE '(' ConstVal ',' ConstVal ConstantIndexList ')' {
if (!isa<StructType>($3->getType()) && !isa<ArrayType>($3->getType()))
GEN_ERROR("InsertValue requires an aggregate operand");
const Type *IdxTy =
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");
$$ = ConstantExpr::getInsertValue($3, $5, &(*$6)[0], $6->size());
delete $6;
$$ = ConstantExpr::getInsertValue($3, $5, &IdxVec[0], IdxVec.size());
CHECK_FOR_ERROR
};
@ -2250,8 +2232,8 @@ LibList : LibList ',' STRINGCONSTANT {
ArgListH : ArgListH ',' Types OptParamAttrs OptLocalName {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
if (*$3 == Type::VoidTy)
GEN_ERROR("void typed arguments are invalid");
if (!(*$3)->isFirstClassType())
GEN_ERROR("Argument types must be first-class");
ArgListEntry E; E.Attrs = $4; E.Ty = $3; E.Name = $5;
$$ = $1;
$1->push_back(E);
@ -2260,8 +2242,8 @@ ArgListH : ArgListH ',' Types OptParamAttrs OptLocalName {
| Types OptParamAttrs OptLocalName {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
if (*$1 == Type::VoidTy)
GEN_ERROR("void typed arguments are invalid");
if (!(*$1)->isFirstClassType())
GEN_ERROR("Argument types must be first-class");
ArgListEntry E; E.Attrs = $2; E.Ty = $1; E.Name = $3;
$$ = new ArgListType;
$$->push_back(E);
@ -2498,6 +2480,9 @@ ConstValueRef : ESINT64VAL { // A reference to a direct constant
| '<' ConstVector '>' { // Nonempty unsized packed vector
const Type *ETy = (*$2)[0]->getType();
int NumElements = $2->size();
if (!ETy->isInteger() && !ETy->isFloatingPoint())
GEN_ERROR("Invalid vector element type: " + ETy->getDescription());
VectorType* pt = VectorType::get(ETy, NumElements);
PATypeHolder* PTy = new PATypeHolder(
@ -2639,7 +2624,8 @@ BBTerminatorInst :
$$ = BranchInst::Create(tmpBB);
} // Conditional Branch...
| 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);
CHECK_FOR_ERROR
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 {
$$ = true;
CHECK_FOR_ERROR
@ -3149,6 +3151,8 @@ MemoryInst : MALLOC Types OptCAlign {
| MALLOC Types ',' INTTYPE ValueRef OptCAlign {
if (!UpRefs.empty())
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);
CHECK_FOR_ERROR
$$ = new MallocInst(*$2, tmpVal, $6);
@ -3164,6 +3168,8 @@ MemoryInst : MALLOC Types OptCAlign {
| ALLOCA Types ',' INTTYPE ValueRef OptCAlign {
if (!UpRefs.empty())
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);
CHECK_FOR_ERROR
$$ = new AllocaInst(*$2, tmpVal, $6);
@ -3231,7 +3237,7 @@ MemoryInst : MALLOC Types OptCAlign {
delete $2;
delete $4;
}
| EXTRACTVALUE Types ValueRef IndexList {
| EXTRACTVALUE Types ValueRef ConstantIndexList {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
if (!isa<StructType>($2->get()) && !isa<ArrayType>($2->get()))
@ -3246,7 +3252,7 @@ MemoryInst : MALLOC Types OptCAlign {
delete $2;
delete $4;
}
| INSERTVALUE Types ValueRef ',' Types ValueRef IndexList {
| INSERTVALUE Types ValueRef ',' Types ValueRef ConstantIndexList {
if (!UpRefs.empty())
GEN_ERROR("Invalid upreference in type: " + (*$2)->getDescription());
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);
break;
}
case bitc::CST_CODE_CE_EXTRACTVAL: { // CE_EXTRACTVAL: [n x operands]
if (Record.size() & 1) return Error("Invalid CE_EXTRACTVAL record");
SmallVector<Constant*, 16> Elts;
for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
const Type *ElTy = getTypeByID(Record[i]);
if (!ElTy) return Error("Invalid CE_EXTRACTVAL record");
Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
case bitc::CST_CODE_CE_EXTRACTVAL: {
// CE_EXTRACTVAL: [opty, opval, n x indices]
const Type *AggTy = getTypeByID(Record[0]);
if (!AggTy || !AggTy->isAggregateType())
return Error("Invalid CE_INSERTVAL record");
Constant *Agg = ValueList.getConstantFwdRef(Record[1], AggTy);
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;
}
case bitc::CST_CODE_CE_INSERTVAL: { // CE_INSERTVAL: [n x operands]
if (Record.size() & 1) return Error("Invalid CE_INSERTVAL record");
SmallVector<Constant*, 16> Elts;
for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
const Type *ElTy = getTypeByID(Record[i]);
if (!ElTy) return Error("Invalid CE_INSERTVAL record");
Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
case bitc::CST_CODE_CE_INSERTVAL: {
// CE_INSERTVAL: [opty, opval, opty, opval, n x indices]
const Type *AggTy = getTypeByID(Record[0]);
if (!AggTy || !AggTy->isAggregateType())
return Error("Invalid CE_INSERTVAL record");
Constant *Agg = ValueList.getConstantFwdRef(Record[1], AggTy);
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],
&Elts[2], Elts.size()-1);
if (ExtractValueInst::getIndexedType(AggTy,
Indices.begin(),
Indices.end()) != ValTy)
return Error("Invalid CE_INSERTVAL record");
V = ConstantExpr::getInsertValue(Agg, Val, &Indices[0], Indices.size());
break;
}
case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#]
@ -1324,18 +1342,20 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
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;
Value *Agg;
if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
return Error("Invalid EXTRACTVAL record");
SmallVector<Value*, 16> EXTRACTVALIdx;
while (OpNum != Record.size()) {
Value *Op;
if (getValueTypePair(Record, OpNum, NextValueNo, Op))
return Error("Invalid EXTRACTVAL record");
EXTRACTVALIdx.push_back(Op);
SmallVector<unsigned, 4> EXTRACTVALIdx;
for (unsigned RecSize = Record.size();
OpNum != RecSize; ++OpNum) {
uint64_t Index = Record[OpNum];
if ((unsigned)Index != Index)
return Error("Invalid EXTRACTVAL index");
EXTRACTVALIdx.push_back((unsigned)Index);
}
I = ExtractValueInst::Create(Agg,
@ -1343,7 +1363,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
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;
Value *Agg;
if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
@ -1352,12 +1373,13 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
if (getValueTypePair(Record, OpNum, NextValueNo, Val))
return Error("Invalid INSERTVAL record");
SmallVector<Value*, 16> INSERTVALIdx;
while (OpNum != Record.size()) {
Value *Op;
if (getValueTypePair(Record, OpNum, NextValueNo, Op))
return Error("Invalid INSERTVAL record");
INSERTVALIdx.push_back(Op);
SmallVector<unsigned, 4> INSERTVALIdx;
for (unsigned RecSize = Record.size();
OpNum != RecSize; ++OpNum) {
uint64_t Index = Record[OpNum];
if ((unsigned)Index != Index)
return Error("Invalid INSERTVAL index");
INSERTVALIdx.push_back((unsigned)Index);
}
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)));
}
break;
case Instruction::ExtractValue:
case Instruction::ExtractValue: {
Code = bitc::CST_CODE_CE_EXTRACTVAL;
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
Record.push_back(VE.getTypeID(C->getOperand(i)->getType()));
Record.push_back(VE.getValueID(C->getOperand(i)));
}
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
Record.push_back(VE.getValueID(C->getOperand(0)));
const SmallVector<unsigned, 4> &Indices = CE->getIndices();
for (unsigned i = 0, e = Indices.size(); i != e; ++i)
Record.push_back(Indices[i]);
break;
case Instruction::InsertValue:
}
case Instruction::InsertValue: {
Code = bitc::CST_CODE_CE_INSERTVAL;
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
Record.push_back(VE.getTypeID(C->getOperand(i)->getType()));
Record.push_back(VE.getValueID(C->getOperand(i)));
}
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
Record.push_back(VE.getValueID(C->getOperand(0)));
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;
}
case Instruction::Select:
Code = bitc::CST_CODE_CE_SELECT;
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
/// extractvalue constant exprs.
class VISIBILITY_HIDDEN ExtractValueConstantExpr : public ConstantExpr {
ExtractValueConstantExpr(Constant *Agg, const std::vector<Constant*> &IdxList,
const Type *DestTy);
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
public:
static ExtractValueConstantExpr *Create(Constant *Agg,
const std::vector<Constant*> &IdxList,
const Type *DestTy) {
return
new(IdxList.size() + 1) ExtractValueConstantExpr(Agg, IdxList, DestTy);
// allocate space for exactly one operand
void *operator new(size_t s) {
return User::operator new(s, 1);
}
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.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
@ -554,17 +562,24 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// insertvalue constant exprs.
class VISIBILITY_HIDDEN InsertValueConstantExpr : public ConstantExpr {
InsertValueConstantExpr(Constant *Agg, Constant *Val,
const std::vector<Constant*> &IdxList,
const Type *DestTy);
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
public:
static InsertValueConstantExpr *Create(Constant *Agg, Constant *Val,
const std::vector<Constant*> &IdxList,
const Type *DestTy) {
return
new(IdxList.size() + 2) InsertValueConstantExpr(Agg, Val,
IdxList, DestTy);
// allocate space for exactly one operand
void *operator new(size_t s) {
return User::operator new(s, 2);
}
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.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
@ -639,45 +654,15 @@ struct OperandTraits<ShuffleVectorConstantExpr> : FixedNumOperandTraits<3> {
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)
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)
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)
template <>
struct OperandTraits<GetElementPtrConstantExpr> : VariadicOperandTraits<1> {
};
@ -718,6 +703,21 @@ bool ConstantExpr::isCompare() const {
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
/// specify the full Instruction::OPCODE identifier.
///
@ -829,29 +829,17 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
Op2 = (OpNo == 2) ? Op : getOperand(2);
return ConstantExpr::getShuffleVector(Op0, Op1, Op2);
case Instruction::InsertValue: {
SmallVector<Constant*, 8> Ops;
Ops.resize(getNumOperands()-2);
for (unsigned i = 2, e = getNumOperands(); i != e; ++i)
Ops[i-2] = getOperand(i);
if (OpNo == 0)
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());
const SmallVector<unsigned, 4> Indices = getIndices();
Op0 = (OpNo == 0) ? Op : getOperand(0);
Op1 = (OpNo == 1) ? Op : getOperand(1);
return ConstantExpr::getInsertValue(Op0, Op1,
&Indices[0], Indices.size());
}
case Instruction::ExtractValue: {
SmallVector<Constant*, 8> Ops;
Ops.resize(getNumOperands()-1);
for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
Ops[i-1] = getOperand(i);
if (OpNo == 0)
return ConstantExpr::getExtractValue(Op, &Ops[0], Ops.size());
Ops[OpNo-1] = Op;
return ConstantExpr::getExtractValue(getOperand(0), &Ops[0], Ops.size());
assert(OpNo == 0 && "ExtractaValue has only one operand!");
const SmallVector<unsigned, 4> Indices = getIndices();
return
ConstantExpr::getExtractValue(Op, &Indices[0], Indices.size());
}
case Instruction::GetElementPtr: {
SmallVector<Constant*, 8> Ops;
@ -908,10 +896,16 @@ getWithOperands(const std::vector<Constant*> &Ops) const {
return ConstantExpr::getExtractElement(Ops[0], Ops[1]);
case Instruction::ShuffleVector:
return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]);
case Instruction::InsertValue:
return ConstantExpr::getInsertValue(Ops[0], Ops[1], &Ops[2], Ops.size()-2);
case Instruction::ExtractValue:
return ConstantExpr::getExtractValue(Ops[0], &Ops[1], Ops.size()-1);
case Instruction::InsertValue: {
const SmallVector<unsigned, 4> Indices = getIndices();
return ConstantExpr::getInsertValue(Ops[0], Ops[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:
return ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], Ops.size()-1);
case Instruction::ICmp:
@ -1624,21 +1618,30 @@ void UndefValue::destroyConstant() {
namespace {
struct ExprMapKeyType {
explicit ExprMapKeyType(unsigned opc, std::vector<Constant*> ops,
unsigned short pred = 0) : opcode(opc), predicate(pred), operands(ops) { }
typedef SmallVector<unsigned, 4> IndexList;
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 predicate;
std::vector<Constant*> operands;
IndexList indices;
bool operator==(const ExprMapKeyType& that) const {
return this->opcode == that.opcode &&
this->predicate == that.predicate &&
this->operands == that.operands;
this->indices == that.indices;
}
bool operator<(const ExprMapKeyType & that) const {
return this->opcode < that.opcode ||
(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 {
@ -1669,15 +1672,11 @@ namespace llvm {
if (V.opcode == Instruction::ShuffleVector)
return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1],
V.operands[2]);
if (V.opcode == Instruction::InsertValue) {
std::vector<Constant*> IdxList(V.operands.begin()+2, V.operands.end());
return InsertValueConstantExpr::Create(V.operands[0], V.operands[1],
IdxList, 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::InsertValue)
return new InsertValueConstantExpr(V.operands[0], V.operands[1],
V.indices, Ty);
if (V.opcode == Instruction::ExtractValue)
return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty);
if (V.opcode == Instruction::GetElementPtr) {
std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
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)
Operands.push_back(cast<Constant>(CE->getOperand(i)));
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,
@ -2298,31 +2299,26 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2,
Constant *ConstantExpr::getInsertValueTy(const Type *ReqTy, Constant *Agg,
Constant *Val,
Constant *const *Idxs, unsigned NumIdx) {
const unsigned *Idxs, unsigned NumIdx) {
assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs,
Idxs+NumIdx) == Val->getType() &&
"insertvalue indices invalid!");
assert(Agg->getType() == ReqTy &&
"insertvalue type invalid!");
if (Constant *FC = ConstantFoldInsertValue(Agg, Val, Idxs, NumIdx))
return FC; // Fold a few common cases...
assert(Agg->getType()->isFirstClassType() &&
"Non-first-class type for constant InsertValue expression");
// Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> ArgVec;
ArgVec.reserve(NumIdx+2);
ArgVec.push_back(Agg);
ArgVec.push_back(Val);
for (unsigned i = 0; i != NumIdx; ++i)
ArgVec.push_back(cast<Constant>(Idxs[i]));
const ExprMapKeyType Key(Instruction::InsertValue, ArgVec);
SmallVector<unsigned, 4> Indices(Idxs, Idxs + NumIdx);
const ExprMapKeyType Key(Instruction::InsertValue, ArgVec, 0, Indices);
return ExprConstants->getOrCreate(ReqTy, Key);
}
Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val,
Constant* const *IdxList, unsigned NumIdx) {
const unsigned *IdxList, unsigned NumIdx) {
assert(Agg->getType()->isFirstClassType() &&
"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 *const *Idxs, unsigned NumIdx) {
const unsigned *Idxs, unsigned NumIdx) {
assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs,
Idxs+NumIdx) == ReqTy &&
"extractvalue indices invalid!");
if (Constant *FC = ConstantFoldExtractValue(Agg, Idxs, NumIdx))
return FC; // Fold a few common cases...
assert(Agg->getType()->isFirstClassType() &&
"Non-first-class type for constant extractvalue expression");
// Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> ArgVec;
ArgVec.reserve(NumIdx+1);
ArgVec.push_back(Agg);
for (unsigned i = 0; i != NumIdx; ++i)
ArgVec.push_back(cast<Constant>(Idxs[i]));
const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec);
SmallVector<unsigned, 4> Indices;
const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec, 0, Indices);
return ExprConstants->getOrCreate(ReqTy, Key);
}
Constant *ConstantExpr::getExtractValue(Constant *Agg,
Constant* const *IdxList, unsigned NumIdx) {
const unsigned *IdxList, unsigned NumIdx) {
assert(Agg->getType()->isFirstClassType() &&
"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,
&Indices[0], Indices.size());
} else if (getOpcode() == Instruction::ExtractValue) {
SmallVector<Constant*, 8> Indices;
Constant *Agg = getOperand(0);
Indices.reserve(getNumOperands()-1);
if (Agg == From) Agg = To;
for (unsigned i = 1, e = getNumOperands(); i != e; ++i) {
Constant *Val = getOperand(i);
if (Val == From) Val = To;
Indices.push_back(Val);
}
const SmallVector<unsigned, 4> &Indices = getIndices();
Replacement = ConstantExpr::getExtractValue(Agg,
&Indices[0], Indices.size());
} else if (getOpcode() == Instruction::InsertValue) {
SmallVector<Constant*, 8> Indices;
Constant *Agg = getOperand(0);
Constant *Val = getOperand(1);
Indices.reserve(getNumOperands()-2);
if (Agg == From) Agg = To;
if (Val == From) Val = To;
for (unsigned i = 2, e = getNumOperands(); i != e; ++i) {
Constant *Val = getOperand(i);
if (Val == From) Val = To;
Indices.push_back(Val);
}
const SmallVector<unsigned, 4> &Indices = getIndices();
Replacement = ConstantExpr::getInsertValue(Agg, Val,
&Indices[0], Indices.size());
} else if (isCast()) {

View File

@ -1058,7 +1058,22 @@ const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
if (NumIdx == 0)
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) {
@ -1335,64 +1350,51 @@ int ShuffleVectorInst::getMaskValue(unsigned i) const {
// InsertValueInst Class
//===----------------------------------------------------------------------===//
void InsertValueInst::init(Value *Agg, Value *Val, Value* const *Idx, unsigned NumIdx) {
assert(NumOperands == 1+NumIdx && "NumOperands not initialized?");
Use *OL = OperandList;
OL[0] = Agg;
OL[1] = Val;
void InsertValueInst::init(Value *Agg, Value *Val,
const unsigned *Idx, unsigned NumIdx) {
assert(NumOperands == 2 && "NumOperands not initialized?");
Op<0>() = Agg;
Op<1>() = Val;
for (unsigned i = 0; i != NumIdx; ++i)
OL[i+2] = Idx[i];
Indices.insert(Indices.end(), Idx, Idx + NumIdx);
}
void InsertValueInst::init(Value *Agg, Value *Val, Value *Idx) {
assert(NumOperands == 3 && "NumOperands not initialized?");
Use *OL = OperandList;
OL[0] = Agg;
OL[1] = Val;
OL[2] = Idx;
void InsertValueInst::init(Value *Agg, Value *Val, unsigned Idx) {
assert(NumOperands == 2 && "NumOperands not initialized?");
Op<0>() = Agg;
Op<1>() = Val;
Indices.push_back(Idx);
}
InsertValueInst::InsertValueInst(const InsertValueInst &IVI)
: Instruction(IVI.getType(), InsertValue,
OperandTraits<InsertValueInst>::op_end(this)
- IVI.getNumOperands(),
IVI.getNumOperands()) {
Use *OL = OperandList;
Use *IVIOL = IVI.OperandList;
for (unsigned i = 0, E = NumOperands; i != E; ++i)
OL[i] = IVIOL[i];
OperandTraits<InsertValueInst>::op_begin(this), 2),
Indices(IVI.Indices) {
}
//===----------------------------------------------------------------------===//
// ExtractValueInst Class
//===----------------------------------------------------------------------===//
void ExtractValueInst::init(Value *Agg, Value* const *Idx, unsigned NumIdx) {
assert(NumOperands == 1+NumIdx && "NumOperands not initialized?");
Use *OL = OperandList;
OL[0] = Agg;
void ExtractValueInst::init(Value *Agg, const unsigned *Idx, unsigned NumIdx) {
assert(NumOperands == 1 && "NumOperands not initialized?");
Op<0>() = Agg;
for (unsigned i = 0; i != NumIdx; ++i)
OL[i+1] = Idx[i];
Indices.insert(Indices.end(), Idx, Idx + NumIdx);
}
void ExtractValueInst::init(Value *Agg, Value *Idx) {
assert(NumOperands == 2 && "NumOperands not initialized?");
Use *OL = OperandList;
OL[0] = Agg;
OL[1] = Idx;
void ExtractValueInst::init(Value *Agg, unsigned Idx) {
assert(NumOperands == 1 && "NumOperands not initialized?");
Op<0>() = Agg;
Indices.push_back(Idx);
}
ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
: Instruction(reinterpret_cast<const Type*>(EVI.getType()), ExtractValue,
OperandTraits<ExtractValueInst>::op_end(this)
- EVI.getNumOperands(),
EVI.getNumOperands()) {
Use *OL = OperandList;
Use *EVIOL = EVI.OperandList;
for (unsigned i = 0, E = NumOperands; i != E; ++i)
OL[i] = EVIOL[i];
OperandTraits<ExtractValueInst>::op_begin(this), 1),
Indices(EVI.Indices) {
}
// getIndexedType - Returns the type of the element that would be extracted
@ -1402,13 +1404,13 @@ ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
// pointer type.
//
const Type* ExtractValueInst::getIndexedType(const Type *Agg,
Value* const *Idxs,
const unsigned *Idxs,
unsigned NumIdx) {
unsigned CurIdx = 0;
for (; CurIdx != NumIdx; ++CurIdx) {
const CompositeType *CT = dyn_cast<CompositeType>(Agg);
if (!CT || isa<PointerType>(CT)) return 0;
Value *Index = Idxs[CurIdx];
if (!CT || isa<PointerType>(CT) || isa<VectorType>(CT)) return 0;
unsigned Index = Idxs[CurIdx];
if (!CT->indexValid(Index)) return 0;
Agg = CT->getTypeAtIndex(Index);
@ -2869,10 +2871,10 @@ VICmpInst* VICmpInst::clone() const {
}
ExtractValueInst *ExtractValueInst::clone() const {
return new(getNumOperands()) ExtractValueInst(*this);
return new ExtractValueInst(*this);
}
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.
if (V->getType() == Type::Int32Ty)
if (const ConstantInt *CU = dyn_cast<ConstantInt>(V))
return CU->getZExtValue() < NumContainedTys;
return indexValid(CU->getZExtValue());
return false;
}
bool StructType::indexValid(unsigned V) const {
return V < NumContainedTys;
}
// getTypeAtIndex - Given an index value into the type, return the type of the
// element. For a structure type, this must be a constant value...
//
const Type *StructType::getTypeAtIndex(const Value *V) const {
assert(indexValid(V) && "Invalid structure index!");
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];
}

View File

@ -1,13 +1,13 @@
; RUN: llvm-as < %s
;define float @foo({{i32},{float, double}}* %p) {
;%t = load {{i32},{float, double}}* %p
;%s = extractvalue {{i32},{float, double}} %t, i32 1, i32 0
;%r = insertvalue {{i32},{float, double}} %t, double 2.0, i32 1, i32 1
;store {{i32},{float, double}} %r, {{i32},{float, double}}* %p
;ret float %s
;}
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
ret float extractvalue ({{i32},{float, double}}{{i32}{i32 3},{float, double}{float 7.0, double 9.0}}, i32 1, i32 0)
define float @foo({{i32},{float, double}}* %p) {
%t = load {{i32},{float, double}}* %p
%s = extractvalue {{i32},{float, double}} %t, 1, 0
%r = insertvalue {{i32},{float, double}} %t, double 2.0, 1, 1
store {{i32},{float, double}} %r, {{i32},{float, double}}* %p
ret float %s
}
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, 1, 1), {{i32},{float, double}}* %p
ret float extractvalue ({{i32},{float, double}}{{i32}{i32 3},{float, double}{float 7.0, double 9.0}}, 1, 0)
}