#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
Type *SourceElementType;
Type *ResultElementType;
+ void anchor() override;
+
GetElementPtrInst(const GetElementPtrInst &GEPI);
void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr);
/// must be identical types.
/// \brief Represent an integer comparison operator.
class ICmpInst: public CmpInst {
+ void anchor() override;
+
void AssertOK() {
assert(getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE &&
getPredicate() <= CmpInst::LAST_ICMP_PREDICATE &&
BasicBlock *InsertAtEnd) {
return new(1) CallInst(F, NameStr, InsertAtEnd);
}
+
+ /// \brief Create a clone of \p CI with a different set of operand bundles and
+ /// insert it before \p InsertPt.
+ ///
+ /// The returned call instruction is identical \p CI in every way except that
+ /// the operand bundles for the new instruction are set to the operand bundles
+ /// in \p Bundles.
+ static CallInst *Create(CallInst *CI, ArrayRef<OperandBundleDef> Bundles,
+ Instruction *InsertPt = nullptr);
+
/// CreateMalloc - Generate the IR for a call to malloc:
/// 1. Compute the malloc call's argument as the specified type's size,
/// possibly multiplied by the array size if the array size is not
}
// Note that 'musttail' implies 'tail'.
- enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 };
+ enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2,
+ TCK_NoTail = 3 };
TailCallKind getTailCallKind() const {
return TailCallKind(getSubclassDataFromInstruction() & 3);
}
bool isTailCall() const {
- return (getSubclassDataFromInstruction() & 3) != TCK_None;
+ unsigned Kind = getSubclassDataFromInstruction() & 3;
+ return Kind == TCK_Tail || Kind == TCK_MustTail;
}
bool isMustTailCall() const {
return (getSubclassDataFromInstruction() & 3) == TCK_MustTail;
}
+ bool isNoTailCall() const {
+ return (getSubclassDataFromInstruction() & 3) == TCK_NoTail;
+ }
void setTailCall(bool isTC = true) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) |
unsigned(isTC ? TCK_Tail : TCK_None));
setOperand(i, v);
}
- /// arg_operands - iteration adapter for range-for loops.
+ /// \brief Return the iterator pointing to the beginning of the argument list.
+ op_iterator arg_begin() { return op_begin(); }
+
+ /// \brief Return the iterator pointing to the end of the argument list.
+ op_iterator arg_end() {
+ // [ call args ], [ operand bundles ], callee
+ return op_end() - getNumTotalBundleOperands() - 1;
+ };
+
+ /// \brief Iteration adapter for range-for loops.
iterator_range<op_iterator> arg_operands() {
- // The last operand in the op list is the callee - it's not one of the args
- // so we don't want to iterate over it.
- return iterator_range<op_iterator>(
- op_begin(), op_end() - getNumTotalBundleOperands() - 1);
+ return make_range(arg_begin(), arg_end());
}
- /// arg_operands - iteration adapter for range-for loops.
+ /// \brief Return the iterator pointing to the beginning of the argument list.
+ const_op_iterator arg_begin() const { return op_begin(); }
+
+ /// \brief Return the iterator pointing to the end of the argument list.
+ const_op_iterator arg_end() const {
+ // [ call args ], [ operand bundles ], callee
+ return op_end() - getNumTotalBundleOperands() - 1;
+ };
+
+ /// \brief Iteration adapter for range-for loops.
iterator_range<const_op_iterator> arg_operands() const {
- return iterator_range<const_op_iterator>(
- op_begin(), op_end() - getNumTotalBundleOperands() - 1);
+ return make_range(arg_begin(), arg_end());
}
/// \brief Wrappers for getting the \c Use of a call argument.
return static_cast<CallingConv::ID>(getSubclassDataFromInstruction() >> 2);
}
void setCallingConv(CallingConv::ID CC) {
+ auto ID = static_cast<unsigned>(CC);
+ assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention");
setInstructionSubclassData((getSubclassDataFromInstruction() & 3) |
- (static_cast<unsigned>(CC) << 2));
+ (ID << 2));
}
/// getAttributes - Return the parameter attributes for this call.
/// \brief Determine whether the call or the callee has the given attributes.
bool paramHasAttr(unsigned i, Attribute::AttrKind A) const;
+ /// \brief Return true if the data operand at index \p i has the attribute \p
+ /// A.
+ ///
+ /// Data operands include call arguments and values used in operand bundles,
+ /// but does not include the callee operand. This routine dispatches to the
+ /// underlying AttributeList or the OperandBundleUser as appropriate.
+ ///
+ /// The index \p i is interpreted as
+ ///
+ /// \p i == Attribute::ReturnIndex -> the return value
+ /// \p i in [1, arg_size + 1) -> argument number (\p i - 1)
+ /// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index
+ /// (\p i - 1) in the operand list.
+ bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const;
+
/// \brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
return AttributeList.getParamAlignment(i);
return AttributeList.getDereferenceableOrNullBytes(i);
}
+ /// @brief Determine if the parameter or return value is marked with NoAlias
+ /// attribute.
+ /// @param n The parameter to check. 1 is the first parameter, 0 is the return
+ bool doesNotAlias(unsigned n) const {
+ return AttributeList.hasAttribute(n, Attribute::NoAlias);
+ }
+
/// \brief Return true if the call should not be treated as a call to a
/// builtin.
bool isNoBuiltin() const {
/// \brief Determine if the call returns a structure through first
/// pointer argument.
bool hasStructRetAttr() const {
+ if (getNumArgOperands() == 0)
+ return false;
+
// Be friendly and also check the callee.
return paramHasAttr(1, Attribute::StructRet);
}
template <typename AttrKind> bool hasFnAttrImpl(AttrKind A) const {
if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, A))
return true;
+
+ // Operand bundles override attributes on the called function, but don't
+ // override attributes directly present on the call instruction.
+ if (isFnAttrDisallowedByOpBundle(A))
+ return false;
+
if (const Function *F = getCalledFunction())
return F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, A);
return false;
inline idx_iterator idx_begin() const { return Indices.begin(); }
inline idx_iterator idx_end() const { return Indices.end(); }
inline iterator_range<idx_iterator> indices() const {
- return iterator_range<idx_iterator>(idx_begin(), idx_end());
+ return make_range(idx_begin(), idx_end());
}
Value *getAggregateOperand() {
inline idx_iterator idx_begin() const { return Indices.begin(); }
inline idx_iterator idx_end() const { return Indices.end(); }
inline iterator_range<idx_iterator> indices() const {
- return iterator_range<idx_iterator>(idx_begin(), idx_end());
+ return make_range(idx_begin(), idx_end());
}
Value *getAggregateOperand() {
// scientist's overactive imagination.
//
class PHINode : public Instruction {
+ void anchor() override;
+
void *operator new(size_t, unsigned) = delete;
/// ReservedSpace - The number of operands actually allocated. NumOperands is
/// the number actually in use.
/// cases - iteration adapter for range-for loops.
iterator_range<CaseIt> cases() {
- return iterator_range<CaseIt>(case_begin(), case_end());
+ return make_range(case_begin(), case_end());
}
/// cases - iteration adapter for range-for loops.
iterator_range<ConstCaseIt> cases() const {
- return iterator_range<ConstCaseIt>(case_begin(), case_end());
+ return make_range(case_begin(), case_end());
}
/// Returns an iterator that points to the default case.
InsertAtEnd);
}
+ /// \brief Create a clone of \p II with a different set of operand bundles and
+ /// insert it before \p InsertPt.
+ ///
+ /// The returned invoke instruction is identical to \p II in every way except
+ /// that the operand bundles for the new instruction are set to the operand
+ /// bundles in \p Bundles.
+ static InvokeInst *Create(InvokeInst *II, ArrayRef<OperandBundleDef> Bundles,
+ Instruction *InsertPt = nullptr);
+
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
setOperand(i, v);
}
- /// arg_operands - iteration adapter for range-for loops.
+ /// \brief Return the iterator pointing to the beginning of the argument list.
+ op_iterator arg_begin() { return op_begin(); }
+
+ /// \brief Return the iterator pointing to the end of the argument list.
+ op_iterator arg_end() {
+ // [ invoke args ], [ operand bundles ], normal dest, unwind dest, callee
+ return op_end() - getNumTotalBundleOperands() - 3;
+ };
+
+ /// \brief Iteration adapter for range-for loops.
iterator_range<op_iterator> arg_operands() {
- return iterator_range<op_iterator>(
- op_begin(), op_end() - getNumTotalBundleOperands() - 3);
+ return make_range(arg_begin(), arg_end());
}
- /// arg_operands - iteration adapter for range-for loops.
+ /// \brief Return the iterator pointing to the beginning of the argument list.
+ const_op_iterator arg_begin() const { return op_begin(); }
+
+ /// \brief Return the iterator pointing to the end of the argument list.
+ const_op_iterator arg_end() const {
+ // [ invoke args ], [ operand bundles ], normal dest, unwind dest, callee
+ return op_end() - getNumTotalBundleOperands() - 3;
+ };
+
+ /// \brief Iteration adapter for range-for loops.
iterator_range<const_op_iterator> arg_operands() const {
- return iterator_range<const_op_iterator>(
- op_begin(), op_end() - getNumTotalBundleOperands() - 3);
+ return make_range(arg_begin(), arg_end());
}
/// \brief Wrappers for getting the \c Use of a invoke argument.
return static_cast<CallingConv::ID>(getSubclassDataFromInstruction());
}
void setCallingConv(CallingConv::ID CC) {
- setInstructionSubclassData(static_cast<unsigned>(CC));
+ auto ID = static_cast<unsigned>(CC);
+ assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention");
+ setInstructionSubclassData(ID);
}
/// getAttributes - Return the parameter attributes for this invoke.
/// \brief Determine whether the call or the callee has the given attributes.
bool paramHasAttr(unsigned i, Attribute::AttrKind A) const;
+ /// \brief Return true if the data operand at index \p i has the attribute \p
+ /// A.
+ ///
+ /// Data operands include invoke arguments and values used in operand bundles,
+ /// but does not include the invokee operand, or the two successor blocks.
+ /// This routine dispatches to the underlying AttributeList or the
+ /// OperandBundleUser as appropriate.
+ ///
+ /// The index \p i is interpreted as
+ ///
+ /// \p i == Attribute::ReturnIndex -> the return value
+ /// \p i in [1, arg_size + 1) -> argument number (\p i - 1)
+ /// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index
+ /// (\p i - 1) in the operand list.
+ bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind A) const;
+
/// \brief Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
return AttributeList.getParamAlignment(i);
return AttributeList.getDereferenceableOrNullBytes(i);
}
+ /// @brief Determine if the parameter or return value is marked with NoAlias
+ /// attribute.
+ /// @param n The parameter to check. 1 is the first parameter, 0 is the return
+ bool doesNotAlias(unsigned n) const {
+ return AttributeList.hasAttribute(n, Attribute::NoAlias);
+ }
+
/// \brief Return true if the call should not be treated as a call to a
/// builtin.
bool isNoBuiltin() const {
/// \brief Determine if the call returns a structure through first
/// pointer argument.
bool hasStructRetAttr() const {
+ if (getNumArgOperands() == 0)
+ return false;
+
// Be friendly and also check the callee.
return paramHasAttr(1, Attribute::StructRet);
}
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value)
//===----------------------------------------------------------------------===//
-// CatchEndPadInst Class
+// CatchSwitchInst Class
//===----------------------------------------------------------------------===//
+class CatchSwitchInst : public TerminatorInst {
+ void *operator new(size_t, unsigned) = delete;
+ /// ReservedSpace - The number of operands actually allocated. NumOperands is
+ /// the number actually in use.
+ unsigned ReservedSpace;
+ // Operand[0] = Outer scope
+ // Operand[1] = Unwind block destination
+ // Operand[n] = BasicBlock to go to on match
+ CatchSwitchInst(const CatchSwitchInst &CSI);
+ void init(Value *ParentPad, BasicBlock *UnwindDest, unsigned NumReserved);
+ void growOperands(unsigned Size);
+ // allocate space for exactly zero operands
+ void *operator new(size_t s) { return User::operator new(s); }
+ /// CatchSwitchInst ctor - Create a new switch instruction, specifying a
+ /// default destination. The number of additional handlers can be specified
+ /// here to make memory allocation more efficient.
+ /// This constructor can also autoinsert before another instruction.
+ CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest,
+ unsigned NumHandlers, const Twine &NameStr,
+ Instruction *InsertBefore);
-class CatchEndPadInst : public TerminatorInst {
-private:
- CatchEndPadInst(const CatchEndPadInst &RI);
-
- void init(BasicBlock *UnwindBB);
- CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values,
- Instruction *InsertBefore = nullptr);
- CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values,
+ /// CatchSwitchInst ctor - Create a new switch instruction, specifying a
+ /// default destination. The number of additional handlers can be specified
+ /// here to make memory allocation more efficient.
+ /// This constructor also autoinserts at the end of the specified BasicBlock.
+ CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest,
+ unsigned NumHandlers, const Twine &NameStr,
BasicBlock *InsertAtEnd);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
- CatchEndPadInst *cloneImpl() const;
+ CatchSwitchInst *cloneImpl() const;
public:
- static CatchEndPadInst *Create(LLVMContext &C, BasicBlock *UnwindBB = nullptr,
+ static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest,
+ unsigned NumHandlers,
+ const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
- unsigned Values = UnwindBB ? 1 : 0;
- return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertBefore);
+ return new CatchSwitchInst(ParentPad, UnwindDest, NumHandlers, NameStr,
+ InsertBefore);
}
- static CatchEndPadInst *Create(LLVMContext &C, BasicBlock *UnwindBB,
+ static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest,
+ unsigned NumHandlers, const Twine &NameStr,
BasicBlock *InsertAtEnd) {
- unsigned Values = UnwindBB ? 1 : 0;
- return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertAtEnd);
+ return new CatchSwitchInst(ParentPad, UnwindDest, NumHandlers, NameStr,
+ InsertAtEnd);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+ // Accessor Methods for CatchSwitch stmt
+ Value *getParentPad() const { return getOperand(0); }
+ void setParentPad(Value *ParentPad) { setOperand(0, ParentPad); }
+
+ // Accessor Methods for CatchSwitch stmt
bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
bool unwindsToCaller() const { return !hasUnwindDest(); }
-
- /// Convenience accessor. Returns null if there is no return value.
- unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
-
BasicBlock *getUnwindDest() const {
- return hasUnwindDest() ? cast<BasicBlock>(Op<-1>()) : nullptr;
+ if (hasUnwindDest())
+ return cast<BasicBlock>(getOperand(1));
+ return nullptr;
}
- void setUnwindDest(BasicBlock *NewDest) {
- assert(NewDest);
- Op<-1>() = NewDest;
+ void setUnwindDest(BasicBlock *UnwindDest) {
+ assert(UnwindDest);
+ assert(hasUnwindDest());
+ setOperand(1, UnwindDest);
}
- // Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const Instruction *I) {
- return (I->getOpcode() == Instruction::CatchEndPad);
- }
- static inline bool classof(const Value *V) {
- return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ /// getNumHandlers - return the number of 'handlers' in this catchswitch
+ /// instruction, except the default handler
+ unsigned getNumHandlers() const {
+ if (hasUnwindDest())
+ return getNumOperands() - 2;
+ return getNumOperands() - 1;
}
private:
- BasicBlock *getSuccessorV(unsigned Idx) const override;
- unsigned getNumSuccessorsV() const override;
- void setSuccessorV(unsigned Idx, BasicBlock *B) override;
-
- // Shadow Instruction::setInstructionSubclassData with a private forwarding
- // method so that subclasses cannot accidentally use it.
- void setInstructionSubclassData(unsigned short D) {
- Instruction::setInstructionSubclassData(D);
+ static BasicBlock *handler_helper(Value *V) { return cast<BasicBlock>(V); }
+ static const BasicBlock *handler_helper(const Value *V) {
+ return cast<BasicBlock>(V);
}
-};
-
-template <>
-struct OperandTraits<CatchEndPadInst>
- : public VariadicOperandTraits<CatchEndPadInst> {};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchEndPadInst, Value)
-
-//===----------------------------------------------------------------------===//
-// CatchPadInst Class
-//===----------------------------------------------------------------------===//
-
-class CatchPadInst : public TerminatorInst {
-private:
- void init(BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, const Twine &NameStr);
-
- CatchPadInst(const CatchPadInst &CPI);
-
- explicit CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, unsigned Values,
- const Twine &NameStr, Instruction *InsertBefore);
- explicit CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, unsigned Values,
- const Twine &NameStr, BasicBlock *InsertAtEnd);
-
-protected:
- // Note: Instruction needs to be a friend here to call cloneImpl.
- friend class Instruction;
- CatchPadInst *cloneImpl() const;
public:
- static CatchPadInst *Create(BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, const Twine &NameStr = "",
- Instruction *InsertBefore = nullptr) {
- unsigned Values = unsigned(Args.size()) + 2;
- return new (Values) CatchPadInst(IfNormal, IfException, Args, Values,
- NameStr, InsertBefore);
- }
- static CatchPadInst *Create(BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, const Twine &NameStr,
- BasicBlock *InsertAtEnd) {
- unsigned Values = unsigned(Args.size()) + 2;
- return new (Values)
- CatchPadInst(IfNormal, IfException, Args, Values, NameStr, InsertAtEnd);
- }
+ typedef std::pointer_to_unary_function<Value *, BasicBlock *> DerefFnTy;
+ typedef mapped_iterator<op_iterator, DerefFnTy> handler_iterator;
+ typedef iterator_range<handler_iterator> handler_range;
- /// Provide fast operand accessors
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- /// getNumArgOperands - Return the number of catchpad arguments.
- ///
- unsigned getNumArgOperands() const { return getNumOperands() - 2; }
+ typedef std::pointer_to_unary_function<const Value *, const BasicBlock *>
+ ConstDerefFnTy;
+ typedef mapped_iterator<const_op_iterator, ConstDerefFnTy> const_handler_iterator;
+ typedef iterator_range<const_handler_iterator> const_handler_range;
- /// getArgOperand/setArgOperand - Return/set the i-th catchpad argument.
- ///
- Value *getArgOperand(unsigned i) const { return getOperand(i); }
- void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
+ /// Returns an iterator that points to the first handler in CatchSwitchInst.
+ handler_iterator handler_begin() {
+ op_iterator It = op_begin() + 1;
+ if (hasUnwindDest())
+ ++It;
+ return handler_iterator(It, DerefFnTy(handler_helper));
+ }
+ /// Returns an iterator that points to the first handler in the
+ /// CatchSwitchInst.
+ const_handler_iterator handler_begin() const {
+ const_op_iterator It = op_begin() + 1;
+ if (hasUnwindDest())
+ ++It;
+ return const_handler_iterator(It, ConstDerefFnTy(handler_helper));
+ }
- /// arg_operands - iteration adapter for range-for loops.
- iterator_range<op_iterator> arg_operands() {
- return iterator_range<op_iterator>(op_begin(), op_end() - 2);
+ /// Returns a read-only iterator that points one past the last
+ /// handler in the CatchSwitchInst.
+ handler_iterator handler_end() {
+ return handler_iterator(op_end(), DerefFnTy(handler_helper));
+ }
+ /// Returns an iterator that points one past the last handler in the
+ /// CatchSwitchInst.
+ const_handler_iterator handler_end() const {
+ return const_handler_iterator(op_end(), ConstDerefFnTy(handler_helper));
}
- /// arg_operands - iteration adapter for range-for loops.
- iterator_range<const_op_iterator> arg_operands() const {
- return iterator_range<const_op_iterator>(op_begin(), op_end() - 2);
+ /// handlers - iteration adapter for range-for loops.
+ handler_range handlers() {
+ return make_range(handler_begin(), handler_end());
}
- /// \brief Wrappers for getting the \c Use of a catchpad argument.
- const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); }
- Use &getArgOperandUse(unsigned i) { return getOperandUse(i); }
+ /// handlers - iteration adapter for range-for loops.
+ const_handler_range handlers() const {
+ return make_range(handler_begin(), handler_end());
+ }
- // get*Dest - Return the destination basic blocks...
- BasicBlock *getNormalDest() const { return cast<BasicBlock>(Op<-2>()); }
- BasicBlock *getUnwindDest() const { return cast<BasicBlock>(Op<-1>()); }
- void setNormalDest(BasicBlock *B) { Op<-2>() = B; }
- void setUnwindDest(BasicBlock *B) { Op<-1>() = B; }
+ /// addHandler - Add an entry to the switch instruction...
+ /// Note:
+ /// This action invalidates handler_end(). Old handler_end() iterator will
+ /// point to the added handler.
+ void addHandler(BasicBlock *Dest);
- BasicBlock *getSuccessor(unsigned i) const {
- assert(i < 2 && "Successor # out of range for catchpad!");
- return i == 0 ? getNormalDest() : getUnwindDest();
+ unsigned getNumSuccessors() const { return getNumOperands() - 1; }
+ BasicBlock *getSuccessor(unsigned Idx) const {
+ assert(Idx < getNumSuccessors() &&
+ "Successor # out of range for catchswitch!");
+ return cast<BasicBlock>(getOperand(Idx + 1));
}
-
- void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
- assert(idx < 2 && "Successor # out of range for catchpad!");
- *(&Op<-2>() + idx) = NewSucc;
+ void setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
+ assert(Idx < getNumSuccessors() &&
+ "Successor # out of range for catchswitch!");
+ setOperand(Idx + 1, NewSucc);
}
- unsigned getNumSuccessors() const { return 2; }
-
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
- return I->getOpcode() == Instruction::CatchPad;
+ return I->getOpcode() == Instruction::CatchSwitch;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
private:
- BasicBlock *getSuccessorV(unsigned idx) const override;
+ BasicBlock *getSuccessorV(unsigned Idx) const override;
unsigned getNumSuccessorsV() const override;
- void setSuccessorV(unsigned idx, BasicBlock *B) override;
+ void setSuccessorV(unsigned Idx, BasicBlock *B) override;
};
template <>
-struct OperandTraits<CatchPadInst>
- : public VariadicOperandTraits<CatchPadInst, /*MINARITY=*/2> {};
+struct OperandTraits<CatchSwitchInst> : public HungoffOperandTraits<2> {};
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchPadInst, Value)
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchSwitchInst, Value)
//===----------------------------------------------------------------------===//
-// TerminatePadInst Class
+// CleanupPadInst Class
//===----------------------------------------------------------------------===//
-
-class TerminatePadInst : public TerminatorInst {
+class CleanupPadInst : public FuncletPadInst {
private:
- void init(BasicBlock *BB, ArrayRef<Value *> Args);
-
- TerminatePadInst(const TerminatePadInst &TPI);
-
- explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB,
- ArrayRef<Value *> Args, unsigned Values,
- Instruction *InsertBefore);
- explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB,
- ArrayRef<Value *> Args, unsigned Values,
- BasicBlock *InsertAtEnd);
-
-protected:
- // Note: Instruction needs to be a friend here to call cloneImpl.
- friend class Instruction;
- TerminatePadInst *cloneImpl() const;
+ explicit CleanupPadInst(Value *ParentPad, ArrayRef<Value *> Args,
+ unsigned Values, const Twine &NameStr,
+ Instruction *InsertBefore)
+ : FuncletPadInst(Instruction::CleanupPad, ParentPad, Args, Values,
+ NameStr, InsertBefore) {}
+ explicit CleanupPadInst(Value *ParentPad, ArrayRef<Value *> Args,
+ unsigned Values, const Twine &NameStr,
+ BasicBlock *InsertAtEnd)
+ : FuncletPadInst(Instruction::CleanupPad, ParentPad, Args, Values,
+ NameStr, InsertAtEnd) {}
public:
- static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB = nullptr,
- ArrayRef<Value *> Args = None,
- Instruction *InsertBefore = nullptr) {
- unsigned Values = unsigned(Args.size());
- if (BB)
- ++Values;
- return new (Values) TerminatePadInst(C, BB, Args, Values, InsertBefore);
- }
- static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB,
- ArrayRef<Value *> Args,
- BasicBlock *InsertAtEnd) {
- unsigned Values = unsigned(Args.size());
- if (BB)
- ++Values;
- return new (Values) TerminatePadInst(C, BB, Args, Values, InsertAtEnd);
- }
-
- /// Provide fast operand accessors
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
-
- bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
- bool unwindsToCaller() const { return !hasUnwindDest(); }
-
- /// getNumArgOperands - Return the number of terminatepad arguments.
- ///
- unsigned getNumArgOperands() const {
- unsigned NumOperands = getNumOperands();
- if (hasUnwindDest())
- return NumOperands - 1;
- return NumOperands;
- }
-
- /// getArgOperand/setArgOperand - Return/set the i-th terminatepad argument.
- ///
- Value *getArgOperand(unsigned i) const { return getOperand(i); }
- void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
-
- const_op_iterator arg_end() const {
- if (hasUnwindDest())
- return op_end() - 1;
- return op_end();
- }
-
- op_iterator arg_end() {
- if (hasUnwindDest())
- return op_end() - 1;
- return op_end();
- }
-
- /// arg_operands - iteration adapter for range-for loops.
- iterator_range<op_iterator> arg_operands() {
- return iterator_range<op_iterator>(op_begin(), arg_end());
- }
-
- /// arg_operands - iteration adapter for range-for loops.
- iterator_range<const_op_iterator> arg_operands() const {
- return iterator_range<const_op_iterator>(op_begin(), arg_end());
- }
-
- /// \brief Wrappers for getting the \c Use of a terminatepad argument.
- const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); }
- Use &getArgOperandUse(unsigned i) { return getOperandUse(i); }
-
- // get*Dest - Return the destination basic blocks...
- BasicBlock *getUnwindDest() const {
- if (!hasUnwindDest())
- return nullptr;
- return cast<BasicBlock>(Op<-1>());
+ static CleanupPadInst *Create(Value *ParentPad, ArrayRef<Value *> Args = None,
+ const Twine &NameStr = "",
+ Instruction *InsertBefore = nullptr) {
+ unsigned Values = 1 + Args.size();
+ return new (Values)
+ CleanupPadInst(ParentPad, Args, Values, NameStr, InsertBefore);
}
- void setUnwindDest(BasicBlock *B) {
- assert(B && hasUnwindDest());
- Op<-1>() = B;
+ static CleanupPadInst *Create(Value *ParentPad, ArrayRef<Value *> Args,
+ const Twine &NameStr, BasicBlock *InsertAtEnd) {
+ unsigned Values = 1 + Args.size();
+ return new (Values)
+ CleanupPadInst(ParentPad, Args, Values, NameStr, InsertAtEnd);
}
- unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
-
- // Methods for support type inquiry through isa, cast, and dyn_cast:
+ /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
- return I->getOpcode() == Instruction::TerminatePad;
+ return I->getOpcode() == Instruction::CleanupPad;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
-
-private:
- BasicBlock *getSuccessorV(unsigned idx) const override;
- unsigned getNumSuccessorsV() const override;
- void setSuccessorV(unsigned idx, BasicBlock *B) override;
-
- // Shadow Instruction::setInstructionSubclassData with a private forwarding
- // method so that subclasses cannot accidentally use it.
- void setInstructionSubclassData(unsigned short D) {
- Instruction::setInstructionSubclassData(D);
- }
};
-template <>
-struct OperandTraits<TerminatePadInst>
- : public VariadicOperandTraits<TerminatePadInst, /*MINARITY=*/1> {};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(TerminatePadInst, Value)
-
//===----------------------------------------------------------------------===//
-// CleanupPadInst Class
+// CatchPadInst Class
//===----------------------------------------------------------------------===//
-
-class CleanupPadInst : public Instruction {
+class CatchPadInst : public FuncletPadInst {
private:
- void init(ArrayRef<Value *> Args, const Twine &NameStr);
-
- CleanupPadInst(const CleanupPadInst &CPI);
-
- explicit CleanupPadInst(LLVMContext &C, ArrayRef<Value *> Args,
- const Twine &NameStr, Instruction *InsertBefore);
- explicit CleanupPadInst(LLVMContext &C, ArrayRef<Value *> Args,
- const Twine &NameStr, BasicBlock *InsertAtEnd);
-
-protected:
- // Note: Instruction needs to be a friend here to call cloneImpl.
- friend class Instruction;
- CleanupPadInst *cloneImpl() const;
+ explicit CatchPadInst(Value *CatchSwitch, ArrayRef<Value *> Args,
+ unsigned Values, const Twine &NameStr,
+ Instruction *InsertBefore)
+ : FuncletPadInst(Instruction::CatchPad, CatchSwitch, Args, Values,
+ NameStr, InsertBefore) {}
+ explicit CatchPadInst(Value *CatchSwitch, ArrayRef<Value *> Args,
+ unsigned Values, const Twine &NameStr,
+ BasicBlock *InsertAtEnd)
+ : FuncletPadInst(Instruction::CatchPad, CatchSwitch, Args, Values,
+ NameStr, InsertAtEnd) {}
public:
- static CleanupPadInst *Create(LLVMContext &C, ArrayRef<Value *> Args,
- const Twine &NameStr = "",
- Instruction *InsertBefore = nullptr) {
- return new (Args.size()) CleanupPadInst(C, Args, NameStr, InsertBefore);
+ static CatchPadInst *Create(Value *CatchSwitch, ArrayRef<Value *> Args,
+ const Twine &NameStr = "",
+ Instruction *InsertBefore = nullptr) {
+ unsigned Values = 1 + Args.size();
+ return new (Values)
+ CatchPadInst(CatchSwitch, Args, Values, NameStr, InsertBefore);
}
- static CleanupPadInst *Create(LLVMContext &C, ArrayRef<Value *> Args,
- const Twine &NameStr, BasicBlock *InsertAtEnd) {
- return new (Args.size()) CleanupPadInst(C, Args, NameStr, InsertAtEnd);
+ static CatchPadInst *Create(Value *CatchSwitch, ArrayRef<Value *> Args,
+ const Twine &NameStr, BasicBlock *InsertAtEnd) {
+ unsigned Values = 1 + Args.size();
+ return new (Values)
+ CatchPadInst(CatchSwitch, Args, Values, NameStr, InsertAtEnd);
}
- /// Provide fast operand accessors
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+ /// Convenience accessors
+ CatchSwitchInst *getCatchSwitch() const {
+ return cast<CatchSwitchInst>(Op<-1>());
+ }
+ void setCatchSwitch(Value *CatchSwitch) {
+ assert(CatchSwitch);
+ Op<-1>() = CatchSwitch;
+ }
- // Methods for support type inquiry through isa, cast, and dyn_cast:
+ /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
- return I->getOpcode() == Instruction::CleanupPad;
+ return I->getOpcode() == Instruction::CatchPad;
}
static inline bool classof(const Value *V) {
return isa<Instruction>(V) && classof(cast<Instruction>(V));
}
};
-template <>
-struct OperandTraits<CleanupPadInst>
- : public VariadicOperandTraits<CleanupPadInst, /*MINARITY=*/0> {};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupPadInst, Value)
-
//===----------------------------------------------------------------------===//
// CatchReturnInst Class
//===----------------------------------------------------------------------===//
class CatchReturnInst : public TerminatorInst {
CatchReturnInst(const CatchReturnInst &RI);
- void init(CatchPadInst *CatchPad, BasicBlock *BB);
- CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB,
- Instruction *InsertBefore);
- CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB,
- BasicBlock *InsertAtEnd);
+ void init(Value *CatchPad, BasicBlock *BB);
+ CatchReturnInst(Value *CatchPad, BasicBlock *BB, Instruction *InsertBefore);
+ CatchReturnInst(Value *CatchPad, BasicBlock *BB, BasicBlock *InsertAtEnd);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
CatchReturnInst *cloneImpl() const;
public:
- static CatchReturnInst *Create(CatchPadInst *CatchPad, BasicBlock *BB,
+ static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB,
Instruction *InsertBefore = nullptr) {
assert(CatchPad);
assert(BB);
return new (2) CatchReturnInst(CatchPad, BB, InsertBefore);
}
- static CatchReturnInst *Create(CatchPadInst *CatchPad, BasicBlock *BB,
+ static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB,
BasicBlock *InsertAtEnd) {
assert(CatchPad);
assert(BB);
}
unsigned getNumSuccessors() const { return 1; }
+ Value *getParentPad() const {
+ return getCatchPad()->getCatchSwitch()->getParentPad();
+ }
+
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::CatchRet);
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value)
-//===----------------------------------------------------------------------===//
-// CleanupEndPadInst Class
-//===----------------------------------------------------------------------===//
-
-class CleanupEndPadInst : public TerminatorInst {
-private:
- CleanupEndPadInst(const CleanupEndPadInst &CEPI);
-
- void init(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB);
- CleanupEndPadInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB,
- unsigned Values, Instruction *InsertBefore = nullptr);
- CleanupEndPadInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB,
- unsigned Values, BasicBlock *InsertAtEnd);
-
-protected:
- // Note: Instruction needs to be a friend here to call cloneImpl.
- friend class Instruction;
- CleanupEndPadInst *cloneImpl() const;
-
-public:
- static CleanupEndPadInst *Create(CleanupPadInst *CleanupPad,
- BasicBlock *UnwindBB = nullptr,
- Instruction *InsertBefore = nullptr) {
- unsigned Values = UnwindBB ? 2 : 1;
- return new (Values)
- CleanupEndPadInst(CleanupPad, UnwindBB, Values, InsertBefore);
- }
- static CleanupEndPadInst *Create(CleanupPadInst *CleanupPad,
- BasicBlock *UnwindBB,
- BasicBlock *InsertAtEnd) {
- unsigned Values = UnwindBB ? 2 : 1;
- return new (Values)
- CleanupEndPadInst(CleanupPad, UnwindBB, Values, InsertAtEnd);
- }
-
- /// Provide fast operand accessors
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
-
- bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
- bool unwindsToCaller() const { return !hasUnwindDest(); }
-
- unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
-
- /// Convenience accessors
- CleanupPadInst *getCleanupPad() const {
- return cast<CleanupPadInst>(Op<-1>());
- }
- void setCleanupPad(CleanupPadInst *CleanupPad) {
- assert(CleanupPad);
- Op<-1>() = CleanupPad;
- }
-
- BasicBlock *getUnwindDest() const {
- return hasUnwindDest() ? cast<BasicBlock>(Op<-2>()) : nullptr;
- }
- void setUnwindDest(BasicBlock *NewDest) {
- assert(hasUnwindDest());
- assert(NewDest);
- Op<-2>() = NewDest;
- }
-
- // Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const Instruction *I) {
- return (I->getOpcode() == Instruction::CleanupEndPad);
- }
- static inline bool classof(const Value *V) {
- return isa<Instruction>(V) && classof(cast<Instruction>(V));
- }
-
-private:
- BasicBlock *getSuccessorV(unsigned Idx) const override;
- unsigned getNumSuccessorsV() const override;
- void setSuccessorV(unsigned Idx, BasicBlock *B) override;
-
- // Shadow Instruction::setInstructionSubclassData with a private forwarding
- // method so that subclasses cannot accidentally use it.
- void setInstructionSubclassData(unsigned short D) {
- Instruction::setInstructionSubclassData(D);
- }
-};
-
-template <>
-struct OperandTraits<CleanupEndPadInst>
- : public VariadicOperandTraits<CleanupEndPadInst, /*MINARITY=*/1> {};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupEndPadInst, Value)
-
//===----------------------------------------------------------------------===//
// CleanupReturnInst Class
//===----------------------------------------------------------------------===//
private:
CleanupReturnInst(const CleanupReturnInst &RI);
- void init(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB);
- CleanupReturnInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB,
- unsigned Values, Instruction *InsertBefore = nullptr);
- CleanupReturnInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB,
- unsigned Values, BasicBlock *InsertAtEnd);
+ void init(Value *CleanupPad, BasicBlock *UnwindBB);
+ CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values,
+ Instruction *InsertBefore = nullptr);
+ CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values,
+ BasicBlock *InsertAtEnd);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
CleanupReturnInst *cloneImpl() const;
public:
- static CleanupReturnInst *Create(CleanupPadInst *CleanupPad,
+ static CleanupReturnInst *Create(Value *CleanupPad,
BasicBlock *UnwindBB = nullptr,
Instruction *InsertBefore = nullptr) {
assert(CleanupPad);
return new (Values)
CleanupReturnInst(CleanupPad, UnwindBB, Values, InsertBefore);
}
- static CleanupReturnInst *Create(CleanupPadInst *CleanupPad,
- BasicBlock *UnwindBB,
+ static CleanupReturnInst *Create(Value *CleanupPad, BasicBlock *UnwindBB,
BasicBlock *InsertAtEnd) {
assert(CleanupPad);
unsigned Values = 1;
/// Convenience accessor.
CleanupPadInst *getCleanupPad() const {
- return cast<CleanupPadInst>(Op<-1>());
+ return cast<CleanupPadInst>(Op<0>());
}
void setCleanupPad(CleanupPadInst *CleanupPad) {
assert(CleanupPad);
- Op<-1>() = CleanupPad;
+ Op<0>() = CleanupPad;
}
unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
BasicBlock *getUnwindDest() const {
- return hasUnwindDest() ? cast<BasicBlock>(Op<-2>()) : nullptr;
+ return hasUnwindDest() ? cast<BasicBlock>(Op<1>()) : nullptr;
}
void setUnwindDest(BasicBlock *NewDest) {
assert(NewDest);
assert(hasUnwindDest());
- Op<-2>() = NewDest;
+ Op<1>() = NewDest;
}
// Methods for support type inquiry through isa, cast, and dyn_cast: