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:
Dan Gohman 2008-05-15 19:50:34 +00:00
parent 48ac9aec33
commit 821bf58428
15 changed files with 946 additions and 360 deletions

View File

@ -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

View File

@ -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

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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));

View File

@ -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()));

View File

@ -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,

View File

@ -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());

View File

@ -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

View File

@ -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,

View File

@ -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