mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-11 13:37:07 +00:00
IR support for extractvalue and insertvalue instructions. Also, begin
moving toward making structs and arrays first-class types. llvm-svn: 51157
This commit is contained in:
parent
48ac9aec33
commit
821bf58428
@ -575,6 +575,11 @@ protected:
|
||||
Constant *Elt, Constant *Idx);
|
||||
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);
|
||||
static Constant *getInsertValueTy(const Type *Ty, Constant *Agg,
|
||||
Constant *Val,
|
||||
Constant * const *Idxs, unsigned NumIdxs);
|
||||
|
||||
public:
|
||||
// Static methods to construct a ConstantExpr of different kinds. Note that
|
||||
@ -706,6 +711,10 @@ public:
|
||||
static Constant *getExtractElement(Constant *Vec, Constant *Idx);
|
||||
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);
|
||||
static Constant *getInsertValue(Constant *Agg, Constant *Val,
|
||||
Constant* const *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
|
||||
|
@ -161,15 +161,17 @@ HANDLE_OTHER_INST(44, Select , SelectInst ) // select instruction
|
||||
HANDLE_OTHER_INST(45, UserOp1, Instruction) // May be used internally in a pass
|
||||
HANDLE_OTHER_INST(46, UserOp2, Instruction) // Internal to passes only
|
||||
HANDLE_OTHER_INST(47, VAArg , VAArgInst ) // vaarg instruction
|
||||
HANDLE_OTHER_INST(48, ExtractElement, ExtractElementInst)// extract from vector.
|
||||
HANDLE_OTHER_INST(48, ExtractElement, ExtractElementInst)// extract from vector
|
||||
HANDLE_OTHER_INST(49, InsertElement, InsertElementInst) // insert into vector
|
||||
HANDLE_OTHER_INST(50, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
||||
HANDLE_OTHER_INST(51, GetResult, GetResultInst) // Extract individual value
|
||||
//from aggregate result
|
||||
HANDLE_OTHER_INST(52, VICmp , VICmpInst ) // Vec Int comparison instruction.
|
||||
HANDLE_OTHER_INST(53, VFCmp , VFCmpInst ) // Vec FP point comparison instr.
|
||||
HANDLE_OTHER_INST(52, ExtractValue, ExtractValueInst)// extract from aggregate
|
||||
HANDLE_OTHER_INST(53, InsertValue, InsertValueInst) // insert into aggregate
|
||||
HANDLE_OTHER_INST(54, VICmp , VICmpInst ) // Vec Int comparison instruction.
|
||||
HANDLE_OTHER_INST(55, VFCmp , VFCmpInst ) // Vec FP point comparison instr.
|
||||
|
||||
LAST_OTHER_INST(53)
|
||||
LAST_OTHER_INST(55)
|
||||
|
||||
#undef FIRST_TERM_INST
|
||||
#undef HANDLE_TERM_INST
|
||||
|
@ -408,28 +408,23 @@ class GetElementPtrInst : public Instruction {
|
||||
/// pointer type.
|
||||
///
|
||||
static const Type *getIndexedType(const Type *Ptr,
|
||||
Value* const *Idx, unsigned NumIdx,
|
||||
bool AllowStructLeaf = false);
|
||||
Value* const *Idx, unsigned NumIdx);
|
||||
|
||||
template<typename InputIterator>
|
||||
static const Type *getIndexedType(const Type *Ptr,
|
||||
InputIterator IdxBegin,
|
||||
InputIterator IdxEnd,
|
||||
bool AllowStructLeaf,
|
||||
// This argument ensures that we
|
||||
// have an iterator we can do
|
||||
// arithmetic on in constant time
|
||||
std::random_access_iterator_tag) {
|
||||
unsigned NumIdx = static_cast<unsigned>(std::distance(IdxBegin, IdxEnd));
|
||||
|
||||
if (NumIdx > 0) {
|
||||
if (NumIdx > 0)
|
||||
// This requires that the iterator points to contiguous memory.
|
||||
return(getIndexedType(Ptr, (Value *const *)&*IdxBegin, NumIdx,
|
||||
AllowStructLeaf));
|
||||
}
|
||||
else {
|
||||
return(getIndexedType(Ptr, (Value *const*)0, NumIdx, AllowStructLeaf));
|
||||
}
|
||||
return getIndexedType(Ptr, (Value *const *)&*IdxBegin, NumIdx);
|
||||
else
|
||||
return getIndexedType(Ptr, (Value *const*)0, NumIdx);
|
||||
}
|
||||
|
||||
/// Constructors - Create a getelementptr instruction with a base pointer an
|
||||
@ -508,11 +503,10 @@ public:
|
||||
template<typename InputIterator>
|
||||
static const Type *getIndexedType(const Type *Ptr,
|
||||
InputIterator IdxBegin,
|
||||
InputIterator IdxEnd,
|
||||
bool AllowStructLeaf = false) {
|
||||
return(getIndexedType(Ptr, IdxBegin, IdxEnd, AllowStructLeaf,
|
||||
InputIterator IdxEnd) {
|
||||
return getIndexedType(Ptr, IdxBegin, IdxEnd,
|
||||
typename std::iterator_traits<InputIterator>::
|
||||
iterator_category()));
|
||||
iterator_category());
|
||||
}
|
||||
static const Type *getIndexedType(const Type *Ptr, Value *Idx);
|
||||
|
||||
@ -573,7 +567,7 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr,
|
||||
Instruction *InsertBefore)
|
||||
: Instruction(PointerType::get(checkType(
|
||||
getIndexedType(Ptr->getType(),
|
||||
IdxBegin, IdxEnd, true)),
|
||||
IdxBegin, IdxEnd)),
|
||||
cast<PointerType>(Ptr->getType())
|
||||
->getAddressSpace()),
|
||||
GetElementPtr,
|
||||
@ -591,7 +585,7 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr,
|
||||
BasicBlock *InsertAtEnd)
|
||||
: Instruction(PointerType::get(checkType(
|
||||
getIndexedType(Ptr->getType(),
|
||||
IdxBegin, IdxEnd, true)),
|
||||
IdxBegin, IdxEnd)),
|
||||
cast<PointerType>(Ptr->getType())
|
||||
->getAddressSpace()),
|
||||
GetElementPtr,
|
||||
@ -1497,6 +1491,338 @@ struct OperandTraits<ShuffleVectorInst> : FixedNumOperandTraits<3> {
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ExtractValueInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// ExtractValueInst - This instruction extracts a value
|
||||
/// from an aggregate value
|
||||
///
|
||||
class ExtractValueInst : public Instruction {
|
||||
ExtractValueInst(const ExtractValueInst &EVI);
|
||||
void init(Value *Agg, Value* const *Idx, unsigned NumIdx);
|
||||
void init(Value *Agg, Value *Idx);
|
||||
|
||||
template<typename InputIterator>
|
||||
void init(Value *Agg, InputIterator IdxBegin, InputIterator IdxEnd,
|
||||
const std::string &Name,
|
||||
// This argument ensures that we have an iterator we can
|
||||
// do arithmetic on in constant time
|
||||
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);
|
||||
}
|
||||
|
||||
setName(Name);
|
||||
}
|
||||
|
||||
/// getIndexedType - Returns the type of the element that would be extracted
|
||||
/// with an extractvalue instruction with the specified parameters.
|
||||
///
|
||||
/// A null type is returned if the indices are invalid for the specified
|
||||
/// pointer type.
|
||||
///
|
||||
static const Type *getIndexedType(const Type *Agg,
|
||||
Value* const *Idx, unsigned NumIdx);
|
||||
|
||||
template<typename InputIterator>
|
||||
static const Type *getIndexedType(const Type *Ptr,
|
||||
InputIterator IdxBegin,
|
||||
InputIterator IdxEnd,
|
||||
// This argument ensures that we
|
||||
// have an iterator we can do
|
||||
// arithmetic on in constant time
|
||||
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.
|
||||
return getIndexedType(Ptr, (Value *const *)&*IdxBegin, NumIdx);
|
||||
else
|
||||
return getIndexedType(Ptr, (Value *const*)0, NumIdx);
|
||||
}
|
||||
|
||||
/// Constructors - Create a extractvalue instruction with a base pointer an
|
||||
/// list of indices. The first ctor can optionally insert before an existing
|
||||
/// instruction, the second appends the new instruction to the specified
|
||||
/// BasicBlock.
|
||||
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 = "",
|
||||
Instruction *InsertBefore = 0);
|
||||
ExtractValueInst(Value *Agg, Value *Idx,
|
||||
const std::string &Name, BasicBlock *InsertAtEnd);
|
||||
public:
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/// 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,
|
||||
const std::string &Name = "",
|
||||
Instruction *InsertBefore = 0) {
|
||||
return new(2) ExtractValueInst(Agg, Idx, Name, InsertBefore);
|
||||
}
|
||||
static ExtractValueInst *Create(Value *Agg, Value *Idx,
|
||||
const std::string &Name,
|
||||
BasicBlock *InsertAtEnd) {
|
||||
return new(2) ExtractValueInst(Agg, Idx, Name, InsertAtEnd);
|
||||
}
|
||||
|
||||
virtual ExtractValueInst *clone() const;
|
||||
|
||||
/// Transparently provide more efficient getOperand methods.
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
||||
// getType - Overload to return most specific pointer type...
|
||||
const PointerType *getType() const {
|
||||
return reinterpret_cast<const PointerType*>(Instruction::getType());
|
||||
}
|
||||
|
||||
/// getIndexedType - Returns the type of the element that would be extracted
|
||||
/// with an extractvalue instruction with the specified parameters.
|
||||
///
|
||||
/// A null type is returned if the indices are invalid for the specified
|
||||
/// pointer type.
|
||||
///
|
||||
template<typename InputIterator>
|
||||
static const Type *getIndexedType(const Type *Ptr,
|
||||
InputIterator IdxBegin,
|
||||
InputIterator IdxEnd) {
|
||||
return getIndexedType(Ptr, IdxBegin, IdxEnd,
|
||||
typename std::iterator_traits<InputIterator>::
|
||||
iterator_category());
|
||||
}
|
||||
static const Type *getIndexedType(const Type *Ptr, Value *Idx);
|
||||
|
||||
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(); }
|
||||
|
||||
Value *getAggregateOperand() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const Value *getAggregateOperand() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
static unsigned getAggregateOperandIndex() {
|
||||
return 0U; // get index for modifying correct operand
|
||||
}
|
||||
|
||||
unsigned getNumIndices() const { // Note: always non-negative
|
||||
return getNumOperands() - 1;
|
||||
}
|
||||
|
||||
bool hasIndices() const {
|
||||
return getNumOperands() > 1;
|
||||
}
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const ExtractValueInst *) { return true; }
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return I->getOpcode() == Instruction::ExtractValue;
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OperandTraits<ExtractValueInst> : VariadicOperandTraits<1> {
|
||||
};
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueInst, Value)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// InsertValueInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// InsertValueInst - This instruction extracts a value
|
||||
/// from an aggregate value
|
||||
///
|
||||
class InsertValueInst : public Instruction {
|
||||
InsertValueInst(const InsertValueInst &IVI);
|
||||
void init(Value *Agg, Value *Val, Value* const *Idx, unsigned NumIdx);
|
||||
void init(Value *Agg, Value *Val, Value *Idx);
|
||||
|
||||
template<typename InputIterator>
|
||||
void init(Value *Agg, Value *Val,
|
||||
InputIterator IdxBegin, InputIterator IdxEnd,
|
||||
const std::string &Name,
|
||||
// This argument ensures that we have an iterator we can
|
||||
// do arithmetic on in constant time
|
||||
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);
|
||||
}
|
||||
|
||||
setName(Name);
|
||||
}
|
||||
|
||||
/// Constructors - Create a insertvalue instruction with a base pointer an
|
||||
/// list of indices. The first ctor can optionally insert before an existing
|
||||
/// instruction, the second appends the new instruction to the specified
|
||||
/// BasicBlock.
|
||||
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 = "",
|
||||
Instruction *InsertBefore = 0);
|
||||
InsertValueInst(Value *Agg, Value *Val, Value *Idx,
|
||||
const std::string &Name, BasicBlock *InsertAtEnd);
|
||||
public:
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/// 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,
|
||||
const std::string &Name = "",
|
||||
Instruction *InsertBefore = 0) {
|
||||
return new(3) InsertValueInst(Agg, Val, Idx, Name, InsertBefore);
|
||||
}
|
||||
static InsertValueInst *Create(Value *Agg, Value *Val, Value *Idx,
|
||||
const std::string &Name,
|
||||
BasicBlock *InsertAtEnd) {
|
||||
return new(3) InsertValueInst(Agg, Val, Idx, Name, InsertAtEnd);
|
||||
}
|
||||
|
||||
virtual InsertValueInst *clone() const;
|
||||
|
||||
/// Transparently provide more efficient getOperand methods.
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
||||
// getType - Overload to return most specific pointer type...
|
||||
const PointerType *getType() const {
|
||||
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(); }
|
||||
|
||||
Value *getAggregateOperand() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const Value *getAggregateOperand() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
static unsigned getAggregateOperandIndex() {
|
||||
return 0U; // get index for modifying correct operand
|
||||
}
|
||||
|
||||
Value *getInsertedValueOperand() {
|
||||
return getOperand(1);
|
||||
}
|
||||
const Value *getInsertedValueOperand() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
static unsigned getInsertedValueOperandIndex() {
|
||||
return 1U; // get index for modifying correct operand
|
||||
}
|
||||
|
||||
unsigned getNumIndices() const { // Note: always non-negative
|
||||
return getNumOperands() - 2;
|
||||
}
|
||||
|
||||
bool hasIndices() const {
|
||||
return getNumOperands() > 2;
|
||||
}
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const InsertValueInst *) { return true; }
|
||||
static inline bool classof(const Instruction *I) {
|
||||
return I->getOpcode() == Instruction::InsertValue;
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<Instruction>(V) && classof(cast<Instruction>(V));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OperandTraits<InsertValueInst> : VariadicOperandTraits<2> {
|
||||
};
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PHINode Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -197,6 +197,8 @@ public:
|
||||
RetTy visitInsertElementInst(InsertElementInst &I) { DELEGATE(Instruction); }
|
||||
RetTy visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction); }
|
||||
RetTy visitGetResultInst(GetResultInst &I) { DELEGATE(Instruction); }
|
||||
RetTy visitExtractValueInst(ExtractValueInst &I) { DELEGATE(Instruction);}
|
||||
RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); }
|
||||
|
||||
// Next level propagators... if the user does not overload a specific
|
||||
// instruction type, they can overload one of these to get the whole class
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -350,7 +350,7 @@
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
#line 949 "/Volumes/MacOS9/gcc/llvm/lib/AsmParser/llvmAsmParser.y"
|
||||
#line 949 "/Volumes/LLVM/llvm/lib/AsmParser/llvmAsmParser.y"
|
||||
{
|
||||
llvm::Module *ModuleVal;
|
||||
llvm::Function *FunctionVal;
|
||||
|
@ -1888,8 +1888,7 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
|
||||
GEN_ERROR("GetElementPtr requires a pointer operand");
|
||||
|
||||
const Type *IdxTy =
|
||||
GetElementPtrInst::getIndexedType($3->getType(), $4->begin(), $4->end(),
|
||||
true);
|
||||
GetElementPtrInst::getIndexedType($3->getType(), $4->begin(), $4->end());
|
||||
if (!IdxTy)
|
||||
GEN_ERROR("Index list invalid for constant getelementptr");
|
||||
|
||||
@ -3180,7 +3179,7 @@ MemoryInst : MALLOC Types OptCAlign {
|
||||
if (!isa<PointerType>($2->get()))
|
||||
GEN_ERROR("getelementptr insn requires pointer operand");
|
||||
|
||||
if (!GetElementPtrInst::getIndexedType(*$2, $4->begin(), $4->end(), true))
|
||||
if (!GetElementPtrInst::getIndexedType(*$2, $4->begin(), $4->end()))
|
||||
GEN_ERROR("Invalid getelementptr indices for type '" +
|
||||
(*$2)->getDescription()+ "'");
|
||||
Value* tmpVal = getVal(*$2, $3);
|
||||
|
@ -1888,8 +1888,7 @@ ConstExpr: CastOps '(' ConstVal TO Types ')' {
|
||||
GEN_ERROR("GetElementPtr requires a pointer operand");
|
||||
|
||||
const Type *IdxTy =
|
||||
GetElementPtrInst::getIndexedType($3->getType(), $4->begin(), $4->end(),
|
||||
true);
|
||||
GetElementPtrInst::getIndexedType($3->getType(), $4->begin(), $4->end());
|
||||
if (!IdxTy)
|
||||
GEN_ERROR("Index list invalid for constant getelementptr");
|
||||
|
||||
@ -2712,7 +2711,8 @@ BBTerminatorInst :
|
||||
PAL = PAListPtr::get(Attrs.begin(), Attrs.end());
|
||||
|
||||
// Create the InvokeInst
|
||||
InvokeInst *II = InvokeInst::Create(V, Normal, Except, Args.begin(),Args.end());
|
||||
InvokeInst *II = InvokeInst::Create(V, Normal, Except,
|
||||
Args.begin(), Args.end());
|
||||
II->setCallingConv($2);
|
||||
II->setParamAttrs(PAL);
|
||||
$$ = II;
|
||||
@ -3179,7 +3179,7 @@ MemoryInst : MALLOC Types OptCAlign {
|
||||
if (!isa<PointerType>($2->get()))
|
||||
GEN_ERROR("getelementptr insn requires pointer operand");
|
||||
|
||||
if (!GetElementPtrInst::getIndexedType(*$2, $4->begin(), $4->end(), true))
|
||||
if (!GetElementPtrInst::getIndexedType(*$2, $4->begin(), $4->end()))
|
||||
GEN_ERROR("Invalid getelementptr indices for type '" +
|
||||
(*$2)->getDescription()+ "'");
|
||||
Value* tmpVal = getVal(*$2, $3);
|
||||
|
@ -703,6 +703,9 @@ public:
|
||||
void visitInsertElement(User &I);
|
||||
void visitShuffleVector(User &I);
|
||||
|
||||
void visitExtractValue(User &I);
|
||||
void visitInsertValue(User &I);
|
||||
|
||||
void visitGetElementPtr(User &I);
|
||||
void visitSelect(User &I);
|
||||
|
||||
@ -2555,6 +2558,16 @@ void SelectionDAGLowering::visitShuffleVector(User &I) {
|
||||
V1, V2, Mask));
|
||||
}
|
||||
|
||||
void SelectionDAGLowering::visitInsertValue(User &I) {
|
||||
assert(0 && "insertvalue instruction not implemented");
|
||||
abort();
|
||||
}
|
||||
|
||||
void SelectionDAGLowering::visitExtractValue(User &I) {
|
||||
assert(0 && "extractvalue instruction not implemented");
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
void SelectionDAGLowering::visitGetElementPtr(User &I) {
|
||||
SDOperand N = getValue(I.getOperand(0));
|
||||
|
@ -447,6 +447,21 @@ Constant *llvm::ConstantFoldShuffleVectorInstruction(const Constant *V1,
|
||||
return ConstantVector::get(&Result[0], Result.size());
|
||||
}
|
||||
|
||||
Constant *llvm::ConstantFoldExtractValue(const Constant *Agg,
|
||||
Constant* const *Idxs,
|
||||
unsigned NumIdx) {
|
||||
// FIXME: implement some constant folds
|
||||
return 0;
|
||||
}
|
||||
|
||||
Constant *llvm::ConstantFoldInsertValue(const Constant *Agg,
|
||||
const Constant *Val,
|
||||
Constant* const *Idxs,
|
||||
unsigned NumIdx) {
|
||||
// FIXME: implement some constant folds
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// EvalVectorOp - Given two vector constants and a function pointer, apply the
|
||||
/// function pointer to each element pair, producing a new ConstantVector
|
||||
/// constant. Either or both of V1 and V2 may be NULL, meaning a
|
||||
@ -1408,8 +1423,7 @@ Constant *llvm::ConstantFoldGetElementPtr(const Constant *C,
|
||||
const PointerType *Ptr = cast<PointerType>(C->getType());
|
||||
const Type *Ty = GetElementPtrInst::getIndexedType(Ptr,
|
||||
(Value **)Idxs,
|
||||
(Value **)Idxs+NumIdx,
|
||||
true);
|
||||
(Value **)Idxs+NumIdx);
|
||||
assert(Ty != 0 && "Invalid indices for GEP!");
|
||||
return UndefValue::get(PointerType::get(Ty, Ptr->getAddressSpace()));
|
||||
}
|
||||
@ -1426,8 +1440,7 @@ Constant *llvm::ConstantFoldGetElementPtr(const Constant *C,
|
||||
const PointerType *Ptr = cast<PointerType>(C->getType());
|
||||
const Type *Ty = GetElementPtrInst::getIndexedType(Ptr,
|
||||
(Value**)Idxs,
|
||||
(Value**)Idxs+NumIdx,
|
||||
true);
|
||||
(Value**)Idxs+NumIdx);
|
||||
assert(Ty != 0 && "Invalid indices for GEP!");
|
||||
return
|
||||
ConstantPointerNull::get(PointerType::get(Ty,Ptr->getAddressSpace()));
|
||||
|
@ -41,6 +41,10 @@ namespace llvm {
|
||||
Constant *ConstantFoldShuffleVectorInstruction(const Constant *V1,
|
||||
const Constant *V2,
|
||||
const Constant *Mask);
|
||||
Constant *ConstantFoldExtractValue(const Constant *Agg,
|
||||
Constant* const *Idxs, unsigned NumIdx);
|
||||
Constant *ConstantFoldInsertValue(const Constant *Agg, const Constant *Val,
|
||||
Constant* const *Idxs, unsigned NumIdx);
|
||||
Constant *ConstantFoldBinaryInstruction(unsigned Opcode, const Constant *V1,
|
||||
const Constant *V2);
|
||||
Constant *ConstantFoldCompareInstruction(unsigned short predicate,
|
||||
|
@ -533,6 +533,43 @@ public:
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
};
|
||||
|
||||
/// ExtractValueConstantExpr - This class is private to
|
||||
/// 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);
|
||||
public:
|
||||
static ExtractValueConstantExpr *Create(Constant *Agg,
|
||||
const std::vector<Constant*> &IdxList,
|
||||
const Type *DestTy) {
|
||||
return
|
||||
new(IdxList.size() + 1) ExtractValueConstantExpr(Agg, IdxList, DestTy);
|
||||
}
|
||||
/// Transparently provide more efficient getOperand methods.
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
};
|
||||
|
||||
/// InsertValueConstantExpr - This class is private to
|
||||
/// 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);
|
||||
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);
|
||||
}
|
||||
/// Transparently provide more efficient getOperand methods.
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
};
|
||||
|
||||
|
||||
/// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
|
||||
/// used behind the scenes to implement getelementpr constant exprs.
|
||||
class VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr {
|
||||
@ -601,6 +638,45 @@ struct OperandTraits<ShuffleVectorConstantExpr> : FixedNumOperandTraits<3> {
|
||||
};
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)
|
||||
|
||||
template <>
|
||||
struct OperandTraits<ExtractValueConstantExpr> : VariadicOperandTraits<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].init(Agg, this);
|
||||
for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
|
||||
OperandList[i+1].init(IdxList[i], this);
|
||||
}
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueConstantExpr, Value)
|
||||
|
||||
template <>
|
||||
struct OperandTraits<InsertValueConstantExpr> : VariadicOperandTraits<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].init(Agg, this);
|
||||
OperandList[1].init(Val, this);
|
||||
for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
|
||||
OperandList[i+2].init(IdxList[i], this);
|
||||
}
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueConstantExpr, Value)
|
||||
|
||||
|
||||
template <>
|
||||
struct OperandTraits<GetElementPtrConstantExpr> : VariadicOperandTraits<1> {
|
||||
@ -752,11 +828,36 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
|
||||
Op1 = (OpNo == 1) ? Op : getOperand(1);
|
||||
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());
|
||||
}
|
||||
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());
|
||||
}
|
||||
case Instruction::GetElementPtr: {
|
||||
SmallVector<Constant*, 8> Ops;
|
||||
Ops.resize(getNumOperands());
|
||||
Ops.resize(getNumOperands()-1);
|
||||
for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
|
||||
Ops[i] = getOperand(i);
|
||||
Ops[i-1] = getOperand(i);
|
||||
if (OpNo == 0)
|
||||
return ConstantExpr::getGetElementPtr(Op, &Ops[0], Ops.size());
|
||||
Ops[OpNo-1] = Op;
|
||||
@ -807,6 +908,10 @@ 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::GetElementPtr:
|
||||
return ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], Ops.size()-1);
|
||||
case Instruction::ICmp:
|
||||
@ -1564,6 +1669,15 @@ 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::GetElementPtr) {
|
||||
std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
|
||||
return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty);
|
||||
@ -1975,9 +2089,10 @@ Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C,
|
||||
Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
|
||||
Value* const *Idxs,
|
||||
unsigned NumIdx) {
|
||||
assert(GetElementPtrInst::getIndexedType(C->getType(),
|
||||
Idxs, Idxs+NumIdx, true)
|
||||
&& "GEP indices invalid!");
|
||||
assert(GetElementPtrInst::getIndexedType(C->getType(), Idxs,
|
||||
Idxs+NumIdx) ==
|
||||
cast<PointerType>(ReqTy)->getElementType() &&
|
||||
"GEP indices invalid!");
|
||||
|
||||
if (Constant *FC = ConstantFoldGetElementPtr(C, (Constant**)Idxs, NumIdx))
|
||||
return FC; // Fold a few common cases...
|
||||
@ -1998,7 +2113,7 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs,
|
||||
unsigned NumIdx) {
|
||||
// Get the result type of the getelementptr!
|
||||
const Type *Ty =
|
||||
GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx, true);
|
||||
GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx);
|
||||
assert(Ty && "GEP indices invalid!");
|
||||
unsigned As = cast<PointerType>(C->getType())->getAddressSpace();
|
||||
return getGetElementPtrTy(PointerType::get(Ty, As), C, Idxs, NumIdx);
|
||||
@ -2181,6 +2296,76 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2,
|
||||
return getShuffleVectorTy(V1->getType(), V1, V2, Mask);
|
||||
}
|
||||
|
||||
Constant *ConstantExpr::getInsertValueTy(const Type *ReqTy, Constant *Agg,
|
||||
Constant *Val,
|
||||
Constant *const *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(isa<PointerType>(Agg->getType()) &&
|
||||
"Non-pointer 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);
|
||||
return ExprConstants->getOrCreate(ReqTy, Key);
|
||||
}
|
||||
|
||||
Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val,
|
||||
Constant* const *IdxList, unsigned NumIdx) {
|
||||
assert((isa<StructType>(Agg->getType()) || isa<ArrayType>(Agg->getType()) ||
|
||||
isa<VectorType>(Agg->getType())) &&
|
||||
"Tried to create insertelement operation on non-aggregate type!");
|
||||
|
||||
const Type *ReqTy =
|
||||
ExtractValueInst::getIndexedType(Agg->getType(), IdxList, IdxList+NumIdx);
|
||||
assert(ReqTy && "insertvalue indices invalid!");
|
||||
return getInsertValueTy(ReqTy, Agg, Val, IdxList, NumIdx);
|
||||
}
|
||||
|
||||
Constant *ConstantExpr::getExtractValueTy(const Type *ReqTy, Constant *Agg,
|
||||
Constant *const *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(isa<PointerType>(Agg->getType()) &&
|
||||
"Non-pointer 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);
|
||||
return ExprConstants->getOrCreate(ReqTy, Key);
|
||||
}
|
||||
|
||||
Constant *ConstantExpr::getExtractValue(Constant *Agg,
|
||||
Constant* const *IdxList, unsigned NumIdx) {
|
||||
assert((isa<StructType>(Agg->getType()) || isa<ArrayType>(Agg->getType()) ||
|
||||
isa<VectorType>(Agg->getType())) &&
|
||||
"Tried to create extractelement operation on non-aggregate type!");
|
||||
|
||||
const Type *ReqTy =
|
||||
ExtractValueInst::getIndexedType(Agg->getType(), IdxList, IdxList+NumIdx);
|
||||
assert(ReqTy && "extractvalue indices invalid!");
|
||||
return getExtractValueTy(ReqTy, Agg, IdxList, NumIdx);
|
||||
}
|
||||
|
||||
Constant *ConstantExpr::getZeroValueForNegationExpr(const Type *Ty) {
|
||||
if (const VectorType *PTy = dyn_cast<VectorType>(Ty))
|
||||
if (PTy->getElementType()->isFloatingPoint()) {
|
||||
@ -2406,6 +2591,34 @@ 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
Replacement = ConstantExpr::getInsertValue(Agg, Val,
|
||||
&Indices[0], Indices.size());
|
||||
} else if (isCast()) {
|
||||
assert(getOperand(0) == From && "Cast only has one use!");
|
||||
Replacement = ConstantExpr::getCast(getOpcode(), To, getType());
|
||||
|
@ -1038,41 +1038,16 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
|
||||
//
|
||||
const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
|
||||
Value* const *Idxs,
|
||||
unsigned NumIdx,
|
||||
bool AllowCompositeLeaf) {
|
||||
if (!isa<PointerType>(Ptr)) return 0; // Type isn't a pointer type!
|
||||
unsigned NumIdx) {
|
||||
const PointerType *PTy = dyn_cast<PointerType>(Ptr);
|
||||
if (!PTy) return 0; // Type isn't a pointer type!
|
||||
const Type *Agg = PTy->getElementType();
|
||||
|
||||
// Handle the special case of the empty set index set...
|
||||
if (NumIdx == 0) {
|
||||
if (AllowCompositeLeaf ||
|
||||
cast<PointerType>(Ptr)->getElementType()->isFirstClassType())
|
||||
return cast<PointerType>(Ptr)->getElementType();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
if (NumIdx == 0)
|
||||
return Agg;
|
||||
|
||||
unsigned CurIdx = 0;
|
||||
while (const CompositeType *CT = dyn_cast<CompositeType>(Ptr)) {
|
||||
if (NumIdx == CurIdx) {
|
||||
if (AllowCompositeLeaf || CT->isFirstClassType()) return Ptr;
|
||||
return 0; // Can't load a whole structure or array!?!?
|
||||
}
|
||||
|
||||
Value *Index = Idxs[CurIdx++];
|
||||
if (isa<PointerType>(CT) && CurIdx != 1)
|
||||
return 0; // Can only index into pointer types at the first index!
|
||||
if (!CT->indexValid(Index)) return 0;
|
||||
Ptr = 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 = Ptr->getForwardedType()) {
|
||||
Ptr = Ty;
|
||||
}
|
||||
}
|
||||
return CurIdx == NumIdx ? Ptr : 0;
|
||||
return ExtractValueInst::getIndexedType(Agg, Idxs+1, Idxs+NumIdx);
|
||||
}
|
||||
|
||||
const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) {
|
||||
@ -1345,6 +1320,36 @@ int ShuffleVectorInst::getMaskValue(unsigned i) const {
|
||||
return cast<ConstantInt>(MaskCV->getOperand(i))->getZExtValue();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ExtractValueInst Class
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// getIndexedType - Returns the type of the element that would be extracted
|
||||
// with an extractvalue instruction with the specified parameters.
|
||||
//
|
||||
// A null type is returned if the indices are invalid for the specified
|
||||
// pointer type.
|
||||
//
|
||||
const Type* ExtractValueInst::getIndexedType(const Type *Agg,
|
||||
Value* const *Idxs,
|
||||
unsigned NumIdx) {
|
||||
unsigned CurIdx = 0;
|
||||
for (; CurIdx != NumIdx; ++CurIdx) {
|
||||
const CompositeType *CT = dyn_cast<CompositeType>(Agg);
|
||||
if (!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;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BinaryOperator Class
|
||||
|
@ -1045,7 +1045,7 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) {
|
||||
SmallVector<Value*, 16> Idxs(GEP.idx_begin(), GEP.idx_end());
|
||||
const Type *ElTy =
|
||||
GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(),
|
||||
Idxs.begin(), Idxs.end(), true);
|
||||
Idxs.begin(), Idxs.end());
|
||||
Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP);
|
||||
Assert2(isa<PointerType>(GEP.getType()) &&
|
||||
cast<PointerType>(GEP.getType())->getElementType() == ElTy,
|
||||
|
@ -1,7 +1,7 @@
|
||||
; RUN: not llvm-as < %s |& grep {Invalid getelementptr indices}
|
||||
; RUN: llvm-as < %s
|
||||
|
||||
; This testcase is invalid because we are indexing into a pointer that is
|
||||
; contained WITHIN a structure.
|
||||
; This testcase was previously considered invalid for indexing into a pointer
|
||||
; that is contained WITHIN a structure, but this is now valid.
|
||||
|
||||
define void @test({i32, i32*} * %X) {
|
||||
getelementptr {i32, i32*} * %X, i32 0, i32 1, i32 0
|
||||
|
Loading…
Reference in New Issue
Block a user