diff options
Diffstat (limited to 'include/llvm/Instructions.h')
-rw-r--r-- | include/llvm/Instructions.h | 591 |
1 files changed, 352 insertions, 239 deletions
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index f292a31..86bc3f5 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -21,10 +21,10 @@ #include "llvm/InstrTypes.h" #include "llvm/DerivedTypes.h" #include "llvm/ParameterAttributes.h" +#include "llvm/BasicBlock.h" namespace llvm { -class BasicBlock; class ConstantInt; class PointerType; class VectorType; @@ -288,11 +288,11 @@ public: /// class StoreInst : public Instruction { void *operator new(size_t, unsigned); // DO NOT IMPLEMENT - Use Ops[2]; - StoreInst(const StoreInst &SI) : Instruction(SI.getType(), Store, Ops, 2) { - Ops[0].init(SI.Ops[0], this); - Ops[1].init(SI.Ops[1], this); + StoreInst(const StoreInst &SI) : Instruction(SI.getType(), Store, + &Op<0>(), 2) { + Op<0>().init(SI.Op<0>(), this); + Op<1>().init(SI.Op<1>(), this); setVolatile(SI.isVolatile()); setAlignment(SI.getAlignment()); @@ -329,15 +329,7 @@ public: } /// Transparently provide more efficient getOperand methods. - Value *getOperand(unsigned i) const { - assert(i < 2 && "getOperand() out of range!"); - return Ops[i]; - } - void setOperand(unsigned i, Value *Val) { - assert(i < 2 && "setOperand() out of range!"); - Ops[i] = Val; - } - unsigned getNumOperands() const { return 2; } + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); /// getAlignment - Return the alignment of the access that is being performed /// @@ -363,6 +355,11 @@ public: } }; +template <> +struct OperandTraits<StoreInst> : FixedNumOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) //===----------------------------------------------------------------------===// // GetElementPtrInst Class @@ -380,14 +377,7 @@ static inline const Type *checkType(const Type *Ty) { /// access elements of arrays and structs /// class GetElementPtrInst : public Instruction { - GetElementPtrInst(const GetElementPtrInst &GEPI) - : Instruction(reinterpret_cast<const Type*>(GEPI.getType()), GetElementPtr, - 0, GEPI.getNumOperands()) { - Use *OL = OperandList = new Use[NumOperands]; - Use *GEPIOL = GEPI.OperandList; - for (unsigned i = 0, E = NumOperands; i != E; ++i) - OL[i].init(GEPIOL[i], this); - } + GetElementPtrInst(const GetElementPtrInst &GEPI); void init(Value *Ptr, Value* const *Idx, unsigned NumIdx); void init(Value *Ptr, Value *Idx); @@ -400,8 +390,9 @@ class GetElementPtrInst : public Instruction { unsigned NumIdx = static_cast<unsigned>(std::distance(IdxBegin, IdxEnd)); if (NumIdx > 0) { - // This requires that the itoerator points to contiguous memory. - init(Ptr, &*IdxBegin, NumIdx); + // This requires that the iterator points to contiguous memory. + init(Ptr, &*IdxBegin, NumIdx); // FIXME: for the general case + // we have to build an array here } else { init(Ptr, 0, NumIdx); @@ -446,34 +437,21 @@ class GetElementPtrInst : public Instruction { /// instruction, the second appends the new instruction to the specified /// BasicBlock. template<typename InputIterator> - GetElementPtrInst(Value *Ptr, InputIterator IdxBegin, - InputIterator IdxEnd, - const std::string &Name = "", - Instruction *InsertBefore = 0) - : Instruction(PointerType::get( - checkType(getIndexedType(Ptr->getType(), - IdxBegin, IdxEnd, true)), - cast<PointerType>(Ptr->getType())->getAddressSpace()), - GetElementPtr, 0, 0, InsertBefore) { - init(Ptr, IdxBegin, IdxEnd, Name, - typename std::iterator_traits<InputIterator>::iterator_category()); - } + inline GetElementPtrInst(Value *Ptr, InputIterator IdxBegin, + InputIterator IdxEnd, + unsigned Values, + const std::string &Name, + Instruction *InsertBefore); template<typename InputIterator> - GetElementPtrInst(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd, - const std::string &Name, BasicBlock *InsertAtEnd) - : Instruction(PointerType::get( - checkType(getIndexedType(Ptr->getType(), - IdxBegin, IdxEnd, true)), - cast<PointerType>(Ptr->getType())->getAddressSpace()), - GetElementPtr, 0, 0, InsertAtEnd) { - init(Ptr, IdxBegin, IdxEnd, Name, - typename std::iterator_traits<InputIterator>::iterator_category()); - } + inline GetElementPtrInst(Value *Ptr, + InputIterator IdxBegin, InputIterator IdxEnd, + unsigned Values, + const std::string &Name, BasicBlock *InsertAtEnd); /// Constructors - These two constructors are convenience methods because one /// and two index getelementptr instructions are so common. - GetElementPtrInst(Value *Ptr, Value *Idx, - const std::string &Name = "", Instruction *InsertBefore = 0); + GetElementPtrInst(Value *Ptr, Value *Idx, const std::string &Name = "", + Instruction *InsertBefore = 0); GetElementPtrInst(Value *Ptr, Value *Idx, const std::string &Name, BasicBlock *InsertAtEnd); public: @@ -482,28 +460,40 @@ public: InputIterator IdxEnd, const std::string &Name = "", Instruction *InsertBefore = 0) { - return new(0/*FIXME*/) GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Name, InsertBefore); + typename std::iterator_traits<InputIterator>::difference_type Values = + 1 + std::distance(IdxBegin, IdxEnd); + return new(Values) + GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, Name, InsertBefore); } template<typename InputIterator> - static GetElementPtrInst *Create(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd, - const std::string &Name, BasicBlock *InsertAtEnd) { - return new(0/*FIXME*/) GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Name, InsertAtEnd); + static GetElementPtrInst *Create(Value *Ptr, + 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) + GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, Name, InsertAtEnd); } - /// Constructors - These two constructors are convenience methods because one - /// and two index getelementptr instructions are so common. + /// Constructors - These two creators are convenience methods because one + /// index getelementptr instructions are so common. static GetElementPtrInst *Create(Value *Ptr, Value *Idx, - const std::string &Name = "", Instruction *InsertBefore = 0) { - return new(2/*FIXME*/) GetElementPtrInst(Ptr, Idx, Name, InsertBefore); + const std::string &Name = "", + Instruction *InsertBefore = 0) { + return new(2) GetElementPtrInst(Ptr, Idx, Name, InsertBefore); } static GetElementPtrInst *Create(Value *Ptr, Value *Idx, - const std::string &Name, BasicBlock *InsertAtEnd) { - return new(2/*FIXME*/) GetElementPtrInst(Ptr, Idx, Name, InsertAtEnd); + const std::string &Name, + BasicBlock *InsertAtEnd) { + return new(2) GetElementPtrInst(Ptr, Idx, Name, InsertAtEnd); } - ~GetElementPtrInst(); virtual GetElementPtrInst *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()); @@ -570,6 +560,51 @@ public: } }; +template <> +struct OperandTraits<GetElementPtrInst> : VariadicOperandTraits<1> { +}; + +template<typename InputIterator> +GetElementPtrInst::GetElementPtrInst(Value *Ptr, + InputIterator IdxBegin, + InputIterator IdxEnd, + unsigned Values, + const std::string &Name, + Instruction *InsertBefore) + : Instruction(PointerType::get(checkType( + getIndexedType(Ptr->getType(), + IdxBegin, IdxEnd, true)), + cast<PointerType>(Ptr->getType()) + ->getAddressSpace()), + GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - Values, + Values, InsertBefore) { + init(Ptr, IdxBegin, IdxEnd, Name, + typename std::iterator_traits<InputIterator>::iterator_category()); +} +template<typename InputIterator> +GetElementPtrInst::GetElementPtrInst(Value *Ptr, + InputIterator IdxBegin, + InputIterator IdxEnd, + unsigned Values, + const std::string &Name, + BasicBlock *InsertAtEnd) + : Instruction(PointerType::get(checkType( + getIndexedType(Ptr->getType(), + IdxBegin, IdxEnd, true)), + cast<PointerType>(Ptr->getType()) + ->getAddressSpace()), + GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - Values, + Values, InsertAtEnd) { + init(Ptr, IdxBegin, IdxEnd, Name, + typename std::iterator_traits<InputIterator>::iterator_category()); +} + + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) + + //===----------------------------------------------------------------------===// // ICmpInst Class //===----------------------------------------------------------------------===// @@ -723,7 +758,7 @@ public: /// @brief Swap operands and adjust predicate. void swapOperands() { SubclassData = getSwappedPredicate(); - std::swap(Ops[0], Ops[1]); + std::swap(Op<0>(), Op<1>()); } virtual ICmpInst *clone() const; @@ -847,7 +882,7 @@ public: /// @brief Swap operands and adjust predicate. void swapOperands() { SubclassData = getSwappedPredicate(); - std::swap(Ops[0], Ops[1]); + std::swap(Op<0>(), Op<1>()); } virtual FCmpInst *clone() const; @@ -900,13 +935,7 @@ class CallInst : public Instruction { /// @brief Construct a CallInst from a range of arguments template<typename InputIterator> CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, - const std::string &Name = "", Instruction *InsertBefore = 0) - : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Call, 0, 0, InsertBefore) { - init(Func, ArgBegin, ArgEnd, Name, - typename std::iterator_traits<InputIterator>::iterator_category()); - } + const std::string &Name, Instruction *InsertBefore); /// Construct a CallInst given a range of arguments. InputIterator /// must be a random-access iterator pointing to contiguous storage @@ -915,35 +944,29 @@ class CallInst : public Instruction { /// incur runtime overhead. /// @brief Construct a CallInst from a range of arguments template<typename InputIterator> - CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, - const std::string &Name, BasicBlock *InsertAtEnd) - : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Call, 0, 0, InsertAtEnd) { - init(Func, ArgBegin, ArgEnd, Name, - typename std::iterator_traits<InputIterator>::iterator_category()); - } + inline CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + const std::string &Name, BasicBlock *InsertAtEnd); - CallInst(Value *F, Value *Actual, const std::string& Name = "", - Instruction *InsertBefore = 0); + CallInst(Value *F, Value *Actual, const std::string& Name, + Instruction *InsertBefore); CallInst(Value *F, Value *Actual, const std::string& Name, BasicBlock *InsertAtEnd); - explicit CallInst(Value *F, const std::string &Name = "", - Instruction *InsertBefore = 0); + explicit CallInst(Value *F, const std::string &Name, + Instruction *InsertBefore); CallInst(Value *F, const std::string &Name, BasicBlock *InsertAtEnd); public: template<typename InputIterator> - static CallInst *Create(Value *Func, InputIterator ArgBegin, - InputIterator ArgEnd, + static CallInst *Create(Value *Func, + InputIterator ArgBegin, InputIterator ArgEnd, const std::string &Name = "", Instruction *InsertBefore = 0) { return new(ArgEnd - ArgBegin + 1) CallInst(Func, ArgBegin, ArgEnd, Name, InsertBefore); } template<typename InputIterator> - static CallInst *Create(Value *Func, InputIterator ArgBegin, - InputIterator ArgEnd, const std::string &Name, - BasicBlock *InsertAtEnd) { + static CallInst *Create(Value *Func, + InputIterator ArgBegin, InputIterator ArgEnd, + const std::string &Name, BasicBlock *InsertAtEnd) { return new(ArgEnd - ArgBegin + 1) CallInst(Func, ArgBegin, ArgEnd, Name, InsertAtEnd); } @@ -967,6 +990,9 @@ public: ~CallInst(); virtual CallInst *clone() const; + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); bool isTailCall() const { return SubclassData & 1; } void setTailCall(bool isTailCall = true) { @@ -1050,6 +1076,36 @@ public: } }; +template <> +struct OperandTraits<CallInst> : VariadicOperandTraits<1> { +}; + +template<typename InputIterator> +CallInst::CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + const std::string &Name, BasicBlock *InsertAtEnd) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, + OperandTraits<CallInst>::op_end(this) - (ArgEnd - ArgBegin + 1), + ArgEnd - ArgBegin + 1, InsertAtEnd) { + init(Func, ArgBegin, ArgEnd, Name, + typename std::iterator_traits<InputIterator>::iterator_category()); +} + +template<typename InputIterator> +CallInst::CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + const std::string &Name, Instruction *InsertBefore) + : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, + OperandTraits<CallInst>::op_end(this) - (ArgEnd - ArgBegin + 1), + ArgEnd - ArgBegin + 1, InsertBefore) { + init(Func, ArgBegin, ArgEnd, Name, + typename std::iterator_traits<InputIterator>::iterator_category()); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CallInst, Value) + //===----------------------------------------------------------------------===// // SelectInst Class //===----------------------------------------------------------------------===// @@ -1057,27 +1113,27 @@ public: /// SelectInst - This class represents the LLVM 'select' instruction. /// class SelectInst : public Instruction { - Use Ops[3]; - void init(Value *C, Value *S1, Value *S2) { - Ops[0].init(C, this); - Ops[1].init(S1, this); - Ops[2].init(S2, this); + Op<0>() = C; + Op<1>() = S1; + Op<2>() = S2; } SelectInst(const SelectInst &SI) - : Instruction(SI.getType(), SI.getOpcode(), Ops, 3) { - init(SI.Ops[0], SI.Ops[1], SI.Ops[2]); + : Instruction(SI.getType(), SI.getOpcode(), &Op<0>(), 3) { + init(SI.Op<0>(), SI.Op<1>(), SI.Op<2>()); } - SelectInst(Value *C, Value *S1, Value *S2, const std::string &Name = "", - Instruction *InsertBefore = 0) - : Instruction(S1->getType(), Instruction::Select, Ops, 3, InsertBefore) { + SelectInst(Value *C, Value *S1, Value *S2, const std::string &Name, + Instruction *InsertBefore) + : Instruction(S1->getType(), Instruction::Select, + &Op<0>(), 3, InsertBefore) { init(C, S1, S2); setName(Name); } SelectInst(Value *C, Value *S1, Value *S2, const std::string &Name, BasicBlock *InsertAtEnd) - : Instruction(S1->getType(), Instruction::Select, Ops, 3, InsertAtEnd) { + : Instruction(S1->getType(), Instruction::Select, + &Op<0>(), 3, InsertAtEnd) { init(C, S1, S2); setName(Name); } @@ -1092,20 +1148,12 @@ public: return new(3) SelectInst(C, S1, S2, Name, InsertAtEnd); } - Value *getCondition() const { return Ops[0]; } - Value *getTrueValue() const { return Ops[1]; } - Value *getFalseValue() const { return Ops[2]; } + Value *getCondition() const { return Op<0>(); } + Value *getTrueValue() const { return Op<1>(); } + Value *getFalseValue() const { return Op<2>(); } /// Transparently provide more efficient getOperand methods. - Value *getOperand(unsigned i) const { - assert(i < 3 && "getOperand() out of range!"); - return Ops[i]; - } - void setOperand(unsigned i, Value *Val) { - assert(i < 3 && "setOperand() out of range!"); - Ops[i] = Val; - } - unsigned getNumOperands() const { return 3; } + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); OtherOps getOpcode() const { return static_cast<OtherOps>(Instruction::getOpcode()); @@ -1123,6 +1171,12 @@ public: } }; +template <> +struct OperandTraits<SelectInst> : FixedNumOperandTraits<3> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectInst, Value) + //===----------------------------------------------------------------------===// // VAArgInst Class //===----------------------------------------------------------------------===// @@ -1165,17 +1219,16 @@ public: /// element from a VectorType value /// class ExtractElementInst : public Instruction { - Use Ops[2]; ExtractElementInst(const ExtractElementInst &EE) : - Instruction(EE.getType(), ExtractElement, Ops, 2) { - Ops[0].init(EE.Ops[0], this); - Ops[1].init(EE.Ops[1], this); + Instruction(EE.getType(), ExtractElement, &Op<0>(), 2) { + Op<0>().init(EE.Op<0>(), this); + Op<1>().init(EE.Op<1>(), this); } public: // allocate space for exactly two operands void *operator new(size_t s) { - return User::operator new(s, 2); // FIXME: unsigned Idx forms of constructor? + return User::operator new(s, 2); // FIXME: "unsigned Idx" forms of ctor? } ExtractElementInst(Value *Vec, Value *Idx, const std::string &Name = "", Instruction *InsertBefore = 0); @@ -1193,15 +1246,7 @@ public: virtual ExtractElementInst *clone() const; /// Transparently provide more efficient getOperand methods. - Value *getOperand(unsigned i) const { - assert(i < 2 && "getOperand() out of range!"); - return Ops[i]; - } - void setOperand(unsigned i, Value *Val) { - assert(i < 2 && "setOperand() out of range!"); - Ops[i] = Val; - } - unsigned getNumOperands() const { return 2; } + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ExtractElementInst *) { return true; } @@ -1213,6 +1258,12 @@ public: } }; +template <> +struct OperandTraits<ExtractElementInst> : FixedNumOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementInst, Value) + //===----------------------------------------------------------------------===// // InsertElementInst Class //===----------------------------------------------------------------------===// @@ -1221,7 +1272,6 @@ public: /// element into a VectorType value /// class InsertElementInst : public Instruction { - Use Ops[3]; InsertElementInst(const InsertElementInst &IE); InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, const std::string &Name = "",Instruction *InsertBefore = 0); @@ -1236,14 +1286,14 @@ public: return new(IE.getNumOperands()) InsertElementInst(IE); } static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, - const std::string &Name = "",Instruction *InsertBefore = 0) { + const std::string &Name = "", + Instruction *InsertBefore = 0) { return new(3) InsertElementInst(Vec, NewElt, Idx, Name, InsertBefore); } static InsertElementInst *Create(Value *Vec, Value *NewElt, unsigned Idx, const std::string &Name = "", Instruction *InsertBefore = 0) { - return new(3/*FIXME*/) - InsertElementInst(Vec, NewElt, Idx, Name, InsertBefore); + return new(3) InsertElementInst(Vec, NewElt, Idx, Name, InsertBefore); } static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, const std::string &Name, @@ -1253,8 +1303,7 @@ public: static InsertElementInst *Create(Value *Vec, Value *NewElt, unsigned Idx, const std::string &Name, BasicBlock *InsertAtEnd) { - return new(3/*FIXME*/) - InsertElementInst(Vec, NewElt, Idx, Name, InsertAtEnd); + return new(3) InsertElementInst(Vec, NewElt, Idx, Name, InsertAtEnd); } /// isValidOperands - Return true if an insertelement instruction can be @@ -1271,15 +1320,7 @@ public: } /// Transparently provide more efficient getOperand methods. - Value *getOperand(unsigned i) const { - assert(i < 3 && "getOperand() out of range!"); - return Ops[i]; - } - void setOperand(unsigned i, Value *Val) { - assert(i < 3 && "setOperand() out of range!"); - Ops[i] = Val; - } - unsigned getNumOperands() const { return 3; } + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const InsertElementInst *) { return true; } @@ -1291,6 +1332,12 @@ public: } }; +template <> +struct OperandTraits<InsertElementInst> : FixedNumOperandTraits<3> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value) + //===----------------------------------------------------------------------===// // ShuffleVectorInst Class //===----------------------------------------------------------------------===// @@ -1299,7 +1346,6 @@ public: /// input vectors. /// class ShuffleVectorInst : public Instruction { - Use Ops[3]; ShuffleVectorInst(const ShuffleVectorInst &IE); public: // allocate space for exactly three operands @@ -1325,19 +1371,7 @@ public: } /// Transparently provide more efficient getOperand methods. - const Value *getOperand(unsigned i) const { - assert(i < 3 && "getOperand() out of range!"); - return Ops[i]; - } - Value *getOperand(unsigned i) { - assert(i < 3 && "getOperand() out of range!"); - return Ops[i]; - } - void setOperand(unsigned i, Value *Val) { - assert(i < 3 && "setOperand() out of range!"); - Ops[i] = Val; - } - unsigned getNumOperands() const { return 3; } + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); /// getMaskValue - Return the index from the shuffle mask for the specified /// output result. This is either -1 if the element is undef or a number less @@ -1354,6 +1388,11 @@ public: } }; +template <> +struct OperandTraits<ShuffleVectorInst> : FixedNumOperandTraits<3> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value) //===----------------------------------------------------------------------===// // PHINode Class @@ -1406,6 +1445,9 @@ public: virtual PHINode *clone() const; + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + /// getNumIncomingValues - Return the number of incoming edges /// unsigned getNumIncomingValues() const { return getNumOperands()/2; } @@ -1427,10 +1469,10 @@ public: /// getIncomingBlock - Return incoming basic block number x /// BasicBlock *getIncomingBlock(unsigned i) const { - return reinterpret_cast<BasicBlock*>(getOperand(i*2+1)); + return static_cast<BasicBlock*>(getOperand(i*2+1)); } void setIncomingBlock(unsigned i, BasicBlock *BB) { - setOperand(i*2+1, reinterpret_cast<Value*>(BB)); + setOperand(i*2+1, BB); } unsigned getOperandNumForIncomingBlock(unsigned i) { return i*2+1; @@ -1449,7 +1491,7 @@ public: // Initialize some new operands. NumOperands = OpNo+2; OperandList[OpNo].init(V, this); - OperandList[OpNo+1].init(reinterpret_cast<Value*>(BB), this); + OperandList[OpNo+1].init(BB, this); } /// removeIncomingValue - Remove an incoming value. This is useful if a @@ -1462,7 +1504,7 @@ public: /// Value *removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty = true); - Value *removeIncomingValue(const BasicBlock *BB, bool DeletePHIIfEmpty =true){ + Value *removeIncomingValue(const BasicBlock *BB, bool DeletePHIIfEmpty=true) { int Idx = getBasicBlockIndex(BB); assert(Idx >= 0 && "Invalid basic block argument to remove!"); return removeIncomingValue(Idx, DeletePHIIfEmpty); @@ -1474,7 +1516,7 @@ public: int getBasicBlockIndex(const BasicBlock *BB) const { Use *OL = OperandList; for (unsigned i = 0, e = getNumOperands(); i != e; i += 2) - if (OL[i+1] == reinterpret_cast<const Value*>(BB)) return i/2; + if (OL[i+1].get() == BB) return i/2; return -1; } @@ -1499,6 +1541,13 @@ public: void resizeOperands(unsigned NumOperands); }; +template <> +struct OperandTraits<PHINode> : HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value) + + //===----------------------------------------------------------------------===// // ReturnInst Class //===----------------------------------------------------------------------===// @@ -1508,7 +1557,6 @@ public: /// does not continue in this function any longer. /// class ReturnInst : public TerminatorInst { - Use RetVal; ReturnInst(const ReturnInst &RI); void init(Value * const* retVals, unsigned N); @@ -1517,20 +1565,19 @@ private: // ReturnInst() - 'ret void' instruction // ReturnInst( null) - 'ret void' instruction // ReturnInst(Value* X) - 'ret X' instruction - // ReturnInst( null, Inst *) - 'ret void' instruction, insert before I + // ReturnInst( null, Inst *I) - 'ret void' instruction, insert before I // ReturnInst(Value* X, Inst *I) - 'ret X' instruction, insert before I - // ReturnInst( null, BB *B) - 'ret void' instruction, insert @ end of BB - // ReturnInst(Value* X, BB *B) - 'ret X' instruction, insert @ end of BB + // ReturnInst( null, BB *B) - 'ret void' instruction, insert @ end of B + // ReturnInst(Value* X, BB *B) - 'ret X' instruction, insert @ end of B // ReturnInst(Value* X, N) - 'ret X,X+1...X+N-1' instruction - // ReturnInst(Value* X, N, Inst *) - 'ret X,X+1...X+N-1', insert before I - // ReturnInst(Value* X, N, BB *) - 'ret X,X+1...X+N-1', insert @ end of BB + // ReturnInst(Value* X, N, Inst *I) - 'ret X,X+1...X+N-1', insert before I + // ReturnInst(Value* X, N, BB *B) - 'ret X,X+1...X+N-1', insert @ end of B // // NOTE: If the Value* passed is of type void then the constructor behaves as // if it was passed NULL. explicit ReturnInst(Value *retVal = 0, Instruction *InsertBefore = 0); ReturnInst(Value *retVal, BasicBlock *InsertAtEnd); - ReturnInst(Value * const* retVals, unsigned N); - ReturnInst(Value * const* retVals, unsigned N, Instruction *InsertBefore); + ReturnInst(Value * const* retVals, unsigned N, Instruction *InsertBefore = 0); ReturnInst(Value * const* retVals, unsigned N, BasicBlock *InsertAtEnd); explicit ReturnInst(BasicBlock *InsertAtEnd); public: @@ -1540,11 +1587,8 @@ public: static ReturnInst* Create(Value *retVal, BasicBlock *InsertAtEnd) { return new(!!retVal) ReturnInst(retVal, InsertAtEnd); } - static ReturnInst* Create(Value * const* retVals, unsigned N) { - return new(N) ReturnInst(retVals, N); - } static ReturnInst* Create(Value * const* retVals, unsigned N, - Instruction *InsertBefore) { + Instruction *InsertBefore = 0) { return new(N) ReturnInst(retVals, N, InsertBefore); } static ReturnInst* Create(Value * const* retVals, unsigned N, @@ -1555,18 +1599,18 @@ public: return new(0) ReturnInst(InsertAtEnd); } virtual ~ReturnInst(); + inline void operator delete(void*); virtual ReturnInst *clone() const; - Value *getOperand(unsigned n = 0) const { - if (getNumOperands() > 1) - return TerminatorInst::getOperand(n); - else - return RetVal; - } + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + /// Convenience accessor Value *getReturnValue(unsigned n = 0) const { - return getOperand(n); + return n < getNumOperands() + ? getOperand(n) + : 0; } unsigned getNumSuccessors() const { return 0; } @@ -1585,6 +1629,18 @@ public: virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; +template <> +struct OperandTraits<ReturnInst> : VariadicOperandTraits<> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ReturnInst, Value) +void ReturnInst::operator delete(void *it) { + ReturnInst* me(static_cast<ReturnInst*>(it)); + Use::zap(OperandTraits<ReturnInst>::op_begin(me), + OperandTraits<ReturnInst>::op_end(me), + true); +} + //===----------------------------------------------------------------------===// // BranchInst Class //===----------------------------------------------------------------------===// @@ -1596,7 +1652,6 @@ class BranchInst : public TerminatorInst { /// Ops list - Branches are strange. The operands are ordered: /// TrueDest, FalseDest, Cond. This makes some accessors faster because /// they don't have to check for cond/uncond branchness. - Use Ops[3]; BranchInst(const BranchInst &BI); void AssertOK(); // BranchInst constructors (where {B, T, F} are blocks, and C is a condition): @@ -1616,28 +1671,29 @@ public: static BranchInst *Create(BasicBlock *IfTrue, Instruction *InsertBefore = 0) { return new(1) BranchInst(IfTrue, InsertBefore); } - static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, - Instruction *InsertBefore = 0) { + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, + Value *Cond, Instruction *InsertBefore = 0) { return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertBefore); } static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) { return new(1) BranchInst(IfTrue, InsertAtEnd); } - static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, - BasicBlock *InsertAtEnd) { + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, + Value *Cond, BasicBlock *InsertAtEnd) { return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertAtEnd); } - /// Transparently provide more efficient getOperand methods. - Value *getOperand(unsigned i) const { - assert(i < getNumOperands() && "getOperand() out of range!"); - return Ops[i]; - } - void setOperand(unsigned i, Value *Val) { - assert(i < getNumOperands() && "setOperand() out of range!"); - Ops[i] = Val; + ~BranchInst() + { + if (NumOperands == 1) + { + NumOperands = (Use*)this - OperandList; + } } + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + virtual BranchInst *clone() const; bool isUnconditional() const { return getNumOperands() == 1; } @@ -1657,12 +1713,12 @@ public: // targeting the specified block. // FIXME: Eliminate this ugly method. void setUnconditionalDest(BasicBlock *Dest) { + Op<0>() = Dest; if (isConditional()) { // Convert this to an uncond branch. + Op<1>().set(0); + Op<2>().set(0); NumOperands = 1; - Ops[1].set(0); - Ops[2].set(0); } - setOperand(0, reinterpret_cast<Value*>(Dest)); } unsigned getNumSuccessors() const { return 1+isConditional(); } @@ -1674,7 +1730,7 @@ public: void setSuccessor(unsigned idx, BasicBlock *NewSucc) { assert(idx < getNumSuccessors() && "Successor # out of range for Branch!"); - setOperand(idx, reinterpret_cast<Value*>(NewSucc)); + setOperand(idx, NewSucc); } // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -1691,6 +1747,15 @@ private: virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; +template <> +struct OperandTraits<BranchInst> : HungoffOperandTraits<> { + // we need to access operands via OperandList, since + // the NumOperands may change from 3 to 1 + static inline void *allocate(unsigned); // FIXME +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) + //===----------------------------------------------------------------------===// // SwitchInst Class //===----------------------------------------------------------------------===// @@ -1699,6 +1764,7 @@ private: /// SwitchInst - Multiway switch /// class SwitchInst : public TerminatorInst { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -1707,6 +1773,10 @@ class SwitchInst : public TerminatorInst { SwitchInst(const SwitchInst &RI); void init(Value *Value, BasicBlock *Default, unsigned NumCases); void resizeOperands(unsigned No); + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } /// SwitchInst ctor - Create a new switch instruction, specifying a value to /// switch on and a default destination. The number of additional cases can /// be specified here to make memory allocation more efficient. This @@ -1721,18 +1791,19 @@ class SwitchInst : public TerminatorInst { SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, BasicBlock *InsertAtEnd); public: - static SwitchInst *Create(Value *Value, BasicBlock *Default, unsigned NumCases, - Instruction *InsertBefore = 0) { - return new(NumCases/*FIXME*/) - SwitchInst(Value, Default, NumCases, InsertBefore); + static SwitchInst *Create(Value *Value, BasicBlock *Default, + unsigned NumCases, Instruction *InsertBefore = 0) { + return new SwitchInst(Value, Default, NumCases, InsertBefore); } - static SwitchInst *Create(Value *Value, BasicBlock *Default, unsigned NumCases, - BasicBlock *InsertAtEnd) { - return new(NumCases/*FIXME*/) - SwitchInst(Value, Default, NumCases, InsertAtEnd); + static SwitchInst *Create(Value *Value, BasicBlock *Default, + unsigned NumCases, BasicBlock *InsertAtEnd) { + return new SwitchInst(Value, Default, NumCases, InsertAtEnd); } ~SwitchInst(); + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + // Accessor Methods for Switch stmt Value *getCondition() const { return getOperand(0); } void setCondition(Value *V) { setOperand(0, V); } @@ -1805,7 +1876,7 @@ public: } void setSuccessor(unsigned idx, BasicBlock *NewSucc) { assert(idx < getNumSuccessors() && "Successor # out of range for switch!"); - setOperand(idx*2+1, reinterpret_cast<Value*>(NewSucc)); + setOperand(idx*2+1, NewSucc); } // getSuccessorValue - Return the value associated with the specified @@ -1829,6 +1900,13 @@ private: virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; +template <> +struct OperandTraits<SwitchInst> : HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) + + //===----------------------------------------------------------------------===// // InvokeInst Class //===----------------------------------------------------------------------===// @@ -1866,15 +1944,10 @@ class InvokeInst : public TerminatorInst { /// /// @brief Construct an InvokeInst from a range of arguments template<typename InputIterator> - InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - InputIterator ArgBegin, InputIterator ArgEnd, - const std::string &Name = "", Instruction *InsertBefore = 0) - : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Invoke, 0, 0, InsertBefore) { - init(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name, - typename std::iterator_traits<InputIterator>::iterator_category()); - } + inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + unsigned Values, + const std::string &Name, Instruction *InsertBefore); /// Construct an InvokeInst given a range of arguments. /// InputIterator must be a random-access iterator pointing to @@ -1884,38 +1957,36 @@ class InvokeInst : public TerminatorInst { /// /// @brief Construct an InvokeInst from a range of arguments template<typename InputIterator> - InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - InputIterator ArgBegin, InputIterator ArgEnd, - const std::string &Name, BasicBlock *InsertAtEnd) - : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Invoke, 0, 0, InsertAtEnd) { - init(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name, - typename std::iterator_traits<InputIterator>::iterator_category()); - } + inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + unsigned Values, + const std::string &Name, BasicBlock *InsertAtEnd); public: template<typename InputIterator> - static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, + static InvokeInst *Create(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, InputIterator ArgBegin, InputIterator ArgEnd, const std::string &Name = "", Instruction *InsertBefore = 0) { - return new(ArgEnd - ArgBegin + 3) - InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name, InsertBefore); + unsigned Values(ArgEnd - ArgBegin + 3); + return new(Values) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, + Values, Name, InsertBefore); } template<typename InputIterator> - static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, - BasicBlock *IfException, + static InvokeInst *Create(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, InputIterator ArgBegin, InputIterator ArgEnd, const std::string &Name, BasicBlock *InsertAtEnd) { - return new(ArgEnd - ArgBegin + 3) - InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name, InsertAtEnd); + unsigned Values(ArgEnd - ArgBegin + 3); + return new(Values) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, + Values, Name, InsertAtEnd); } - ~InvokeInst(); - virtual InvokeInst *clone() const; + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + /// getCallingConv/setCallingConv - Get or set the calling convention of this /// function call. unsigned getCallingConv() const { return SubclassData; } @@ -1985,11 +2056,11 @@ public: return cast<BasicBlock>(getOperand(2)); } void setNormalDest(BasicBlock *B) { - setOperand(1, reinterpret_cast<Value*>(B)); + setOperand(1, B); } void setUnwindDest(BasicBlock *B) { - setOperand(2, reinterpret_cast<Value*>(B)); + setOperand(2, B); } BasicBlock *getSuccessor(unsigned i) const { @@ -1999,7 +2070,7 @@ public: void setSuccessor(unsigned idx, BasicBlock *NewSucc) { assert(idx < 2 && "Successor # out of range for invoke!"); - setOperand(idx+1, reinterpret_cast<Value*>(NewSucc)); + setOperand(idx+1, NewSucc); } unsigned getNumSuccessors() const { return 2; } @@ -2018,6 +2089,40 @@ private: virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; +template <> +struct OperandTraits<InvokeInst> : VariadicOperandTraits<3> { +}; + +template<typename InputIterator> +InvokeInst::InvokeInst(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + unsigned Values, + const std::string &Name, Instruction *InsertBefore) + : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, + OperandTraits<InvokeInst>::op_end(this) - Values, + Values, InsertBefore) { + init(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name, + typename std::iterator_traits<InputIterator>::iterator_category()); +} +template<typename InputIterator> +InvokeInst::InvokeInst(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + InputIterator ArgBegin, InputIterator ArgEnd, + unsigned Values, + const std::string &Name, BasicBlock *InsertAtEnd) + : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, + OperandTraits<InvokeInst>::op_end(this) - Values, + Values, InsertAtEnd) { + init(Func, IfNormal, IfException, ArgBegin, ArgEnd, Name, + typename std::iterator_traits<InputIterator>::iterator_category()); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value) //===----------------------------------------------------------------------===// // UnwindInst Class @@ -2572,11 +2677,10 @@ public: /// class GetResultInst : public /*FIXME: Unary*/Instruction { void *operator new(size_t, unsigned); // DO NOT IMPLEMENT - Use Aggr; unsigned Idx; GetResultInst(const GetResultInst &GRI) : - Instruction(GRI.getType(), Instruction::GetResult, &Aggr, 1) { - Aggr.init(GRI.Aggr, this); + Instruction(GRI.getType(), Instruction::GetResult, &Op<0>(), 1) { + Op<0>().init(GRI.Op<0>(), this); Idx = GRI.Idx; } @@ -2585,9 +2689,9 @@ public: void *operator new(size_t s) { return User::operator new(s, 1); } - explicit GetResultInst(Value *Aggr, unsigned index, - const std::string &Name = "", - Instruction *InsertBefore = 0); + GetResultInst(Value *Aggr, unsigned index, + const std::string &Name = "", + Instruction *InsertBefore = 0); /// isValidOperands - Return true if an getresult instruction can be /// formed with the specified operands. @@ -2607,7 +2711,8 @@ public: return Idx; } - unsigned getNumOperands() const { return 1; } + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const GetResultInst *) { return true; } @@ -2619,6 +2724,14 @@ public: } }; +// FIXME: these are redundant if GetResultInst < UnaryInstruction +template <> +struct OperandTraits<GetResultInst> : FixedNumOperandTraits<1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetResultInst, Value) + + } // End llvm namespace #endif |