diff options
Diffstat (limited to 'include/llvm/IR')
64 files changed, 6275 insertions, 2608 deletions
diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index dd76a90aa5ea..fc04fe71cbf0 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -64,6 +64,11 @@ public: /// containing function, return the number of bytes known to be /// dereferenceable. Otherwise, zero is returned. uint64_t getDereferenceableBytes() const; + + /// \brief If this argument has the dereferenceable_or_null attribute on + /// it in its containing function, return the number of bytes known to be + /// dereferenceable. Otherwise, zero is returned. + uint64_t getDereferenceableOrNullBytes() const; /// \brief Return true if this argument has the byval attribute on it in its /// containing function. diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 5ff48d688918..e2a0a7ee395a 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -73,6 +73,7 @@ public: ByVal, ///< Pass structure by value InAlloca, ///< Pass structure in an alloca Cold, ///< Marks function as being in a cold path. + Convergent, ///< Can only be moved to control-equivalent blocks InlineHint, ///< Source said inlining was desirable InReg, ///< Force argument to be passed in register JumpTable, ///< Build jump-instruction tables and replace refs. @@ -89,6 +90,7 @@ public: ///< often, so lazy binding isn't worthwhile NonNull, ///< Pointer is known to be not null Dereferenceable, ///< Pointer is known to be dereferenceable + DereferenceableOrNull, ///< Pointer is either null or dereferenceable NoRedZone, ///< Disable redzone NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack @@ -136,6 +138,8 @@ public: static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align); static Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes); + static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, + uint64_t Bytes); //===--------------------------------------------------------------------===// // Attribute Accessors @@ -185,6 +189,10 @@ public: /// dereferenceable attribute (or zero if unknown). uint64_t getDereferenceableBytes() const; + /// \brief Returns the number of dereferenceable_or_null bytes from the + /// dereferenceable_or_null attribute (or zero if unknown). + uint64_t getDereferenceableOrNullBytes() const; + /// \brief The Attribute is converted to a string of equivalent mnemonic. This /// is, presumably, for writing out the mnemonics for the assembly writer. std::string getAsString(bool InAttrGrp = false) const; @@ -253,35 +261,52 @@ public: ArrayRef<Attribute::AttrKind> Kind); static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B); - /// \brief Add an attribute to the attribute set at the given index. Since + /// \brief Add an attribute to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeSet addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const; - /// \brief Add an attribute to the attribute set at the given index. Since + /// \brief Add an attribute to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind) const; AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind, StringRef Value) const; - /// \brief Add attributes to the attribute set at the given index. Since + /// \brief Add attributes to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeSet addAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; /// \brief Remove the specified attribute at the specified index from this - /// attribute list. Since attribute lists are immutable, this returns the new - /// list. + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. AttributeSet removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const; /// \brief Remove the specified attributes at the specified index from this - /// attribute list. Since attribute lists are immutable, this returns the new - /// list. + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. AttributeSet removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; + /// \brief Remove the specified attributes at the specified index from this + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. + AttributeSet removeAttributes(LLVMContext &C, unsigned Index, + const AttrBuilder &Attrs) const; + + /// \brief Add the dereferenceable attribute to the attribute set at the given + /// index. Because attribute sets are immutable, this returns a new set. + AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + + /// \brief Add the dereferenceable_or_null attribute to the attribute set at + /// the given index. Because attribute sets are immutable, this returns a new + /// set. + AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + //===--------------------------------------------------------------------===// // AttributeSet Accessors //===--------------------------------------------------------------------===// @@ -326,6 +351,10 @@ public: /// \brief Get the number of dereferenceable bytes (or zero if unknown). uint64_t getDereferenceableBytes(unsigned Index) const; + /// \brief Get the number of dereferenceable_or_null bytes (or zero if + /// unknown). + uint64_t getDereferenceableOrNullBytes(unsigned Index) const; + /// \brief Return the attributes at the index as a string. std::string getAsString(unsigned Index, bool InAttrGrp = false) const; @@ -406,14 +435,19 @@ class AttrBuilder { uint64_t Alignment; uint64_t StackAlignment; uint64_t DerefBytes; + uint64_t DerefOrNullBytes; public: - AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {} + AttrBuilder() + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0) {} explicit AttrBuilder(uint64_t Val) - : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0) { addRawValue(Val); } AttrBuilder(const Attribute &A) - : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0) { addAttribute(A); } AttrBuilder(AttributeSet AS, unsigned Idx); @@ -441,6 +475,13 @@ public: /// \brief Add the attributes from the builder. AttrBuilder &merge(const AttrBuilder &B); + /// \brief Remove the attributes from the builder. + AttrBuilder &remove(const AttrBuilder &B); + + /// \brief Return true if the builder has any attribute that's in the + /// specified builder. + bool overlaps(const AttrBuilder &B) const; + /// \brief Return true if the builder has the specified attribute. bool contains(Attribute::AttrKind A) const { assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!"); @@ -471,6 +512,10 @@ public: /// attribute exists (zero is returned otherwise). uint64_t getDereferenceableBytes() const { return DerefBytes; } + /// \brief Retrieve the number of dereferenceable_or_null bytes, if the + /// dereferenceable_or_null attribute exists (zero is returned otherwise). + uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; } + /// \brief This turns an int alignment (which must be a power of 2) into the /// form used internally in Attribute. AttrBuilder &addAlignmentAttr(unsigned Align); @@ -483,6 +528,10 @@ public: /// internally in Attribute. AttrBuilder &addDereferenceableAttr(uint64_t Bytes); + /// \brief This turns the number of dereferenceable_or_null bytes into the + /// form used internally in Attribute. + AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes); + /// \brief Return true if the builder contains no target-independent /// attributes. bool empty() const { return Attrs.none(); } @@ -521,7 +570,7 @@ public: namespace AttributeFuncs { /// \brief Which attributes cannot be applied to a type. -AttributeSet typeIncompatible(Type *Ty, uint64_t Index); +AttrBuilder typeIncompatible(const Type *Ty); } // end AttributeFuncs namespace diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 7c7dd2ca5643..66581bfedbe6 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -28,33 +28,25 @@ class LandingPadInst; class TerminatorInst; class LLVMContext; class BlockAddress; +class Function; -template<> struct ilist_traits<Instruction> - : public SymbolTableListTraits<Instruction, BasicBlock> { +// Traits for intrusive list of basic blocks... +template<> struct ilist_traits<BasicBlock> + : public SymbolTableListTraits<BasicBlock, Function> { - /// \brief Return a node that marks the end of a list. - /// - /// The sentinel is relative to this instance, so we use a non-static - /// method. - Instruction *createSentinel() const { - // Since i(p)lists always publicly derive from their corresponding traits, - // placing a data member in this class will augment the i(p)list. But since - // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>, - // there is a legal viable downcast from it to NodeTy. We use this trick to - // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the - // sentinel. Dereferencing the sentinel is forbidden (save the - // ilist_node<NodeTy>), so no one will ever notice the superposition. - return static_cast<Instruction*>(&Sentinel); - } - static void destroySentinel(Instruction*) {} + BasicBlock *createSentinel() const; + static void destroySentinel(BasicBlock*) {} - Instruction *provideInitialHead() const { return createSentinel(); } - Instruction *ensureHead(Instruction*) const { return createSentinel(); } - static void noteHead(Instruction*, Instruction*) {} + BasicBlock *provideInitialHead() const { return createSentinel(); } + BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } + static void noteHead(BasicBlock*, BasicBlock*) {} + + static ValueSymbolTable *getSymTab(Function *ItemParent); private: - mutable ilist_half_node<Instruction> Sentinel; + mutable ilist_half_node<BasicBlock> Sentinel; }; + /// \brief LLVM Basic Block Representation /// /// This represents a single basic block in LLVM. A basic block is simply a @@ -82,8 +74,8 @@ private: void setParent(Function *parent); friend class SymbolTableListTraits<BasicBlock, Function>; - BasicBlock(const BasicBlock &) LLVM_DELETED_FUNCTION; - void operator=(const BasicBlock &) LLVM_DELETED_FUNCTION; + BasicBlock(const BasicBlock &) = delete; + void operator=(const BasicBlock &) = delete; /// \brief Constructor. /// @@ -113,13 +105,18 @@ public: BasicBlock *InsertBefore = nullptr) { return new BasicBlock(Context, Name, Parent, InsertBefore); } - ~BasicBlock(); + ~BasicBlock() override; /// \brief Return the enclosing method, or null if none. const Function *getParent() const { return Parent; } Function *getParent() { return Parent; } - const DataLayout *getDataLayout() const; + /// \brief Return the module owning the function this basic block belongs to, + /// or nullptr it the function does not have a module. + /// + /// Note: this is undefined behavior if the block does not have a parent. + const Module *getModule() const; + Module *getModule(); /// \brief Returns the terminator instruction if the block is well formed or /// null if the block is not well formed. @@ -172,7 +169,9 @@ public: void removeFromParent(); /// \brief Unlink 'this' from the containing function and delete it. - void eraseFromParent(); + /// + // \returns an iterator pointing to the element after the erased one. + iplist<BasicBlock>::iterator eraseFromParent(); /// \brief Unlink this basic block from its current function and insert it /// into the function that \p MovePos lives in, right before \p MovePos. @@ -208,6 +207,24 @@ public: return const_cast<BasicBlock*>(this)->getUniquePredecessor(); } + /// \brief Return the successor of this block if it has a single successor. + /// Otherwise return a null pointer. + /// + /// This method is analogous to getSinglePredecessor above. + BasicBlock *getSingleSuccessor(); + const BasicBlock *getSingleSuccessor() const { + return const_cast<BasicBlock*>(this)->getSingleSuccessor(); + } + + /// \brief Return the successor of this block if it has a unique successor. + /// Otherwise return a null pointer. + /// + /// This method is analogous to getUniquePredecessor above. + BasicBlock *getUniqueSuccessor(); + const BasicBlock *getUniqueSuccessor() const { + return const_cast<BasicBlock*>(this)->getUniqueSuccessor(); + } + //===--------------------------------------------------------------------===// /// Instruction iterator methods /// @@ -320,6 +337,12 @@ private: } }; +// createSentinel is used to get hold of the node that marks the end of the +// list... (same trick used here as in ilist_traits<Instruction>) +inline BasicBlock *ilist_traits<BasicBlock>::createSentinel() const { + return static_cast<BasicBlock*>(&Sentinel); +} + // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef) diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h index 5400d2384868..f78220a52033 100644 --- a/include/llvm/IR/CFG.h +++ b/include/llvm/IR/CFG.h @@ -16,6 +16,7 @@ #define LLVM_IR_CFG_H #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" @@ -84,6 +85,8 @@ public: typedef PredIterator<BasicBlock, Value::user_iterator> pred_iterator; typedef PredIterator<const BasicBlock, Value::const_user_iterator> const_pred_iterator; +typedef llvm::iterator_range<pred_iterator> pred_range; +typedef llvm::iterator_range<const_pred_iterator> pred_const_range; inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } inline const_pred_iterator pred_begin(const BasicBlock *BB) { @@ -96,8 +99,12 @@ inline const_pred_iterator pred_end(const BasicBlock *BB) { inline bool pred_empty(const BasicBlock *BB) { return pred_begin(BB) == pred_end(BB); } - - +inline pred_range predecessors(BasicBlock *BB) { + return pred_range(pred_begin(BB), pred_end(BB)); +} +inline pred_const_range predecessors(const BasicBlock *BB) { + return pred_const_range(pred_begin(BB), pred_end(BB)); +} //===----------------------------------------------------------------------===// // BasicBlock succ_iterator definition @@ -114,7 +121,7 @@ public: typedef typename super::reference reference; private: - const Term_ Term; + Term_ Term; unsigned idx; typedef SuccIterator<Term_, BB_> Self; @@ -129,6 +136,8 @@ private: public: explicit SuccessorProxy(const Self &it) : it(it) {} + SuccessorProxy(const SuccessorProxy&) = default; + SuccessorProxy &operator=(SuccessorProxy r) { *this = reference(r); return *this; @@ -158,12 +167,6 @@ public: idx = 0; } - inline const Self &operator=(const Self &I) { - assert(Term == I.Term &&"Cannot assign iterators to two different blocks!"); - idx = I.idx; - return *this; - } - /// getSuccessorIndex - This is used to interface between code that wants to /// operate on terminator instructions directly. unsigned getSuccessorIndex() const { return idx; } @@ -247,6 +250,8 @@ public: typedef SuccIterator<TerminatorInst*, BasicBlock> succ_iterator; typedef SuccIterator<const TerminatorInst*, const BasicBlock> succ_const_iterator; +typedef llvm::iterator_range<succ_iterator> succ_range; +typedef llvm::iterator_range<succ_const_iterator> succ_const_range; inline succ_iterator succ_begin(BasicBlock *BB) { return succ_iterator(BB->getTerminator()); @@ -263,6 +268,13 @@ inline succ_const_iterator succ_end(const BasicBlock *BB) { inline bool succ_empty(const BasicBlock *BB) { return succ_begin(BB) == succ_end(BB); } +inline succ_range successors(BasicBlock *BB) { + return succ_range(succ_begin(BB), succ_end(BB)); +} +inline succ_const_range successors(const BasicBlock *BB) { + return succ_const_range(succ_begin(BB), succ_end(BB)); +} + template <typename T, typename U> struct isPodLike<SuccIterator<T, U> > { static const bool value = isPodLike<T>::value; diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index df082577a0e2..170d263dfc79 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -46,12 +46,13 @@ template <typename FunTy = const Function, class CallSiteBase { protected: PointerIntPair<InstrTy*, 1, bool> I; -public: + CallSiteBase() : I(nullptr, false) {} CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } - CallSiteBase(ValTy *II) { *this = get(II); } -protected: + explicit CallSiteBase(ValTy *II) { *this = get(II); } + +private: /// CallSiteBase::get - This static method is sort of like a constructor. It /// will create an appropriate call site for a Call or Invoke instruction, but /// it can also create a null initialized CallSiteBase object for something @@ -78,7 +79,7 @@ public: InstrTy *getInstruction() const { return I.getPointer(); } InstrTy *operator->() const { return I.getPointer(); } - LLVM_EXPLICIT operator bool() const { return I.getPointer(); } + explicit operator bool() const { return I.getPointer(); } /// getCalledValue - Return the pointer to function that is being called. /// @@ -151,7 +152,7 @@ public: IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); } bool arg_empty() const { return arg_end() == arg_begin(); } unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } - + /// getType - Return the type of the instruction that generated this call site /// Type *getType() const { return (*this)->getType(); } @@ -193,6 +194,14 @@ public: CALLSITE_DELEGATE_SETTER(setCallingConv(CC)); } + FunctionType *getFunctionType() const { + CALLSITE_DELEGATE_GETTER(getFunctionType()); + } + + void mutateFunctionType(FunctionType *Ty) const { + CALLSITE_DELEGATE_SETTER(mutateFunctionType(Ty)); + } + /// getAttributes/setAttributes - get or set the parameter attributes of /// the call. const AttributeSet &getAttributes() const { @@ -222,7 +231,13 @@ public: uint64_t getDereferenceableBytes(uint16_t i) const { CALLSITE_DELEGATE_GETTER(getDereferenceableBytes(i)); } - + + /// @brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(uint16_t i) const { + CALLSITE_DELEGATE_GETTER(getDereferenceableOrNullBytes(i)); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -349,15 +364,13 @@ private: class CallSite : public CallSiteBase<Function, Value, User, Instruction, CallInst, InvokeInst, User::op_iterator> { - typedef CallSiteBase<Function, Value, User, Instruction, - CallInst, InvokeInst, User::op_iterator> Base; public: CallSite() {} - CallSite(Base B) : Base(B) {} - CallSite(Value* V) : Base(V) {} - CallSite(CallInst *CI) : Base(CI) {} - CallSite(InvokeInst *II) : Base(II) {} - CallSite(Instruction *II) : Base(II) {} + CallSite(CallSiteBase B) : CallSiteBase(B) {} + CallSite(CallInst *CI) : CallSiteBase(CI) {} + CallSite(InvokeInst *II) : CallSiteBase(II) {} + explicit CallSite(Instruction *II) : CallSiteBase(II) {} + explicit CallSite(Value *V) : CallSiteBase(V) {} bool operator==(const CallSite &CS) const { return I == CS.I; } bool operator!=(const CallSite &CS) const { return I != CS.I; } @@ -371,13 +384,13 @@ private: /// ImmutableCallSite - establish a view to a call site for examination class ImmutableCallSite : public CallSiteBase<> { - typedef CallSiteBase<> Base; public: - ImmutableCallSite(const Value* V) : Base(V) {} - ImmutableCallSite(const CallInst *CI) : Base(CI) {} - ImmutableCallSite(const InvokeInst *II) : Base(II) {} - ImmutableCallSite(const Instruction *II) : Base(II) {} - ImmutableCallSite(CallSite CS) : Base(CS.getInstruction()) {} + ImmutableCallSite() {} + ImmutableCallSite(const CallInst *CI) : CallSiteBase(CI) {} + ImmutableCallSite(const InvokeInst *II) : CallSiteBase(II) {} + explicit ImmutableCallSite(const Instruction *II) : CallSiteBase(II) {} + explicit ImmutableCallSite(const Value *V) : CallSiteBase(V) {} + ImmutableCallSite(CallSite CS) : CallSiteBase(CS.getInstruction()) {} }; } // End llvm namespace diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h index 3e77a7709d5c..4d4c15fb68cd 100644 --- a/include/llvm/IR/Comdat.h +++ b/include/llvm/IR/Comdat.h @@ -49,7 +49,7 @@ private: friend class Module; Comdat(); Comdat(SelectionKind SK, StringMapEntry<Comdat> *Name); - Comdat(const Comdat &) LLVM_DELETED_FUNCTION; + Comdat(const Comdat &) = delete; // Points to the map in Module. StringMapEntry<Comdat> *Name; diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index d26991eaab75..75499e0a4db3 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -39,8 +39,8 @@ namespace llvm { /// don't have to worry about the lifetime of the objects. /// @brief LLVM Constant Representation class Constant : public User { - void operator=(const Constant &) LLVM_DELETED_FUNCTION; - Constant(const Constant &) LLVM_DELETED_FUNCTION; + void operator=(const Constant &) = delete; + Constant(const Constant &) = delete; void anchor() override; protected: diff --git a/include/llvm/IR/ConstantFolder.h b/include/llvm/IR/ConstantFolder.h index e271a1482117..fb6ca3b3184c 100644 --- a/include/llvm/IR/ConstantFolder.h +++ b/include/llvm/IR/ConstantFolder.h @@ -118,34 +118,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getGetElementPtr(C, Idx); + return ConstantExpr::getGetElementPtr(Ty, C, Idx); } - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getInBoundsGetElementPtr(C, Idx); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index 5e8cd34c4d69..9ded3ca36a70 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -33,6 +33,7 @@ #define LLVM_IR_CONSTANTRANGE_H #include "llvm/ADT/APInt.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -59,15 +60,27 @@ public: /// assert out if the two APInt's are not the same bit width. ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper); - /// Produce the smallest range that contains all values that - /// might satisfy the comparison specified by Pred when compared to any value - /// contained within Other. + /// Produce the smallest range such that all values that may satisfy the given + /// predicate with any value contained within Other is contained in the + /// returned range. Formally, this returns a superset of + /// 'union over all y in Other . { x : icmp op x y is true }'. If the exact + /// answer is not representable as a ConstantRange, the return value will be a + /// proper superset of the above. /// - /// Solves for range X in 'for all x in X, there exists a y in Y such that - /// icmp op x, y is true'. Every value that might make the comparison true - /// is included in the resulting range. - static ConstantRange makeICmpRegion(unsigned Pred, - const ConstantRange &Other); + /// Example: Pred = ult and Other = i8 [2, 5) returns Result = [0, 4) + static ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, + const ConstantRange &Other); + + /// Produce the largest range such that all values in the returned range + /// satisfy the given predicate with all values contained within Other. + /// Formally, this returns a subset of + /// 'intersection over all y in Other . { x : icmp op x y is true }'. If the + /// exact answer is not representable as a ConstantRange, the return value + /// will be a proper subset of the above. + /// + /// Example: Pred = ult and Other = i8 [2, 5) returns [0, 2) + static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred, + const ConstantRange &Other); /// Return the lower value for this range. /// @@ -208,8 +221,8 @@ public: ConstantRange sub(const ConstantRange &Other) const; /// Return a new range representing the possible values resulting - /// from a multiplication of a value in this range and a value in \p Other. - /// TODO: This isn't fully implemented yet. + /// from a multiplication of a value in this range and a value in \p Other, + /// treating both this and \p Other as unsigned ranges. ConstantRange multiply(const ConstantRange &Other) const; /// Return a new range representing the possible values resulting diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 5b098b4f51d6..e97bda54e8f0 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -12,7 +12,7 @@ /// which represent the different flavors of constant values that live in LLVM. /// Note that Constants are immutable (once created they never change) and are /// fully shared by structural equivalence. This means that two structurally -/// equivalent constants will always have the same address. Constant's are +/// equivalent constants will always have the same address. Constants are /// created on demand as needed and never deleted: thus clients don't have to /// worry about the lifetime of the objects. // @@ -46,8 +46,8 @@ template <class ConstantClass> struct ConstantAggrKeyType; /// @brief Class for constant integers. class ConstantInt : public Constant { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantInt(const ConstantInt &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantInt(const ConstantInt &) = delete; ConstantInt(IntegerType *Ty, const APInt& V); APInt Val; protected: @@ -228,8 +228,8 @@ public: class ConstantFP : public Constant { APFloat Val; void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantFP(const ConstantFP &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantFP(const ConstantFP &) = delete; friend class LLVMContextImpl; protected: ConstantFP(Type *Ty, const APFloat& V); @@ -251,6 +251,7 @@ public: static Constant *get(Type* Ty, double V); static Constant *get(Type* Ty, StringRef Str); static ConstantFP *get(LLVMContext &Context, const APFloat &V); + static Constant *getNaN(Type *Ty, bool Negative = false, unsigned type = 0); static Constant *getNegativeZero(Type *Ty); static Constant *getInfinity(Type *Ty, bool Negative = false); @@ -294,8 +295,8 @@ public: /// ConstantAggregateZero - All zero aggregate value /// class ConstantAggregateZero : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantAggregateZero(const ConstantAggregateZero &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantAggregateZero(const ConstantAggregateZero &) = delete; protected: explicit ConstantAggregateZero(Type *ty) : Constant(ty, ConstantAggregateZeroVal, nullptr, 0) {} @@ -341,7 +342,7 @@ public: /// class ConstantArray : public Constant { friend struct ConstantAggrKeyType<ConstantArray>; - ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION; + ConstantArray(const ConstantArray &) = delete; protected: ConstantArray(ArrayType *T, ArrayRef<Constant *> Val); public: @@ -383,7 +384,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) // class ConstantStruct : public Constant { friend struct ConstantAggrKeyType<ConstantStruct>; - ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION; + ConstantStruct(const ConstantStruct &) = delete; protected: ConstantStruct(StructType *T, ArrayRef<Constant *> Val); public: @@ -442,7 +443,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) /// class ConstantVector : public Constant { friend struct ConstantAggrKeyType<ConstantVector>; - ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION; + ConstantVector(const ConstantVector &) = delete; protected: ConstantVector(VectorType *T, ArrayRef<Constant *> Val); public: @@ -491,8 +492,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) /// ConstantPointerNull - a constant pointer value that points to null /// class ConstantPointerNull : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantPointerNull(const ConstantPointerNull &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantPointerNull(const ConstantPointerNull &) = delete; protected: explicit ConstantPointerNull(PointerType *T) : Constant(T, @@ -542,12 +543,12 @@ class ConstantDataSequential : public Constant { /// element array of i8, or a 1-element array of i32. They'll both end up in /// the same StringMap bucket, linked up. ConstantDataSequential *Next; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataSequential(const ConstantDataSequential &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataSequential(const ConstantDataSequential &) = delete; protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {} - ~ConstantDataSequential() { delete Next; } + ~ConstantDataSequential() override { delete Next; } static Constant *getImpl(StringRef Bytes, Type *Ty); @@ -653,8 +654,8 @@ private: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataArray : public ConstantDataSequential { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataArray(const ConstantDataArray &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataArray(const ConstantDataArray &) = delete; void anchor() override; friend class ConstantDataSequential; explicit ConstantDataArray(Type *ty, const char *Data) @@ -676,6 +677,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef<float> Elts); static Constant *get(LLVMContext &Context, ArrayRef<double> Elts); + /// getFP() constructors - Return a constant with array type with an element + /// count and element type of float with precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef<uint16_t> Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef<uint32_t> Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef<uint64_t> Elts); + /// getString - This method constructs a CDS and initializes it with a text /// string. The default behavior (AddNull==true) causes a null terminator to /// be placed at the end of the array (increasing the length of the string by @@ -705,8 +715,8 @@ public: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataVector : public ConstantDataSequential { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataVector(const ConstantDataVector &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataVector(const ConstantDataVector &) = delete; void anchor() override; friend class ConstantDataSequential; explicit ConstantDataVector(Type *ty, const char *Data) @@ -728,6 +738,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef<float> Elts); static Constant *get(LLVMContext &Context, ArrayRef<double> Elts); + /// getFP() constructors - Return a constant with vector type with an element + /// count and element type of float with the precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef<uint16_t> Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef<uint32_t> Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef<uint64_t> Elts); + /// getSplat - Return a ConstantVector with the specified constant in each /// element. The specified constant has to be a of a compatible type (i8/i16/ /// i32/i64/float/double) and must be a ConstantFP or ConstantInt. @@ -756,7 +775,7 @@ public: /// BlockAddress - The address of a basic block. /// class BlockAddress : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void *operator new(size_t s) { return User::operator new(s, 2); } BlockAddress(Function *F, BasicBlock *BB); public: @@ -1036,44 +1055,46 @@ public: bool OnlyIfReduced = false); /// Getelementptr form. Value* is only accepted for convenience; - /// all elements must be Constant's. + /// all elements must be Constants. /// /// \param OnlyIfReducedTy see \a getWithOperands() docs. - static Constant *getGetElementPtr(Constant *C, ArrayRef<Constant *> IdxList, + static Constant *getGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Constant *> IdxList, bool InBounds = false, Type *OnlyIfReducedTy = nullptr) { return getGetElementPtr( - C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()), + Ty, C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()), InBounds, OnlyIfReducedTy); } - static Constant *getGetElementPtr(Constant *C, Constant *Idx, + static Constant *getGetElementPtr(Type *Ty, Constant *C, Constant *Idx, bool InBounds = false, Type *OnlyIfReducedTy = nullptr) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return getGetElementPtr(C, cast<Value>(Idx), InBounds, OnlyIfReducedTy); + return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, OnlyIfReducedTy); } - static Constant *getGetElementPtr(Constant *C, ArrayRef<Value *> IdxList, + static Constant *getGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Value *> IdxList, bool InBounds = false, Type *OnlyIfReducedTy = nullptr); /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) { - return getGetElementPtr(C, IdxList, true); + return getGetElementPtr(Ty, C, IdxList, true); } - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, Constant *Idx) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return getGetElementPtr(C, Idx, true); + return getGetElementPtr(Ty, C, Idx, true); } - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) { - return getGetElementPtr(C, IdxList, true); + return getGetElementPtr(Ty, C, IdxList, true); } static Constant *getExtractElement(Constant *Vec, Constant *Idx, @@ -1125,8 +1146,9 @@ public: Constant *getWithOperands(ArrayRef<Constant *> Ops, Type *Ty, bool OnlyIfReduced = false) const; - /// getAsInstruction - Returns an Instruction which implements the same operation - /// as this ConstantExpr. The instruction is not linked to any basic block. + /// getAsInstruction - Returns an Instruction which implements the same + /// operation as this ConstantExpr. The instruction is not linked to any basic + /// block. /// /// A better approach to this could be to have a constructor for Instruction /// which would take a ConstantExpr parameter, but that would have spread @@ -1168,8 +1190,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) /// LangRef.html#undefvalues for details. /// class UndefValue : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - UndefValue(const UndefValue &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + UndefValue(const UndefValue &) = delete; protected: explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {} protected: diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index ae1ac650a9ec..997113191d19 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -30,38 +30,17 @@ namespace llvm { class Value; class Constant; class LLVMContext; - class MDNode; class StringRef; - class DIBasicType; - class DICompileUnit; - class DICompositeType; - class DIDerivedType; - class DIDescriptor; - class DIFile; - class DIEnumerator; - class DIType; - class DIGlobalVariable; - class DIImportedEntity; - class DINameSpace; - class DIVariable; - class DISubrange; - class DILexicalBlockFile; - class DILexicalBlock; - class DIScope; - class DISubprogram; - class DITemplateTypeParameter; - class DITemplateValueParameter; - class DIObjCProperty; class DIBuilder { Module &M; LLVMContext &VMContext; - MDNode *TempEnumTypes; - MDNode *TempRetainTypes; - MDNode *TempSubprograms; - MDNode *TempGVs; - MDNode *TempImportedModules; + TempMDTuple TempEnumTypes; + TempMDTuple TempRetainTypes; + TempMDTuple TempSubprograms; + TempMDTuple TempGVs; + TempMDTuple TempImportedModules; Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value @@ -80,12 +59,12 @@ namespace llvm { /// Each subprogram's preserved local variables. DenseMap<MDNode *, std::vector<TrackingMDNodeRef>> PreservedVariables; - DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; - void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; + DIBuilder(const DIBuilder &) = delete; + void operator=(const DIBuilder &) = delete; /// \brief Create a temporary. /// - /// Create an \a MDNodeFwdDecl and track it in \a UnresolvedNodes. + /// Create an \a temporary node and track it in \a UnresolvedNodes. void trackIfUnresolved(MDNode *N); public: @@ -116,6 +95,7 @@ namespace llvm { /// @param SplitName The name of the file that we'll split debug info out /// into. /// @param Kind The kind of debug information to generate. + /// @param DWOId The DWOId if this is a split skeleton compile unit. /// @param EmitDebugInfo A boolean flag which indicates whether debug /// information should be written to the final /// output or not. When this is false, debug @@ -125,26 +105,25 @@ namespace llvm { /// source location information in the back end /// without actually changing the output (e.g., /// when using optimization remarks). - DICompileUnit createCompileUnit(unsigned Lang, StringRef File, - StringRef Dir, StringRef Producer, - bool isOptimized, StringRef Flags, - unsigned RV, - StringRef SplitName = StringRef(), - DebugEmissionKind Kind = FullDebug, - bool EmitDebugInfo = true); + DICompileUnit * + createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, + StringRef Producer, bool isOptimized, StringRef Flags, + unsigned RV, StringRef SplitName = StringRef(), + DebugEmissionKind Kind = FullDebug, uint64_t DWOId = 0, + bool EmitDebugInfo = true); /// createFile - Create a file descriptor to hold debugging information /// for a file. - DIFile createFile(StringRef Filename, StringRef Directory); + DIFile *createFile(StringRef Filename, StringRef Directory); /// createEnumerator - Create a single enumerator value. - DIEnumerator createEnumerator(StringRef Name, int64_t Val); + DIEnumerator *createEnumerator(StringRef Name, int64_t Val); /// \brief Create a DWARF unspecified type. - DIBasicType createUnspecifiedType(StringRef Name); + DIBasicType *createUnspecifiedType(StringRef Name); /// \brief Create C++11 nullptr type. - DIBasicType createNullPtrType(); + DIBasicType *createNullPtrType(); /// createBasicType - Create debugging information entry for a basic /// type. @@ -152,36 +131,36 @@ namespace llvm { /// @param SizeInBits Size of the type. /// @param AlignInBits Type alignment. /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. - DIBasicType createBasicType(StringRef Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding); + DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding); /// createQualifiedType - Create debugging information entry for a qualified /// type, e.g. 'const int'. /// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type /// @param FromTy Base Type. - DIDerivedType createQualifiedType(unsigned Tag, DIType FromTy); + DIDerivedType *createQualifiedType(unsigned Tag, DIType *FromTy); /// createPointerType - Create debugging information entry for a pointer. /// @param PointeeTy Type pointed by this pointer. /// @param SizeInBits Size. /// @param AlignInBits Alignment. (optional) /// @param Name Pointer type name. (optional) - DIDerivedType - createPointerType(DIType PointeeTy, uint64_t SizeInBits, - uint64_t AlignInBits = 0, StringRef Name = StringRef()); + DIDerivedType *createPointerType(DIType *PointeeTy, uint64_t SizeInBits, + uint64_t AlignInBits = 0, + StringRef Name = ""); /// \brief Create debugging information entry for a pointer to member. /// @param PointeeTy Type pointed to by this pointer. /// @param SizeInBits Size. /// @param AlignInBits Alignment. (optional) /// @param Class Type for which this pointer points to members of. - DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class, - uint64_t SizeInBits, - uint64_t AlignInBits = 0); + DIDerivedType *createMemberPointerType(DIType *PointeeTy, DIType *Class, + uint64_t SizeInBits, + uint64_t AlignInBits = 0); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. - DIDerivedType createReferenceType(unsigned Tag, DIType RTy); + DIDerivedType *createReferenceType(unsigned Tag, DIType *RTy); /// createTypedef - Create debugging information entry for a typedef. /// @param Ty Original type. @@ -189,11 +168,11 @@ namespace llvm { /// @param File File where this type is defined. /// @param LineNo Line number. /// @param Context The surrounding context for the typedef. - DIDerivedType createTypedef(DIType Ty, StringRef Name, DIFile File, - unsigned LineNo, DIDescriptor Context); + DIDerivedType *createTypedef(DIType *Ty, StringRef Name, DIFile *File, + unsigned LineNo, DIScope *Context); /// createFriend - Create debugging information entry for a 'friend'. - DIDerivedType createFriend(DIType Ty, DIType FriendTy); + DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy); /// createInheritance - Create debugging information entry to establish /// inheritance relationship between two types. @@ -202,8 +181,8 @@ namespace llvm { /// @param BaseOffset Base offset. /// @param Flags Flags to describe inheritance attribute, /// e.g. private - DIDerivedType createInheritance(DIType Ty, DIType BaseTy, - uint64_t BaseOffset, unsigned Flags); + DIDerivedType *createInheritance(DIType *Ty, DIType *BaseTy, + uint64_t BaseOffset, unsigned Flags); /// createMemberType - Create debugging information entry for a member. /// @param Scope Member scope. @@ -215,10 +194,11 @@ namespace llvm { /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. - DIDerivedType - createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, DIType Ty); + DIDerivedType *createMemberType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNo, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType *Ty); /// createStaticMemberType - Create debugging information entry for a /// C++ static data member. @@ -229,10 +209,10 @@ namespace llvm { /// @param Ty Type of the static member. /// @param Flags Flags to encode member attribute, e.g. private. /// @param Val Const initializer of the member. - DIDerivedType createStaticMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo, - DIType Ty, unsigned Flags, - llvm::Constant *Val); + DIDerivedType *createStaticMemberType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNo, + DIType *Ty, unsigned Flags, + llvm::Constant *Val); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -245,11 +225,10 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. /// @param PropertyNode Property associated with this ivar. - DIDerivedType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty, - MDNode *PropertyNode); + DIDerivedType *createObjCIVar(StringRef Name, DIFile *File, unsigned LineNo, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType *Ty, MDNode *PropertyNode); /// createObjCProperty - Create debugging information entry for Objective-C /// property. @@ -260,12 +239,11 @@ namespace llvm { /// @param SetterName Name of the Objective C property setter selector. /// @param PropertyAttributes Objective C property attributes. /// @param Ty Type. - DIObjCProperty createObjCProperty(StringRef Name, - DIFile File, unsigned LineNumber, - StringRef GetterName, - StringRef SetterName, - unsigned PropertyAttributes, - DIType Ty); + DIObjCProperty *createObjCProperty(StringRef Name, DIFile *File, + unsigned LineNumber, + StringRef GetterName, + StringRef SetterName, + unsigned PropertyAttributes, DIType *Ty); /// createClassType - Create debugging information entry for a class. /// @param Scope Scope in which this class is defined. @@ -283,14 +261,14 @@ namespace llvm { /// for more info. /// @param TemplateParms Template type parameters. /// @param UniqueIdentifier A unique identifier for the class. - DICompositeType createClassType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - DIType DerivedFrom, DIArray Elements, - DIType VTableHolder = DIType(), - MDNode *TemplateParms = nullptr, - StringRef UniqueIdentifier = StringRef()); + DICompositeType *createClassType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType *DerivedFrom, DINodeArray Elements, + DIType *VTableHolder = nullptr, + MDNode *TemplateParms = nullptr, + StringRef UniqueIdentifier = ""); /// createStructType - Create debugging information entry for a struct. /// @param Scope Scope in which this struct is defined. @@ -303,13 +281,11 @@ namespace llvm { /// @param Elements Struct elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. /// @param UniqueIdentifier A unique identifier for the struct. - DICompositeType createStructType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - unsigned Flags, DIType DerivedFrom, - DIArray Elements, unsigned RunTimeLang = 0, - DIType VTableHolder = DIType(), - StringRef UniqueIdentifier = StringRef()); + DICompositeType *createStructType( + DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, + DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang = 0, + DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = ""); /// createUnionType - Create debugging information entry for an union. /// @param Scope Scope in which this union is defined. @@ -322,24 +298,20 @@ namespace llvm { /// @param Elements Union elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. /// @param UniqueIdentifier A unique identifier for the union. - DICompositeType createUnionType( - DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - DIArray Elements, unsigned RunTimeLang = 0, - StringRef UniqueIdentifier = StringRef()); + DICompositeType *createUnionType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + unsigned Flags, DINodeArray Elements, + unsigned RunTimeLang = 0, + StringRef UniqueIdentifier = ""); /// createTemplateTypeParameter - Create debugging information for template /// type parameter. /// @param Scope Scope in which this type is defined. /// @param Name Type parameter name. /// @param Ty Parameter type. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateTypeParameter - createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, - MDNode *File = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + DITemplateTypeParameter * + createTemplateTypeParameter(DIScope *Scope, StringRef Name, DIType *Ty); /// createTemplateValueParameter - Create debugging information for template /// value parameter. @@ -347,56 +319,46 @@ namespace llvm { /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val Constant parameter value. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, - Constant *Val, MDNode *File = nullptr, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DITemplateValueParameter *createTemplateValueParameter(DIScope *Scope, + StringRef Name, + DIType *Ty, + Constant *Val); /// \brief Create debugging information for a template template parameter. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val The fully qualified name of the template. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateTemplateParameter(DIDescriptor Scope, StringRef Name, - DIType Ty, StringRef Val, - MDNode *File = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + DITemplateValueParameter *createTemplateTemplateParameter(DIScope *Scope, + StringRef Name, + DIType *Ty, + StringRef Val); /// \brief Create debugging information for a template parameter pack. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val An array of types in the pack. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateParameterPack(DIDescriptor Scope, StringRef Name, - DIType Ty, DIArray Val, MDNode *File = nullptr, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DITemplateValueParameter *createTemplateParameterPack(DIScope *Scope, + StringRef Name, + DIType *Ty, + DINodeArray Val); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DICompositeType createArrayType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + DICompositeType *createArrayType(uint64_t Size, uint64_t AlignInBits, + DIType *Ty, DINodeArray Subscripts); /// createVectorType - Create debugging information entry for a vector type. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DICompositeType createVectorType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + DICompositeType *createVectorType(uint64_t Size, uint64_t AlignInBits, + DIType *Ty, DINodeArray Subscripts); /// createEnumerationType - Create debugging information entry for an /// enumeration. @@ -409,10 +371,10 @@ namespace llvm { /// @param Elements Enumeration elements. /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. /// @param UniqueIdentifier A unique identifier for the enum. - DICompositeType createEnumerationType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, uint64_t SizeInBits, - uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType, - StringRef UniqueIdentifier = StringRef()); + DICompositeType *createEnumerationType( + DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, DINodeArray Elements, + DIType *UnderlyingType, StringRef UniqueIdentifier = ""); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. @@ -420,49 +382,49 @@ namespace llvm { /// includes return type at 0th index. /// @param Flags E.g.: LValueReference. /// These flags are used to emit dwarf attributes. - DISubroutineType createSubroutineType(DIFile File, - DITypeArray ParameterTypes, - unsigned Flags = 0); + DISubroutineType *createSubroutineType(DIFile *File, + DITypeRefArray ParameterTypes, + unsigned Flags = 0); - /// createArtificialType - Create a new DIType with "artificial" flag set. - DIType createArtificialType(DIType Ty); + /// createArtificialType - Create a new DIType* with "artificial" flag set. + DIType *createArtificialType(DIType *Ty); - /// createObjectPointerType - Create a new DIType with the "object pointer" + /// createObjectPointerType - Create a new DIType* with the "object pointer" /// flag set. - DIType createObjectPointerType(DIType Ty); + DIType *createObjectPointerType(DIType *Ty); /// \brief Create a permanent forward-declared type. - DICompositeType createForwardDecl(unsigned Tag, StringRef Name, - DIDescriptor Scope, DIFile F, - unsigned Line, unsigned RuntimeLang = 0, - uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, - StringRef UniqueIdentifier = StringRef()); + DICompositeType *createForwardDecl(unsigned Tag, StringRef Name, + DIScope *Scope, DIFile *F, unsigned Line, + unsigned RuntimeLang = 0, + uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, + StringRef UniqueIdentifier = ""); /// \brief Create a temporary forward-declared type. - DICompositeType createReplaceableForwardDecl( - unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, - unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, StringRef UniqueIdentifier = StringRef()); + DICompositeType *createReplaceableCompositeType( + unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, + unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, unsigned Flags = DINode::FlagFwdDecl, + StringRef UniqueIdentifier = ""); - /// retainType - Retain DIType in a module even if it is not referenced + /// retainType - Retain DIType* in a module even if it is not referenced /// through debug info anchors. - void retainType(DIType T); + void retainType(DIType *T); /// createUnspecifiedParameter - Create unspecified parameter type /// for a subroutine type. - DIBasicType createUnspecifiedParameter(); + DIBasicType *createUnspecifiedParameter(); - /// getOrCreateArray - Get a DIArray, create one if required. - DIArray getOrCreateArray(ArrayRef<Metadata *> Elements); + /// getOrCreateArray - Get a DINodeArray, create one if required. + DINodeArray getOrCreateArray(ArrayRef<Metadata *> Elements); - /// getOrCreateTypeArray - Get a DITypeArray, create one if required. - DITypeArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements); + /// getOrCreateTypeArray - Get a DITypeRefArray, create one if required. + DITypeRefArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements); /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. - DISubrange getOrCreateSubrange(int64_t Lo, int64_t Count); - + DISubrange *getOrCreateSubrange(int64_t Lo, int64_t Count); /// createGlobalVariable - Create a new descriptor for the specified /// variable. @@ -476,19 +438,19 @@ namespace llvm { /// externally visible or not. /// @param Val llvm::Value of the variable. /// @param Decl Reference to the corresponding declaration. - DIGlobalVariable createGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef LinkageName, DIFile File, - unsigned LineNo, DITypeRef Ty, - bool isLocalToUnit, - llvm::Constant *Val, - MDNode *Decl = nullptr); + DIGlobalVariable *createGlobalVariable(DIScope *Context, StringRef Name, + StringRef LinkageName, DIFile *File, + unsigned LineNo, DIType *Ty, + bool isLocalToUnit, + llvm::Constant *Val, + MDNode *Decl = nullptr); /// createTempGlobalVariableFwdDecl - Identical to createGlobalVariable /// except that the resulting DbgNode is temporary and meant to be RAUWed. - DIGlobalVariable createTempGlobalVariableFwdDecl( - DIDescriptor Context, StringRef Name, StringRef LinkageName, - DIFile File, unsigned LineNo, DITypeRef Ty, bool isLocalToUnit, - llvm::Constant *Val, MDNode *Decl = nullptr); + DIGlobalVariable *createTempGlobalVariableFwdDecl( + DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, + unsigned LineNo, DIType *Ty, bool isLocalToUnit, llvm::Constant *Val, + MDNode *Decl = nullptr); /// createLocalVariable - Create a new descriptor for the specified /// local variable. @@ -504,28 +466,29 @@ namespace llvm { /// @param Flags Flags, e.g. artificial variable. /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. - DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, - StringRef Name, - DIFile File, unsigned LineNo, - DITypeRef Ty, bool AlwaysPreserve = false, - unsigned Flags = 0, - unsigned ArgNo = 0); + DILocalVariable *createLocalVariable(unsigned Tag, DIScope *Scope, + StringRef Name, DIFile *File, + unsigned LineNo, DIType *Ty, + bool AlwaysPreserve = false, + unsigned Flags = 0, + unsigned ArgNo = 0); /// createExpression - Create a new descriptor for the specified /// variable which has a complex address expression for its address. /// @param Addr An array of complex address operations. - DIExpression createExpression(ArrayRef<int64_t> Addr = None); + DIExpression *createExpression(ArrayRef<uint64_t> Addr = None); + DIExpression *createExpression(ArrayRef<int64_t> Addr); - /// createPieceExpression - Create a descriptor to describe one part + /// createBitPieceExpression - Create a descriptor to describe one part /// of aggregate variable that is fragmented across multiple Values. /// - /// @param OffsetInBytes Offset of the piece in bytes. - /// @param SizeInBytes Size of the piece in bytes. - DIExpression createPieceExpression(unsigned OffsetInBytes, - unsigned SizeInBytes); + /// @param OffsetInBits Offset of the piece in bits. + /// @param SizeInBits Size of the piece in bits. + DIExpression *createBitPieceExpression(unsigned OffsetInBits, + unsigned SizeInBits); /// createFunction - Create a new descriptor for the specified subprogram. - /// See comments in DISubprogram for descriptions of these fields. + /// See comments in DISubprogram* for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. /// @param LinkageName Mangled function name. @@ -540,49 +503,35 @@ namespace llvm { /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. - DISubprogram createFunction(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); + DISubprogram * + createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned LineNo, DISubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr, + MDNode *Decl = nullptr); /// createTempFunctionFwdDecl - Identical to createFunction, /// except that the resulting DbgNode is meant to be RAUWed. - DISubprogram createTempFunctionFwdDecl(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); - + DISubprogram *createTempFunctionFwdDecl( + DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, + unsigned LineNo, DISubroutineType *Ty, bool isLocalToUnit, + bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, + bool isOptimized = false, Function *Fn = nullptr, + MDNode *TParam = nullptr, MDNode *Decl = nullptr); /// FIXME: this is added for dragonegg. Once we update dragonegg /// to call resolve function, this will be removed. - DISubprogram createFunction(DIScopeRef Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); + DISubprogram * + createFunction(DIScopeRef Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned LineNo, DISubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr, + MDNode *Decl = nullptr); /// createMethod - Create a new descriptor for the specified C++ method. - /// See comments in DISubprogram for descriptions of these fields. + /// See comments in DISubprogram* for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. /// @param LinkageName Mangled function name. @@ -600,17 +549,13 @@ namespace llvm { /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. - DISubprogram createMethod(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned Virtuality = 0, unsigned VTableIndex = 0, - DIType VTableHolder = DIType(), - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr); + DISubprogram * + createMethod(DIScope *Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned LineNo, DISubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0, + unsigned VTableIndex = 0, DIType *VTableHolder = nullptr, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr); /// createNameSpace - This creates new descriptor for a namespace /// with the specified parent scope. @@ -618,9 +563,8 @@ namespace llvm { /// @param Name Name of this namespace /// @param File Source file /// @param LineNo Line number - DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo); - + DINamespace *createNameSpace(DIScope *Scope, StringRef Name, DIFile *File, + unsigned LineNo); /// createLexicalBlockFile - This creates a descriptor for a lexical /// block with a new file attached. This merely extends the existing @@ -628,8 +572,8 @@ namespace llvm { /// @param Scope Lexical block. /// @param File Source file. /// @param Discriminator DWARF path discriminator value. - DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File, - unsigned Discriminator = 0); + DILexicalBlockFile *createLexicalBlockFile(DIScope *Scope, DIFile *File, + unsigned Discriminator = 0); /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. @@ -637,60 +581,63 @@ namespace llvm { /// @param File Source file. /// @param Line Line number. /// @param Col Column number. - DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, - unsigned Line, unsigned Col); + DILexicalBlock *createLexicalBlock(DIScope *Scope, DIFile *File, + unsigned Line, unsigned Col); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS The namespace being imported here /// @param Line Line number - DIImportedEntity createImportedModule(DIScope Context, DINameSpace NS, - unsigned Line); + DIImportedEntity *createImportedModule(DIScope *Context, DINamespace *NS, + unsigned Line); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS An aliased namespace /// @param Line Line number - DIImportedEntity createImportedModule(DIScope Context, DIImportedEntity NS, - unsigned Line); + DIImportedEntity *createImportedModule(DIScope *Context, + DIImportedEntity *NS, unsigned Line); /// \brief Create a descriptor for an imported function. /// @param Context The scope this module is imported into /// @param Decl The declaration (or definition) of a function, type, or /// variable /// @param Line Line number - DIImportedEntity createImportedDeclaration(DIScope Context, DIDescriptor Decl, - unsigned Line, - StringRef Name = StringRef()); - DIImportedEntity createImportedDeclaration(DIScope Context, - DIImportedEntity NS, - unsigned Line, - StringRef Name = StringRef()); + DIImportedEntity *createImportedDeclaration(DIScope *Context, DINode *Decl, + unsigned Line, + StringRef Name = ""); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertAtEnd Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - DIExpression Expr, BasicBlock *InsertAtEnd); + Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + BasicBlock *InsertAtEnd); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertBefore Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - DIExpression Expr, Instruction *InsertBefore); + Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + Instruction *InsertBefore); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, DIExpression Expr, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, BasicBlock *InsertAtEnd); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. @@ -698,24 +645,45 @@ namespace llvm { /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, DIExpression Expr, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, Instruction *InsertBefore); /// \brief Replace the vtable holder in the given composite type. /// /// If this creates a self reference, it may orphan some unresolved cycles /// in the operands of \c T, so \a DIBuilder needs to track that. - void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder); + void replaceVTableHolder(DICompositeType *&T, + DICompositeType *VTableHolder); /// \brief Replace arrays on a composite type. /// /// If \c T is resolved, but the arrays aren't -- which can happen if \c T /// has a self-reference -- \a DIBuilder needs to track the array to /// resolve cycles. - void replaceArrays(DICompositeType &T, DIArray Elements, - DIArray TParems = DIArray()); + void replaceArrays(DICompositeType *&T, DINodeArray Elements, + DINodeArray TParems = DINodeArray()); + + /// \brief Replace a temporary node. + /// + /// Call \a MDNode::replaceAllUsesWith() on \c N, replacing it with \c + /// Replacement. + /// + /// If \c Replacement is the same as \c N.get(), instead call \a + /// MDNode::replaceWithUniqued(). In this case, the uniqued node could + /// have a different address, so we return the final address. + template <class NodeTy> + NodeTy *replaceTemporary(TempMDNode &&N, NodeTy *Replacement) { + if (N.get() == Replacement) + return cast<NodeTy>(MDNode::replaceWithUniqued(std::move(N))); + + N->replaceAllUsesWith(Replacement); + return Replacement; + } }; } // end namespace llvm diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index a9e75955ce74..3e1f9744f9e8 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -53,6 +53,11 @@ enum AlignTypeEnum { AGGREGATE_ALIGN = 'a' }; +// FIXME: Currently the DataLayout string carries a "preferred alignment" +// for types. As the DataLayout is module/global, this should likely be +// sunk down to an FTTI element that is queried rather than a global +// preference. + /// \brief Layout alignment element. /// /// Stores the alignment data associated with a given alignment type (integer, @@ -103,7 +108,14 @@ private: unsigned StackNaturalAlign; - enum ManglingModeT { MM_None, MM_ELF, MM_MachO, MM_WINCOFF, MM_Mips }; + enum ManglingModeT { + MM_None, + MM_ELF, + MM_MachO, + MM_WinCOFF, + MM_WinCOFFX86, + MM_Mips + }; ManglingModeT ManglingMode; SmallVector<unsigned char, 8> LegalIntWidths; @@ -111,6 +123,9 @@ private: /// \brief Primitive type alignment data. SmallVector<LayoutAlignElem, 16> Alignments; + /// \brief The string representation used to create this DataLayout + std::string StringRepresentation; + typedef SmallVector<PointerAlignElem, 8> PointersTy; PointersTy Pointers; @@ -180,6 +195,7 @@ public: DataLayout &operator=(const DataLayout &DL) { clear(); + StringRepresentation = DL.StringRepresentation; BigEndian = DL.isBigEndian(); StackNaturalAlign = DL.StackNaturalAlign; ManglingMode = DL.ManglingMode; @@ -204,8 +220,12 @@ public: /// \brief Returns the string representation of the DataLayout. /// /// This representation is in the same format accepted by the string - /// constructor above. - std::string getStringRepresentation() const; + /// constructor above. This should not be used to compare two DataLayout as + /// different string can represent the same layout. + std::string getStringRepresentation() const { return StringRepresentation; } + + /// \brief Test if the DataLayout was constructed from an empty string. + bool isDefault() const { return StringRepresentation.empty(); } /// \brief Returns true if the specified type is known to be a native integer /// type supported by the CPU. @@ -231,7 +251,7 @@ public: unsigned getStackAlignment() const { return StackNaturalAlign; } bool hasMicrosoftFastStdCallMangling() const { - return ManglingMode == MM_WINCOFF; + return ManglingMode == MM_WinCOFFX86; } bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; } @@ -239,7 +259,7 @@ public: const char *getLinkerPrivateGlobalPrefix() const { if (ManglingMode == MM_MachO) return "l"; - return getPrivateGlobalPrefix(); + return ""; } char getGlobalPrefix() const { @@ -247,9 +267,10 @@ public: case MM_None: case MM_ELF: case MM_Mips: + case MM_WinCOFF: return '\0'; case MM_MachO: - case MM_WINCOFF: + case MM_WinCOFFX86: return '_'; } llvm_unreachable("invalid mangling mode"); @@ -264,7 +285,8 @@ public: case MM_Mips: return "$"; case MM_MachO: - case MM_WINCOFF: + case MM_WinCOFF: + case MM_WinCOFFX86: return "L"; } llvm_unreachable("invalid mangling mode"); @@ -446,22 +468,6 @@ inline LLVMTargetDataRef wrap(const DataLayout *P) { return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout *>(P)); } -class DataLayoutPass : public ImmutablePass { - DataLayout DL; - -public: - /// This has to exist, because this is a pass, but it should never be used. - DataLayoutPass(); - ~DataLayoutPass(); - - const DataLayout &getDataLayout() const { return DL; } - - static char ID; // Pass identification, replacement for typeid - - bool doFinalization(Module &M) override; - bool doInitialization(Module &M) override; -}; - /// Used to lazily calculate structure layout information for a target machine, /// based on the DataLayout structure. class StructLayout { diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 5c85d6d52824..5429648ade2c 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -22,990 +22,30 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Metadata.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include <iterator> namespace llvm { -class BasicBlock; -class Constant; -class Function; -class GlobalVariable; class Module; -class Type; -class Value; class DbgDeclareInst; class DbgValueInst; -class Instruction; -class Metadata; -class MDNode; -class MDString; -class NamedMDNode; -class LLVMContext; -class raw_ostream; - -class DIFile; -class DISubprogram; -class DILexicalBlock; -class DILexicalBlockFile; -class DIVariable; -class DIType; -class DIScope; -class DIObjCProperty; /// \brief Maps from type identifier to the actual MDNode. -typedef DenseMap<const MDString *, MDNode *> DITypeIdentifierMap; - -class DIHeaderFieldIterator - : public std::iterator<std::input_iterator_tag, StringRef, std::ptrdiff_t, - const StringRef *, StringRef> { - StringRef Header; - StringRef Current; - -public: - DIHeaderFieldIterator() {} - DIHeaderFieldIterator(StringRef Header) - : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} - StringRef operator*() const { return Current; } - const StringRef * operator->() const { return &Current; } - DIHeaderFieldIterator &operator++() { - increment(); - return *this; - } - DIHeaderFieldIterator operator++(int) { - DIHeaderFieldIterator X(*this); - increment(); - return X; - } - bool operator==(const DIHeaderFieldIterator &X) const { - return Current.data() == X.Current.data(); - } - bool operator!=(const DIHeaderFieldIterator &X) const { - return !(*this == X); - } - - StringRef getHeader() const { return Header; } - StringRef getCurrent() const { return Current; } - StringRef getPrefix() const { - if (Current.begin() == Header.begin()) - return StringRef(); - return Header.slice(0, Current.begin() - Header.begin() - 1); - } - StringRef getSuffix() const { - if (Current.end() == Header.end()) - return StringRef(); - return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos); - } - -private: - void increment() { - assert(Current.data() != nullptr && "Cannot increment past the end"); - StringRef Suffix = getSuffix(); - Current = Suffix.slice(0, Suffix.find('\0')); - } -}; - -/// \brief A thin wraper around MDNode to access encoded debug info. -/// -/// This should not be stored in a container, because the underlying MDNode may -/// change in certain situations. -class DIDescriptor { - // Befriends DIRef so DIRef can befriend the protected member - // function: getFieldAs<DIRef>. - template <typename T> friend class DIRef; - -public: - /// \brief Accessibility flags. - /// - /// The three accessibility flags are mutually exclusive and rolled together - /// in the first two bits. - enum { - FlagAccessibility = 1 << 0 | 1 << 1, - FlagPrivate = 1, - FlagProtected = 2, - FlagPublic = 3, - - FlagFwdDecl = 1 << 2, - FlagAppleBlock = 1 << 3, - FlagBlockByrefStruct = 1 << 4, - FlagVirtual = 1 << 5, - FlagArtificial = 1 << 6, - FlagExplicit = 1 << 7, - FlagPrototyped = 1 << 8, - FlagObjcClassComplete = 1 << 9, - FlagObjectPointer = 1 << 10, - FlagVector = 1 << 11, - FlagStaticMember = 1 << 12, - FlagIndirectVariable = 1 << 13, - FlagLValueReference = 1 << 14, - FlagRValueReference = 1 << 15 - }; - -protected: - const MDNode *DbgNode; - - StringRef getStringField(unsigned Elt) const; - unsigned getUnsignedField(unsigned Elt) const { - return (unsigned)getUInt64Field(Elt); - } - uint64_t getUInt64Field(unsigned Elt) const; - int64_t getInt64Field(unsigned Elt) const; - DIDescriptor getDescriptorField(unsigned Elt) const; - - template <typename DescTy> DescTy getFieldAs(unsigned Elt) const { - return DescTy(getDescriptorField(Elt)); - } - - GlobalVariable *getGlobalVariableField(unsigned Elt) const; - Constant *getConstantField(unsigned Elt) const; - Function *getFunctionField(unsigned Elt) const; - void replaceFunctionField(unsigned Elt, Function *F); - -public: - explicit DIDescriptor(const MDNode *N = nullptr) : DbgNode(N) {} - - bool Verify() const; - - MDNode *get() const { return const_cast<MDNode *>(DbgNode); } - operator MDNode *() const { return get(); } - MDNode *operator->() const { return get(); } - - // An explicit operator bool so that we can do testing of DI values - // easily. - // FIXME: This operator bool isn't actually protecting anything at the - // moment due to the conversion operator above making DIDescriptor nodes - // implicitly convertable to bool. - LLVM_EXPLICIT operator bool() const { return DbgNode != nullptr; } - - bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } - bool operator!=(DIDescriptor Other) const { return !operator==(Other); } - - StringRef getHeader() const { - return getStringField(0); - } - - size_t getNumHeaderFields() const { - return std::distance(DIHeaderFieldIterator(getHeader()), - DIHeaderFieldIterator()); - } - - StringRef getHeaderField(unsigned Index) const { - // Since callers expect an empty string for out-of-range accesses, we can't - // use std::advance() here. - for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index) - if (!Index) - return *I; - return StringRef(); - } - - template <class T> T getHeaderFieldAs(unsigned Index) const { - T Int; - if (getHeaderField(Index).getAsInteger(0, Int)) - return 0; - return Int; - } - - uint16_t getTag() const { return getHeaderFieldAs<uint16_t>(0); } - - bool isDerivedType() const; - bool isCompositeType() const; - bool isSubroutineType() const; - bool isBasicType() const; - bool isVariable() const; - bool isSubprogram() const; - bool isGlobalVariable() const; - bool isScope() const; - bool isFile() const; - bool isCompileUnit() const; - bool isNameSpace() const; - bool isLexicalBlockFile() const; - bool isLexicalBlock() const; - bool isSubrange() const; - bool isEnumerator() const; - bool isType() const; - bool isTemplateTypeParameter() const; - bool isTemplateValueParameter() const; - bool isObjCProperty() const; - bool isImportedEntity() const; - bool isExpression() const; - - void print(raw_ostream &OS) const; - void dump() const; - - /// \brief Replace all uses of debug info referenced by this descriptor. - void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); - void replaceAllUsesWith(MDNode *D); -}; - -/// \brief This is used to represent ranges, for array bounds. -class DISubrange : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {} - - int64_t getLo() const { return getHeaderFieldAs<int64_t>(1); } - int64_t getCount() const { return getHeaderFieldAs<int64_t>(2); } - bool Verify() const; -}; - -/// \brief This descriptor holds an array of nodes with type T. -template <typename T> class DITypedArray : public DIDescriptor { -public: - explicit DITypedArray(const MDNode *N = nullptr) : DIDescriptor(N) {} - unsigned getNumElements() const { - return DbgNode ? DbgNode->getNumOperands() : 0; - } - T getElement(unsigned Idx) const { - return getFieldAs<T>(Idx); - } -}; - -typedef DITypedArray<DIDescriptor> DIArray; - -/// \brief A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). -/// -/// FIXME: it seems strange that this doesn't have either a reference to the -/// type/precision or a file/line pair for location info. -class DIEnumerator : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {} - - StringRef getName() const { return getHeaderField(1); } - int64_t getEnumValue() const { return getHeaderFieldAs<int64_t>(2); } - bool Verify() const; -}; - -template <typename T> class DIRef; -typedef DIRef<DIScope> DIScopeRef; -typedef DIRef<DIType> DITypeRef; -typedef DITypedArray<DITypeRef> DITypeArray; - -/// \brief A base class for various scopes. -/// -/// Although, implementation-wise, DIScope is the parent class of most -/// other DIxxx classes, including DIType and its descendants, most of -/// DIScope's descendants are not a substitutable subtype of -/// DIScope. The DIDescriptor::isScope() method only is true for -/// DIScopes that are scopes in the strict lexical scope sense -/// (DICompileUnit, DISubprogram, etc.), but not for, e.g., a DIType. -class DIScope : public DIDescriptor { -protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {} - - /// \brief Get the parent scope. - /// - /// Gets the parent scope for this scope node or returns a default - /// constructed scope. - DIScopeRef getContext() const; - /// \brief Get the scope name. - /// - /// If the scope node has a name, return that, else return an empty string. - StringRef getName() const; - StringRef getFilename() const; - StringRef getDirectory() const; - - /// \brief Generate a reference to this DIScope. - /// - /// Uses the type identifier instead of the actual MDNode if possible, to - /// help type uniquing. - DIScopeRef getRef() const; -}; - -/// \brief Represents reference to a DIDescriptor. -/// -/// Abstracts over direct and identifier-based metadata references. -template <typename T> class DIRef { - template <typename DescTy> - friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; - friend DIScopeRef DIScope::getContext() const; - friend DIScopeRef DIScope::getRef() const; - friend class DIType; - - /// \brief Val can be either a MDNode or a MDString. - /// - /// In the latter, MDString specifies the type identifier. - const Metadata *Val; - explicit DIRef(const Metadata *V); - -public: - T resolve(const DITypeIdentifierMap &Map) const; - StringRef getName() const; - operator Metadata *() const { return const_cast<Metadata *>(Val); } -}; - -template <typename T> -T DIRef<T>::resolve(const DITypeIdentifierMap &Map) const { - if (!Val) - return T(); - - if (const MDNode *MD = dyn_cast<MDNode>(Val)) - return T(MD); - - const MDString *MS = cast<MDString>(Val); - // Find the corresponding MDNode. - DITypeIdentifierMap::const_iterator Iter = Map.find(MS); - assert(Iter != Map.end() && "Identifier not in the type map?"); - assert(DIDescriptor(Iter->second).isType() && - "MDNode in DITypeIdentifierMap should be a DIType."); - return T(Iter->second); -} - -template <typename T> StringRef DIRef<T>::getName() const { - if (!Val) - return StringRef(); - - if (const MDNode *MD = dyn_cast<MDNode>(Val)) - return T(MD).getName(); - - const MDString *MS = cast<MDString>(Val); - return MS->getString(); -} - -/// \brief Handle fields that are references to DIScopes. -template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const; -/// \brief Specialize DIRef constructor for DIScopeRef. -template <> DIRef<DIScope>::DIRef(const Metadata *V); - -/// \brief Handle fields that are references to DITypes. -template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const; -/// \brief Specialize DIRef constructor for DITypeRef. -template <> DIRef<DIType>::DIRef(const Metadata *V); - -/// \briefThis is a wrapper for a type. -/// -/// FIXME: Types should be factored much better so that CV qualifiers and -/// others do not require a huge and empty descriptor full of zeros. -class DIType : public DIScope { -protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIType(const MDNode *N = nullptr) : DIScope(N) {} - operator DITypeRef () const { - assert(isType() && - "constructing DITypeRef from an MDNode that is not a type"); - return DITypeRef(&*getRef()); - } - - bool Verify() const; - - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { - return getHeaderFieldAs<unsigned>(2); - } - uint64_t getSizeInBits() const { - return getHeaderFieldAs<unsigned>(3); - } - uint64_t getAlignInBits() const { - return getHeaderFieldAs<unsigned>(4); - } - // FIXME: Offset is only used for DW_TAG_member nodes. Making every type - // carry this is just plain insane. - uint64_t getOffsetInBits() const { - return getHeaderFieldAs<unsigned>(5); - } - unsigned getFlags() const { return getHeaderFieldAs<unsigned>(6); } - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; } - bool isAppleBlockExtension() const { - return (getFlags() & FlagAppleBlock) != 0; - } - bool isBlockByrefStruct() const { - return (getFlags() & FlagBlockByrefStruct) != 0; - } - bool isVirtual() const { return (getFlags() & FlagVirtual) != 0; } - bool isArtificial() const { return (getFlags() & FlagArtificial) != 0; } - bool isObjectPointer() const { return (getFlags() & FlagObjectPointer) != 0; } - bool isObjcClassComplete() const { - return (getFlags() & FlagObjcClassComplete) != 0; - } - bool isVector() const { return (getFlags() & FlagVector) != 0; } - bool isStaticMember() const { return (getFlags() & FlagStaticMember) != 0; } - bool isLValueReference() const { - return (getFlags() & FlagLValueReference) != 0; - } - bool isRValueReference() const { - return (getFlags() & FlagRValueReference) != 0; - } - bool isValid() const { return DbgNode && isType(); } -}; - -/// \brief A basic type, like 'int' or 'float'. -class DIBasicType : public DIType { -public: - explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {} - - unsigned getEncoding() const { return getHeaderFieldAs<unsigned>(7); } - - bool Verify() const; -}; - -/// \brief A simple derived type -/// -/// Like a const qualified type, a typedef, a pointer or reference, et cetera. -/// Or, a data member of a class/struct/union. -class DIDerivedType : public DIType { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {} - - DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(3); } - - /// \brief Return property node, if this ivar is associated with one. - MDNode *getObjCProperty() const; - - DITypeRef getClassType() const { - assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs<DITypeRef>(4); - } - - Constant *getConstant() const { - assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - return getConstantField(4); - } - - bool Verify() const; -}; - -/// \brief Types that refer to multiple other types. -/// -/// This descriptor holds a type that can refer to multiple other types, like a -/// function or struct. -/// -/// DICompositeType is derived from DIDerivedType because some -/// composite types (such as enums) can be derived from basic types -// FIXME: Make this derive from DIType directly & just store the -// base type in a single DIType field. -class DICompositeType : public DIDerivedType { - friend class DIBuilder; - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - - /// \brief Set the array of member DITypes. - void setArraysHelper(MDNode *Elements, MDNode *TParams); - -public: - explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {} - - DIArray getElements() const { - assert(!isSubroutineType() && "no elements for DISubroutineType"); - return getFieldAs<DIArray>(4); - } - -private: - template <typename T> - void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) { - assert((!TParams || DbgNode->getNumOperands() == 8) && - "If you're setting the template parameters this should include a slot " - "for that!"); - setArraysHelper(Elements, TParams); - } - -public: - unsigned getRunTimeLang() const { - return getHeaderFieldAs<unsigned>(7); - } - DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(5); } - -private: - /// \brief Set the containing type. - void setContainingType(DICompositeType ContainingType); - -public: - DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } - MDString *getIdentifier() const; - - bool Verify() const; -}; - -class DISubroutineType : public DICompositeType { -public: - explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {} - DITypedArray<DITypeRef> getTypeArray() const { - return getFieldAs<DITypedArray<DITypeRef>>(4); - } -}; - -/// \brief This is a wrapper for a file. -class DIFile : public DIScope { - friend class DIDescriptor; - -public: - explicit DIFile(const MDNode *N = nullptr) : DIScope(N) {} - - /// \brief Retrieve the MDNode for the directory/file pair. - MDNode *getFileNode() const; - bool Verify() const; -}; - -/// \brief A wrapper for a compile unit. -class DICompileUnit : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {} - - dwarf::SourceLanguage getLanguage() const { - return static_cast<dwarf::SourceLanguage>(getHeaderFieldAs<unsigned>(1)); - } - StringRef getProducer() const { return getHeaderField(2); } - - bool isOptimized() const { return getHeaderFieldAs<bool>(3) != 0; } - StringRef getFlags() const { return getHeaderField(4); } - unsigned getRunTimeVersion() const { return getHeaderFieldAs<unsigned>(5); } - - DIArray getEnumTypes() const; - DIArray getRetainedTypes() const; - DIArray getSubprograms() const; - DIArray getGlobalVariables() const; - DIArray getImportedEntities() const; - - void replaceSubprograms(DIArray Subprograms); - void replaceGlobalVariables(DIArray GlobalVariables); - - StringRef getSplitDebugFilename() const { return getHeaderField(6); } - unsigned getEmissionKind() const { return getHeaderFieldAs<unsigned>(7); } - - bool Verify() const; -}; - -/// \brief This is a wrapper for a subprogram (e.g. a function). -class DISubprogram : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {} - - StringRef getName() const { return getHeaderField(1); } - StringRef getDisplayName() const { return getHeaderField(2); } - StringRef getLinkageName() const { return getHeaderField(3); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); } - - /// \brief Check if this is local (like 'static' in C). - unsigned isLocalToUnit() const { return getHeaderFieldAs<unsigned>(5); } - unsigned isDefinition() const { return getHeaderFieldAs<unsigned>(6); } - - unsigned getVirtuality() const { return getHeaderFieldAs<unsigned>(7); } - unsigned getVirtualIndex() const { return getHeaderFieldAs<unsigned>(8); } - - unsigned getFlags() const { return getHeaderFieldAs<unsigned>(9); } - - unsigned isOptimized() const { return getHeaderFieldAs<bool>(10); } - - /// \brief Get the beginning of the scope of the function (not the name). - unsigned getScopeLineNumber() const { return getHeaderFieldAs<unsigned>(11); } - - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } - DISubroutineType getType() const { return getFieldAs<DISubroutineType>(3); } - - DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(4); } - - bool Verify() const; - - /// \brief Check if this provides debugging information for the function F. - bool describes(const Function *F); - - Function *getFunction() const { return getFunctionField(5); } - void replaceFunction(Function *F) { replaceFunctionField(5, F); } - DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } - DISubprogram getFunctionDeclaration() const { - return getFieldAs<DISubprogram>(7); - } - MDNode *getVariablesNodes() const; - DIArray getVariables() const; - - unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; } - /// \brief Check for the "private" access specifier. - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - /// \brief Check for the "protected" access specifier. - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - /// \brief Check for the "public" access specifier. - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - /// \brief Check for "explicit". - bool isExplicit() const { return (getFlags() & FlagExplicit) != 0; } - /// \brief Check if this is prototyped. - bool isPrototyped() const { return (getFlags() & FlagPrototyped) != 0; } - - /// \brief Check if this is reference-qualified. - /// - /// Return true if this subprogram is a C++11 reference-qualified non-static - /// member function (void foo() &). - unsigned isLValueReference() const { - return (getFlags() & FlagLValueReference) != 0; - } - - /// \brief Check if this is rvalue-reference-qualified. - /// - /// Return true if this subprogram is a C++11 rvalue-reference-qualified - /// non-static member function (void foo() &&). - unsigned isRValueReference() const { - return (getFlags() & FlagRValueReference) != 0; - } - -}; - -/// \brief This is a wrapper for a lexical block. -class DILexicalBlock : public DIScope { -public: - explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(2); } - unsigned getLineNumber() const { - return getHeaderFieldAs<unsigned>(1); - } - unsigned getColumnNumber() const { - return getHeaderFieldAs<unsigned>(2); - } - bool Verify() const; -}; - -/// \brief This is a wrapper for a lexical block with a filename change. -class DILexicalBlockFile : public DIScope { -public: - explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} - DIScope getContext() const { - if (getScope().isSubprogram()) - return getScope(); - return getScope().getContext(); - } - unsigned getLineNumber() const { return getScope().getLineNumber(); } - unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); } - unsigned getDiscriminator() const { return getHeaderFieldAs<unsigned>(1); } - bool Verify() const; -}; - -/// \brief A wrapper for a C++ style name space. -class DINameSpace : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {} - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - DIScope getContext() const { return getFieldAs<DIScope>(2); } - bool Verify() const; -}; - -/// \brief This is a wrapper for template type parameter. -class DITemplateTypeParameter : public DIDescriptor { -public: - explicit DITemplateTypeParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} - - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); } - - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } - StringRef getFilename() const { return getFieldAs<DIFile>(3).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(3).getDirectory(); - } - bool Verify() const; -}; - -/// \brief This is a wrapper for template value parameter. -class DITemplateValueParameter : public DIDescriptor { -public: - explicit DITemplateValueParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} - - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); } - - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } - Metadata *getValue() const; - StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(4).getDirectory(); - } - bool Verify() const; -}; - -/// \brief This is a wrapper for a global variable. -class DIGlobalVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - - StringRef getName() const { return getHeaderField(1); } - StringRef getDisplayName() const { return getHeaderField(2); } - StringRef getLinkageName() const { return getHeaderField(3); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); } - unsigned isLocalToUnit() const { return getHeaderFieldAs<bool>(5); } - unsigned isDefinition() const { return getHeaderFieldAs<bool>(6); } - - DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getFilename() const { return getFieldAs<DIFile>(2).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(2).getDirectory(); - } - DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - - GlobalVariable *getGlobal() const { return getGlobalVariableField(4); } - Constant *getConstant() const { return getConstantField(4); } - DIDerivedType getStaticDataMemberDeclaration() const { - return getFieldAs<DIDerivedType>(5); - } - - bool Verify() const; -}; - -/// \brief This is a wrapper for a variable (e.g. parameter, local, global etc). -class DIVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { - // FIXME: Line number and arg number shouldn't be merged together like this. - return (getHeaderFieldAs<unsigned>(2) << 8) >> 8; - } - unsigned getArgNumber() const { return getHeaderFieldAs<unsigned>(2) >> 24; } - - DIScope getContext() const { return getFieldAs<DIScope>(1); } - DIFile getFile() const { return getFieldAs<DIFile>(2); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - - /// \brief Return true if this variable is marked as "artificial". - bool isArtificial() const { - return (getHeaderFieldAs<unsigned>(3) & FlagArtificial) != 0; - } - - bool isObjectPointer() const { - return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0; - } - - /// \brief Return true if this variable is represented as a pointer. - bool isIndirect() const { - return (getHeaderFieldAs<unsigned>(3) & FlagIndirectVariable) != 0; - } - - /// \brief If this variable is inlined then return inline location. - MDNode *getInlinedAt() const; - - bool Verify() const; - - /// \brief Check if this is a "__block" variable (Apple Blocks). - bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const { - return (getType().resolve(Map)).isBlockByrefStruct(); - } - - /// \brief Check if this is an inlined function argument. - bool isInlinedFnArgument(const Function *CurFn); - - /// \brief Return the size reported by the variable's type. - unsigned getSizeInBits(const DITypeIdentifierMap &Map); - - void printExtendedName(raw_ostream &OS) const; -}; - -/// \brief A complex location expression. -class DIExpression : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {} - - bool Verify() const; - - /// \brief Return the number of elements in the complex expression. - unsigned getNumElements() const { - if (!DbgNode) - return 0; - unsigned N = getNumHeaderFields(); - assert(N > 0 && "missing tag"); - return N - 1; - } - - /// \brief return the Idx'th complex address element. - uint64_t getElement(unsigned Idx) const; - - /// \brief Return whether this is a piece of an aggregate variable. - bool isVariablePiece() const; - /// \brief Return the offset of this piece in bytes. - uint64_t getPieceOffset() const; - /// \brief Return the size of this piece in bytes. - uint64_t getPieceSize() const; -}; - -/// \brief This object holds location information. -/// -/// This object is not associated with any DWARF tag. -class DILocation : public DIDescriptor { -public: - explicit DILocation(const MDNode *N) : DIDescriptor(N) {} - - unsigned getLineNumber() const { - if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) - return L->getLine(); - return 0; - } - unsigned getColumnNumber() const { - if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) - return L->getColumn(); - return 0; - } - DIScope getScope() const { - if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) - return DIScope(dyn_cast_or_null<MDNode>(L->getScope())); - return DIScope(nullptr); - } - DILocation getOrigLocation() const { - if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) - return DILocation(dyn_cast_or_null<MDNode>(L->getInlinedAt())); - return DILocation(nullptr); - } - StringRef getFilename() const { return getScope().getFilename(); } - StringRef getDirectory() const { return getScope().getDirectory(); } - bool Verify() const; - bool atSameLineAs(const DILocation &Other) const { - return (getLineNumber() == Other.getLineNumber() && - getFilename() == Other.getFilename()); - } - /// \brief Get the DWAF discriminator. - /// - /// DWARF discriminators are used to distinguish identical file locations for - /// instructions that are on different basic blocks. If two instructions are - /// inside the same lexical block and are in different basic blocks, we - /// create a new lexical block with identical location as the original but - /// with a different discriminator value - /// (lib/Transforms/Util/AddDiscriminators.cpp for details). - unsigned getDiscriminator() const { - // Since discriminators are associated with lexical blocks, make - // sure this location is a lexical block before retrieving its - // value. - return getScope().isLexicalBlockFile() - ? DILexicalBlockFile( - cast<MDNode>(cast<MDLocation>(DbgNode)->getScope())) - .getDiscriminator() - : 0; - } - - /// \brief Generate a new discriminator value for this location. - unsigned computeNewDiscriminator(LLVMContext &Ctx); - - /// \brief Return a copy of this location with a different scope. - DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope); -}; - -class DIObjCProperty : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} - - StringRef getObjCPropertyName() const { return getHeaderField(1); } - DIFile getFile() const { return getFieldAs<DIFile>(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - - StringRef getObjCPropertyGetterName() const { return getHeaderField(3); } - StringRef getObjCPropertySetterName() const { return getHeaderField(4); } - unsigned getAttributes() const { return getHeaderFieldAs<unsigned>(5); } - bool isReadOnlyObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readonly) != 0; - } - bool isReadWriteObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; - } - bool isAssignObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_assign) != 0; - } - bool isRetainObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_retain) != 0; - } - bool isCopyObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_copy) != 0; - } - bool isNonAtomicObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; - } - - /// \brief Get the type. - /// - /// \note Objective-C doesn't have an ODR, so there is no benefit in storing - /// the type as a DITypeRef here. - DIType getType() const { return getFieldAs<DIType>(2); } - - bool Verify() const; -}; - -/// \brief An imported module (C++ using directive or similar). -class DIImportedEntity : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(1); } - DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); } - StringRef getName() const { return getHeaderField(2); } - bool Verify() const; -}; +typedef DenseMap<const MDString *, DIType *> DITypeIdentifierMap; /// \brief Find subprogram that is enclosing this scope. -DISubprogram getDISubprogram(const MDNode *Scope); +DISubprogram *getDISubprogram(const MDNode *Scope); /// \brief Find debug info for a given function. -/// \returns a valid DISubprogram, if found. Otherwise, it returns an empty -/// DISubprogram. -DISubprogram getDISubprogram(const Function *F); - -/// \brief Find underlying composite type. -DICompositeType getDICompositeType(DIType T); - -/// \brief Create a new inlined variable based on current variable. /// -/// @param DV Current Variable. -/// @param InlinedScope Location at current variable is inlined. -DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, - LLVMContext &VMContext); +/// \returns a valid subprogram, if found. Otherwise, return \c nullptr. +DISubprogram *getDISubprogram(const Function *F); -/// \brief Remove inlined scope from the variable. -DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); +/// \brief Find underlying composite type. +DICompositeTypeBase *getDICompositeType(DIType *T); /// \brief Generate map by visiting all retained types. DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); @@ -1016,6 +56,7 @@ DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); /// metadata for debugging. We also remove debug locations for instructions. /// Return true if module is modified. bool StripDebugInfo(Module &M); +bool stripDebugInfo(Function &F); /// \brief Return Debug Info Metadata Version by checking module flags. unsigned getDebugMetadataVersionFromModule(const Module &M); @@ -1039,8 +80,8 @@ public: void processDeclare(const Module &M, const DbgDeclareInst *DDI); /// \brief Process DbgValueInst. void processValue(const Module &M, const DbgValueInst *DVI); - /// \brief Process DILocation. - void processLocation(const Module &M, DILocation Loc); + /// \brief Process debug info location. + void processLocation(const Module &M, const DILocation *Loc); /// \brief Clear all lists. void reset(); @@ -1048,21 +89,23 @@ public: private: void InitializeTypeMap(const Module &M); - void processType(DIType DT); - void processSubprogram(DISubprogram SP); - void processScope(DIScope Scope); - bool addCompileUnit(DICompileUnit CU); - bool addGlobalVariable(DIGlobalVariable DIG); - bool addSubprogram(DISubprogram SP); - bool addType(DIType DT); - bool addScope(DIScope Scope); + void processType(DIType *DT); + void processSubprogram(DISubprogram *SP); + void processScope(DIScope *Scope); + bool addCompileUnit(DICompileUnit *CU); + bool addGlobalVariable(DIGlobalVariable *DIG); + bool addSubprogram(DISubprogram *SP); + bool addType(DIType *DT); + bool addScope(DIScope *Scope); public: - typedef SmallVectorImpl<DICompileUnit>::const_iterator compile_unit_iterator; - typedef SmallVectorImpl<DISubprogram>::const_iterator subprogram_iterator; - typedef SmallVectorImpl<DIGlobalVariable>::const_iterator global_variable_iterator; - typedef SmallVectorImpl<DIType>::const_iterator type_iterator; - typedef SmallVectorImpl<DIScope>::const_iterator scope_iterator; + typedef SmallVectorImpl<DICompileUnit *>::const_iterator + compile_unit_iterator; + typedef SmallVectorImpl<DISubprogram *>::const_iterator subprogram_iterator; + typedef SmallVectorImpl<DIGlobalVariable *>::const_iterator + global_variable_iterator; + typedef SmallVectorImpl<DIType *>::const_iterator type_iterator; + typedef SmallVectorImpl<DIScope *>::const_iterator scope_iterator; iterator_range<compile_unit_iterator> compile_units() const { return iterator_range<compile_unit_iterator>(CUs.begin(), CUs.end()); @@ -1091,19 +134,19 @@ public: unsigned scope_count() const { return Scopes.size(); } private: - SmallVector<DICompileUnit, 8> CUs; - SmallVector<DISubprogram, 8> SPs; - SmallVector<DIGlobalVariable, 8> GVs; - SmallVector<DIType, 8> TYs; - SmallVector<DIScope, 8> Scopes; - SmallPtrSet<MDNode *, 64> NodesSeen; + SmallVector<DICompileUnit *, 8> CUs; + SmallVector<DISubprogram *, 8> SPs; + SmallVector<DIGlobalVariable *, 8> GVs; + SmallVector<DIType *, 8> TYs; + SmallVector<DIScope *, 8> Scopes; + SmallPtrSet<const MDNode *, 64> NodesSeen; DITypeIdentifierMap TypeIdentifierMap; /// \brief Specify if TypeIdentifierMap is initialized. bool TypeMapInitialized; }; -DenseMap<const Function *, DISubprogram> makeSubprogramMap(const Module &M); +DenseMap<const Function *, DISubprogram *> makeSubprogramMap(const Module &M); } // end namespace llvm diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def new file mode 100644 index 000000000000..d5de8683fd3b --- /dev/null +++ b/include/llvm/IR/DebugInfoFlags.def @@ -0,0 +1,36 @@ +//===- llvm/IR/DebugInfoFlags.def - Debug info flag definitions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through debug info flags. +// +//===----------------------------------------------------------------------===// + +// TODO: Add other DW-based macros. +#ifndef HANDLE_DI_FLAG +#error "Missing macro definition of HANDLE_DI_FLAG" +#endif + +HANDLE_DI_FLAG(1, Private) +HANDLE_DI_FLAG(2, Protected) +HANDLE_DI_FLAG(3, Public) +HANDLE_DI_FLAG((1 << 2), FwdDecl) +HANDLE_DI_FLAG((1 << 3), AppleBlock) +HANDLE_DI_FLAG((1 << 4), BlockByrefStruct) +HANDLE_DI_FLAG((1 << 5), Virtual) +HANDLE_DI_FLAG((1 << 6), Artificial) +HANDLE_DI_FLAG((1 << 7), Explicit) +HANDLE_DI_FLAG((1 << 8), Prototyped) +HANDLE_DI_FLAG((1 << 9), ObjcClassComplete) +HANDLE_DI_FLAG((1 << 10), ObjectPointer) +HANDLE_DI_FLAG((1 << 11), Vector) +HANDLE_DI_FLAG((1 << 12), StaticMember) +HANDLE_DI_FLAG((1 << 13), LValueReference) +HANDLE_DI_FLAG((1 << 14), RValueReference) + +#undef HANDLE_DI_FLAG diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h new file mode 100644 index 000000000000..0125de5d40f5 --- /dev/null +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -0,0 +1,2227 @@ +//===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declarations for metadata specific to debug info. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DEBUGINFOMETADATA_H +#define LLVM_IR_DEBUGINFOMETADATA_H + +#include "llvm/IR/Metadata.h" +#include "llvm/Support/Dwarf.h" + +// Helper macros for defining get() overrides. +#define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ +#define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS +#define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ + static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ + } \ + static CLASS *getIfExists(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ + /* ShouldCreate */ false); \ + } \ + static CLASS *getDistinct(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ + } \ + static Temp##CLASS getTemporary(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return Temp##CLASS( \ + getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ + } + +namespace llvm { + +/// \brief Pointer union between a subclass of DINode and MDString. +/// +/// \a DICompositeType can be referenced via an \a MDString unique identifier. +/// This class allows some type safety in the face of that, requiring either a +/// node of a particular type or an \a MDString. +template <class T> class TypedDINodeRef { + const Metadata *MD = nullptr; + +public: + TypedDINodeRef() = default; + TypedDINodeRef(std::nullptr_t) {} + + /// \brief Construct from a raw pointer. + explicit TypedDINodeRef(const Metadata *MD) : MD(MD) { + assert((!MD || isa<MDString>(MD) || isa<T>(MD)) && "Expected valid ref"); + } + + template <class U> + TypedDINodeRef( + const TypedDINodeRef<U> &X, + typename std::enable_if<std::is_convertible<U *, T *>::value>::type * = + nullptr) + : MD(X) {} + + operator Metadata *() const { return const_cast<Metadata *>(MD); } + + bool operator==(const TypedDINodeRef<T> &X) const { return MD == X.MD; }; + bool operator!=(const TypedDINodeRef<T> &X) const { return MD != X.MD; }; + + /// \brief Create a reference. + /// + /// Get a reference to \c N, using an \a MDString reference if available. + static TypedDINodeRef get(const T *N); + + template <class MapTy> T *resolve(const MapTy &Map) const { + if (!MD) + return nullptr; + + if (auto *Typed = dyn_cast<T>(MD)) + return const_cast<T *>(Typed); + + auto *S = cast<MDString>(MD); + auto I = Map.find(S); + assert(I != Map.end() && "Missing identifier in type map"); + return cast<T>(I->second); + } +}; + +typedef TypedDINodeRef<DINode> DINodeRef; +typedef TypedDINodeRef<DIScope> DIScopeRef; +typedef TypedDINodeRef<DIType> DITypeRef; + +class DITypeRefArray { + const MDTuple *N = nullptr; + +public: + DITypeRefArray(const MDTuple *N) : N(N) {} + + explicit operator bool() const { return get(); } + explicit operator MDTuple *() const { return get(); } + + MDTuple *get() const { return const_cast<MDTuple *>(N); } + MDTuple *operator->() const { return get(); } + MDTuple &operator*() const { return *get(); } + + // FIXME: Fix callers and remove condition on N. + unsigned size() const { return N ? N->getNumOperands() : 0u; } + DITypeRef operator[](unsigned I) const { return DITypeRef(N->getOperand(I)); } + + class iterator : std::iterator<std::input_iterator_tag, DITypeRef, + std::ptrdiff_t, void, DITypeRef> { + MDNode::op_iterator I = nullptr; + + public: + iterator() = default; + explicit iterator(MDNode::op_iterator I) : I(I) {} + DITypeRef operator*() const { return DITypeRef(*I); } + iterator &operator++() { + ++I; + return *this; + } + iterator operator++(int) { + iterator Temp(*this); + ++I; + return Temp; + } + bool operator==(const iterator &X) const { return I == X.I; } + bool operator!=(const iterator &X) const { return I != X.I; } + }; + + // FIXME: Fix callers and remove condition on N. + iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } + iterator end() const { return N ? iterator(N->op_end()) : iterator(); } +}; + +/// \brief Tagged DWARF-like metadata node. +/// +/// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, +/// defined in llvm/Support/Dwarf.h). Called \a DINode because it's +/// potentially used for non-DWARF output. +class DINode : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + +protected: + DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None) + : MDNode(C, ID, Storage, Ops1, Ops2) { + assert(Tag < 1u << 16); + SubclassData16 = Tag; + } + ~DINode() = default; + + template <class Ty> Ty *getOperandAs(unsigned I) const { + return cast_or_null<Ty>(getOperand(I)); + } + + StringRef getStringOperand(unsigned I) const { + if (auto *S = getOperandAs<MDString>(I)) + return S->getString(); + return StringRef(); + } + + static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { + if (S.empty()) + return nullptr; + return MDString::get(Context, S); + } + +public: + unsigned getTag() const { return SubclassData16; } + + /// \brief Debug info flags. + /// + /// The three accessibility flags are mutually exclusive and rolled together + /// in the first two bits. + enum DIFlags { +#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, +#include "llvm/IR/DebugInfoFlags.def" + FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic + }; + + static unsigned getFlag(StringRef Flag); + static const char *getFlagString(unsigned Flag); + + /// \brief Split up a flags bitfield. + /// + /// Split \c Flags into \c SplitFlags, a vector of its components. Returns + /// any remaining (unrecognized) bits. + static unsigned splitFlags(unsigned Flags, + SmallVectorImpl<unsigned> &SplitFlags); + + DINodeRef getRef() const { return DINodeRef::get(this); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case GenericDINodeKind: + case DISubrangeKind: + case DIEnumeratorKind: + case DIBasicTypeKind: + case DIDerivedTypeKind: + case DICompositeTypeKind: + case DISubroutineTypeKind: + case DIFileKind: + case DICompileUnitKind: + case DISubprogramKind: + case DILexicalBlockKind: + case DILexicalBlockFileKind: + case DINamespaceKind: + case DITemplateTypeParameterKind: + case DITemplateValueParameterKind: + case DIGlobalVariableKind: + case DILocalVariableKind: + case DIObjCPropertyKind: + case DIImportedEntityKind: + return true; + } + } +}; + +template <class T> struct simplify_type<const TypedDINodeRef<T>> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TypedDINodeRef<T> &MD) { + return MD; + } +}; + +template <class T> +struct simplify_type<TypedDINodeRef<T>> + : simplify_type<const TypedDINodeRef<T>> {}; + +/// \brief Generic tagged DWARF-like metadata node. +/// +/// An un-specialized DWARF-like metadata node. The first operand is a +/// (possibly empty) null-separated \a MDString header that contains arbitrary +/// fields. The remaining operands are \a dwarf_operands(), and are pointers +/// to other metadata. +class GenericDINode : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + GenericDINode(LLVMContext &C, StorageType Storage, unsigned Hash, + unsigned Tag, ArrayRef<Metadata *> Ops1, + ArrayRef<Metadata *> Ops2) + : DINode(C, GenericDINodeKind, Storage, Tag, Ops1, Ops2) { + setHash(Hash); + } + ~GenericDINode() { dropAllReferences(); } + + void setHash(unsigned Hash) { SubclassData32 = Hash; } + void recalculateHash(); + + static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Header, ArrayRef<Metadata *> DwarfOps, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Header), + DwarfOps, Storage, ShouldCreate); + } + + static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Header, ArrayRef<Metadata *> DwarfOps, + StorageType Storage, bool ShouldCreate = true); + + TempGenericDINode cloneImpl() const { + return getTemporary( + getContext(), getTag(), getHeader(), + SmallVector<Metadata *, 4>(dwarf_op_begin(), dwarf_op_end())); + } + +public: + unsigned getHash() const { return SubclassData32; } + + DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, StringRef Header, + ArrayRef<Metadata *> DwarfOps), + (Tag, Header, DwarfOps)) + DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, MDString *Header, + ArrayRef<Metadata *> DwarfOps), + (Tag, Header, DwarfOps)) + + /// \brief Return a (temporary) clone of this. + TempGenericDINode clone() const { return cloneImpl(); } + + unsigned getTag() const { return SubclassData16; } + StringRef getHeader() const { return getStringOperand(0); } + + op_iterator dwarf_op_begin() const { return op_begin() + 1; } + op_iterator dwarf_op_end() const { return op_end(); } + op_range dwarf_operands() const { + return op_range(dwarf_op_begin(), dwarf_op_end()); + } + + unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } + const MDOperand &getDwarfOperand(unsigned I) const { + return getOperand(I + 1); + } + void replaceDwarfOperandWith(unsigned I, Metadata *New) { + replaceOperandWith(I + 1, New); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == GenericDINodeKind; + } +}; + +/// \brief Array subrange. +/// +/// TODO: Merge into node for DW_TAG_array_type, which should have a custom +/// type. +class DISubrange : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Count; + int64_t LowerBound; + + DISubrange(LLVMContext &C, StorageType Storage, int64_t Count, + int64_t LowerBound) + : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, None), + Count(Count), LowerBound(LowerBound) {} + ~DISubrange() = default; + + static DISubrange *getImpl(LLVMContext &Context, int64_t Count, + int64_t LowerBound, StorageType Storage, + bool ShouldCreate = true); + + TempDISubrange cloneImpl() const { + return getTemporary(getContext(), getCount(), getLowerBound()); + } + +public: + DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0), + (Count, LowerBound)) + + TempDISubrange clone() const { return cloneImpl(); } + + int64_t getLowerBound() const { return LowerBound; } + int64_t getCount() const { return Count; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DISubrangeKind; + } +}; + +/// \brief Enumeration value. +/// +/// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no +/// longer creates a type cycle. +class DIEnumerator : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Value; + + DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + ArrayRef<Metadata *> Ops) + : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), + Value(Value) {} + ~DIEnumerator() = default; + + static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, + StringRef Name, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage, + ShouldCreate); + } + static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, + MDString *Name, StorageType Storage, + bool ShouldCreate = true); + + TempDIEnumerator cloneImpl() const { + return getTemporary(getContext(), getValue(), getName()); + } + +public: + DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, StringRef Name), + (Value, Name)) + DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, MDString *Name), + (Value, Name)) + + TempDIEnumerator clone() const { return cloneImpl(); } + + int64_t getValue() const { return Value; } + StringRef getName() const { return getStringOperand(0); } + + MDString *getRawName() const { return getOperandAs<MDString>(0); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIEnumeratorKind; + } +}; + +/// \brief Base class for scope-like contexts. +/// +/// Base class for lexical scopes and types (which are also declaration +/// contexts). +/// +/// TODO: Separate the concepts of declaration contexts and lexical scopes. +class DIScope : public DINode { +protected: + DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef<Metadata *> Ops) + : DINode(C, ID, Storage, Tag, Ops) {} + ~DIScope() = default; + +public: + DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } + + inline StringRef getFilename() const; + inline StringRef getDirectory() const; + + StringRef getName() const; + DIScopeRef getScope() const; + + /// \brief Return the raw underlying file. + /// + /// An \a DIFile is an \a DIScope, but it doesn't point at a separate file + /// (it\em is the file). If \c this is an \a DIFile, we need to return \c + /// this. Otherwise, return the first operand, which is where all other + /// subclasses store their file pointer. + Metadata *getRawFile() const { + return isa<DIFile>(this) ? const_cast<DIScope *>(this) + : static_cast<Metadata *>(getOperand(0)); + } + + DIScopeRef getRef() const { return DIScopeRef::get(this); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case DIBasicTypeKind: + case DIDerivedTypeKind: + case DICompositeTypeKind: + case DISubroutineTypeKind: + case DIFileKind: + case DICompileUnitKind: + case DISubprogramKind: + case DILexicalBlockKind: + case DILexicalBlockFileKind: + case DINamespaceKind: + return true; + } + } +}; + +/// \brief File. +/// +/// TODO: Merge with directory/file node (including users). +/// TODO: Canonicalize paths on creation. +class DIFile : public DIScope { + friend class LLVMContextImpl; + friend class MDNode; + + DIFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops) + : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} + ~DIFile() = default; + + static DIFile *getImpl(LLVMContext &Context, StringRef Filename, + StringRef Directory, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Filename), + getCanonicalMDString(Context, Directory), Storage, + ShouldCreate); + } + static DIFile *getImpl(LLVMContext &Context, MDString *Filename, + MDString *Directory, StorageType Storage, + bool ShouldCreate = true); + + TempDIFile cloneImpl() const { + return getTemporary(getContext(), getFilename(), getDirectory()); + } + +public: + DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory), + (Filename, Directory)) + DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory), + (Filename, Directory)) + + TempDIFile clone() const { return cloneImpl(); } + + StringRef getFilename() const { return getStringOperand(0); } + StringRef getDirectory() const { return getStringOperand(1); } + + MDString *getRawFilename() const { return getOperandAs<MDString>(0); } + MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIFileKind; + } +}; + +StringRef DIScope::getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; +} + +StringRef DIScope::getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; +} + +/// \brief Base class for types. +/// +/// TODO: Remove the hardcoded name and context, since many types don't use +/// them. +/// TODO: Split up flags. +class DIType : public DIScope { + unsigned Line; + unsigned Flags; + uint64_t SizeInBits; + uint64_t AlignInBits; + uint64_t OffsetInBits; + +protected: + DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops) + : DIScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), + SizeInBits(SizeInBits), AlignInBits(AlignInBits), + OffsetInBits(OffsetInBits) {} + ~DIType() = default; + +public: + TempDIType clone() const { + return TempDIType(cast<DIType>(MDNode::clone().release())); + } + + unsigned getLine() const { return Line; } + uint64_t getSizeInBits() const { return SizeInBits; } + uint64_t getAlignInBits() const { return AlignInBits; } + uint64_t getOffsetInBits() const { return OffsetInBits; } + unsigned getFlags() const { return Flags; } + + DIScopeRef getScope() const { return DIScopeRef(getRawScope()); } + StringRef getName() const { return getStringOperand(2); } + + + Metadata *getRawScope() const { return getOperand(1); } + MDString *getRawName() const { return getOperandAs<MDString>(2); } + + void setFlags(unsigned NewFlags) { + assert(!isUniqued() && "Cannot set flags on uniqued nodes"); + Flags = NewFlags; + } + + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } + bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } + bool isBlockByrefStruct() const { return getFlags() & FlagBlockByrefStruct; } + bool isVirtual() const { return getFlags() & FlagVirtual; } + bool isArtificial() const { return getFlags() & FlagArtificial; } + bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + bool isObjcClassComplete() const { + return getFlags() & FlagObjcClassComplete; + } + bool isVector() const { return getFlags() & FlagVector; } + bool isStaticMember() const { return getFlags() & FlagStaticMember; } + bool isLValueReference() const { return getFlags() & FlagLValueReference; } + bool isRValueReference() const { return getFlags() & FlagRValueReference; } + + DITypeRef getRef() const { return DITypeRef::get(this); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case DIBasicTypeKind: + case DIDerivedTypeKind: + case DICompositeTypeKind: + case DISubroutineTypeKind: + return true; + } + } +}; + +/// \brief Basic type, like 'int' or 'float'. +/// +/// TODO: Split out DW_TAG_unspecified_type. +/// TODO: Drop unused accessors. +class DIBasicType : public DIType { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Encoding; + + DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding, + ArrayRef<Metadata *> Ops) + : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, + 0, Ops), + Encoding(Encoding) {} + ~DIBasicType() = default; + + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), + SizeInBits, AlignInBits, Encoding, Storage, ShouldCreate); + } + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true); + + TempDIBasicType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), + getAlignInBits(), getEncoding()); + } + +public: + DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), + (Tag, Name, 0, 0, 0)) + DEFINE_MDNODE_GET(DIBasicType, + (unsigned Tag, StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + DEFINE_MDNODE_GET(DIBasicType, + (unsigned Tag, MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + + TempDIBasicType clone() const { return cloneImpl(); } + + unsigned getEncoding() const { return Encoding; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIBasicTypeKind; + } +}; + +/// \brief Base class for DIDerivedType and DICompositeType. +/// +/// TODO: Delete; they're not really related. +class DIDerivedTypeBase : public DIType { +protected: + DIDerivedTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef<Metadata *> Ops) + : DIType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~DIDerivedTypeBase() = default; + +public: + DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); } + Metadata *getRawBaseType() const { return getOperand(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIDerivedTypeKind || + MD->getMetadataID() == DICompositeTypeKind || + MD->getMetadataID() == DISubroutineTypeKind; + } +}; + +/// \brief Derived types. +/// +/// This includes qualified types, pointers, references, friends, typedefs, and +/// class members. +/// +/// TODO: Split out members (inheritance, fields, methods, etc.). +class DIDerivedType : public DIDerivedTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops) + : DIDerivedTypeBase(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, + AlignInBits, OffsetInBits, Flags, Ops) {} + ~DIDerivedType() = default; + + static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, DIFile *File, unsigned Line, + DIScopeRef Scope, DITypeRef BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, + Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, + Flags, ExtraData, Storage, ShouldCreate); + } + static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true); + + TempDIDerivedType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getExtraData()); + } + +public: + DEFINE_MDNODE_GET(DIDerivedType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + DEFINE_MDNODE_GET(DIDerivedType, + (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, + DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, Metadata *ExtraData = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + + TempDIDerivedType clone() const { return cloneImpl(); } + + /// \brief Get extra data associated with this derived type. + /// + /// Class type for pointer-to-members, objective-c property node for ivars, + /// or global constant wrapper for static members. + /// + /// TODO: Separate out types that need this extra operand: pointer-to-member + /// types and member fields (static members and ivars). + Metadata *getExtraData() const { return getRawExtraData(); } + Metadata *getRawExtraData() const { return getOperand(4); } + + /// \brief Get casted version of extra data. + /// @{ + DITypeRef getClassType() const { + assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); + return DITypeRef(getExtraData()); + } + DIObjCProperty *getObjCProperty() const { + return dyn_cast_or_null<DIObjCProperty>(getExtraData()); + } + Constant *getConstant() const { + assert(getTag() == dwarf::DW_TAG_member && isStaticMember()); + if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) + return C->getValue(); + return nullptr; + } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIDerivedTypeKind; + } +}; + +/// \brief Base class for DICompositeType and DISubroutineType. +/// +/// TODO: Delete; they're not really related. +class DICompositeTypeBase : public DIDerivedTypeBase { + unsigned RuntimeLang; + +protected: + DICompositeTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, unsigned RuntimeLang, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + ArrayRef<Metadata *> Ops) + : DIDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, + OffsetInBits, Flags, Ops), + RuntimeLang(RuntimeLang) {} + ~DICompositeTypeBase() = default; + +public: + /// \brief Get the elements of the composite type. + /// + /// \note Calling this is only valid for \a DICompositeType. This assertion + /// can be removed once \a DISubroutineType has been separated from + /// "composite types". + DINodeArray getElements() const { + assert(!isa<DISubroutineType>(this) && "no elements for DISubroutineType"); + return cast_or_null<MDTuple>(getRawElements()); + } + DITypeRef getVTableHolder() const { return DITypeRef(getRawVTableHolder()); } + DITemplateParameterArray getTemplateParams() const { + return cast_or_null<MDTuple>(getRawTemplateParams()); + } + StringRef getIdentifier() const { return getStringOperand(7); } + unsigned getRuntimeLang() const { return RuntimeLang; } + + Metadata *getRawElements() const { return getOperand(4); } + Metadata *getRawVTableHolder() const { return getOperand(5); } + Metadata *getRawTemplateParams() const { return getOperand(6); } + MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } + + /// \brief Replace operands. + /// + /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision + /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track + /// of its movement if necessary. + /// @{ + void replaceElements(DINodeArray Elements) { +#ifndef NDEBUG + for (DINode *Op : getElements()) + assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && + "Lost a member during member list replacement"); +#endif + replaceOperandWith(4, Elements.get()); + } + void replaceVTableHolder(DITypeRef VTableHolder) { + replaceOperandWith(5, VTableHolder); + } + void replaceTemplateParams(DITemplateParameterArray TemplateParams) { + replaceOperandWith(6, TemplateParams.get()); + } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DICompositeTypeKind || + MD->getMetadataID() == DISubroutineTypeKind; + } +}; + +/// \brief Composite types. +/// +/// TODO: Detach from DerivedTypeBase (split out MDEnumType?). +/// TODO: Create a custom, unrelated node for DW_TAG_array_type. +class DICompositeType : public DICompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef<Metadata *> Ops) + : DICompositeTypeBase(C, DICompositeTypeKind, Storage, Tag, Line, + RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~DICompositeType() = default; + + static DICompositeType * + getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, DIScopeRef Scope, DITypeRef BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t Flags, DINodeArray Elements, unsigned RuntimeLang, + DITypeRef VTableHolder, DITemplateParameterArray TemplateParams, + StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { + return getImpl( + Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, + BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), + RuntimeLang, VTableHolder, TemplateParams.get(), + getCanonicalMDString(Context, Identifier), Storage, ShouldCreate); + } + static DICompositeType * + getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, Metadata *Elements, unsigned RuntimeLang, + Metadata *VTableHolder, Metadata *TemplateParams, + MDString *Identifier, StorageType Storage, bool ShouldCreate = true); + + TempDICompositeType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getElements(), getRuntimeLang(), getVTableHolder(), + getTemplateParams(), getIdentifier()); + } + +public: + DEFINE_MDNODE_GET(DICompositeType, + (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, + DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DINodeArray Elements, unsigned RuntimeLang, + DITypeRef VTableHolder, + DITemplateParameterArray TemplateParams = nullptr, + StringRef Identifier = ""), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + DEFINE_MDNODE_GET(DICompositeType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, + unsigned RuntimeLang, Metadata *VTableHolder, + Metadata *TemplateParams = nullptr, + MDString *Identifier = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + + TempDICompositeType clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DICompositeTypeKind; + } +}; + +template <class T> TypedDINodeRef<T> TypedDINodeRef<T>::get(const T *N) { + if (N) + if (auto *Composite = dyn_cast<DICompositeType>(N)) + if (auto *S = Composite->getRawIdentifier()) + return TypedDINodeRef<T>(S); + return TypedDINodeRef<T>(N); +} + +/// \brief Type array for a subprogram. +/// +/// TODO: Detach from CompositeType, and fold the array of types in directly +/// as operands. +class DISubroutineType : public DICompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + DISubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags, + ArrayRef<Metadata *> Ops) + : DICompositeTypeBase(C, DISubroutineTypeKind, Storage, + dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags, + Ops) {} + ~DISubroutineType() = default; + + static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + DITypeRefArray TypeArray, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate); + } + static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + Metadata *TypeArray, StorageType Storage, + bool ShouldCreate = true); + + TempDISubroutineType cloneImpl() const { + return getTemporary(getContext(), getFlags(), getTypeArray()); + } + +public: + DEFINE_MDNODE_GET(DISubroutineType, + (unsigned Flags, DITypeRefArray TypeArray), + (Flags, TypeArray)) + DEFINE_MDNODE_GET(DISubroutineType, (unsigned Flags, Metadata *TypeArray), + (Flags, TypeArray)) + + TempDISubroutineType clone() const { return cloneImpl(); } + + DITypeRefArray getTypeArray() const { + return cast_or_null<MDTuple>(getRawTypeArray()); + } + Metadata *getRawTypeArray() const { return getRawElements(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DISubroutineTypeKind; + } +}; + +/// \brief Compile unit. +class DICompileUnit : public DIScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned SourceLanguage; + bool IsOptimized; + unsigned RuntimeVersion; + unsigned EmissionKind; + uint64_t DWOId; + + DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, + bool IsOptimized, unsigned RuntimeVersion, + unsigned EmissionKind, uint64_t DWOId, ArrayRef<Metadata *> Ops) + : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), + SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), + RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind), + DWOId(DWOId) {} + ~DICompileUnit() = default; + + static DICompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File, + StringRef Producer, bool IsOptimized, StringRef Flags, + unsigned RuntimeVersion, StringRef SplitDebugFilename, + unsigned EmissionKind, DICompositeTypeArray EnumTypes, + DITypeArray RetainedTypes, DISubprogramArray Subprograms, + DIGlobalVariableArray GlobalVariables, + DIImportedEntityArray ImportedEntities, uint64_t DWOId, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, SourceLanguage, File, + getCanonicalMDString(Context, Producer), IsOptimized, + getCanonicalMDString(Context, Flags), RuntimeVersion, + getCanonicalMDString(Context, SplitDebugFilename), + EmissionKind, EnumTypes.get(), RetainedTypes.get(), + Subprograms.get(), GlobalVariables.get(), + ImportedEntities.get(), DWOId, Storage, ShouldCreate); + } + static DICompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, uint64_t DWOId, StorageType Storage, + bool ShouldCreate = true); + + TempDICompileUnit cloneImpl() const { + return getTemporary( + getContext(), getSourceLanguage(), getFile(), getProducer(), + isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), + getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(), + getGlobalVariables(), getImportedEntities(), DWOId); + } + +public: + DEFINE_MDNODE_GET(DICompileUnit, + (unsigned SourceLanguage, DIFile *File, StringRef Producer, + bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, + StringRef SplitDebugFilename, unsigned EmissionKind, + DICompositeTypeArray EnumTypes, DITypeArray RetainedTypes, + DISubprogramArray Subprograms, + DIGlobalVariableArray GlobalVariables, + DIImportedEntityArray ImportedEntities, uint64_t DWOId), + (SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities, DWOId)) + DEFINE_MDNODE_GET( + DICompileUnit, + (unsigned SourceLanguage, Metadata *File, MDString *Producer, + bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, + MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, + Metadata *RetainedTypes, Metadata *Subprograms, + Metadata *GlobalVariables, Metadata *ImportedEntities, uint64_t DWOId), + (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms, + GlobalVariables, ImportedEntities, DWOId)) + + TempDICompileUnit clone() const { return cloneImpl(); } + + unsigned getSourceLanguage() const { return SourceLanguage; } + bool isOptimized() const { return IsOptimized; } + unsigned getRuntimeVersion() const { return RuntimeVersion; } + unsigned getEmissionKind() const { return EmissionKind; } + StringRef getProducer() const { return getStringOperand(1); } + StringRef getFlags() const { return getStringOperand(2); } + StringRef getSplitDebugFilename() const { return getStringOperand(3); } + DICompositeTypeArray getEnumTypes() const { + return cast_or_null<MDTuple>(getRawEnumTypes()); + } + DITypeArray getRetainedTypes() const { + return cast_or_null<MDTuple>(getRawRetainedTypes()); + } + DISubprogramArray getSubprograms() const { + return cast_or_null<MDTuple>(getRawSubprograms()); + } + DIGlobalVariableArray getGlobalVariables() const { + return cast_or_null<MDTuple>(getRawGlobalVariables()); + } + DIImportedEntityArray getImportedEntities() const { + return cast_or_null<MDTuple>(getRawImportedEntities()); + } + unsigned getDWOId() const { return DWOId; } + + MDString *getRawProducer() const { return getOperandAs<MDString>(1); } + MDString *getRawFlags() const { return getOperandAs<MDString>(2); } + MDString *getRawSplitDebugFilename() const { + return getOperandAs<MDString>(3); + } + Metadata *getRawEnumTypes() const { return getOperand(4); } + Metadata *getRawRetainedTypes() const { return getOperand(5); } + Metadata *getRawSubprograms() const { return getOperand(6); } + Metadata *getRawGlobalVariables() const { return getOperand(7); } + Metadata *getRawImportedEntities() const { return getOperand(8); } + + /// \brief Replace arrays. + /// + /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and + /// deleted on a uniquing collision. In practice, uniquing collisions on \a + /// DICompileUnit should be fairly rare. + /// @{ + void replaceSubprograms(DISubprogramArray N) { + replaceOperandWith(6, N.get()); + } + void replaceGlobalVariables(DIGlobalVariableArray N) { + replaceOperandWith(7, N.get()); + } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DICompileUnitKind; + } +}; + +/// \brief A scope for locals. +/// +/// A legal scope for lexical blocks, local variables, and debug info +/// locations. Subclasses are \a DISubprogram, \a DILexicalBlock, and \a +/// DILexicalBlockFile. +class DILocalScope : public DIScope { +protected: + DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef<Metadata *> Ops) + : DIScope(C, ID, Storage, Tag, Ops) {} + ~DILocalScope() = default; + +public: + /// \brief Get the subprogram for this scope. + /// + /// Return this if it's an \a DISubprogram; otherwise, look up the scope + /// chain. + DISubprogram *getSubprogram() const; + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DISubprogramKind || + MD->getMetadataID() == DILexicalBlockKind || + MD->getMetadataID() == DILexicalBlockFileKind; + } +}; + +/// \brief Debug location. +/// +/// A debug location in source code, used for debug info and otherwise. +class DILocation : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + + DILocation(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef<Metadata *> MDs); + ~DILocation() { dropAllReferences(); } + + static DILocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true); + static DILocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, DILocalScope *Scope, + DILocation *InlinedAt, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Line, Column, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(InlinedAt), Storage, ShouldCreate); + } + + TempDILocation cloneImpl() const { + return getTemporary(getContext(), getLine(), getColumn(), getScope(), + getInlinedAt()); + } + + // Disallow replacing operands. + void replaceOperandWith(unsigned I, Metadata *New) = delete; + +public: + DEFINE_MDNODE_GET(DILocation, + (unsigned Line, unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr), + (Line, Column, Scope, InlinedAt)) + DEFINE_MDNODE_GET(DILocation, + (unsigned Line, unsigned Column, DILocalScope *Scope, + DILocation *InlinedAt = nullptr), + (Line, Column, Scope, InlinedAt)) + + /// \brief Return a (temporary) clone of this. + TempDILocation clone() const { return cloneImpl(); } + + unsigned getLine() const { return SubclassData32; } + unsigned getColumn() const { return SubclassData16; } + DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } + DILocation *getInlinedAt() const { + return cast_or_null<DILocation>(getRawInlinedAt()); + } + + DIFile *getFile() const { return getScope()->getFile(); } + StringRef getFilename() const { return getScope()->getFilename(); } + StringRef getDirectory() const { return getScope()->getDirectory(); } + + /// \brief Get the scope where this is inlined. + /// + /// Walk through \a getInlinedAt() and return \a getScope() from the deepest + /// location. + DILocalScope *getInlinedAtScope() const { + if (auto *IA = getInlinedAt()) + return IA->getInlinedAtScope(); + return getScope(); + } + + /// \brief Check whether this can be discriminated from another location. + /// + /// Check \c this can be discriminated from \c RHS in a linetable entry. + /// Scope and inlined-at chains are not recorded in the linetable, so they + /// cannot be used to distinguish basic blocks. + /// + /// The current implementation is weaker than it should be, since it just + /// checks filename and line. + /// + /// FIXME: Add a check for getDiscriminator(). + /// FIXME: Add a check for getColumn(). + /// FIXME: Change the getFilename() check to getFile() (or add one for + /// getDirectory()). + bool canDiscriminate(const DILocation &RHS) const { + return getFilename() != RHS.getFilename() || getLine() != RHS.getLine(); + } + + /// \brief Get the DWARF discriminator. + /// + /// DWARF discriminators distinguish identical file locations between + /// instructions that are on different basic blocks. + inline unsigned getDiscriminator() const; + + /// \brief Compute new discriminator in the given context. + /// + /// This modifies the \a LLVMContext that \c this is in to increment the next + /// discriminator for \c this's line/filename combination. + /// + /// FIXME: Delete this. See comments in implementation and at the only call + /// site in \a AddDiscriminators::runOnFunction(). + unsigned computeNewDiscriminator() const; + + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawInlinedAt() const { + if (getNumOperands() == 2) + return getOperand(1); + return nullptr; + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILocationKind; + } +}; + +/// \brief Subprogram description. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +/// TODO: Split up flags. +class DISubprogram : public DILocalScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned ScopeLine; + unsigned Virtuality; + unsigned VirtualIndex; + unsigned Flags; + bool IsLocalToUnit; + bool IsDefinition; + bool IsOptimized; + + DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsLocalToUnit, bool IsDefinition, + bool IsOptimized, ArrayRef<Metadata *> Ops) + : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, + Ops), + Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), + VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), + IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} + ~DISubprogram() = default; + + static DISubprogram * + getImpl(LLVMContext &Context, DIScopeRef Scope, StringRef Name, + StringRef LinkageName, DIFile *File, unsigned Line, + DISubroutineType *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, DITypeRef ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Constant *Function, DITemplateParameterArray TemplateParams, + DISubprogram *Declaration, DILocalVariableArray Variables, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, + Virtuality, VirtualIndex, Flags, IsOptimized, + Function ? ConstantAsMetadata::get(Function) : nullptr, + TemplateParams.get(), Declaration, Variables.get(), Storage, + ShouldCreate); + } + static DISubprogram * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsOptimized, Metadata *Function, + Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + StorageType Storage, bool ShouldCreate = true); + + TempDISubprogram cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getScopeLine(), getContainingType(), + getVirtuality(), getVirtualIndex(), getFlags(), + isOptimized(), getFunctionConstant(), + getTemplateParams(), getDeclaration(), getVariables()); + } + +public: + DEFINE_MDNODE_GET(DISubprogram, + (DIScopeRef Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned Line, DISubroutineType *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + DITypeRef ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Constant *Function = nullptr, + DITemplateParameterArray TemplateParams = nullptr, + DISubprogram *Declaration = nullptr, + DILocalVariableArray Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, ScopeLine, ContainingType, Virtuality, + VirtualIndex, Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)) + DEFINE_MDNODE_GET( + DISubprogram, + (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, + unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Metadata *Function = nullptr, Metadata *TemplateParams = nullptr, + Metadata *Declaration = nullptr, Metadata *Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, + Function, TemplateParams, Declaration, Variables)) + + TempDISubprogram clone() const { return cloneImpl(); } + +public: + unsigned getLine() const { return Line; } + unsigned getVirtuality() const { return Virtuality; } + unsigned getVirtualIndex() const { return VirtualIndex; } + unsigned getScopeLine() const { return ScopeLine; } + unsigned getFlags() const { return Flags; } + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + bool isOptimized() const { return IsOptimized; } + + unsigned isArtificial() const { return getFlags() & FlagArtificial; } + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + bool isExplicit() const { return getFlags() & FlagExplicit; } + bool isPrototyped() const { return getFlags() & FlagPrototyped; } + + /// \brief Check if this is reference-qualified. + /// + /// Return true if this subprogram is a C++11 reference-qualified non-static + /// member function (void foo() &). + unsigned isLValueReference() const { + return getFlags() & FlagLValueReference; + } + + /// \brief Check if this is rvalue-reference-qualified. + /// + /// Return true if this subprogram is a C++11 rvalue-reference-qualified + /// non-static member function (void foo() &&). + unsigned isRValueReference() const { + return getFlags() & FlagRValueReference; + } + + DIScopeRef getScope() const { return DIScopeRef(getRawScope()); } + + StringRef getName() const { return getStringOperand(2); } + StringRef getDisplayName() const { return getStringOperand(3); } + StringRef getLinkageName() const { return getStringOperand(4); } + + MDString *getRawName() const { return getOperandAs<MDString>(2); } + MDString *getRawLinkageName() const { return getOperandAs<MDString>(4); } + + DISubroutineType *getType() const { + return cast_or_null<DISubroutineType>(getRawType()); + } + DITypeRef getContainingType() const { + return DITypeRef(getRawContainingType()); + } + + Constant *getFunctionConstant() const { + if (auto *C = cast_or_null<ConstantAsMetadata>(getRawFunction())) + return C->getValue(); + return nullptr; + } + DITemplateParameterArray getTemplateParams() const { + return cast_or_null<MDTuple>(getRawTemplateParams()); + } + DISubprogram *getDeclaration() const { + return cast_or_null<DISubprogram>(getRawDeclaration()); + } + DILocalVariableArray getVariables() const { + return cast_or_null<MDTuple>(getRawVariables()); + } + + Metadata *getRawScope() const { return getOperand(1); } + Metadata *getRawType() const { return getOperand(5); } + Metadata *getRawContainingType() const { return getOperand(6); } + Metadata *getRawFunction() const { return getOperand(7); } + Metadata *getRawTemplateParams() const { return getOperand(8); } + Metadata *getRawDeclaration() const { return getOperand(9); } + Metadata *getRawVariables() const { return getOperand(10); } + + /// \brief Get a pointer to the function this subprogram describes. + /// + /// This dyn_casts \a getFunctionConstant() to \a Function. + /// + /// FIXME: Should this be looking through bitcasts? + Function *getFunction() const; + + /// \brief Replace the function. + /// + /// If \a isUniqued() and not \a isResolved(), this could node will be + /// RAUW'ed and deleted out from under the caller. Use a \a TrackingMDRef if + /// that's a problem. + /// @{ + void replaceFunction(Function *F); + void replaceFunction(ConstantAsMetadata *MD) { replaceOperandWith(7, MD); } + void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); } + /// @} + + /// \brief Check if this subprogram decribes the given function. + /// + /// FIXME: Should this be looking through bitcasts? + bool describes(const Function *F) const; + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DISubprogramKind; + } +}; + +class DILexicalBlockBase : public DILocalScope { +protected: + DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, + ArrayRef<Metadata *> Ops) + : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} + ~DILexicalBlockBase() = default; + +public: + DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } + + Metadata *getRawScope() const { return getOperand(1); } + + /// \brief Forwarding accessors to LexicalBlock. + /// + /// TODO: Remove these and update code to use \a DILexicalBlock directly. + /// @{ + inline unsigned getLine() const; + inline unsigned getColumn() const; + /// @} + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILexicalBlockKind || + MD->getMetadataID() == DILexicalBlockFileKind; + } +}; + +class DILexicalBlock : public DILexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Column; + + DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef<Metadata *> Ops) + : DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line), + Column(Column) {} + ~DILexicalBlock() = default; + + static DILexicalBlock *getImpl(LLVMContext &Context, DILocalScope *Scope, + DIFile *File, unsigned Line, unsigned Column, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(File), Line, Column, Storage, + ShouldCreate); + } + + static DILexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Line, unsigned Column, + StorageType Storage, bool ShouldCreate = true); + + TempDILexicalBlock cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getLine(), + getColumn()); + } + +public: + DEFINE_MDNODE_GET(DILexicalBlock, (DILocalScope * Scope, DIFile *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) + DEFINE_MDNODE_GET(DILexicalBlock, (Metadata * Scope, Metadata *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) + + TempDILexicalBlock clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILexicalBlockKind; + } +}; + +unsigned DILexicalBlockBase::getLine() const { + if (auto *N = dyn_cast<DILexicalBlock>(this)) + return N->getLine(); + return 0; +} + +unsigned DILexicalBlockBase::getColumn() const { + if (auto *N = dyn_cast<DILexicalBlock>(this)) + return N->getColumn(); + return 0; +} + +class DILexicalBlockFile : public DILexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Discriminator; + + DILexicalBlockFile(LLVMContext &C, StorageType Storage, + unsigned Discriminator, ArrayRef<Metadata *> Ops) + : DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops), + Discriminator(Discriminator) {} + ~DILexicalBlockFile() = default; + + static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope, + DIFile *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(File), Discriminator, Storage, + ShouldCreate); + } + + static DILexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true); + + TempDILexicalBlockFile cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), + getDiscriminator()); + } + +public: + DEFINE_MDNODE_GET(DILexicalBlockFile, (DILocalScope * Scope, DIFile *File, + unsigned Discriminator), + (Scope, File, Discriminator)) + DEFINE_MDNODE_GET(DILexicalBlockFile, + (Metadata * Scope, Metadata *File, unsigned Discriminator), + (Scope, File, Discriminator)) + + TempDILexicalBlockFile clone() const { return cloneImpl(); } + + // TODO: Remove these once they're gone from DILexicalBlockBase. + unsigned getLine() const = delete; + unsigned getColumn() const = delete; + + unsigned getDiscriminator() const { return Discriminator; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILexicalBlockFileKind; + } +}; + +unsigned DILocation::getDiscriminator() const { + if (auto *F = dyn_cast<DILexicalBlockFile>(getScope())) + return F->getDiscriminator(); + return 0; +} + +class DINamespace : public DIScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + DINamespace(LLVMContext &Context, StorageType Storage, unsigned Line, + ArrayRef<Metadata *> Ops) + : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, + Ops), + Line(Line) {} + ~DINamespace() = default; + + static DINamespace *getImpl(LLVMContext &Context, DIScope *Scope, + DIFile *File, StringRef Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name), + Line, Storage, ShouldCreate); + } + static DINamespace *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, MDString *Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true); + + TempDINamespace cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getName(), + getLine()); + } + +public: + DEFINE_MDNODE_GET(DINamespace, (DIScope * Scope, DIFile *File, StringRef Name, + unsigned Line), + (Scope, File, Name, Line)) + DEFINE_MDNODE_GET(DINamespace, (Metadata * Scope, Metadata *File, + MDString *Name, unsigned Line), + (Scope, File, Name, Line)) + + TempDINamespace clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } + StringRef getName() const { return getStringOperand(2); } + + Metadata *getRawScope() const { return getOperand(1); } + MDString *getRawName() const { return getOperandAs<MDString>(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DINamespaceKind; + } +}; + +/// \brief Base class for template parameters. +class DITemplateParameter : public DINode { +protected: + DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, + unsigned Tag, ArrayRef<Metadata *> Ops) + : DINode(Context, ID, Storage, Tag, Ops) {} + ~DITemplateParameter() = default; + +public: + StringRef getName() const { return getStringOperand(0); } + DITypeRef getType() const { return DITypeRef(getRawType()); } + + MDString *getRawName() const { return getOperandAs<MDString>(0); } + Metadata *getRawType() const { return getOperand(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DITemplateTypeParameterKind || + MD->getMetadataID() == DITemplateValueParameterKind; + } +}; + +class DITemplateTypeParameter : public DITemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + DITemplateTypeParameter(LLVMContext &Context, StorageType Storage, + ArrayRef<Metadata *> Ops) + : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage, + dwarf::DW_TAG_template_type_parameter, Ops) {} + ~DITemplateTypeParameter() = default; + + static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, + DITypeRef Type, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, + ShouldCreate); + } + static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, + Metadata *Type, StorageType Storage, + bool ShouldCreate = true); + + TempDITemplateTypeParameter cloneImpl() const { + return getTemporary(getContext(), getName(), getType()); + } + +public: + DEFINE_MDNODE_GET(DITemplateTypeParameter, (StringRef Name, DITypeRef Type), + (Name, Type)) + DEFINE_MDNODE_GET(DITemplateTypeParameter, (MDString * Name, Metadata *Type), + (Name, Type)) + + TempDITemplateTypeParameter clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DITemplateTypeParameterKind; + } +}; + +class DITemplateValueParameter : public DITemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + DITemplateValueParameter(LLVMContext &Context, StorageType Storage, + unsigned Tag, ArrayRef<Metadata *> Ops) + : DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag, + Ops) {} + ~DITemplateValueParameter() = default; + + static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, DITypeRef Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, + Value, Storage, ShouldCreate); + } + static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true); + + TempDITemplateValueParameter cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getType(), + getValue()); + } + +public: + DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, StringRef Name, + DITypeRef Type, Metadata *Value), + (Tag, Name, Type, Value)) + DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, MDString *Name, + Metadata *Type, Metadata *Value), + (Tag, Name, Type, Value)) + + TempDITemplateValueParameter clone() const { return cloneImpl(); } + + Metadata *getValue() const { return getOperand(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DITemplateValueParameterKind; + } +}; + +/// \brief Base class for variables. +/// +/// TODO: Hardcode to DW_TAG_variable. +class DIVariable : public DINode { + unsigned Line; + +protected: + DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef<Metadata *> Ops) + : DINode(C, ID, Storage, Tag, Ops), Line(Line) {} + ~DIVariable() = default; + +public: + unsigned getLine() const { return Line; } + DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } + StringRef getName() const { return getStringOperand(1); } + DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } + DITypeRef getType() const { return DITypeRef(getRawType()); } + + StringRef getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; + } + StringRef getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; + } + + Metadata *getRawScope() const { return getOperand(0); } + MDString *getRawName() const { return getOperandAs<MDString>(1); } + Metadata *getRawFile() const { return getOperand(2); } + Metadata *getRawType() const { return getOperand(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILocalVariableKind || + MD->getMetadataID() == DIGlobalVariableKind; + } +}; + +/// \brief Global variables. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +class DIGlobalVariable : public DIVariable { + friend class LLVMContextImpl; + friend class MDNode; + + bool IsLocalToUnit; + bool IsDefinition; + + DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, + bool IsLocalToUnit, bool IsDefinition, + ArrayRef<Metadata *> Ops) + : DIVariable(C, DIGlobalVariableKind, Storage, dwarf::DW_TAG_variable, + Line, Ops), + IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} + ~DIGlobalVariable() = default; + + static DIGlobalVariable * + getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, + StringRef LinkageName, DIFile *File, unsigned Line, DITypeRef Type, + bool IsLocalToUnit, bool IsDefinition, Constant *Variable, + DIDerivedType *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, + Variable ? ConstantAsMetadata::get(Variable) : nullptr, + StaticDataMemberDeclaration, Storage, ShouldCreate); + } + static DIGlobalVariable * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true); + + TempDIGlobalVariable cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getVariable(), + getStaticDataMemberDeclaration()); + } + +public: + DEFINE_MDNODE_GET(DIGlobalVariable, + (DIScope * Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned Line, DITypeRef Type, + bool IsLocalToUnit, bool IsDefinition, Constant *Variable, + DIDerivedType *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + DEFINE_MDNODE_GET(DIGlobalVariable, + (Metadata * Scope, MDString *Name, MDString *LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + + TempDIGlobalVariable clone() const { return cloneImpl(); } + + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + StringRef getDisplayName() const { return getStringOperand(4); } + StringRef getLinkageName() const { return getStringOperand(5); } + Constant *getVariable() const { + if (auto *C = cast_or_null<ConstantAsMetadata>(getRawVariable())) + return dyn_cast<Constant>(C->getValue()); + return nullptr; + } + DIDerivedType *getStaticDataMemberDeclaration() const { + return cast_or_null<DIDerivedType>(getRawStaticDataMemberDeclaration()); + } + + MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); } + Metadata *getRawVariable() const { return getOperand(6); } + Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(7); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIGlobalVariableKind; + } +}; + +/// \brief Local variable. +/// +/// TODO: Split between arguments and otherwise. +/// TODO: Use \c DW_TAG_variable instead of fake tags. +/// TODO: Split up flags. +class DILocalVariable : public DIVariable { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Arg; + unsigned Flags; + + DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned Arg, unsigned Flags, + ArrayRef<Metadata *> Ops) + : DIVariable(C, DILocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), + Flags(Flags) {} + ~DILocalVariable() = default; + + static DILocalVariable *getImpl(LLVMContext &Context, unsigned Tag, + DIScope *Scope, StringRef Name, DIFile *File, + unsigned Line, DITypeRef Type, unsigned Arg, + unsigned Flags, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), + File, Line, Type, Arg, Flags, Storage, ShouldCreate); + } + static DILocalVariable * + getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, + unsigned Flags, StorageType Storage, bool ShouldCreate = true); + + TempDILocalVariable cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getName(), + getFile(), getLine(), getType(), getArg(), getFlags()); + } + +public: + DEFINE_MDNODE_GET(DILocalVariable, + (unsigned Tag, DILocalScope *Scope, StringRef Name, + DIFile *File, unsigned Line, DITypeRef Type, unsigned Arg, + unsigned Flags), + (Tag, Scope, Name, File, Line, Type, Arg, Flags)) + DEFINE_MDNODE_GET(DILocalVariable, + (unsigned Tag, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags), + (Tag, Scope, Name, File, Line, Type, Arg, Flags)) + + TempDILocalVariable clone() const { return cloneImpl(); } + + /// \brief Get the local scope for this variable. + /// + /// Variables must be defined in a local scope. + DILocalScope *getScope() const { + return cast<DILocalScope>(DIVariable::getScope()); + } + + unsigned getArg() const { return Arg; } + unsigned getFlags() const { return Flags; } + + bool isArtificial() const { return getFlags() & FlagArtificial; } + bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + + /// \brief Check that a location is valid for this variable. + /// + /// Check that \c DL exists, is in the same subprogram, and has the same + /// inlined-at location as \c this. (Otherwise, it's not a valid attachemnt + /// to a \a DbgInfoIntrinsic.) + bool isValidLocationForIntrinsic(const DILocation *DL) const { + return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILocalVariableKind; + } +}; + +/// \brief DWARF expression. +/// +/// This is (almost) a DWARF expression that modifies the location of a +/// variable or (or the location of a single piece of a variable). +/// +/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const +/// and have DW_OP_plus consume the topmost elements on the stack. +/// +/// TODO: Co-allocate the expression elements. +/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary +/// storage types. +class DIExpression : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + + std::vector<uint64_t> Elements; + + DIExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements) + : MDNode(C, DIExpressionKind, Storage, None), + Elements(Elements.begin(), Elements.end()) {} + ~DIExpression() = default; + + static DIExpression *getImpl(LLVMContext &Context, + ArrayRef<uint64_t> Elements, StorageType Storage, + bool ShouldCreate = true); + + TempDIExpression cloneImpl() const { + return getTemporary(getContext(), getElements()); + } + +public: + DEFINE_MDNODE_GET(DIExpression, (ArrayRef<uint64_t> Elements), (Elements)) + + TempDIExpression clone() const { return cloneImpl(); } + + ArrayRef<uint64_t> getElements() const { return Elements; } + + unsigned getNumElements() const { return Elements.size(); } + uint64_t getElement(unsigned I) const { + assert(I < Elements.size() && "Index out of range"); + return Elements[I]; + } + + /// \brief Return whether this is a piece of an aggregate variable. + bool isBitPiece() const; + + /// \brief Return the offset of this piece in bits. + uint64_t getBitPieceOffset() const; + + /// \brief Return the size of this piece in bits. + uint64_t getBitPieceSize() const; + + typedef ArrayRef<uint64_t>::iterator element_iterator; + element_iterator elements_begin() const { return getElements().begin(); } + element_iterator elements_end() const { return getElements().end(); } + + /// \brief A lightweight wrapper around an expression operand. + /// + /// TODO: Store arguments directly and change \a DIExpression to store a + /// range of these. + class ExprOperand { + const uint64_t *Op; + + public: + explicit ExprOperand(const uint64_t *Op) : Op(Op) {} + + const uint64_t *get() const { return Op; } + + /// \brief Get the operand code. + uint64_t getOp() const { return *Op; } + + /// \brief Get an argument to the operand. + /// + /// Never returns the operand itself. + uint64_t getArg(unsigned I) const { return Op[I + 1]; } + + unsigned getNumArgs() const { return getSize() - 1; } + + /// \brief Return the size of the operand. + /// + /// Return the number of elements in the operand (1 + args). + unsigned getSize() const; + }; + + /// \brief An iterator for expression operands. + class expr_op_iterator + : public std::iterator<std::input_iterator_tag, ExprOperand> { + ExprOperand Op; + + public: + explicit expr_op_iterator(element_iterator I) : Op(I) {} + + element_iterator getBase() const { return Op.get(); } + const ExprOperand &operator*() const { return Op; } + const ExprOperand *operator->() const { return &Op; } + + expr_op_iterator &operator++() { + increment(); + return *this; + } + expr_op_iterator operator++(int) { + expr_op_iterator T(*this); + increment(); + return T; + } + + /// \brief Get the next iterator. + /// + /// \a std::next() doesn't work because this is technically an + /// input_iterator, but it's a perfectly valid operation. This is an + /// accessor to provide the same functionality. + expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } + + bool operator==(const expr_op_iterator &X) const { + return getBase() == X.getBase(); + } + bool operator!=(const expr_op_iterator &X) const { + return getBase() != X.getBase(); + } + + private: + void increment() { Op = ExprOperand(getBase() + Op.getSize()); } + }; + + /// \brief Visit the elements via ExprOperand wrappers. + /// + /// These range iterators visit elements through \a ExprOperand wrappers. + /// This is not guaranteed to be a valid range unless \a isValid() gives \c + /// true. + /// + /// \pre \a isValid() gives \c true. + /// @{ + expr_op_iterator expr_op_begin() const { + return expr_op_iterator(elements_begin()); + } + expr_op_iterator expr_op_end() const { + return expr_op_iterator(elements_end()); + } + /// @} + + bool isValid() const; + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIExpressionKind; + } +}; + +class DIObjCProperty : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Attributes; + + DIObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Attributes, ArrayRef<Metadata *> Ops) + : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, + Ops), + Line(Line), Attributes(Attributes) {} + ~DIObjCProperty() = default; + + static DIObjCProperty * + getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line, + StringRef GetterName, StringRef SetterName, unsigned Attributes, + DIType *Type, StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, + getCanonicalMDString(Context, GetterName), + getCanonicalMDString(Context, SetterName), Attributes, Type, + Storage, ShouldCreate); + } + static DIObjCProperty *getImpl(LLVMContext &Context, MDString *Name, + Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type, + StorageType Storage, bool ShouldCreate = true); + + TempDIObjCProperty cloneImpl() const { + return getTemporary(getContext(), getName(), getFile(), getLine(), + getGetterName(), getSetterName(), getAttributes(), + getType()); + } + +public: + DEFINE_MDNODE_GET(DIObjCProperty, + (StringRef Name, DIFile *File, unsigned Line, + StringRef GetterName, StringRef SetterName, + unsigned Attributes, DIType *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + DEFINE_MDNODE_GET(DIObjCProperty, + (MDString * Name, Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + + TempDIObjCProperty clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getAttributes() const { return Attributes; } + StringRef getName() const { return getStringOperand(0); } + DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } + StringRef getGetterName() const { return getStringOperand(2); } + StringRef getSetterName() const { return getStringOperand(3); } + + /// \brief Get the type. + /// + /// \note Objective-C doesn't have an ODR, so there is no benefit in storing + /// a type ref here. + DIType *getType() const { return cast_or_null<DIType>(getRawType()); } + + StringRef getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; + } + StringRef getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; + } + + MDString *getRawName() const { return getOperandAs<MDString>(0); } + Metadata *getRawFile() const { return getOperand(1); } + MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } + MDString *getRawSetterName() const { return getOperandAs<MDString>(3); } + Metadata *getRawType() const { return getOperand(4); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIObjCPropertyKind; + } +}; + +/// \brief An imported module (C++ using directive or similar). +class DIImportedEntity : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef<Metadata *> Ops) + : DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {} + ~DIImportedEntity() = default; + + static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + DIScope *Scope, DINodeRef Entity, + unsigned Line, StringRef Name, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, Entity, Line, + getCanonicalMDString(Context, Name), Storage, ShouldCreate); + } + static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name, + StorageType Storage, + bool ShouldCreate = true); + + TempDIImportedEntity cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getEntity(), + getLine(), getName()); + } + +public: + DEFINE_MDNODE_GET(DIImportedEntity, + (unsigned Tag, DIScope *Scope, DINodeRef Entity, + unsigned Line, StringRef Name = ""), + (Tag, Scope, Entity, Line, Name)) + DEFINE_MDNODE_GET(DIImportedEntity, + (unsigned Tag, Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name), + (Tag, Scope, Entity, Line, Name)) + + TempDIImportedEntity clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } + DINodeRef getEntity() const { return DINodeRef(getRawEntity()); } + StringRef getName() const { return getStringOperand(2); } + + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawEntity() const { return getOperand(1); } + MDString *getRawName() const { return getOperandAs<MDString>(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIImportedEntityKind; + } +}; + +} // end namespace llvm + +#undef DEFINE_MDNODE_GET_UNPACK_IMPL +#undef DEFINE_MDNODE_GET_UNPACK +#undef DEFINE_MDNODE_GET + +#endif diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 86e64417099d..8ea5875e1f85 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -22,11 +22,15 @@ namespace llvm { class LLVMContext; class raw_ostream; - class MDNode; - - /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, - /// and MachineInstr to compactly encode file/line/scope information for an - /// operation. + class DILocation; + + /// \brief A debug info location. + /// + /// This class is a wrapper around a tracking reference to an \a DILocation + /// pointer. + /// + /// To avoid extra includes, \a DebugLoc doubles the \a DILocation API with a + /// one based on relatively opaque \a MDNode pointers. class DebugLoc { TrackingMDNodeRef Loc; @@ -43,67 +47,78 @@ namespace llvm { return *this; } + /// \brief Construct from an \a DILocation. + DebugLoc(const DILocation *L); + + /// \brief Construct from an \a MDNode. + /// + /// Note: if \c N is not an \a DILocation, a verifier check will fail, and + /// accessors will crash. However, construction from other nodes is + /// supported in order to handle forward references when reading textual + /// IR. + explicit DebugLoc(const MDNode *N); + + /// \brief Get the underlying \a DILocation. + /// + /// \pre !*this or \c isa<DILocation>(getAsMDNode()). + /// @{ + DILocation *get() const; + operator DILocation *() const { return get(); } + DILocation *operator->() const { return get(); } + DILocation &operator*() const { return *get(); } + /// @} + + /// \brief Check for null. + /// + /// Check for null in a way that is safe with broken debug info. Unlike + /// the conversion to \c DILocation, this doesn't require that \c Loc is of + /// the right type. Important for cases like \a llvm::StripDebugInfo() and + /// \a Instruction::hasMetadata(). + explicit operator bool() const { return Loc; } + /// \brief Check whether this has a trivial destructor. bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } - /// get - Get a new DebugLoc that corresponds to the specified line/col - /// scope/inline location. - static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, - MDNode *InlinedAt = nullptr); - - /// getFromDILocation - Translate the DILocation quad into a DebugLoc. - static DebugLoc getFromDILocation(MDNode *N); - - /// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. - static DebugLoc getFromDILexicalBlock(MDNode *N); - - /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return !Loc; } + /// \brief Create a new DebugLoc. + /// + /// Create a new DebugLoc at the specified line/col and scope/inline. This + /// forwards to \a DILocation::get(). + /// + /// If \c !Scope, returns a default-constructed \a DebugLoc. + /// + /// FIXME: Remove this. Users should use DILocation::get(). + static DebugLoc get(unsigned Line, unsigned Col, const MDNode *Scope, + const MDNode *InlinedAt = nullptr); unsigned getLine() const; unsigned getCol() const; - - /// getScope - This returns the scope pointer for this DebugLoc, or null if - /// invalid. MDNode *getScope() const; - MDNode *getScope(const LLVMContext &) const { return getScope(); } - - /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or - /// null if invalid or not present. - MDNode *getInlinedAt() const; - MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); } - - /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. - void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const; - void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, - const LLVMContext &) const { - return getScopeAndInlinedAt(Scope, IA); - } - - /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. - MDNode *getScopeNode() const; - MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); } - - // getFnDebugLoc - Walk up the scope chain of given debug loc and find line - // number info for the function. + DILocation *getInlinedAt() const; + + /// \brief Get the fully inlined-at scope for a DebugLoc. + /// + /// Gets the inlined-at scope for a DebugLoc. + MDNode *getInlinedAtScope() const; + + /// \brief Find the debug info location for the start of the function. + /// + /// Walk up the scope chain of given debug loc and find line number info + /// for the function. + /// + /// FIXME: Remove this. Users should use DILocation/DILocalScope API to + /// find the subprogram, and then DILocation::get(). DebugLoc getFnDebugLoc() const; - DebugLoc getFnDebugLoc(const LLVMContext &) const { - return getFnDebugLoc(); - } - /// getAsMDNode - This method converts the compressed DebugLoc node into a - /// DILocation compatible MDNode. - MDNode *getAsMDNode() const; - MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); } + /// \brief Return \c this as a bar \a MDNode. + MDNode *getAsMDNode() const { return Loc; } bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } - bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } + bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; } void dump() const; - void dump(const LLVMContext &) const { dump(); } + /// \brief prints source location /path/to/file.exe:line:col @[inlined at] void print(raw_ostream &OS) const; - void print(const LLVMContext &, raw_ostream &OS) const { print(OS); } }; } // end namespace llvm diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index 182015c98aa2..38f1af0d70da 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -94,8 +94,8 @@ public: /// FunctionType - Class to represent function types /// class FunctionType : public Type { - FunctionType(const FunctionType &) LLVM_DELETED_FUNCTION; - const FunctionType &operator=(const FunctionType &) LLVM_DELETED_FUNCTION; + FunctionType(const FunctionType &) = delete; + const FunctionType &operator=(const FunctionType &) = delete; FunctionType(Type *Result, ArrayRef<Type*> Params, bool IsVarArgs); public: @@ -188,8 +188,8 @@ public: /// generator for a target expects). /// class StructType : public CompositeType { - StructType(const StructType &) LLVM_DELETED_FUNCTION; - const StructType &operator=(const StructType &) LLVM_DELETED_FUNCTION; + StructType(const StructType &) = delete; + const StructType &operator=(const StructType &) = delete; StructType(LLVMContext &C) : CompositeType(C, StructTyID), SymbolTableEntry(nullptr) {} enum { @@ -308,8 +308,8 @@ public: /// class SequentialType : public CompositeType { Type *ContainedType; ///< Storage for the single contained type. - SequentialType(const SequentialType &) LLVM_DELETED_FUNCTION; - const SequentialType &operator=(const SequentialType &) LLVM_DELETED_FUNCTION; + SequentialType(const SequentialType &) = delete; + const SequentialType &operator=(const SequentialType &) = delete; protected: SequentialType(TypeID TID, Type *ElType) @@ -335,8 +335,8 @@ public: class ArrayType : public SequentialType { uint64_t NumElements; - ArrayType(const ArrayType &) LLVM_DELETED_FUNCTION; - const ArrayType &operator=(const ArrayType &) LLVM_DELETED_FUNCTION; + ArrayType(const ArrayType &) = delete; + const ArrayType &operator=(const ArrayType &) = delete; ArrayType(Type *ElType, uint64_t NumEl); public: /// ArrayType::get - This static method is the primary way to construct an @@ -361,8 +361,8 @@ public: class VectorType : public SequentialType { unsigned NumElements; - VectorType(const VectorType &) LLVM_DELETED_FUNCTION; - const VectorType &operator=(const VectorType &) LLVM_DELETED_FUNCTION; + VectorType(const VectorType &) = delete; + const VectorType &operator=(const VectorType &) = delete; VectorType(Type *ElType, unsigned NumEl); public: /// VectorType::get - This static method is the primary way to construct an @@ -446,8 +446,8 @@ public: /// PointerType - Class to represent pointers. /// class PointerType : public SequentialType { - PointerType(const PointerType &) LLVM_DELETED_FUNCTION; - const PointerType &operator=(const PointerType &) LLVM_DELETED_FUNCTION; + PointerType(const PointerType &) = delete; + const PointerType &operator=(const PointerType &) = delete; explicit PointerType(Type *ElType, unsigned AddrSpace); public: /// PointerType::get - This constructs a pointer to an object of the specified @@ -464,6 +464,9 @@ public: /// element type. static bool isValidElementType(Type *ElemTy); + /// Return true if we can load or store from a pointer to this type. + static bool isLoadableOrStorableType(Type *ElemTy); + /// @brief Return the address space of the Pointer type. inline unsigned getAddressSpace() const { return getSubclassData(); } diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index c6a8854e0774..6db5a40c5772 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -20,6 +20,7 @@ #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Module.h" #include "llvm/Support/Casting.h" +#include <functional> namespace llvm { diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 51403281e964..6c228eae633a 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -19,6 +19,7 @@ #define LLVM_IR_FUNCTION_H #include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/Optional.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" @@ -31,26 +32,6 @@ namespace llvm { class FunctionType; class LLVMContext; -// Traits for intrusive list of basic blocks... -template<> struct ilist_traits<BasicBlock> - : public SymbolTableListTraits<BasicBlock, Function> { - - // createSentinel is used to get hold of the node that marks the end of the - // list... (same trick used here as in ilist_traits<Instruction>) - BasicBlock *createSentinel() const { - return static_cast<BasicBlock*>(&Sentinel); - } - static void destroySentinel(BasicBlock*) {} - - BasicBlock *provideInitialHead() const { return createSentinel(); } - BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } - static void noteHead(BasicBlock*, BasicBlock*) {} - - static ValueSymbolTable *getSymTab(Function *ItemParent); -private: - mutable ilist_half_node<BasicBlock> Sentinel; -}; - template<> struct ilist_traits<Argument> : public SymbolTableListTraits<Argument, Function> { @@ -86,6 +67,7 @@ private: mutable ArgumentListType ArgumentList; ///< The formal arguments ValueSymbolTable *SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes + FunctionType *Ty; /* * Value::SubclassData @@ -96,6 +78,17 @@ private: * bit 3-6: CallingConvention */ + /// Bits from GlobalObject::GlobalObjectSubclassData. + enum { + /// Whether this function is materializable. + IsMaterializableBit = 1 << 0, + HasMetadataHashEntryBit = 1 << 1 + }; + void setGlobalObjectBit(unsigned Mask, bool Value) { + setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) | + (Value ? Mask : 0u)); + } + friend class SymbolTableListTraits<Function, Module>; void setParent(Module *parent); @@ -113,12 +106,8 @@ private: } void BuildLazyArguments() const; - Function(const Function&) LLVM_DELETED_FUNCTION; - void operator=(const Function&) LLVM_DELETED_FUNCTION; - - /// Do the actual lookup of an intrinsic ID when the query could not be - /// answered from the cache. - unsigned lookupIntrinsicID() const LLVM_READONLY; + Function(const Function&) = delete; + void operator=(const Function&) = delete; /// Function ctor - If the (optional) Module argument is specified, the /// function is automatically inserted into the end of the function list for @@ -133,13 +122,13 @@ public: return new(0) Function(Ty, Linkage, N, M); } - ~Function(); + ~Function() override; Type *getReturnType() const; // Return the type of the ret val FunctionType *getFunctionType() const; // Return the FunctionType for me - /// getContext - Return a pointer to the LLVMContext associated with this - /// function, or NULL if this function is not bound to a context yet. + /// getContext - Return a reference to the LLVMContext associated with this + /// function. LLVMContext &getContext() const; /// isVarArg - Return true if this function takes a variable number of @@ -154,13 +143,17 @@ public: /// intrinsic, or if the pointer is null. This value is always defined to be /// zero to allow easy checking for whether a function is intrinsic or not. /// The particular intrinsic functions which correspond to this value are - /// defined in llvm/Intrinsics.h. Results are cached in the LLVM context, - /// subsequent requests for the same ID return results much faster from the - /// cache. - /// - unsigned getIntrinsicID() const LLVM_READONLY; + /// defined in llvm/Intrinsics.h. + Intrinsic::ID getIntrinsicID() const LLVM_READONLY { return IntID; } bool isIntrinsic() const { return getName().startswith("llvm."); } + /// \brief Recalculate the ID for this function if it is an Intrinsic defined + /// in llvm/Intrinsics.h. Sets the intrinsic ID to Intrinsic::not_intrinsic + /// if the name of this function does not match an intrinsic in that header. + /// Note, this method does not need to be called directly, as it is called + /// from Value::setName() whenever the name of this function changes. + void recalculateIntrinsicID(); + /// getCallingConv()/setCallingConv(CC) - These method get and set the /// calling convention of this function. The enum values for the known /// calling conventions are defined in CallingConv.h. @@ -202,6 +195,12 @@ public: AttributeSet::FunctionIndex, Kind, Value)); } + /// Set the entry count for this function. + void setEntryCount(uint64_t Count); + + /// Get the entry count for this function. + Optional<uint64_t> getEntryCount() const; + /// @brief Return true if the function has the attribute. bool hasFnAttribute(Attribute::AttrKind Kind) const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); @@ -218,6 +217,11 @@ public: return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); } + /// \brief Return the stack alignment for the function. + unsigned getFnStackAlignment() const { + return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex); + } + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm /// to use during code generation. bool hasGC() const; @@ -234,6 +238,13 @@ public: /// @brief removes the attributes from the list of attributes. void removeAttributes(unsigned i, AttributeSet attr); + /// @brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + + /// @brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// @brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { return AttributeSets.getParamAlignment(i); @@ -244,7 +255,13 @@ public: uint64_t getDereferenceableBytes(unsigned i) const { return AttributeSets.getDereferenceableBytes(i); } - + + /// @brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(unsigned i) const { + return AttributeSets.getDereferenceableOrNullBytes(i); + } + /// @brief Determine if the function does not access memory. bool doesNotAccessMemory() const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, @@ -291,6 +308,16 @@ public: addFnAttr(Attribute::NoDuplicate); } + /// @brief Determine if the call is convergent. + bool isConvergent() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::Convergent); + } + void setConvergent() { + addFnAttr(Attribute::Convergent); + } + + /// @brief True if the ABI mandates (or the user requested) that this /// function be in a unwind table. bool hasUWTable() const { @@ -464,6 +491,10 @@ public: Constant *getPrologueData() const; void setPrologueData(Constant *PrologueData); + /// Print the function to an output stream with an optional + /// AssemblyAnnotationWriter. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr) const; + /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the /// program, displaying the CFG of the current function with the code for each @@ -514,12 +545,50 @@ public: /// setjmp or other function that gcc recognizes as "returning twice". bool callsFunctionThatReturnsTwice() const; + /// \brief Check if this has any metadata. + bool hasMetadata() const { return hasMetadataHashEntry(); } + + /// \brief Get the current metadata attachment, if any. + /// + /// Returns \c nullptr if such an attachment is missing. + /// @{ + MDNode *getMetadata(unsigned KindID) const; + MDNode *getMetadata(StringRef Kind) const; + /// @} + + /// \brief Set a particular kind of metadata attachment. + /// + /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or + /// replacing it if it already exists. + /// @{ + void setMetadata(unsigned KindID, MDNode *MD); + void setMetadata(StringRef Kind, MDNode *MD); + /// @} + + /// \brief Get all current metadata attachments. + void + getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const; + + /// \brief Drop metadata not in the given list. + /// + /// Drop all metadata from \c this not included in \c KnownIDs. + void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs); + private: // Shadow Value::setValueSubclassData with a private forwarding method so that // subclasses cannot accidentally use it. void setValueSubclassData(unsigned short D) { Value::setValueSubclassData(D); } + + bool hasMetadataHashEntry() const { + return getGlobalObjectSubClassData() & HasMetadataHashEntryBit; + } + void setHasMetadataHashEntry(bool HasEntry) { + setGlobalObjectBit(HasMetadataHashEntryBit, HasEntry); + } + + void clearMetadata(); }; inline ValueSymbolTable * diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index 6f57dc2a98a6..1d6c9157f0b8 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -47,11 +47,14 @@ public: /// lazily. If the Materializer doesn't support this capability, this method /// is a noop. /// - virtual void Dematerialize(GlobalValue *) {} + virtual void dematerialize(GlobalValue *) {} /// Make sure the entire Module has been completely read. /// - virtual std::error_code MaterializeModule(Module *M) = 0; + virtual std::error_code materializeModule(Module *M) = 0; + + virtual std::error_code materializeMetadata() = 0; + virtual void setStripDebugInfo() = 0; virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0; }; diff --git a/include/llvm/IR/GetElementPtrTypeIterator.h b/include/llvm/IR/GetElementPtrTypeIterator.h index dcf8e64dbb27..6bba0ae29e98 100644 --- a/include/llvm/IR/GetElementPtrTypeIterator.h +++ b/include/llvm/IR/GetElementPtrTypeIterator.h @@ -16,7 +16,9 @@ #define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/User.h" +#include "llvm/ADT/PointerIntPair.h" namespace llvm { template<typename ItTy = User::const_op_iterator> @@ -26,19 +28,28 @@ namespace llvm { Type *, ptrdiff_t> super; ItTy OpIt; - Type *CurTy; + PointerIntPair<Type *, 1> CurTy; + unsigned AddrSpace; generic_gep_type_iterator() {} public: static generic_gep_type_iterator begin(Type *Ty, ItTy It) { generic_gep_type_iterator I; - I.CurTy = Ty; + I.CurTy.setPointer(Ty); + I.OpIt = It; + return I; + } + static generic_gep_type_iterator begin(Type *Ty, unsigned AddrSpace, + ItTy It) { + generic_gep_type_iterator I; + I.CurTy.setPointer(Ty); + I.CurTy.setInt(true); + I.AddrSpace = AddrSpace; I.OpIt = It; return I; } static generic_gep_type_iterator end(ItTy It) { generic_gep_type_iterator I; - I.CurTy = nullptr; I.OpIt = It; return I; } @@ -51,11 +62,15 @@ namespace llvm { } Type *operator*() const { - return CurTy; + if (CurTy.getInt()) + return CurTy.getPointer()->getPointerTo(AddrSpace); + return CurTy.getPointer(); } Type *getIndexedType() const { - CompositeType *CT = cast<CompositeType>(CurTy); + if (CurTy.getInt()) + return CurTy.getPointer(); + CompositeType *CT = cast<CompositeType>(CurTy.getPointer()); return CT->getTypeAtIndex(getOperand()); } @@ -66,10 +81,13 @@ namespace llvm { Value *getOperand() const { return *OpIt; } generic_gep_type_iterator& operator++() { // Preincrement - if (CompositeType *CT = dyn_cast<CompositeType>(CurTy)) { - CurTy = CT->getTypeAtIndex(getOperand()); + if (CurTy.getInt()) { + CurTy.setInt(false); + } else if (CompositeType *CT = + dyn_cast<CompositeType>(CurTy.getPointer())) { + CurTy.setPointer(CT->getTypeAtIndex(getOperand())); } else { - CurTy = nullptr; + CurTy.setPointer(nullptr); } ++OpIt; return *this; @@ -83,15 +101,23 @@ namespace llvm { typedef generic_gep_type_iterator<> gep_type_iterator; inline gep_type_iterator gep_type_begin(const User *GEP) { - return gep_type_iterator::begin - (GEP->getOperand(0)->getType()->getScalarType(), GEP->op_begin()+1); + auto *GEPOp = cast<GEPOperator>(GEP); + return gep_type_iterator::begin( + GEPOp->getSourceElementType(), + cast<PointerType>(GEPOp->getPointerOperandType()->getScalarType()) + ->getAddressSpace(), + GEP->op_begin() + 1); } inline gep_type_iterator gep_type_end(const User *GEP) { return gep_type_iterator::end(GEP->op_end()); } inline gep_type_iterator gep_type_begin(const User &GEP) { - return gep_type_iterator::begin - (GEP.getOperand(0)->getType()->getScalarType(), GEP.op_begin()+1); + auto &GEPOp = cast<GEPOperator>(GEP); + return gep_type_iterator::begin( + GEPOp.getSourceElementType(), + cast<PointerType>(GEPOp.getPointerOperandType()->getScalarType()) + ->getAddressSpace(), + GEP.op_begin() + 1); } inline gep_type_iterator gep_type_end(const User &GEP) { return gep_type_iterator::end(GEP.op_end()); diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index 075b5703bccf..ce73b7af8ca1 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -28,13 +28,13 @@ template<typename ValueSubClass, typename ItemParentClass> class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> { friend class SymbolTableListTraits<GlobalAlias, Module>; - void operator=(const GlobalAlias &) LLVM_DELETED_FUNCTION; - GlobalAlias(const GlobalAlias &) LLVM_DELETED_FUNCTION; + void operator=(const GlobalAlias &) = delete; + GlobalAlias(const GlobalAlias &) = delete; void setParent(Module *parent); - GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, - const Twine &Name, Constant *Aliasee, Module *Parent); + GlobalAlias(PointerType *Ty, LinkageTypes Linkage, const Twine &Name, + Constant *Aliasee, Module *Parent); public: // allocate space for exactly one operand @@ -44,19 +44,17 @@ public: /// If a parent module is specified, the alias is automatically inserted into /// the end of the specified module's alias list. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - Constant *Aliasee, Module *Parent); + static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, Constant *Aliasee, + Module *Parent); // Without the Aliasee. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - Module *Parent); + static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, Module *Parent); // The module is taken from the Aliasee. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - GlobalValue *Aliasee); + static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, GlobalValue *Aliasee); // Type, Parent and AddressSpace taken from the Aliasee. static GlobalAlias *create(LinkageTypes Linkage, const Twine &Name, diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 546fea2dfa9b..f0552410b61d 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -24,10 +24,10 @@ class Comdat; class Module; class GlobalObject : public GlobalValue { - GlobalObject(const GlobalObject &) LLVM_DELETED_FUNCTION; + GlobalObject(const GlobalObject &) = delete; protected: - GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + GlobalObject(PointerType *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name) : GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name), ObjComdat(nullptr) { setGlobalValueSubClassData(0); diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index d0f7e9a11790..1dfe0c28b02c 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -28,8 +28,12 @@ class Comdat; class PointerType; class Module; +namespace Intrinsic { + enum ID : unsigned; +} + class GlobalValue : public Constant { - GlobalValue(const GlobalValue &) LLVM_DELETED_FUNCTION; + GlobalValue(const GlobalValue &) = delete; public: /// @brief An enumeration for the kinds of linkage for global values. enum LinkageTypes { @@ -61,12 +65,12 @@ public: }; protected: - GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + GlobalValue(PointerType *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name) : Constant(Ty, VTy, Ops, NumOps), Linkage(Linkage), Visibility(DefaultVisibility), UnnamedAddr(0), DllStorageClass(DefaultStorageClass), - ThreadLocal(NotThreadLocal), Parent(nullptr) { + ThreadLocal(NotThreadLocal), IntID((Intrinsic::ID)0U), Parent(nullptr) { setName(Name); } @@ -84,7 +88,16 @@ private: // Give subclasses access to what otherwise would be wasted padding. // (19 + 3 + 2 + 1 + 2 + 5) == 32. unsigned SubClassData : 19; + protected: + /// \brief The intrinsic ID for this subclass (which must be a Function). + /// + /// This member is defined by this class, but not used for anything. + /// Subclasses can use it to store their intrinsic ID, if they have one. + /// + /// This is stored here to save space in Function on 64-bit hosts. + Intrinsic::ID IntID; + static const unsigned GlobalValueSubClassDataBits = 19; unsigned getGlobalValueSubClassData() const { return SubClassData; @@ -104,7 +117,7 @@ public: LocalExecTLSModel }; - ~GlobalValue() { + ~GlobalValue() override { removeDeadConstantUsers(); // remove any dead constants using this. } @@ -165,9 +178,9 @@ public: const char *getSection() const; /// Global values are always pointers. - inline PointerType *getType() const { - return cast<PointerType>(User::getType()); - } + PointerType *getType() const { return cast<PointerType>(User::getType()); } + + Type *getValueType() const { return getType()->getElementType(); } static LinkageTypes getLinkOnceLinkage(bool ODR) { return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; @@ -317,7 +330,7 @@ public: /// If this GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized /// lazily. If !isDematerializable(), this method is a noop. - void Dematerialize(); + void dematerialize(); /// @} @@ -343,13 +356,11 @@ public: virtual void eraseFromParent() = 0; /// Get the module that this global value is contained inside of... - inline Module *getParent() { return Parent; } - inline const Module *getParent() const { return Parent; } - - const DataLayout *getDataLayout() const; + Module *getParent() { return Parent; } + const Module *getParent() const { return Parent; } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Value *V) { + static bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || V->getValueID() == Value::GlobalVariableVal || V->getValueID() == Value::GlobalAliasVal; diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 4189ccb90a54..9f57705dae72 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -34,9 +34,9 @@ template<typename ValueSubClass, typename ItemParentClass> class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> { friend class SymbolTableListTraits<GlobalVariable, Module>; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void operator=(const GlobalVariable &) LLVM_DELETED_FUNCTION; - GlobalVariable(const GlobalVariable &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void operator=(const GlobalVariable &) = delete; + GlobalVariable(const GlobalVariable &) = delete; void setParent(Module *parent); @@ -66,7 +66,7 @@ public: ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, bool isExternallyInitialized = false); - ~GlobalVariable() { + ~GlobalVariable() override { NumOperands = 1; // FIXME: needed by operator delete } diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index e5f62fb9625e..adf692469ad3 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -21,6 +21,8 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/ConstantFolder.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Operator.h" @@ -115,17 +117,15 @@ public: } /// \brief Set location information used by debugging information. - void SetCurrentDebugLocation(const DebugLoc &L) { - CurDbgLocation = L; - } + void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); } /// \brief Get location information used by debugging information. - DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } + const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } /// \brief If this builder has a current debug location, set it on the /// specified instruction. void SetInstDebugLocation(Instruction *I) const { - if (!CurDbgLocation.isUnknown()) + if (CurDbgLocation) I->setDebugLoc(CurDbgLocation); } @@ -200,8 +200,8 @@ public: BasicBlock::iterator Point; DebugLoc DbgLoc; - InsertPointGuard(const InsertPointGuard &) LLVM_DELETED_FUNCTION; - InsertPointGuard &operator=(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + InsertPointGuard(const InsertPointGuard &) = delete; + InsertPointGuard &operator=(const InsertPointGuard &) = delete; public: InsertPointGuard(IRBuilderBase &B) @@ -221,9 +221,9 @@ public: FastMathFlags FMF; MDNode *FPMathTag; - FastMathFlagGuard(const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + FastMathFlagGuard(const FastMathFlagGuard &) = delete; FastMathFlagGuard &operator=( - const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + const FastMathFlagGuard &) = delete; public: FastMathFlagGuard(IRBuilderBase &B) @@ -245,7 +245,7 @@ public: /// filled in with the null terminated string value specified. The new global /// variable will be marked mergable with any others of the same contents. If /// Name is specified, it is the name of the global variable created. - Value *CreateGlobalString(StringRef Str, const Twine &Name = ""); + GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = ""); /// \brief Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { @@ -322,6 +322,11 @@ public: return Type::getInt64Ty(Context); } + /// \brief Fetch the type representing a 128-bit integer. + IntegerType *getInt128Ty() { + return Type::getInt128Ty(Context); + } + /// \brief Fetch the type representing an N-bit integer. IntegerType *getIntNTy(unsigned N) { return Type::getIntNTy(Context, N); @@ -353,8 +358,8 @@ public: } /// \brief Fetch the type representing a pointer to an integer value. - IntegerType* getIntPtrTy(const DataLayout *DL, unsigned AddrSpace = 0) { - return DL->getIntPtrType(Context, AddrSpace); + IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) { + return DL.getIntPtrType(Context, AddrSpace); } //===--------------------------------------------------------------------===// @@ -443,11 +448,40 @@ public: /// \brief Create a call to the experimental.gc.statepoint intrinsic to /// start a new statepoint sequence. - CallInst *CreateGCStatepoint(Value *ActualCallee, - ArrayRef<Value*> CallArgs, - ArrayRef<Value*> DeoptArgs, - ArrayRef<Value*> GCArgs, - const Twine &Name = ""); + CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualCallee, + ArrayRef<Value *> CallArgs, + ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, + const Twine &Name = ""); + + // \brief Conveninence function for the common case when CallArgs are filled + // in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be + // .get()'ed to get the Value pointer. + CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualCallee, ArrayRef<Use> CallArgs, + ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, + const Twine &Name = ""); + + /// brief Create an invoke to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + InvokeInst * + CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualInvokee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, ArrayRef<Value *> InvokeArgs, + ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, const Twine &Name = ""); + + // Conveninence function for the common case when CallArgs are filled in using + // makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to + // get the Value *. + InvokeInst * + CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualInvokee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, ArrayRef<Use> InvokeArgs, + ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, const Twine &Name = ""); /// \brief Create a call to the experimental.gc.result intrinsic to extract /// the result from a call wrapped in a statepoint. @@ -466,7 +500,7 @@ public: private: /// \brief Create a call to a masked intrinsic with given Id. /// Masked intrinsic has only one overloaded type - data type. - CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef<Value *> Ops, + CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops, Type *DataTy, const Twine &Name = ""); Value *getCastedInt8PtrValue(Value *Ptr); @@ -959,6 +993,9 @@ public: LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") { return Insert(new LoadInst(Ptr), Name); } + LoadInst *CreateLoad(Type *Ty, Value *Ptr, const Twine &Name = "") { + return Insert(new LoadInst(Ty, Ptr), Name); + } LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") { return Insert(new LoadInst(Ptr, nullptr, isVolatile), Name); } @@ -1011,6 +1048,10 @@ public: } Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { + return CreateGEP(nullptr, Ptr, IdxList, Name); + } + Value *CreateGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. size_t i, e; @@ -1018,12 +1059,16 @@ public: if (!isa<Constant>(IdxList[i])) break; if (i == e) - return Insert(Folder.CreateGetElementPtr(PC, IdxList), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, IdxList), Name); } - return Insert(GetElementPtrInst::Create(Ptr, IdxList), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name); } Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { + return CreateInBoundsGEP(nullptr, Ptr, IdxList, Name); + } + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. size_t i, e; @@ -1031,79 +1076,88 @@ public: if (!isa<Constant>(IdxList[i])) break; if (i == e) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IdxList), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IdxList), + Name); } - return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxList), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name); } Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + return CreateGEP(nullptr, Ptr, Idx, Name); + } + Value *CreateGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, IC), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, Value *Idx, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IC), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { + return CreateConstGEP1_32(nullptr, Ptr, Idx0, Name); + } + Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, + const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, Idx), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, + Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } - Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { + Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name); } - Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { + Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, + unsigned Idx1, const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idxs), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name); } Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idx), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); } Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); } Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -1113,9 +1167,9 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name); } Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -1125,21 +1179,23 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idxs), + Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name); } - Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { - return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); + Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, + const Twine &Name = "") { + return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name); } /// \brief Same as CreateGlobalString, but return a pointer with "i8*" type /// instead of a pointer to array of i8. Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") { - Value *gv = CreateGlobalString(Str, Name); + GlobalVariable *gv = CreateGlobalString(Str, Name); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Value *Args[] = { zero, zero }; - return CreateInBoundsGEP(gv, Args, Name); + return CreateInBoundsGEP(gv->getValueType(), gv, Args, Name); } //===--------------------------------------------------------------------===// @@ -1297,7 +1353,7 @@ private: // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a // compile time error, instead of converting the string to bool for the // isSigned parameter. - Value *CreateIntCast(Value *, Type *, const char *) LLVM_DELETED_FUNCTION; + Value *CreateIntCast(Value *, Type *, const char *) = delete; public: Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) @@ -1409,36 +1465,19 @@ public: return Insert(PHINode::Create(Ty, NumReservedValues), Name); } - CallInst *CreateCall(Value *Callee, const Twine &Name = "") { - return Insert(CallInst::Create(Callee), Name); - } - CallInst *CreateCall(Value *Callee, Value *Arg, const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Arg), Name); - } - CallInst *CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall3(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall4(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - Value *Arg4, const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3, Arg4 }; + CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args, + const Twine &Name = "") { return Insert(CallInst::Create(Callee, Args), Name); } - CallInst *CreateCall5(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - Value *Arg4, Value *Arg5, const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3, Arg4, Arg5 }; - return Insert(CallInst::Create(Callee, Args), Name); + + CallInst *CreateCall(llvm::FunctionType *FTy, Value *Callee, + ArrayRef<Value *> Args, const Twine &Name = "") { + return Insert(CallInst::Create(FTy, Callee, Args), Name); } - CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args, + CallInst *CreateCall(Function *Callee, ArrayRef<Value *> Args, const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Args), Name); + return CreateCall(Callee->getFunctionType(), Callee, Args, Name); } Value *CreateSelect(Value *C, Value *True, Value *False, @@ -1462,6 +1501,11 @@ public: return Insert(ExtractElementInst::Create(Vec, Idx), Name); } + Value *CreateExtractElement(Value *Vec, uint64_t Idx, + const Twine &Name = "") { + return CreateExtractElement(Vec, getInt64(Idx), Name); + } + Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(Vec)) @@ -1471,6 +1515,11 @@ public: return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); } + Value *CreateInsertElement(Value *Vec, Value *NewElt, uint64_t Idx, + const Twine &Name = "") { + return CreateInsertElement(Vec, NewElt, getInt64(Idx), Name); + } + Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name = "") { if (Constant *V1C = dyn_cast<Constant>(V1)) @@ -1480,6 +1529,16 @@ public: return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); } + Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<int> IntMask, + const Twine &Name = "") { + size_t MaskSize = IntMask.size(); + SmallVector<Constant*, 8> MaskVec(MaskSize); + for (size_t i = 0; i != MaskSize; ++i) + MaskVec[i] = getInt32(IntMask[i]); + Value *Mask = ConstantVector::get(MaskVec); + return CreateShuffleVector(V1, V2, Mask, Name); + } + Value *CreateExtractValue(Value *Agg, ArrayRef<unsigned> Idxs, const Twine &Name = "") { @@ -1589,7 +1648,7 @@ public: "trying to create an alignment assumption on a non-pointer?"); PointerType *PtrTy = cast<PointerType>(PtrValue->getType()); - Type *IntPtrTy = getIntPtrTy(&DL, PtrTy->getAddressSpace()); + Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); Value *Mask = ConstantInt::get(IntPtrTy, diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index 7f2027b6e297..5f1d56f7e831 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -34,7 +34,8 @@ class raw_ostream; /// \brief Create and return a pass that writes the module to the specified /// \c raw_ostream. ModulePass *createPrintModulePass(raw_ostream &OS, - const std::string &Banner = ""); + const std::string &Banner = "", + bool ShouldPreserveUseListOrder = false); /// \brief Create and return a pass that prints functions to the specified /// \c raw_ostream as they are processed. @@ -53,10 +54,12 @@ BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS, class PrintModulePass { raw_ostream &OS; std::string Banner; + bool ShouldPreserveUseListOrder; public: PrintModulePass(); - PrintModulePass(raw_ostream &OS, const std::string &Banner = ""); + PrintModulePass(raw_ostream &OS, const std::string &Banner = "", + bool ShouldPreserveUseListOrder = false); PreservedAnalyses run(Module &M); diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index b2d79d0f0bfc..15942f16e67e 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -40,8 +40,8 @@ private: friend struct InlineAsmKeyType; friend class ConstantUniqueMap<InlineAsm>; - InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION; - void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION; + InlineAsm(const InlineAsm &) = delete; + void operator=(const InlineAsm&) = delete; std::string AsmString, Constraints; bool HasSideEffects; @@ -51,7 +51,7 @@ private: InlineAsm(PointerType *Ty, const std::string &AsmString, const std::string &Constraints, bool hasSideEffects, bool isAlignStack, AsmDialect asmDialect); - virtual ~InlineAsm(); + ~InlineAsm() override; /// When the ConstantUniqueMap merges two types and makes two InlineAsms /// identical, it destroys one of them with this method. @@ -189,6 +189,20 @@ public: // These are helper methods for dealing with flags in the INLINEASM SDNode // in the backend. + // + // The encoding of the flag word is currently: + // Bits 2-0 - A Kind_* value indicating the kind of the operand. + // Bits 15-3 - The number of SDNode operands associated with this inline + // assembly operand. + // If bit 31 is set: + // Bit 30-16 - The operand number that this operand must match. + // When bits 2-0 are Kind_Mem, the Constraint_* value must be + // obtained from the flags for this operand number. + // Else if bits 2-0 are Kind_Mem: + // Bit 30-16 - A Constraint_* value indicating the original constraint + // code. + // Else: + // Bit 30-16 - The register class ID to use for the operand. enum : uint32_t { // Fixed operands on an INLINEASM SDNode. @@ -220,6 +234,27 @@ public: Kind_Imm = 5, // Immediate. Kind_Mem = 6, // Memory operand, "m". + // Memory constraint codes. + // These could be tablegenerated but there's little need to do that since + // there's plenty of space in the encoding to support the union of all + // constraint codes for all targets. + Constraint_Unknown = 0, + Constraint_es, + Constraint_i, + Constraint_m, + Constraint_o, + Constraint_v, + Constraint_Q, + Constraint_R, + Constraint_S, + Constraint_T, + Constraint_X, + Constraint_Z, + Constraint_ZC, + Constraint_Zy, + Constraints_Max = Constraint_Zy, + Constraints_ShiftAmount = 16, + Flag_MatchingOperand = 0x80000000 }; @@ -252,6 +287,20 @@ public: return InputFlag | (RC << 16); } + /// Augment an existing flag word returned by getFlagWord with the constraint + /// code for a memory constraint. + static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) { + assert(Constraint <= 0x7fff && "Too large a memory constraint ID"); + assert(Constraint <= Constraints_Max && "Unknown constraint ID"); + assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); + return InputFlag | (Constraint << Constraints_ShiftAmount); + } + + static unsigned convertMemFlagWordToMatchingFlagWord(unsigned InputFlag) { + assert(isMemKind(InputFlag)); + return InputFlag & ~(0x7fff << Constraints_ShiftAmount); + } + static unsigned getKind(unsigned Flags) { return Flags & 7; } @@ -266,6 +315,11 @@ public: return getKind(Flag) == Kind_Clobber; } + static unsigned getMemoryConstraintID(unsigned Flag) { + assert(isMemKind(Flag)); + return (Flag >> Constraints_ShiftAmount) & 0x7fff; + } + /// getNumOperandRegisters - Extract the number of registers field from the /// inline asm operand flag. static unsigned getNumOperandRegisters(unsigned Flag) { diff --git a/include/llvm/IR/InstIterator.h b/include/llvm/IR/InstIterator.h index 75e93bd2ff8c..f3ce6490fb66 100644 --- a/include/llvm/IR/InstIterator.h +++ b/include/llvm/IR/InstIterator.h @@ -27,15 +27,14 @@ namespace llvm { // This class implements inst_begin() & inst_end() for // inst_iterator and const_inst_iterator's. // -template <class _BB_t, class _BB_i_t, class _BI_t, class _II_t> -class InstIterator { - typedef _BB_t BBty; - typedef _BB_i_t BBIty; - typedef _BI_t BIty; - typedef _II_t IIty; - _BB_t *BBs; // BasicBlocksType - _BB_i_t BB; // BasicBlocksType::iterator - _BI_t BI; // BasicBlock::iterator +template <class BB_t, class BB_i_t, class BI_t, class II_t> class InstIterator { + typedef BB_t BBty; + typedef BB_i_t BBIty; + typedef BI_t BIty; + typedef II_t IIty; + BB_t *BBs; // BasicBlocksType + BB_i_t BB; // BasicBlocksType::iterator + BI_t BI; // BasicBlock::iterator public: typedef std::bidirectional_iterator_tag iterator_category; typedef IIty value_type; @@ -127,20 +126,32 @@ typedef InstIterator<const iplist<BasicBlock>, inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } +inline iterator_range<inst_iterator> inst_range(Function *F) { + return iterator_range<inst_iterator>(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function *F) { return const_inst_iterator(*F); } inline const_inst_iterator inst_end(const Function *F) { return const_inst_iterator(*F, true); } +inline iterator_range<const_inst_iterator> inst_range(const Function *F) { + return iterator_range<const_inst_iterator>(inst_begin(F), inst_end(F)); +} inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } +inline iterator_range<inst_iterator> inst_range(Function &F) { + return iterator_range<inst_iterator>(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function &F) { return const_inst_iterator(F); } inline const_inst_iterator inst_end(const Function &F) { return const_inst_iterator(F, true); } +inline iterator_range<const_inst_iterator> inst_range(const Function &F) { + return iterator_range<const_inst_iterator>(inst_begin(F), inst_end(F)); +} } // End llvm namespace diff --git a/include/llvm/IR/InstVisitor.h b/include/llvm/IR/InstVisitor.h index 1cdcd55448c9..581e860b8382 100644 --- a/include/llvm/IR/InstVisitor.h +++ b/include/llvm/IR/InstVisitor.h @@ -259,7 +259,7 @@ private: // Special helper function to delegate to CallInst subclass visitors. RetTy delegateCallInst(CallInst &I) { if (const Function *F = I.getCalledFunction()) { - switch ((Intrinsic::ID)F->getIntrinsicID()) { + switch (F->getIntrinsicID()) { default: DELEGATE(IntrinsicInst); case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst); case Intrinsic::dbg_value: DELEGATE(DbgValueInst); diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 030f5d690a0c..108b9eb36b7e 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -44,7 +44,7 @@ protected: : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {} // Out of line virtual method, so the vtable, etc has a home. - ~TerminatorInst(); + ~TerminatorInst() override; /// Virtual methods - Terminators should overload these and provide inline /// overrides of non-V methods. @@ -83,7 +83,7 @@ public: //===----------------------------------------------------------------------===// class UnaryInstruction : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: UnaryInstruction(Type *Ty, unsigned iType, Value *V, @@ -102,7 +102,7 @@ public: } // Out of line virtual method, so the vtable, etc has a home. - ~UnaryInstruction(); + ~UnaryInstruction() override; /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -132,7 +132,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) //===----------------------------------------------------------------------===// class BinaryOperator : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: void init(BinaryOps iType); BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, @@ -570,10 +570,9 @@ public: /// This ensures that any pointer<->integer cast has enough bits in the /// integer and any other cast is a bitcast. static bool isBitOrNoopPointerCastable( - Type *SrcTy, ///< The Type from which the value should be cast. - Type *DestTy, ///< The Type to which the value should be cast. - const DataLayout *Layout = 0 ///< Optional DataLayout. - ); + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy, ///< The Type to which the value should be cast. + const DataLayout &DL); /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. @@ -621,9 +620,9 @@ public: ) const; /// @brief Determine if this cast is a no-op cast. - bool isNoopCast( - const DataLayout *DL ///< DataLayout to get the Int Ptr type from. - ) const; + /// + /// \param DL is the DataLayout to get the Int Ptr type from. + bool isNoopCast(const DataLayout &DL) const; /// Determine how a pair of casts can be eliminated, if they can be at all. /// This is a helper function for both CastInst and ConstantExpr. @@ -674,8 +673,8 @@ public: /// This class is the base class for the comparison instructions. /// @brief Abstract base class of comparison instructions. class CmpInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - CmpInst() LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + CmpInst() = delete; protected: CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, const Twine &Name = "", diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index ba7791c99b6a..752c3f09bded 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ilist_node.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/SymbolTableListTraits.h" #include "llvm/IR/User.h" namespace llvm { @@ -25,14 +26,31 @@ namespace llvm { class FastMathFlags; class LLVMContext; class MDNode; +class BasicBlock; struct AAMDNodes; -template<typename ValueSubClass, typename ItemParentClass> - class SymbolTableListTraits; +template <> +struct ilist_traits<Instruction> + : public SymbolTableListTraits<Instruction, BasicBlock> { + + /// \brief Return a node that marks the end of a list. + /// + /// The sentinel is relative to this instance, so we use a non-static + /// method. + Instruction *createSentinel() const; + static void destroySentinel(Instruction *) {} + + Instruction *provideInitialHead() const { return createSentinel(); } + Instruction *ensureHead(Instruction *) const { return createSentinel(); } + static void noteHead(Instruction *, Instruction *) {} + +private: + mutable ilist_half_node<Instruction> Sentinel; +}; class Instruction : public User, public ilist_node<Instruction> { - void operator=(const Instruction &) LLVM_DELETED_FUNCTION; - Instruction(const Instruction &) LLVM_DELETED_FUNCTION; + void operator=(const Instruction &) = delete; + Instruction(const Instruction &) = delete; BasicBlock *Parent; DebugLoc DbgLoc; // 'dbg' Metadata cache. @@ -44,7 +62,7 @@ class Instruction : public User, public ilist_node<Instruction> { }; public: // Out of line virtual method, so the vtable, etc has a home. - ~Instruction(); + ~Instruction() override; /// user_back - Specialize the methods defined in Value, as we know that an /// instruction can only be used by other instructions. @@ -54,7 +72,13 @@ public: inline const BasicBlock *getParent() const { return Parent; } inline BasicBlock *getParent() { return Parent; } - const DataLayout *getDataLayout() const; + /// \brief Return the module owning the function this instruction belongs to + /// or nullptr it the function does not have a module. + /// + /// Note: this is undefined behavior if the instruction does not have a + /// parent, or the parent basic block does not have a parent function. + const Module *getModule() const; + Module *getModule(); /// removeFromParent - This method unlinks 'this' from the containing basic /// block, but does not delete it. @@ -64,14 +88,15 @@ public: /// eraseFromParent - This method unlinks 'this' from the containing basic /// block and deletes it. /// - void eraseFromParent(); + /// \returns an iterator pointing to the element after the erased one + iplist<Instruction>::iterator eraseFromParent(); - /// insertBefore - Insert an unlinked instructions into a basic block - /// immediately before the specified instruction. + /// Insert an unlinked instruction into a basic block immediately before + /// the specified instruction. void insertBefore(Instruction *InsertPos); - /// insertAfter - Insert an unlinked instructions into a basic block - /// immediately after the specified instruction. + /// Insert an unlinked instruction into a basic block immediately after the + /// specified instruction. void insertAfter(Instruction *InsertPos); /// moveBefore - Unlink this instruction from its current basic block and @@ -129,9 +154,7 @@ public: /// hasMetadata() - Return true if this instruction has any metadata attached /// to it. - bool hasMetadata() const { - return !DbgLoc.isUnknown() || hasMetadataHashEntry(); - } + bool hasMetadata() const { return DbgLoc || hasMetadataHashEntry(); } /// hasMetadataOtherThanDebugLoc - Return true if this instruction has /// metadata attached to it other than a debug location. @@ -201,7 +224,7 @@ public: void setAAMetadata(const AAMDNodes &N); /// setDebugLoc - Set the debug location information for this instruction. - void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } + void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); } /// getDebugLoc - Return the debug location for this node as a DebugLoc. const DebugLoc &getDebugLoc() const { return DbgLoc; } @@ -490,6 +513,17 @@ protected: }; +inline Instruction *ilist_traits<Instruction>::createSentinel() const { + // Since i(p)lists always publicly derive from their corresponding traits, + // placing a data member in this class will augment the i(p)list. But since + // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>, + // there is a legal viable downcast from it to NodeTy. We use this trick to + // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the + // sentinel. Dereferencing the sentinel is forbidden (save the + // ilist_node<NodeTy>), so no one will ever notice the superposition. + return static_cast<Instruction *>(&Sentinel); +} + // Instruction* is only 4-byte aligned. template<> class PointerLikeTypeTraits<Instruction*> { diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 045e51eb1baa..9f5e244f0021 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -73,6 +73,8 @@ return (Ord == Release || /// AllocaInst - an instruction to allocate memory on the stack /// class AllocaInst : public UnaryInstruction { + Type *AllocatedType; + protected: AllocaInst *clone_impl() const override; public: @@ -91,7 +93,7 @@ public: const Twine &Name, BasicBlock *InsertAtEnd); // Out of line virtual method, so the vtable, etc. has a home. - virtual ~AllocaInst(); + ~AllocaInst() override; /// isArrayAllocation - Return true if there is an allocation size parameter /// to the allocation instruction that is not 1. @@ -113,7 +115,10 @@ public: /// getAllocatedType - Return the type that is being allocated by the /// instruction. /// - Type *getAllocatedType() const; + Type *getAllocatedType() const { return AllocatedType; } + /// \brief for use only in special circumstances that need to generically + /// transform a whole instruction (eg: IR linking and vectorization). + void setAllocatedType(Type *Ty) { AllocatedType = Ty; } /// getAlignment - Return the alignment of the memory that is being allocated /// by the instruction. @@ -172,15 +177,28 @@ protected: public: LoadInst(Value *Ptr, const Twine &NameStr, Instruction *InsertBefore); LoadInst(Value *Ptr, const Twine &NameStr, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, + LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile = false, Instruction *InsertBefore = nullptr); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, + Instruction *InsertBefore = nullptr) + : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, InsertBefore) {} LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, + Instruction *InsertBefore = nullptr) + : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, Align, InsertBefore) {} + LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, Instruction *InsertBefore = nullptr); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, + AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread, + Instruction *InsertBefore = nullptr) + : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, Align, Order, SynchScope, InsertBefore) {} + LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread, Instruction *InsertBefore = nullptr); @@ -191,9 +209,13 @@ public: LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore); LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd); + LoadInst(Type *Ty, Value *Ptr, const char *NameStr = nullptr, + bool isVolatile = false, Instruction *InsertBefore = nullptr); explicit LoadInst(Value *Ptr, const char *NameStr = nullptr, bool isVolatile = false, - Instruction *InsertBefore = nullptr); + Instruction *InsertBefore = nullptr) + : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, InsertBefore) {} LoadInst(Value *Ptr, const char *NameStr, bool isVolatile, BasicBlock *InsertAtEnd); @@ -285,7 +307,7 @@ private: /// StoreInst - an instruction for storing to memory /// class StoreInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void AssertOK(); protected: StoreInst *clone_impl() const override; @@ -411,7 +433,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) /// FenceInst - an instruction for ordering other memory operations /// class FenceInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); protected: FenceInst *clone_impl() const override; @@ -478,7 +500,7 @@ private: /// there. Returns the value that was loaded. /// class AtomicCmpXchgInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void Init(Value *Ptr, Value *Cmp, Value *NewVal, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); @@ -634,7 +656,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) /// the old value. /// class AtomicRMWInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: AtomicRMWInst *clone_impl() const override; public: @@ -787,6 +809,8 @@ inline Type *checkGEPType(Type *Ty) { /// access elements of arrays and structs /// class GetElementPtrInst : public Instruction { + Type *SourceElementType; + GetElementPtrInst(const GetElementPtrInst &GEPI); void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr); @@ -794,28 +818,45 @@ class GetElementPtrInst : public Instruction { /// list of indices. The first ctor can optionally insert before an existing /// instruction, the second appends the new instruction to the specified /// BasicBlock. - inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList, - unsigned Values, const Twine &NameStr, - Instruction *InsertBefore); - inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList, - unsigned Values, const Twine &NameStr, - BasicBlock *InsertAtEnd); + inline GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, + const Twine &NameStr, Instruction *InsertBefore); + inline GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd); + protected: GetElementPtrInst *clone_impl() const override; public: - static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList, + static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { unsigned Values = 1 + unsigned(IdxList.size()); - return new(Values) - GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertBefore); - } - static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList, + if (!PointeeType) + PointeeType = + cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(); + else + assert( + PointeeType == + cast<PointerType>(Ptr->getType()->getScalarType())->getElementType()); + return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, + NameStr, InsertBefore); + } + static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, const Twine &NameStr, BasicBlock *InsertAtEnd) { unsigned Values = 1 + unsigned(IdxList.size()); - return new(Values) - GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertAtEnd); + if (!PointeeType) + PointeeType = + cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(); + else + assert( + PointeeType == + cast<PointerType>(Ptr->getType()->getScalarType())->getElementType()); + return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, + NameStr, InsertAtEnd); } /// Create an "inbounds" getelementptr. See the documentation for the @@ -824,7 +865,14 @@ public: ArrayRef<Value *> IdxList, const Twine &NameStr = "", Instruction *InsertBefore = nullptr){ - GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertBefore); + return CreateInBounds(nullptr, Ptr, IdxList, NameStr, InsertBefore); + } + static GetElementPtrInst * + CreateInBounds(Type *PointeeType, Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + GetElementPtrInst *GEP = + Create(PointeeType, Ptr, IdxList, NameStr, InsertBefore); GEP->setIsInBounds(true); return GEP; } @@ -832,7 +880,14 @@ public: ArrayRef<Value *> IdxList, const Twine &NameStr, BasicBlock *InsertAtEnd) { - GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertAtEnd); + return CreateInBounds(nullptr, Ptr, IdxList, NameStr, InsertAtEnd); + } + static GetElementPtrInst *CreateInBounds(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + GetElementPtrInst *GEP = + Create(PointeeType, Ptr, IdxList, NameStr, InsertAtEnd); GEP->setIsInBounds(true); return GEP; } @@ -845,6 +900,14 @@ public: return cast<SequentialType>(Instruction::getType()); } + Type *getSourceElementType() const { return SourceElementType; } + + void setSourceElementType(Type *Ty) { SourceElementType = Ty; } + + Type *getResultElementType() const { + return cast<PointerType>(getType()->getScalarType())->getElementType(); + } + /// \brief Returns the address space of this instruction's pointer type. unsigned getAddressSpace() const { // Note that this is always the same as the pointer operand's address space @@ -858,9 +921,9 @@ public: /// Null is returned if the indices are invalid for the specified /// pointer type. /// - static Type *getIndexedType(Type *Ptr, ArrayRef<Value *> IdxList); - static Type *getIndexedType(Type *Ptr, ArrayRef<Constant *> IdxList); - static Type *getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<Value *> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<Constant *> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<uint64_t> IdxList); inline op_iterator idx_begin() { return op_begin()+1; } inline const_op_iterator idx_begin() const { return op_begin()+1; } @@ -891,8 +954,13 @@ public: /// GetGEPReturnType - Returns the pointer type returned by the GEP /// instruction, which may be a vector of pointers. static Type *getGEPReturnType(Value *Ptr, ArrayRef<Value *> IdxList) { - Type *PtrTy = PointerType::get(checkGEPType( - getIndexedType(Ptr->getType(), IdxList)), + return getGEPReturnType( + cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(), + Ptr, IdxList); + } + static Type *getGEPReturnType(Type *ElTy, Value *Ptr, + ArrayRef<Value *> IdxList) { + Type *PtrTy = PointerType::get(checkGEPType(getIndexedType(ElTy, IdxList)), Ptr->getType()->getPointerAddressSpace()); // Vector GEP if (Ptr->getType()->isVectorTy()) { @@ -953,26 +1021,24 @@ struct OperandTraits<GetElementPtrInst> : public VariadicOperandTraits<GetElementPtrInst, 1> { }; -GetElementPtrInst::GetElementPtrInst(Value *Ptr, - ArrayRef<Value *> IdxList, - unsigned Values, +GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(getGEPReturnType(Ptr, IdxList), - GetElementPtr, - OperandTraits<GetElementPtrInst>::op_end(this) - Values, - Values, InsertBefore) { + : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - Values, + Values, InsertBefore), + SourceElementType(PointeeType) { init(Ptr, IdxList, NameStr); } -GetElementPtrInst::GetElementPtrInst(Value *Ptr, - ArrayRef<Value *> IdxList, - unsigned Values, +GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd) - : Instruction(getGEPReturnType(Ptr, IdxList), - GetElementPtr, - OperandTraits<GetElementPtrInst>::op_end(this) - Values, - Values, InsertAtEnd) { + : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - Values, + Values, InsertAtEnd), + SourceElementType(PointeeType) { init(Ptr, IdxList, NameStr); } @@ -1194,11 +1260,15 @@ public: /// @returns true if the predicate of this instruction is EQ or NE. /// \brief Determine if this is an equality predicate. - bool isEquality() const { - return getPredicate() == FCMP_OEQ || getPredicate() == FCMP_ONE || - getPredicate() == FCMP_UEQ || getPredicate() == FCMP_UNE; + static bool isEquality(Predicate Pred) { + return Pred == FCMP_OEQ || Pred == FCMP_ONE || Pred == FCMP_UEQ || + Pred == FCMP_UNE; } + /// @returns true if the predicate of this instruction is EQ or NE. + /// \brief Determine if this is an equality predicate. + bool isEquality() const { return isEquality(getPredicate()); } + /// @returns true if the predicate of this instruction is commutative. /// \brief Determine if this is a commutative predicate. bool isCommutative() const { @@ -1240,14 +1310,26 @@ public: /// class CallInst : public Instruction { AttributeSet AttributeList; ///< parameter attributes for call + FunctionType *FTy; CallInst(const CallInst &CI); - void init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr); + void init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr) { + init(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, Args, NameStr); + } + void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr); void init(Value *Func, const Twine &NameStr); /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments - inline CallInst(Value *Func, ArrayRef<Value *> Args, + inline CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, Instruction *InsertBefore); + inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, + Instruction *InsertBefore) + : CallInst(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, Args, NameStr, InsertBefore) {} /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments @@ -1264,8 +1346,15 @@ public: ArrayRef<Value *> Args, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { - return new(unsigned(Args.size() + 1)) - CallInst(Func, Args, NameStr, InsertBefore); + return Create(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, Args, NameStr, InsertBefore); + } + static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + return new (unsigned(Args.size() + 1)) + CallInst(Ty, Func, Args, NameStr, InsertBefore); } static CallInst *Create(Value *Func, ArrayRef<Value *> Args, @@ -1301,7 +1390,14 @@ public: static Instruction* CreateFree(Value* Source, Instruction *InsertBefore); static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd); - ~CallInst(); + ~CallInst() override; + + FunctionType *getFunctionType() const { return FTy; } + + void mutateFunctionType(FunctionType *FTy) { + mutateType(FTy->getReturnType()); + this->FTy = FTy; + } // Note that 'musttail' implies 'tail'. enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 }; @@ -1375,6 +1471,13 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); + /// \brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + + /// \brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -1396,6 +1499,12 @@ public: return AttributeList.getDereferenceableBytes(i); } + /// \brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(unsigned i) const { + return AttributeList.getDereferenceableOrNullBytes(i); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -1477,6 +1586,14 @@ public: /// setCalledFunction - Set the function called. void setCalledFunction(Value* Fn) { + setCalledFunction( + cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()), + Fn); + } + void setCalledFunction(FunctionType *FTy, Value *Fn) { + this->FTy = FTy; + assert(FTy == cast<FunctionType>( + cast<PointerType>(Fn->getType())->getElementType())); Op<-1>() = Fn; } @@ -1517,14 +1634,12 @@ CallInst::CallInst(Value *Func, ArrayRef<Value *> Args, init(Func, Args, NameStr); } -CallInst::CallInst(Value *Func, ArrayRef<Value *> Args, +CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Call, - OperandTraits<CallInst>::op_end(this) - (Args.size() + 1), - unsigned(Args.size() + 1), InsertBefore) { - init(Func, Args, NameStr); + : Instruction(Ty->getReturnType(), Instruction::Call, + OperandTraits<CallInst>::op_end(this) - (Args.size() + 1), + unsigned(Args.size() + 1), InsertBefore) { + init(Ty, Func, Args, NameStr); } @@ -1898,6 +2013,9 @@ public: typedef const unsigned* idx_iterator; 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()); + } Value *getAggregateOperand() { return getOperand(0); @@ -1958,7 +2076,7 @@ ExtractValueInst::ExtractValueInst(Value *Agg, class InsertValueInst : public Instruction { SmallVector<unsigned, 4> Indices; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; InsertValueInst(const InsertValueInst &IVI); void init(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, const Twine &NameStr); @@ -2009,6 +2127,9 @@ public: typedef const unsigned* idx_iterator; 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()); + } Value *getAggregateOperand() { return getOperand(0); @@ -2088,7 +2209,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) // scientist's overactive imagination. // class PHINode : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; /// ReservedSpace - The number of operands actually allocated. NumOperands is /// the number actually in use. unsigned ReservedSpace; @@ -2132,7 +2253,7 @@ public: const Twine &NameStr, BasicBlock *InsertAtEnd) { return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd); } - ~PHINode(); + ~PHINode() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2163,6 +2284,10 @@ public: return block_begin() + getNumOperands(); } + op_range incoming_values() { return operands(); } + + const_op_range incoming_values() const { return operands(); } + /// getNumIncomingValues - Return the number of incoming edges /// unsigned getNumIncomingValues() const { return getNumOperands(); } @@ -2295,7 +2420,7 @@ class LandingPadInst : public Instruction { public: enum ClauseType { Catch, Filter }; private: - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; // Allocate space for exactly zero operands. void *operator new(size_t s) { return User::operator new(s, 0); @@ -2321,7 +2446,7 @@ public: static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, unsigned NumReservedClauses, const Twine &NameStr, BasicBlock *InsertAtEnd); - ~LandingPadInst(); + ~LandingPadInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2423,7 +2548,7 @@ public: static ReturnInst* Create(LLVMContext &C, BasicBlock *InsertAtEnd) { return new(0) ReturnInst(C, InsertAtEnd); } - virtual ~ReturnInst(); + ~ReturnInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2562,7 +2687,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) /// SwitchInst - Multiway switch /// class SwitchInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -2720,7 +2845,7 @@ public: return new SwitchInst(Value, Default, NumCases, InsertAtEnd); } - ~SwitchInst(); + ~SwitchInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2871,7 +2996,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) /// IndirectBrInst - Indirect Branch Instruction. /// class IndirectBrInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -2906,7 +3031,7 @@ public: BasicBlock *InsertAtEnd) { return new IndirectBrInst(Address, NumDests, InsertAtEnd); } - ~IndirectBrInst(); + ~IndirectBrInst() override; /// Provide fast operand accessors. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2970,17 +3095,33 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) /// class InvokeInst : public TerminatorInst { AttributeSet AttributeList; + FunctionType *FTy; InvokeInst(const InvokeInst &BI); void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef<Value *> Args, const Twine &NameStr); + ArrayRef<Value *> Args, const Twine &NameStr) { + init(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, IfNormal, IfException, Args, NameStr); + } + void init(FunctionType *FTy, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef<Value *> Args, + const Twine &NameStr); /// Construct an InvokeInst given a range of arguments. /// /// \brief Construct an InvokeInst from a range of arguments inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, unsigned Values, - const Twine &NameStr, Instruction *InsertBefore); - + const Twine &NameStr, Instruction *InsertBefore) + : InvokeInst(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, IfNormal, IfException, Args, Values, NameStr, + InsertBefore) {} + + inline InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef<Value *> Args, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore); /// Construct an InvokeInst given a range of arguments. /// /// \brief Construct an InvokeInst from a range of arguments @@ -2994,9 +3135,17 @@ public: BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { + return Create(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, IfNormal, IfException, Args, NameStr, InsertBefore); + } + static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef<Value *> Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { unsigned Values = unsigned(Args.size()) + 3; - return new(Values) InvokeInst(Func, IfNormal, IfException, Args, - Values, NameStr, InsertBefore); + return new (Values) InvokeInst(Ty, Func, IfNormal, IfException, Args, + Values, NameStr, InsertBefore); } static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, @@ -3010,6 +3159,13 @@ public: /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + FunctionType *getFunctionType() const { return FTy; } + + void mutateFunctionType(FunctionType *FTy) { + mutateType(FTy->getReturnType()); + this->FTy = FTy; + } + /// getNumArgOperands - Return the number of invoke arguments. /// unsigned getNumArgOperands() const { return getNumOperands() - 3; } @@ -3056,6 +3212,13 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); + /// \brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + + /// \brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -3076,6 +3239,12 @@ public: uint64_t getDereferenceableBytes(unsigned i) const { return AttributeList.getDereferenceableBytes(i); } + + /// \brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(unsigned i) const { + return AttributeList.getDereferenceableOrNullBytes(i); + } /// \brief Return true if the call should not be treated as a call to a /// builtin. @@ -3152,6 +3321,14 @@ public: /// setCalledFunction - Set the function called. void setCalledFunction(Value* Fn) { + setCalledFunction( + cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()), + Fn); + } + void setCalledFunction(FunctionType *FTy, Value *Fn) { + this->FTy = FTy; + assert(FTy == cast<FunctionType>( + cast<PointerType>(Fn->getType())->getElementType())); Op<-3>() = Fn; } @@ -3211,16 +3388,14 @@ template <> struct OperandTraits<InvokeInst> : public VariadicOperandTraits<InvokeInst, 3> { }; -InvokeInst::InvokeInst(Value *Func, - BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef<Value *> Args, unsigned Values, - const Twine &NameStr, 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, Args, NameStr); +InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef<Value *> Args, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore) + : TerminatorInst(Ty->getReturnType(), Instruction::Invoke, + OperandTraits<InvokeInst>::op_end(this) - Values, Values, + InsertBefore) { + init(Ty, Func, IfNormal, IfException, Args, NameStr); } InvokeInst::InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, @@ -3296,7 +3471,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) /// end of the block cannot be reached. /// class UnreachableInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: UnreachableInst *clone_impl() const override; diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index c227ea080167..2c8b6eb6f39a 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -35,14 +35,14 @@ namespace llvm { /// functions. This allows the standard isa/dyncast/cast functionality to /// work with calls to intrinsic functions. class IntrinsicInst : public CallInst { - IntrinsicInst() LLVM_DELETED_FUNCTION; - IntrinsicInst(const IntrinsicInst&) LLVM_DELETED_FUNCTION; - void operator=(const IntrinsicInst&) LLVM_DELETED_FUNCTION; + IntrinsicInst() = delete; + IntrinsicInst(const IntrinsicInst&) = delete; + void operator=(const IntrinsicInst&) = delete; public: /// getIntrinsicID - Return the intrinsic ID of this intrinsic. /// Intrinsic::ID getIntrinsicID() const { - return (Intrinsic::ID)getCalledFunction()->getIntrinsicID(); + return getCalledFunction()->getIntrinsicID(); } // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -82,13 +82,18 @@ namespace llvm { class DbgDeclareInst : public DbgInfoIntrinsic { public: Value *getAddress() const; - MDNode *getVariable() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(1))->getMetadata()); + DILocalVariable *getVariable() const { + return cast<DILocalVariable>(getRawVariable()); } - MDNode *getExpression() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(2))->getMetadata()); + DIExpression *getExpression() const { + return cast<DIExpression>(getRawExpression()); + } + + Metadata *getRawVariable() const { + return cast<MetadataAsValue>(getArgOperand(1))->getMetadata(); + } + Metadata *getRawExpression() const { + return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); } // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -110,13 +115,18 @@ namespace llvm { return cast<ConstantInt>( const_cast<Value*>(getArgOperand(1)))->getZExtValue(); } - MDNode *getVariable() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(2))->getMetadata()); + DILocalVariable *getVariable() const { + return cast<DILocalVariable>(getRawVariable()); + } + DIExpression *getExpression() const { + return cast<DIExpression>(getRawExpression()); + } + + Metadata *getRawVariable() const { + return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); } - MDNode *getExpression() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(3))->getMetadata()); + Metadata *getRawExpression() const { + return cast<MetadataAsValue>(getArgOperand(3))->getMetadata(); } // Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index 56d1e4af26aa..e12ccace25ca 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -32,7 +32,7 @@ class AttributeSet; /// function known by LLVM. The enum values are returned by /// Function::getIntrinsicID(). namespace Intrinsic { - enum ID { + enum ID : unsigned { not_intrinsic = 0, // Must be zero // Get the intrinsic enums generated from Intrinsics.td @@ -41,7 +41,7 @@ namespace Intrinsic { #undef GET_INTRINSIC_ENUM_VALUES , num_intrinsics }; - + /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx". std::string getName(ID id, ArrayRef<Type*> Tys = None); @@ -69,7 +69,7 @@ namespace Intrinsic { /// Map a MS builtin name to an intrinsic ID. ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName); - + /// This is a type descriptor which explains the type requirements of an /// intrinsic. This is returned by getIntrinsicInfoTableEntries. struct IITDescriptor { @@ -77,9 +77,9 @@ namespace Intrinsic { Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, Argument, ExtendArgument, TruncArgument, HalfVecArgument, - SameVecWidthArgument, PtrToArgument + SameVecWidthArgument, PtrToArgument, VecOfPtrsToElt } Kind; - + union { unsigned Integer_Width; unsigned Float_Width; @@ -88,8 +88,9 @@ namespace Intrinsic { unsigned Struct_NumElements; unsigned Argument_Info; }; - + enum ArgKind { + AK_Any, AK_AnyInteger, AK_AnyFloat, AK_AnyVector, @@ -98,26 +99,28 @@ namespace Intrinsic { unsigned getArgumentNumber() const { assert(Kind == Argument || Kind == ExtendArgument || Kind == TruncArgument || Kind == HalfVecArgument || - Kind == SameVecWidthArgument || Kind == PtrToArgument); - return Argument_Info >> 2; + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecOfPtrsToElt); + return Argument_Info >> 3; } ArgKind getArgumentKind() const { assert(Kind == Argument || Kind == ExtendArgument || Kind == TruncArgument || Kind == HalfVecArgument || - Kind == SameVecWidthArgument || Kind == PtrToArgument); - return (ArgKind)(Argument_Info & 3); + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecOfPtrsToElt); + return (ArgKind)(Argument_Info & 7); } - + static IITDescriptor get(IITDescriptorKind K, unsigned Field) { IITDescriptor Result = { K, { Field } }; return Result; } }; - + /// Return the IIT table descriptor for the specified intrinsic into an array /// of IITDescriptors. void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T); - + } // End Intrinsic namespace } // End llvm namespace diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index a1188bccdc25..8f6cdebb0491 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -73,6 +73,11 @@ def IntrNoReturn : IntrinsicProperty; // Parallels the noduplicate attribute on LLVM IR functions. def IntrNoDuplicate : IntrinsicProperty; +// IntrConvergent - Calls to this intrinsic are convergent and may only be +// moved to control equivalent blocks. +// Parallels the convergent attribute on LLVM IR functions. +def IntrConvergent : IntrinsicProperty; + //===----------------------------------------------------------------------===// // Types used by intrinsics. //===----------------------------------------------------------------------===// @@ -117,12 +122,14 @@ class LLVMVectorSameWidth<int num, LLVMType elty> ValueType ElTy = elty.VT; } class LLVMPointerTo<int num> : LLVMMatchType<num>; +class LLVMVectorOfPointersToElt<int num> : LLVMMatchType<num>; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be half as many class LLVMHalfElementsVectorType<int num> : LLVMMatchType<num>; def llvm_void_ty : LLVMType<isVoid>; +def llvm_any_ty : LLVMType<Any>; def llvm_anyint_ty : LLVMType<iAny>; def llvm_anyfloat_ty : LLVMType<fAny>; def llvm_anyvector_ty : LLVMType<vAny>; @@ -179,6 +186,8 @@ def llvm_v4i64_ty : LLVMType<v4i64>; // 4 x i64 def llvm_v8i64_ty : LLVMType<v8i64>; // 8 x i64 def llvm_v16i64_ty : LLVMType<v16i64>; // 16 x i64 +def llvm_v1i128_ty : LLVMType<v1i128>; // 1 x i128 + def llvm_v2f16_ty : LLVMType<v2f16>; // 2 x half (__fp16) def llvm_v4f16_ty : LLVMType<v4f16>; // 4 x half (__fp16) def llvm_v8f16_ty : LLVMType<v8f16>; // 8 x half (__fp16) @@ -259,12 +268,12 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; +def int_frameescape : Intrinsic<[], [llvm_vararg_ty]>; def int_framerecover : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_ptr_ty], - [IntrNoMem]>; + [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], - [IntrNoMem], "llvm.read_register">; + [IntrReadMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], [], "llvm.write_register">; @@ -409,6 +418,19 @@ def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; +// eh.begincatch takes a pointer returned by a landingpad instruction and +// copies the exception object into the memory pointed to by the second +// parameter. If the second parameter is null, no copy occurs. +def int_eh_begincatch : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], + [NoCapture<0>, NoCapture<1>]>; +def int_eh_endcatch : Intrinsic<[], []>; + +// Represents the list of actions to take when an exception is thrown. +def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>; + +def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], []>; +def int_eh_exceptioninfo : Intrinsic<[llvm_ptr_ty], []>; + // __builtin_unwind_init is an undocumented GCC intrinsic that causes all // callee-saved registers to be saved and restored (regardless of whether they // are used) in the calling function. It is used by libgcc_eh. @@ -513,17 +535,20 @@ def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], // These are documented in docs/Statepoint.rst def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty], - [llvm_anyptr_ty, llvm_i32_ty, + [llvm_i64_ty, llvm_i32_ty, + llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_vararg_ty]>; +def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>; +def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; + +// Deprecated: will be removed in a couple of weeks def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>; -def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty], +def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty], [llvm_i32_ty]>; def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>; -def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; - //===-------------------------- Other Intrinsics --------------------------===// // def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, @@ -581,6 +606,23 @@ def int_masked_load : Intrinsic<[llvm_anyvector_ty], [LLVMPointerTo<0>, llvm_i32_ty, LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>], [IntrReadArgMem]>; + +def int_masked_gather: Intrinsic<[llvm_anyvector_ty], + [LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>, + LLVMMatchType<0>], + [IntrReadArgMem]>; + +def int_masked_scatter: Intrinsic<[], + [llvm_anyvector_ty, + LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>], + [IntrReadWriteArgMem]>; + +// Intrinsics to support bit sets. +def int_bitset_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], + [IntrNoMem]>; + //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// @@ -594,3 +636,5 @@ include "llvm/IR/IntrinsicsHexagon.td" include "llvm/IR/IntrinsicsNVVM.td" include "llvm/IR/IntrinsicsMips.td" include "llvm/IR/IntrinsicsR600.td" +include "llvm/IR/IntrinsicsBPF.td" +include "llvm/IR/IntrinsicsSystemZ.td" diff --git a/include/llvm/IR/IntrinsicsBPF.td b/include/llvm/IR/IntrinsicsBPF.td new file mode 100644 index 000000000000..94eca8e40332 --- /dev/null +++ b/include/llvm/IR/IntrinsicsBPF.td @@ -0,0 +1,24 @@ +//===- IntrinsicsBPF.td - Defines BPF intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the BPF-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +// Specialized loads from packet +let TargetPrefix = "bpf" in { // All intrinsics start with "llvm.bpf." + def int_bpf_load_byte : GCCBuiltin<"__builtin_bpf_load_byte">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_load_half : GCCBuiltin<"__builtin_bpf_load_half">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_load_word : GCCBuiltin<"__builtin_bpf_load_word">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_pseudo : GCCBuiltin<"__builtin_bpf_pseudo">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty]>; +} diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td index 8a8872931f36..78ee651d20f9 100644 --- a/include/llvm/IR/IntrinsicsHexagon.td +++ b/include/llvm/IR/IntrinsicsHexagon.td @@ -254,7 +254,7 @@ class Hexagon_qi_qiqi_Intrinsic<string GCCIntSuffix> // class Hexagon_qi_qiqiqi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, - [llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i1_ty], [llvm_i1_ty, llvm_i1_ty, llvm_i1_ty], [IntrNoMem]>; // // DEF_FUNCTION_TYPE_2(SI_ftype_QIQI,BT_INT,BT_BOOL,BT_BOOL) -> @@ -422,19 +422,49 @@ class Hexagon_di_didisisi_Intrinsic<string GCCIntSuffix> llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +class Hexagon_mem_memmemsi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + +class Hexagon_mem_memsisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + +class Hexagon_mem_memdisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + class Hexagon_mem_memmemsisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; +class Hexagon_mem_memsisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +class Hexagon_mem_memdisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + // // Hexagon_sf_df_Intrinsic<string GCCIntSuffix> // class Hexagon_sf_si_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_float_ty], [llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_sf_df_Intrinsic<string GCCIntSuffix> // @@ -490,21 +520,21 @@ class Hexagon_si_df_Intrinsic<string GCCIntSuffix> class Hexagon_sf_sfsf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // -// Hexagon_qi_sfsf_Intrinsic<string GCCIntSuffix> +// Hexagon_si_sfsf_Intrinsic<string GCCIntSuffix> // -class Hexagon_qi_sfsf_Intrinsic<string GCCIntSuffix> +class Hexagon_si_sfsf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, - [llvm_i1_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; + [llvm_i32_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Throws]>; // -// Hexagon_qi_sfsi_Intrinsic<string GCCIntSuffix> +// Hexagon_si_sfsi_Intrinsic<string GCCIntSuffix> // -class Hexagon_qi_sfsi_Intrinsic<string GCCIntSuffix> +class Hexagon_si_sfsi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, - [llvm_i1_ty], [llvm_float_ty, llvm_i32_ty], - [IntrNoMem]>; + [llvm_i32_ty], [llvm_float_ty, llvm_i32_ty], + [IntrNoMem, Throws]>; // // Hexagon_qi_sfqi_Intrinsic<string GCCIntSuffix> // @@ -519,7 +549,7 @@ class Hexagon_sf_sfsfsf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_sf_sfsfsfqi_Intrinsic<string GCCIntSuffix> // @@ -528,7 +558,7 @@ class Hexagon_sf_sfsfsfqi_Intrinsic<string GCCIntSuffix> [llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_di_dididi_Intrinsic<string GCCIntSuffix> // @@ -543,7 +573,7 @@ class Hexagon_di_dididisi_Intrinsic<string GCCIntSuffix> class Hexagon_df_si_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_double_ty], [llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_df_di_Intrinsic<string GCCIntSuffix> // @@ -571,21 +601,21 @@ class Hexagon_df_df_Intrinsic<string GCCIntSuffix> class Hexagon_df_dfdf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // -// Hexagon_qi_dfdf_Intrinsic<string GCCIntSuffix> +// Hexagon_si_dfdf_Intrinsic<string GCCIntSuffix> // -class Hexagon_qi_dfdf_Intrinsic<string GCCIntSuffix> +class Hexagon_si_dfdf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, - [llvm_i1_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; + [llvm_i32_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Throws]>; // -// Hexagon_qi_dfsi_Intrinsic<string GCCIntSuffix> +// Hexagon_si_dfsi_Intrinsic<string GCCIntSuffix> // -class Hexagon_qi_dfsi_Intrinsic<string GCCIntSuffix> +class Hexagon_si_dfsi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, - [llvm_i1_ty], [llvm_double_ty, llvm_i32_ty], - [IntrNoMem]>; + [llvm_i32_ty], [llvm_double_ty, llvm_i32_ty], + [IntrNoMem, Throws]>; // // // Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix> @@ -594,7 +624,7 @@ class Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_double_ty], [llvm_double_ty, llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix> // @@ -603,53 +633,159 @@ class Hexagon_df_dfdfdfqi_Intrinsic<string GCCIntSuffix> [llvm_double_ty], [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; -// This one below will not be generated from iset.py. -// So make sure, you don't overwrite this one. +// This one below will not be auto-generated, +// so make sure, you don't overwrite this one. // // BUILTIN_INFO(SI_to_SXTHI_asrh,SI_ftype_SI,1) // def int_hexagon_SI_to_SXTHI_asrh : Hexagon_si_si_Intrinsic<"SI_to_SXTHI_asrh">; // +// BUILTIN_INFO_NONCONST(brev_ldd,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldd : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldd">; +// +// BUILTIN_INFO_NONCONST(brev_ldw,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldw : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldw">; +// +// BUILTIN_INFO_NONCONST(brev_ldh,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldh : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldh">; +// +// BUILTIN_INFO_NONCONST(brev_lduh,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_lduh : +Hexagon_mem_memmemsi_Intrinsic<"brev_lduh">; +// +// BUILTIN_INFO_NONCONST(brev_ldb,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldb : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldb">; +// +// BUILTIN_INFO_NONCONST(brev_ldub,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldub : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldub">; +// // BUILTIN_INFO_NONCONST(circ_ldd,PTR_ftype_PTRPTRSISI,4) // def int_hexagon_circ_ldd : Hexagon_mem_memmemsisi_Intrinsic<"circ_ldd">; -// This one above will not be generated from iset.py. -// So make sure, you don't overwrite this one. +// +// BUILTIN_INFO_NONCONST(circ_ldw,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldw : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldw">; +// +// BUILTIN_INFO_NONCONST(circ_ldh,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldh : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldh">; +// +// BUILTIN_INFO_NONCONST(circ_lduh,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_lduh : +Hexagon_mem_memmemsisi_Intrinsic<"circ_lduh">; +// +// BUILTIN_INFO_NONCONST(circ_ldb,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldb : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldb">; +// +// BUILTIN_INFO_NONCONST(circ_ldub,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldub : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldub">; + +// +// BUILTIN_INFO_NONCONST(brev_stb,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_stb : +Hexagon_mem_memsisi_Intrinsic<"brev_stb">; +// +// BUILTIN_INFO_NONCONST(brev_sthhi,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_sthhi : +Hexagon_mem_memsisi_Intrinsic<"brev_sthhi">; +// +// BUILTIN_INFO_NONCONST(brev_sth,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_sth : +Hexagon_mem_memsisi_Intrinsic<"brev_sth">; +// +// BUILTIN_INFO_NONCONST(brev_stw,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_stw : +Hexagon_mem_memsisi_Intrinsic<"brev_stw">; +// +// BUILTIN_INFO_NONCONST(brev_std,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_std : +Hexagon_mem_memdisi_Intrinsic<"brev_std">; +// +// BUILTIN_INFO_NONCONST(circ_std,PTR_ftype_PTRDISISI,4) +// +def int_hexagon_circ_std : +Hexagon_mem_memdisisi_Intrinsic<"circ_std">; +// +// BUILTIN_INFO_NONCONST(circ_stw,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_stw : +Hexagon_mem_memsisisi_Intrinsic<"circ_stw">; +// +// BUILTIN_INFO_NONCONST(circ_sth,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_sth : +Hexagon_mem_memsisisi_Intrinsic<"circ_sth">; +// +// BUILTIN_INFO_NONCONST(circ_sthhi,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_sthhi : +Hexagon_mem_memsisisi_Intrinsic<"circ_sthhi">; +// +// BUILTIN_INFO_NONCONST(circ_stb,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_stb : +Hexagon_mem_memsisisi_Intrinsic<"circ_stb">; + + // // BUILTIN_INFO(HEXAGON.C2_cmpeq,QI_ftype_SISI,2) // def int_hexagon_C2_cmpeq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; // // BUILTIN_INFO(HEXAGON.C2_cmpgt,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtu,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; // // BUILTIN_INFO(HEXAGON.C2_cmpeqp,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpeqp : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtp,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpgtp : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtup,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpgtup : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; // // BUILTIN_INFO(HEXAGON.A4_rcmpeqi,SI_ftype_SISI,2) // @@ -674,182 +810,182 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_rcmpneq">; // BUILTIN_INFO(HEXAGON.C2_bitsset,QI_ftype_SISI,2) // def int_hexagon_C2_bitsset : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsset">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsset">; // // BUILTIN_INFO(HEXAGON.C2_bitsclr,QI_ftype_SISI,2) // def int_hexagon_C2_bitsclr : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; // // BUILTIN_INFO(HEXAGON.C4_nbitsset,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsset : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; // // BUILTIN_INFO(HEXAGON.C4_nbitsclr,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsclr : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; // // BUILTIN_INFO(HEXAGON.C2_cmpeqi,QI_ftype_SISI,2) // def int_hexagon_C2_cmpeqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; // // BUILTIN_INFO(HEXAGON.C2_cmpgti,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtui,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; // // BUILTIN_INFO(HEXAGON.C2_cmpgei,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; // // BUILTIN_INFO(HEXAGON.C2_cmpgeui,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgeui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; // // BUILTIN_INFO(HEXAGON.C2_cmplt,QI_ftype_SISI,2) // def int_hexagon_C2_cmplt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmplt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmplt">; // // BUILTIN_INFO(HEXAGON.C2_cmpltu,QI_ftype_SISI,2) // def int_hexagon_C2_cmpltu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; // // BUILTIN_INFO(HEXAGON.C2_bitsclri,QI_ftype_SISI,2) // def int_hexagon_C2_bitsclri : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; // // BUILTIN_INFO(HEXAGON.C4_nbitsclri,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsclri : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; // // BUILTIN_INFO(HEXAGON.C4_cmpneqi,QI_ftype_SISI,2) // def int_hexagon_C4_cmpneqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; // // BUILTIN_INFO(HEXAGON.C4_cmpltei,QI_ftype_SISI,2) // def int_hexagon_C4_cmpltei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; // // BUILTIN_INFO(HEXAGON.C4_cmplteui,QI_ftype_SISI,2) // def int_hexagon_C4_cmplteui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; // // BUILTIN_INFO(HEXAGON.C4_cmpneq,QI_ftype_SISI,2) // def int_hexagon_C4_cmpneq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; // // BUILTIN_INFO(HEXAGON.C4_cmplte,QI_ftype_SISI,2) // def int_hexagon_C4_cmplte : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplte">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplte">; // // BUILTIN_INFO(HEXAGON.C4_cmplteu,QI_ftype_SISI,2) // def int_hexagon_C4_cmplteu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; // // BUILTIN_INFO(HEXAGON.C2_and,QI_ftype_QIQI,2) // def int_hexagon_C2_and : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_and">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_and">; // // BUILTIN_INFO(HEXAGON.C2_or,QI_ftype_QIQI,2) // def int_hexagon_C2_or : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_or">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_or">; // // BUILTIN_INFO(HEXAGON.C2_xor,QI_ftype_QIQI,2) // def int_hexagon_C2_xor : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_xor">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_xor">; // // BUILTIN_INFO(HEXAGON.C2_andn,QI_ftype_QIQI,2) // def int_hexagon_C2_andn : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_andn">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_andn">; // // BUILTIN_INFO(HEXAGON.C2_not,QI_ftype_QI,1) // def int_hexagon_C2_not : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_not">; +Hexagon_si_si_Intrinsic<"HEXAGON_C2_not">; // // BUILTIN_INFO(HEXAGON.C2_orn,QI_ftype_QIQI,2) // def int_hexagon_C2_orn : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_orn">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_orn">; // // BUILTIN_INFO(HEXAGON.C4_and_and,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_and">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_and">; // // BUILTIN_INFO(HEXAGON.C4_and_or,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_or : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_or">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_or">; // // BUILTIN_INFO(HEXAGON.C4_or_and,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_and">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_and">; // // BUILTIN_INFO(HEXAGON.C4_or_or,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_or : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_or">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_or">; // // BUILTIN_INFO(HEXAGON.C4_and_andn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_andn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_andn">; // // BUILTIN_INFO(HEXAGON.C4_and_orn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_orn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_orn">; // // BUILTIN_INFO(HEXAGON.C4_or_andn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_andn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_andn">; // // BUILTIN_INFO(HEXAGON.C4_or_orn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_orn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_orn">; // // BUILTIN_INFO(HEXAGON.C2_pxfer_map,QI_ftype_QI,1) // def int_hexagon_C2_pxfer_map : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; // // BUILTIN_INFO(HEXAGON.C2_any8,QI_ftype_QI,1) // def int_hexagon_C2_any8 : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_any8">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_any8">; // // BUILTIN_INFO(HEXAGON.C2_all8,QI_ftype_QI,1) // def int_hexagon_C2_all8 : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_all8">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_all8">; // // BUILTIN_INFO(HEXAGON.C2_vitpack,SI_ftype_QIQI,2) // @@ -889,167 +1025,167 @@ Hexagon_di_qi_Intrinsic<"HEXAGON_C2_mask">; // BUILTIN_INFO(HEXAGON.A2_vcmpbeq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpbeq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbeqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbeqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbeq_any,QI_ftype_DIDI,2) // def int_hexagon_A4_vcmpbeq_any : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; // // BUILTIN_INFO(HEXAGON.A2_vcmpbgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpbgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgt,QI_ftype_DIDI,2) // def int_hexagon_A4_vcmpbgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; // // BUILTIN_INFO(HEXAGON.A4_cmpbeq,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbeq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; // // BUILTIN_INFO(HEXAGON.A4_cmpbeqi,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbeqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgtu,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgtui,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgt,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgti,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; // // BUILTIN_INFO(HEXAGON.A2_vcmpheq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpheq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; // // BUILTIN_INFO(HEXAGON.A2_vcmphgt,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmphgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; // // BUILTIN_INFO(HEXAGON.A2_vcmphgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmphgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpheqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpheqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmphgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmphgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; // // BUILTIN_INFO(HEXAGON.A4_vcmphgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmphgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; // // BUILTIN_INFO(HEXAGON.A4_cmpheq,QI_ftype_SISI,2) // def int_hexagon_A4_cmpheq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; // // BUILTIN_INFO(HEXAGON.A4_cmphgt,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; // // BUILTIN_INFO(HEXAGON.A4_cmphgtu,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; // // BUILTIN_INFO(HEXAGON.A4_cmpheqi,QI_ftype_SISI,2) // def int_hexagon_A4_cmpheqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; // // BUILTIN_INFO(HEXAGON.A4_cmphgti,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; // // BUILTIN_INFO(HEXAGON.A4_cmphgtui,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; // // BUILTIN_INFO(HEXAGON.A2_vcmpweq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpweq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; // // BUILTIN_INFO(HEXAGON.A2_vcmpwgt,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpwgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; // // BUILTIN_INFO(HEXAGON.A2_vcmpwgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpwgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpweqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpweqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmpwgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpwgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; // // BUILTIN_INFO(HEXAGON.A4_vcmpwgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpwgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; // // BUILTIN_INFO(HEXAGON.A4_boundscheck,QI_ftype_SIDI,2) // def int_hexagon_A4_boundscheck : -Hexagon_qi_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; +Hexagon_si_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; // // BUILTIN_INFO(HEXAGON.A4_tlbmatch,QI_ftype_DISI,2) // def int_hexagon_A4_tlbmatch : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; // // BUILTIN_INFO(HEXAGON.C2_tfrpr,SI_ftype_QI,1) // @@ -1059,17 +1195,17 @@ Hexagon_si_qi_Intrinsic<"HEXAGON_C2_tfrpr">; // BUILTIN_INFO(HEXAGON.C2_tfrrp,QI_ftype_SI,1) // def int_hexagon_C2_tfrrp : -Hexagon_qi_si_Intrinsic<"HEXAGON_C2_tfrrp">; +Hexagon_si_si_Intrinsic<"HEXAGON_C2_tfrrp">; // // BUILTIN_INFO(HEXAGON.C4_fastcorner9,QI_ftype_QIQI,2) // def int_hexagon_C4_fastcorner9 : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; // // BUILTIN_INFO(HEXAGON.C4_fastcorner9_not,QI_ftype_QIQI,2) // def int_hexagon_C4_fastcorner9_not : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; // // BUILTIN_INFO(HEXAGON.M2_mpy_acc_hh_s0,SI_ftype_SISISI,3) // @@ -2849,7 +2985,7 @@ Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrp">; // BUILTIN_INFO(HEXAGON.A2_tfrpi,DI_ftype_SI,1) // def int_hexagon_A2_tfrpi : -Hexagon_di_si_Intrinsic<"HEXAGON_A2_tfrpi">; +Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrpi">; // // BUILTIN_INFO(HEXAGON.A2_zxtb,SI_ftype_SI,1) // @@ -3609,22 +3745,22 @@ Hexagon_sf_sfsfsf_Intrinsic<"HEXAGON_F2_sffms_lib">; // BUILTIN_INFO(HEXAGON.F2_sfcmpeq,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpeq : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpgt,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpgt : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpge,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpge : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpuo,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpuo : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; // // BUILTIN_INFO(HEXAGON.F2_sfmax,SF_ftype_SFSF,2) // @@ -3639,7 +3775,7 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfmin">; // BUILTIN_INFO(HEXAGON.F2_sfclass,QI_ftype_SFSI,2) // def int_hexagon_F2_sfclass : -Hexagon_qi_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; +Hexagon_si_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; // // BUILTIN_INFO(HEXAGON.F2_sfimm_p,SF_ftype_SI,1) // @@ -3666,80 +3802,30 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sffixupd">; def int_hexagon_F2_sffixupr : Hexagon_sf_sf_Intrinsic<"HEXAGON_F2_sffixupr">; // -// BUILTIN_INFO(HEXAGON.F2_dfadd,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfadd : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfadd">; -// -// BUILTIN_INFO(HEXAGON.F2_dfsub,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfsub : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfsub">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmpy,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmpy : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmpy">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffma : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma">; -// -// BUILTIN_INFO(HEXAGON.F2_dffms,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffms : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma_lib,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffma_lib : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma_lib">; -// -// BUILTIN_INFO(HEXAGON.F2_dffms_lib,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffms_lib : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms_lib">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma_sc,DF_ftype_DFDFDFQI,4) -// -def int_hexagon_F2_dffma_sc : -Hexagon_df_dfdfdfqi_Intrinsic<"HEXAGON_F2_dffma_sc">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmax,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmax : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmax">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmin,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmin : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmin">; -// // BUILTIN_INFO(HEXAGON.F2_dfcmpeq,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpeq : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpgt,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpgt : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpge,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpge : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpuo,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpuo : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; // // BUILTIN_INFO(HEXAGON.F2_dfclass,QI_ftype_DFSI,2) // def int_hexagon_F2_dfclass : -Hexagon_qi_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; +Hexagon_si_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; // // BUILTIN_INFO(HEXAGON.F2_dfimm_p,DF_ftype_SI,1) // @@ -3751,21 +3837,6 @@ Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_p">; def int_hexagon_F2_dfimm_n : Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_n">; // -// BUILTIN_INFO(HEXAGON.F2_dffixupn,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dffixupn : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupn">; -// -// BUILTIN_INFO(HEXAGON.F2_dffixupd,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dffixupd : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupd">; -// -// BUILTIN_INFO(HEXAGON.F2_dffixupr,DF_ftype_DF,1) -// -def int_hexagon_F2_dffixupr : -Hexagon_df_df_Intrinsic<"HEXAGON_F2_dffixupr">; -// // BUILTIN_INFO(HEXAGON.F2_conv_sf2df,DF_ftype_SF,1) // def int_hexagon_F2_conv_sf2df : @@ -4494,12 +4565,12 @@ Hexagon_di_didi_Intrinsic<"HEXAGON_S2_extractup_rp">; // BUILTIN_INFO(HEXAGON.S2_tstbit_i,QI_ftype_SISI,2) // def int_hexagon_S2_tstbit_i : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; // // BUILTIN_INFO(HEXAGON.S4_ntstbit_i,QI_ftype_SISI,2) // def int_hexagon_S4_ntstbit_i : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; // // BUILTIN_INFO(HEXAGON.S2_setbit_i,SI_ftype_SISI,2) // @@ -4519,12 +4590,12 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_clrbit_i">; // BUILTIN_INFO(HEXAGON.S2_tstbit_r,QI_ftype_SISI,2) // def int_hexagon_S2_tstbit_r : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; // // BUILTIN_INFO(HEXAGON.S4_ntstbit_r,QI_ftype_SISI,2) // def int_hexagon_S4_ntstbit_r : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; // // BUILTIN_INFO(HEXAGON.S2_setbit_r,SI_ftype_SISI,2) // @@ -4875,3 +4946,21 @@ Hexagon_di_di_Intrinsic<"HEXAGON_S2_interleave">; // def int_hexagon_S2_deinterleave : Hexagon_di_di_Intrinsic<"HEXAGON_S2_deinterleave">; + +def llvm_ptr32_ty : LLVMPointerType<llvm_i32_ty>; +def llvm_ptr64_ty : LLVMPointerType<llvm_i64_ty>; + +// Mark locked loads as read/write to prevent any accidental reordering. +def int_hexagon_L2_loadw_locked : +Hexagon_Intrinsic<"HEXAGON_L2_loadw_locked", [llvm_i32_ty], [llvm_ptr32_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; +def int_hexagon_L4_loadd_locked : +Hexagon_Intrinsic<"HEXAGON_L4_loadd_locked", [llvm_i64_ty], [llvm_ptr64_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + +def int_hexagon_S2_storew_locked : +Hexagon_Intrinsic<"HEXAGON_S2_storew_locked", [llvm_i32_ty], + [llvm_ptr32_ty, llvm_i32_ty], [IntrReadWriteArgMem, NoCapture<0>]>; +def int_hexagon_S4_stored_locked : +Hexagon_Intrinsic<"HEXAGON_S4_stored_locked", [llvm_i32_ty], + [llvm_ptr64_ty, llvm_i64_ty], [IntrReadWriteArgMem, NoCapture<0>]>; diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 5cdabdeadaea..79654695837d 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -24,7 +24,8 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty], [IntrReadWriteArgMem, NoCapture<0>]>; - def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>; @@ -37,6 +38,25 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". // generated by the PowerPC backend! def int_ppc_mtctr : Intrinsic<[], [llvm_anyint_ty], []>; def int_ppc_is_decremented_ctr_nonzero : Intrinsic<[llvm_i1_ty], [], []>; + + // Intrinsics for [double]word extended forms of divide instructions + def int_ppc_divwe : GCCBuiltin<"__builtin_divwe">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_divweu : GCCBuiltin<"__builtin_divweu">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_divde : GCCBuiltin<"__builtin_divde">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_ppc_divdeu : GCCBuiltin<"__builtin_divdeu">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; + + // Bit permute doubleword + def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; } @@ -73,7 +93,7 @@ class PowerPC_Vec_FFF_Intrinsic<string GCCIntSuffix> [llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16f8 +/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16i8 /// vectors and returns one. These intrinsics have no side effects. class PowerPC_Vec_BBB_Intrinsic<string GCCIntSuffix> : PowerPC_Vec_Intrinsic<GCCIntSuffix, @@ -94,6 +114,19 @@ class PowerPC_Vec_WWW_Intrinsic<string GCCIntSuffix> [llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +/// PowerPC_Vec_DDD_Intrinsic - A PowerPC intrinsic that takes two v2i64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_DDD_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +/// PowerPC_Vec_QQQ_Intrinsic - A PowerPC intrinsic that takes two v1i128 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_QQQ_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v1i128_ty], [llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; //===----------------------------------------------------------------------===// // PowerPC VSX Intrinsic Class Definitions. @@ -120,7 +153,6 @@ class PowerPC_VSX_Sca_DDD_Intrinsic<string GCCIntSuffix> [llvm_double_ty], [llvm_double_ty, llvm_double_ty], [IntrNoMem]>; - //===----------------------------------------------------------------------===// // PowerPC Altivec Intrinsic Definitions. @@ -198,7 +230,17 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_altivec_vcmpgtfp : GCCBuiltin<"__builtin_altivec_vcmpgtfp">, Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; - + + def int_ppc_altivec_vcmpequd : GCCBuiltin<"__builtin_altivec_vcmpequd">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsd : GCCBuiltin<"__builtin_altivec_vcmpgtsd">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtud : GCCBuiltin<"__builtin_altivec_vcmpgtud">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpequw : GCCBuiltin<"__builtin_altivec_vcmpequw">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; @@ -242,7 +284,17 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_altivec_vcmpgtfp_p : GCCBuiltin<"__builtin_altivec_vcmpgtfp_p">, Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], [IntrNoMem]>; - + + def int_ppc_altivec_vcmpequd_p : GCCBuiltin<"__builtin_altivec_vcmpequd_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsd_p : GCCBuiltin<"__builtin_altivec_vcmpgtsd_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtud_p : GCCBuiltin<"__builtin_altivec_vcmpgtud_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpequw_p : GCCBuiltin<"__builtin_altivec_vcmpequw_p">, Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], [IntrNoMem]>; @@ -287,18 +339,22 @@ def int_ppc_altivec_vmaxfp : PowerPC_Vec_FFF_Intrinsic<"vmaxfp">; def int_ppc_altivec_vmaxsb : PowerPC_Vec_BBB_Intrinsic<"vmaxsb">; def int_ppc_altivec_vmaxsh : PowerPC_Vec_HHH_Intrinsic<"vmaxsh">; def int_ppc_altivec_vmaxsw : PowerPC_Vec_WWW_Intrinsic<"vmaxsw">; +def int_ppc_altivec_vmaxsd : PowerPC_Vec_DDD_Intrinsic<"vmaxsd">; def int_ppc_altivec_vmaxub : PowerPC_Vec_BBB_Intrinsic<"vmaxub">; def int_ppc_altivec_vmaxuh : PowerPC_Vec_HHH_Intrinsic<"vmaxuh">; def int_ppc_altivec_vmaxuw : PowerPC_Vec_WWW_Intrinsic<"vmaxuw">; +def int_ppc_altivec_vmaxud : PowerPC_Vec_DDD_Intrinsic<"vmaxud">; // Vector minimum. def int_ppc_altivec_vminfp : PowerPC_Vec_FFF_Intrinsic<"vminfp">; def int_ppc_altivec_vminsb : PowerPC_Vec_BBB_Intrinsic<"vminsb">; def int_ppc_altivec_vminsh : PowerPC_Vec_HHH_Intrinsic<"vminsh">; def int_ppc_altivec_vminsw : PowerPC_Vec_WWW_Intrinsic<"vminsw">; +def int_ppc_altivec_vminsd : PowerPC_Vec_DDD_Intrinsic<"vminsd">; def int_ppc_altivec_vminub : PowerPC_Vec_BBB_Intrinsic<"vminub">; def int_ppc_altivec_vminuh : PowerPC_Vec_HHH_Intrinsic<"vminuh">; def int_ppc_altivec_vminuw : PowerPC_Vec_WWW_Intrinsic<"vminuw">; +def int_ppc_altivec_vminud : PowerPC_Vec_DDD_Intrinsic<"vminud">; // Saturating adds. def int_ppc_altivec_vaddubs : PowerPC_Vec_BBB_Intrinsic<"vaddubs">; @@ -308,6 +364,7 @@ def int_ppc_altivec_vaddshs : PowerPC_Vec_HHH_Intrinsic<"vaddshs">; def int_ppc_altivec_vadduws : PowerPC_Vec_WWW_Intrinsic<"vadduws">; def int_ppc_altivec_vaddsws : PowerPC_Vec_WWW_Intrinsic<"vaddsws">; def int_ppc_altivec_vaddcuw : PowerPC_Vec_WWW_Intrinsic<"vaddcuw">; +def int_ppc_altivec_vaddcuq : PowerPC_Vec_QQQ_Intrinsic<"vaddcuq">; // Saturating subs. def int_ppc_altivec_vsububs : PowerPC_Vec_BBB_Intrinsic<"vsububs">; @@ -317,6 +374,7 @@ def int_ppc_altivec_vsubshs : PowerPC_Vec_HHH_Intrinsic<"vsubshs">; def int_ppc_altivec_vsubuws : PowerPC_Vec_WWW_Intrinsic<"vsubuws">; def int_ppc_altivec_vsubsws : PowerPC_Vec_WWW_Intrinsic<"vsubsws">; def int_ppc_altivec_vsubcuw : PowerPC_Vec_WWW_Intrinsic<"vsubcuw">; +def int_ppc_altivec_vsubcuq : PowerPC_Vec_QQQ_Intrinsic<"vsubcuq">; let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". // Saturating multiply-adds. @@ -361,12 +419,18 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vmulesh : GCCBuiltin<"__builtin_altivec_vmulesh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmulesw : GCCBuiltin<"__builtin_altivec_vmulesw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_ppc_altivec_vmuleub : GCCBuiltin<"__builtin_altivec_vmuleub">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vmuleuh : GCCBuiltin<"__builtin_altivec_vmuleuh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmuleuw : GCCBuiltin<"__builtin_altivec_vmuleuw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_ppc_altivec_vmulosb : GCCBuiltin<"__builtin_altivec_vmulosb">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], @@ -374,12 +438,18 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vmulosh : GCCBuiltin<"__builtin_altivec_vmulosh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmulosw : GCCBuiltin<"__builtin_altivec_vmulosw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_ppc_altivec_vmuloub : GCCBuiltin<"__builtin_altivec_vmuloub">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vmulouh : GCCBuiltin<"__builtin_altivec_vmulouh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmulouw : GCCBuiltin<"__builtin_altivec_vmulouw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; // Vector Sum Intructions. def int_ppc_altivec_vsumsws : GCCBuiltin<"__builtin_altivec_vsumsws">, @@ -419,6 +489,12 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vpkswus : GCCBuiltin<"__builtin_altivec_vpkswus">, Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vpksdss : GCCBuiltin<"__builtin_altivec_vpksdss">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpksdus : GCCBuiltin<"__builtin_altivec_vpksdus">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; // vpkuhum is lowered to a shuffle. def int_ppc_altivec_vpkuhus : GCCBuiltin<"__builtin_altivec_vpkuhus">, Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], @@ -427,6 +503,10 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vpkuwus : GCCBuiltin<"__builtin_altivec_vpkuwus">, Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + // vpkudum is lowered to a shuffle. + def int_ppc_altivec_vpkudus : GCCBuiltin<"__builtin_altivec_vpkudus">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; // Unpacks. def int_ppc_altivec_vupkhpx : GCCBuiltin<"__builtin_altivec_vupkhpx">, @@ -435,12 +515,16 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vupkhsh : GCCBuiltin<"__builtin_altivec_vupkhsh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsw : GCCBuiltin<"__builtin_altivec_vupkhsw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; def int_ppc_altivec_vupklpx : GCCBuiltin<"__builtin_altivec_vupklpx">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; def int_ppc_altivec_vupklsb : GCCBuiltin<"__builtin_altivec_vupklsb">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vupklsh : GCCBuiltin<"__builtin_altivec_vupklsh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsw : GCCBuiltin<"__builtin_altivec_vupklsw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; // FP <-> integer conversion. @@ -465,6 +549,26 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_ppc_altivec_vrfiz : GCCBuiltin<"__builtin_altivec_vrfiz">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + + // Add Extended Quadword + def int_ppc_altivec_vaddeuqm : GCCBuiltin<"__builtin_altivec_vaddeuqm">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; + def int_ppc_altivec_vaddecuq : GCCBuiltin<"__builtin_altivec_vaddecuq">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; + + // Sub Extended Quadword + def int_ppc_altivec_vsubeuqm : GCCBuiltin<"__builtin_altivec_vsubeuqm">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsubecuq : GCCBuiltin<"__builtin_altivec_vsubecuq">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; } def int_ppc_altivec_vsl : PowerPC_Vec_WWW_Intrinsic<"vsl">; @@ -489,6 +593,7 @@ def int_ppc_altivec_vsraw : PowerPC_Vec_WWW_Intrinsic<"vsraw">; def int_ppc_altivec_vrlb : PowerPC_Vec_BBB_Intrinsic<"vrlb">; def int_ppc_altivec_vrlh : PowerPC_Vec_HHH_Intrinsic<"vrlh">; def int_ppc_altivec_vrlw : PowerPC_Vec_WWW_Intrinsic<"vrlw">; +def int_ppc_altivec_vrld : PowerPC_Vec_DDD_Intrinsic<"vrld">; let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". // Miscellaneous. @@ -510,6 +615,42 @@ def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">; def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">; def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">; +// Power8 Intrinsics +// Crypto +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + def int_ppc_altivec_crypto_vsbox : + GCCBuiltin<"__builtin_altivec_crypto_vsbox">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + def int_ppc_altivec_crypto_vpermxor : + GCCBuiltin<"__builtin_altivec_crypto_vpermxor">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_ppc_altivec_crypto_vshasigmad : + GCCBuiltin<"__builtin_altivec_crypto_vshasigmad">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_ppc_altivec_crypto_vshasigmaw : + GCCBuiltin<"__builtin_altivec_crypto_vshasigmaw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +} +def int_ppc_altivec_crypto_vcipher : + PowerPC_Vec_DDD_Intrinsic<"crypto_vcipher">; +def int_ppc_altivec_crypto_vcipherlast : + PowerPC_Vec_DDD_Intrinsic<"crypto_vcipherlast">; +def int_ppc_altivec_crypto_vncipher : + PowerPC_Vec_DDD_Intrinsic<"crypto_vncipher">; +def int_ppc_altivec_crypto_vncipherlast : + PowerPC_Vec_DDD_Intrinsic<"crypto_vncipherlast">; +def int_ppc_altivec_crypto_vpmsumb : + PowerPC_Vec_BBB_Intrinsic<"crypto_vpmsumb">; +def int_ppc_altivec_crypto_vpmsumh : + PowerPC_Vec_HHH_Intrinsic<"crypto_vpmsumh">; +def int_ppc_altivec_crypto_vpmsumw : + PowerPC_Vec_WWW_Intrinsic<"crypto_vpmsumw">; +def int_ppc_altivec_crypto_vpmsumd : + PowerPC_Vec_DDD_Intrinsic<"crypto_vpmsumd">; //===----------------------------------------------------------------------===// // PowerPC VSX Intrinsic Definitions. @@ -542,3 +683,239 @@ def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">; def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">; def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">; } + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsics. +// + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + /// PowerPC_QPX_Intrinsic - Base class for all QPX intrinsics. + class PowerPC_QPX_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types, + list<LLVMType> param_types, + list<IntrinsicProperty> properties> + : GCCBuiltin<!strconcat("__builtin_qpx_", GCCIntSuffix)>, + Intrinsic<ret_types, param_types, properties>; +} + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsic Class Definitions. +// + +/// PowerPC_QPX_FF_Intrinsic - A PowerPC intrinsic that takes one v4f64 +/// vector and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FF_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; + +/// PowerPC_QPX_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FFF_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], + [IntrNoMem]>; + +/// PowerPC_QPX_FFFF_Intrinsic - A PowerPC intrinsic that takes three v4f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FFFF_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], + [IntrNoMem]>; + +/// PowerPC_QPX_Load_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and returns a v4f64. +class PowerPC_QPX_Load_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + +/// PowerPC_QPX_LoadPerm_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and returns a v4f64 permutation. +class PowerPC_QPX_LoadPerm_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [llvm_v4f64_ty], [llvm_ptr_ty], [IntrNoMem]>; + +/// PowerPC_QPX_Store_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and stores a v4f64. +class PowerPC_QPX_Store_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [], [llvm_v4f64_ty, llvm_ptr_ty], + [IntrReadWriteArgMem]>; + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // Add Instructions + def int_ppc_qpx_qvfadd : PowerPC_QPX_FFF_Intrinsic<"qvfadd">; + def int_ppc_qpx_qvfadds : PowerPC_QPX_FFF_Intrinsic<"qvfadds">; + def int_ppc_qpx_qvfsub : PowerPC_QPX_FFF_Intrinsic<"qvfsub">; + def int_ppc_qpx_qvfsubs : PowerPC_QPX_FFF_Intrinsic<"qvfsubs">; + + // Estimate Instructions + def int_ppc_qpx_qvfre : PowerPC_QPX_FF_Intrinsic<"qvfre">; + def int_ppc_qpx_qvfres : PowerPC_QPX_FF_Intrinsic<"qvfres">; + def int_ppc_qpx_qvfrsqrte : PowerPC_QPX_FF_Intrinsic<"qvfrsqrte">; + def int_ppc_qpx_qvfrsqrtes : PowerPC_QPX_FF_Intrinsic<"qvfrsqrtes">; + + // Multiply Instructions + def int_ppc_qpx_qvfmul : PowerPC_QPX_FFF_Intrinsic<"qvfmul">; + def int_ppc_qpx_qvfmuls : PowerPC_QPX_FFF_Intrinsic<"qvfmuls">; + def int_ppc_qpx_qvfxmul : PowerPC_QPX_FFF_Intrinsic<"qvfxmul">; + def int_ppc_qpx_qvfxmuls : PowerPC_QPX_FFF_Intrinsic<"qvfxmuls">; + + // Multiply-add instructions + def int_ppc_qpx_qvfmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfmadd">; + def int_ppc_qpx_qvfmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfmadds">; + def int_ppc_qpx_qvfnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadd">; + def int_ppc_qpx_qvfnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadds">; + def int_ppc_qpx_qvfmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfmsub">; + def int_ppc_qpx_qvfmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfmsubs">; + def int_ppc_qpx_qvfnmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsub">; + def int_ppc_qpx_qvfnmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsubs">; + def int_ppc_qpx_qvfxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadd">; + def int_ppc_qpx_qvfxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadds">; + def int_ppc_qpx_qvfxxnpmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadd">; + def int_ppc_qpx_qvfxxnpmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadds">; + def int_ppc_qpx_qvfxxcpnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadd">; + def int_ppc_qpx_qvfxxcpnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadds">; + def int_ppc_qpx_qvfxxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadd">; + def int_ppc_qpx_qvfxxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadds">; + + // Select Instruction + def int_ppc_qpx_qvfsel : PowerPC_QPX_FFFF_Intrinsic<"qvfsel">; + + // Permute Instruction + def int_ppc_qpx_qvfperm : PowerPC_QPX_FFFF_Intrinsic<"qvfperm">; + + // Convert and Round Instructions + def int_ppc_qpx_qvfctid : PowerPC_QPX_FF_Intrinsic<"qvfctid">; + def int_ppc_qpx_qvfctidu : PowerPC_QPX_FF_Intrinsic<"qvfctidu">; + def int_ppc_qpx_qvfctidz : PowerPC_QPX_FF_Intrinsic<"qvfctidz">; + def int_ppc_qpx_qvfctiduz : PowerPC_QPX_FF_Intrinsic<"qvfctiduz">; + def int_ppc_qpx_qvfctiw : PowerPC_QPX_FF_Intrinsic<"qvfctiw">; + def int_ppc_qpx_qvfctiwu : PowerPC_QPX_FF_Intrinsic<"qvfctiwu">; + def int_ppc_qpx_qvfctiwz : PowerPC_QPX_FF_Intrinsic<"qvfctiwz">; + def int_ppc_qpx_qvfctiwuz : PowerPC_QPX_FF_Intrinsic<"qvfctiwuz">; + def int_ppc_qpx_qvfcfid : PowerPC_QPX_FF_Intrinsic<"qvfcfid">; + def int_ppc_qpx_qvfcfidu : PowerPC_QPX_FF_Intrinsic<"qvfcfidu">; + def int_ppc_qpx_qvfcfids : PowerPC_QPX_FF_Intrinsic<"qvfcfids">; + def int_ppc_qpx_qvfcfidus : PowerPC_QPX_FF_Intrinsic<"qvfcfidus">; + def int_ppc_qpx_qvfrsp : PowerPC_QPX_FF_Intrinsic<"qvfrsp">; + def int_ppc_qpx_qvfriz : PowerPC_QPX_FF_Intrinsic<"qvfriz">; + def int_ppc_qpx_qvfrin : PowerPC_QPX_FF_Intrinsic<"qvfrin">; + def int_ppc_qpx_qvfrip : PowerPC_QPX_FF_Intrinsic<"qvfrip">; + def int_ppc_qpx_qvfrim : PowerPC_QPX_FF_Intrinsic<"qvfrim">; + + // Move Instructions + def int_ppc_qpx_qvfneg : PowerPC_QPX_FF_Intrinsic<"qvfneg">; + def int_ppc_qpx_qvfabs : PowerPC_QPX_FF_Intrinsic<"qvfabs">; + def int_ppc_qpx_qvfnabs : PowerPC_QPX_FF_Intrinsic<"qvfnabs">; + def int_ppc_qpx_qvfcpsgn : PowerPC_QPX_FFF_Intrinsic<"qvfcpsgn">; + + // Compare Instructions + def int_ppc_qpx_qvftstnan : PowerPC_QPX_FFF_Intrinsic<"qvftstnan">; + def int_ppc_qpx_qvfcmplt : PowerPC_QPX_FFF_Intrinsic<"qvfcmplt">; + def int_ppc_qpx_qvfcmpgt : PowerPC_QPX_FFF_Intrinsic<"qvfcmpgt">; + def int_ppc_qpx_qvfcmpeq : PowerPC_QPX_FFF_Intrinsic<"qvfcmpeq">; + + // Load instructions + def int_ppc_qpx_qvlfd : PowerPC_QPX_Load_Intrinsic<"qvlfd">; + def int_ppc_qpx_qvlfda : PowerPC_QPX_Load_Intrinsic<"qvlfda">; + def int_ppc_qpx_qvlfs : PowerPC_QPX_Load_Intrinsic<"qvlfs">; + def int_ppc_qpx_qvlfsa : PowerPC_QPX_Load_Intrinsic<"qvlfsa">; + + def int_ppc_qpx_qvlfcda : PowerPC_QPX_Load_Intrinsic<"qvlfcda">; + def int_ppc_qpx_qvlfcd : PowerPC_QPX_Load_Intrinsic<"qvlfcd">; + def int_ppc_qpx_qvlfcsa : PowerPC_QPX_Load_Intrinsic<"qvlfcsa">; + def int_ppc_qpx_qvlfcs : PowerPC_QPX_Load_Intrinsic<"qvlfcs">; + def int_ppc_qpx_qvlfiwaa : PowerPC_QPX_Load_Intrinsic<"qvlfiwaa">; + def int_ppc_qpx_qvlfiwa : PowerPC_QPX_Load_Intrinsic<"qvlfiwa">; + def int_ppc_qpx_qvlfiwza : PowerPC_QPX_Load_Intrinsic<"qvlfiwza">; + def int_ppc_qpx_qvlfiwz : PowerPC_QPX_Load_Intrinsic<"qvlfiwz">; + + def int_ppc_qpx_qvlpcld : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcld">; + def int_ppc_qpx_qvlpcls : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcls">; + def int_ppc_qpx_qvlpcrd : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrd">; + def int_ppc_qpx_qvlpcrs : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrs">; + + // Store instructions + def int_ppc_qpx_qvstfd : PowerPC_QPX_Store_Intrinsic<"qvstfd">; + def int_ppc_qpx_qvstfda : PowerPC_QPX_Store_Intrinsic<"qvstfda">; + def int_ppc_qpx_qvstfs : PowerPC_QPX_Store_Intrinsic<"qvstfs">; + def int_ppc_qpx_qvstfsa : PowerPC_QPX_Store_Intrinsic<"qvstfsa">; + + def int_ppc_qpx_qvstfcda : PowerPC_QPX_Store_Intrinsic<"qvstfcda">; + def int_ppc_qpx_qvstfcd : PowerPC_QPX_Store_Intrinsic<"qvstfcd">; + def int_ppc_qpx_qvstfcsa : PowerPC_QPX_Store_Intrinsic<"qvstfcsa">; + def int_ppc_qpx_qvstfcs : PowerPC_QPX_Store_Intrinsic<"qvstfcs">; + def int_ppc_qpx_qvstfiwa : PowerPC_QPX_Store_Intrinsic<"qvstfiwa">; + def int_ppc_qpx_qvstfiw : PowerPC_QPX_Store_Intrinsic<"qvstfiw">; + + // Logical and permutation formation + def int_ppc_qpx_qvflogical : PowerPC_QPX_Intrinsic<"qvflogical", + [llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_qpx_qvgpci : PowerPC_QPX_Intrinsic<"qvgpci", + [llvm_v4f64_ty], [llvm_i32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// PowerPC HTM Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + +def int_ppc_tbegin : GCCBuiltin<"__builtin_tbegin">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; +def int_ppc_tend : GCCBuiltin<"__builtin_tend">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + +def int_ppc_tabort : GCCBuiltin<"__builtin_tabort">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; +def int_ppc_tabortwc : GCCBuiltin<"__builtin_tabortwc">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_ppc_tabortwci : GCCBuiltin<"__builtin_tabortwci">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_ppc_tabortdc : GCCBuiltin<"__builtin_tabortdc">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_ppc_tabortdci : GCCBuiltin<"__builtin_tabortdci">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + +def int_ppc_tcheck : GCCBuiltin<"__builtin_tcheck">, + Intrinsic<[llvm_i32_ty], [], []>; +def int_ppc_treclaim : GCCBuiltin<"__builtin_treclaim">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; +def int_ppc_trechkpt : GCCBuiltin<"__builtin_trechkpt">, + Intrinsic<[llvm_i32_ty], [], []>; +def int_ppc_tsr : GCCBuiltin<"__builtin_tsr">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + +def int_ppc_get_texasr : GCCBuiltin<"__builtin_get_texasr">, + Intrinsic<[llvm_i64_ty], [], []>; +def int_ppc_get_texasru : GCCBuiltin<"__builtin_get_texasru">, + Intrinsic<[llvm_i64_ty], [], []>; +def int_ppc_get_tfhar : GCCBuiltin<"__builtin_get_tfhar">, + Intrinsic<[llvm_i64_ty], [], []>; +def int_ppc_get_tfiar : GCCBuiltin<"__builtin_get_tfiar">, + Intrinsic<[llvm_i64_ty], [], []>; + +def int_ppc_set_texasr : GCCBuiltin<"__builtin_set_texasr">, + Intrinsic<[], [llvm_i64_ty], []>; +def int_ppc_set_texasru : GCCBuiltin<"__builtin_set_texasru">, + Intrinsic<[], [llvm_i64_ty], []>; +def int_ppc_set_tfhar : GCCBuiltin<"__builtin_set_tfhar">, + Intrinsic<[], [llvm_i64_ty], []>; +def int_ppc_set_tfiar : GCCBuiltin<"__builtin_set_tfiar">, + Intrinsic<[], [llvm_i64_ty], []>; + +// Extended mnemonics +def int_ppc_tendall : GCCBuiltin<"__builtin_tendall">, + Intrinsic<[llvm_i32_ty], [], []>; +def int_ppc_tresume : GCCBuiltin<"__builtin_tresume">, + Intrinsic<[llvm_i32_ty], [], []>; +def int_ppc_tsuspend : GCCBuiltin<"__builtin_tsuspend">, + Intrinsic<[llvm_i32_ty], [], []>; + +def int_ppc_ttest : GCCBuiltin<"__builtin_ttest">, + Intrinsic<[llvm_i64_ty], [], []>; +} diff --git a/include/llvm/IR/IntrinsicsSystemZ.td b/include/llvm/IR/IntrinsicsSystemZ.td new file mode 100644 index 000000000000..96e7ca525696 --- /dev/null +++ b/include/llvm/IR/IntrinsicsSystemZ.td @@ -0,0 +1,376 @@ +//===- IntrinsicsSystemZ.td - Defines SystemZ intrinsics ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the SystemZ-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +class SystemZUnaryConv<string name, LLVMType result, LLVMType arg> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[result], [arg], [IntrNoMem]>; + +class SystemZUnary<string name, LLVMType type> + : SystemZUnaryConv<name, type, type>; + +class SystemZUnaryConvCC<LLVMType result, LLVMType arg> + : Intrinsic<[result, llvm_i32_ty], [arg], [IntrNoMem]>; + +class SystemZUnaryCC<LLVMType type> + : SystemZUnaryConvCC<type, type>; + +class SystemZBinaryConv<string name, LLVMType result, LLVMType arg> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[result], [arg, arg], [IntrNoMem]>; + +class SystemZBinary<string name, LLVMType type> + : SystemZBinaryConv<name, type, type>; + +class SystemZBinaryInt<string name, LLVMType type> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[type], [type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZBinaryConvCC<LLVMType result, LLVMType arg> + : Intrinsic<[result, llvm_i32_ty], [arg, arg], [IntrNoMem]>; + +class SystemZBinaryConvIntCC<LLVMType result, LLVMType arg> + : Intrinsic<[result, llvm_i32_ty], [arg, llvm_i32_ty], [IntrNoMem]>; + +class SystemZBinaryCC<LLVMType type> + : SystemZBinaryConvCC<type, type>; + +class SystemZTernaryConv<string name, LLVMType result, LLVMType arg> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[result], [arg, arg, result], [IntrNoMem]>; + +class SystemZTernary<string name, LLVMType type> + : SystemZTernaryConv<name, type, type>; + +class SystemZTernaryInt<string name, LLVMType type> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[type], [type, type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZTernaryIntCC<LLVMType type> + : Intrinsic<[type, llvm_i32_ty], [type, type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZQuaternaryInt<string name, LLVMType type> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[type], [type, type, type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZQuaternaryIntCC<LLVMType type> + : Intrinsic<[type, llvm_i32_ty], [type, type, type, llvm_i32_ty], + [IntrNoMem]>; + +multiclass SystemZUnaryExtBHF<string name> { + def b : SystemZUnaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>; + def h : SystemZUnaryConv<name##"h", llvm_v4i32_ty, llvm_v8i16_ty>; + def f : SystemZUnaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>; +} + +multiclass SystemZUnaryExtBHWF<string name> { + def b : SystemZUnaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>; + def hw : SystemZUnaryConv<name##"hw", llvm_v4i32_ty, llvm_v8i16_ty>; + def f : SystemZUnaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>; +} + +multiclass SystemZUnaryBHF<string name> { + def b : SystemZUnary<name##"b", llvm_v16i8_ty>; + def h : SystemZUnary<name##"h", llvm_v8i16_ty>; + def f : SystemZUnary<name##"f", llvm_v4i32_ty>; +} + +multiclass SystemZUnaryBHFG<string name> : SystemZUnaryBHF<name> { + def g : SystemZUnary<name##"g", llvm_v2i64_ty>; +} + +multiclass SystemZUnaryCCBHF { + def bs : SystemZUnaryCC<llvm_v16i8_ty>; + def hs : SystemZUnaryCC<llvm_v8i16_ty>; + def fs : SystemZUnaryCC<llvm_v4i32_ty>; +} + +multiclass SystemZBinaryTruncHFG<string name> { + def h : SystemZBinaryConv<name##"h", llvm_v16i8_ty, llvm_v8i16_ty>; + def f : SystemZBinaryConv<name##"f", llvm_v8i16_ty, llvm_v4i32_ty>; + def g : SystemZBinaryConv<name##"g", llvm_v4i32_ty, llvm_v2i64_ty>; +} + +multiclass SystemZBinaryTruncCCHFG { + def hs : SystemZBinaryConvCC<llvm_v16i8_ty, llvm_v8i16_ty>; + def fs : SystemZBinaryConvCC<llvm_v8i16_ty, llvm_v4i32_ty>; + def gs : SystemZBinaryConvCC<llvm_v4i32_ty, llvm_v2i64_ty>; +} + +multiclass SystemZBinaryExtBHF<string name> { + def b : SystemZBinaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>; + def h : SystemZBinaryConv<name##"h", llvm_v4i32_ty, llvm_v8i16_ty>; + def f : SystemZBinaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>; +} + +multiclass SystemZBinaryExtBHFG<string name> : SystemZBinaryExtBHF<name> { + def g : SystemZBinaryConv<name##"g", llvm_v16i8_ty, llvm_v2i64_ty>; +} + +multiclass SystemZBinaryBHF<string name> { + def b : SystemZBinary<name##"b", llvm_v16i8_ty>; + def h : SystemZBinary<name##"h", llvm_v8i16_ty>; + def f : SystemZBinary<name##"f", llvm_v4i32_ty>; +} + +multiclass SystemZBinaryBHFG<string name> : SystemZBinaryBHF<name> { + def g : SystemZBinary<name##"g", llvm_v2i64_ty>; +} + +multiclass SystemZBinaryIntBHFG<string name> { + def b : SystemZBinaryInt<name##"b", llvm_v16i8_ty>; + def h : SystemZBinaryInt<name##"h", llvm_v8i16_ty>; + def f : SystemZBinaryInt<name##"f", llvm_v4i32_ty>; + def g : SystemZBinaryInt<name##"g", llvm_v2i64_ty>; +} + +multiclass SystemZBinaryCCBHF { + def bs : SystemZBinaryCC<llvm_v16i8_ty>; + def hs : SystemZBinaryCC<llvm_v8i16_ty>; + def fs : SystemZBinaryCC<llvm_v4i32_ty>; +} + +multiclass SystemZCompareBHFG<string name> { + def bs : SystemZBinaryCC<llvm_v16i8_ty>; + def hs : SystemZBinaryCC<llvm_v8i16_ty>; + def fs : SystemZBinaryCC<llvm_v4i32_ty>; + def gs : SystemZBinaryCC<llvm_v2i64_ty>; +} + +multiclass SystemZTernaryExtBHF<string name> { + def b : SystemZTernaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>; + def h : SystemZTernaryConv<name##"h", llvm_v4i32_ty, llvm_v8i16_ty>; + def f : SystemZTernaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>; +} + +multiclass SystemZTernaryExtBHFG<string name> : SystemZTernaryExtBHF<name> { + def g : SystemZTernaryConv<name##"g", llvm_v16i8_ty, llvm_v2i64_ty>; +} + +multiclass SystemZTernaryBHF<string name> { + def b : SystemZTernary<name##"b", llvm_v16i8_ty>; + def h : SystemZTernary<name##"h", llvm_v8i16_ty>; + def f : SystemZTernary<name##"f", llvm_v4i32_ty>; +} + +multiclass SystemZTernaryIntBHF<string name> { + def b : SystemZTernaryInt<name##"b", llvm_v16i8_ty>; + def h : SystemZTernaryInt<name##"h", llvm_v8i16_ty>; + def f : SystemZTernaryInt<name##"f", llvm_v4i32_ty>; +} + +multiclass SystemZTernaryIntCCBHF { + def bs : SystemZTernaryIntCC<llvm_v16i8_ty>; + def hs : SystemZTernaryIntCC<llvm_v8i16_ty>; + def fs : SystemZTernaryIntCC<llvm_v4i32_ty>; +} + +multiclass SystemZQuaternaryIntBHF<string name> { + def b : SystemZQuaternaryInt<name##"b", llvm_v16i8_ty>; + def h : SystemZQuaternaryInt<name##"h", llvm_v8i16_ty>; + def f : SystemZQuaternaryInt<name##"f", llvm_v4i32_ty>; +} + +multiclass SystemZQuaternaryIntBHFG<string name> : SystemZQuaternaryIntBHF<name> { + def g : SystemZQuaternaryInt<name##"g", llvm_v2i64_ty>; +} + +multiclass SystemZQuaternaryIntCCBHF { + def bs : SystemZQuaternaryIntCC<llvm_v16i8_ty>; + def hs : SystemZQuaternaryIntCC<llvm_v8i16_ty>; + def fs : SystemZQuaternaryIntCC<llvm_v4i32_ty>; +} + +//===----------------------------------------------------------------------===// +// +// Transactional-execution intrinsics +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "s390" in { + def int_s390_tbegin : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tbegin_nofloat : Intrinsic<[llvm_i32_ty], + [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tbeginc : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tabort : Intrinsic<[], [llvm_i64_ty], + [IntrNoReturn, Throws]>; + + def int_s390_tend : GCCBuiltin<"__builtin_tend">, + Intrinsic<[llvm_i32_ty], []>; + + def int_s390_etnd : GCCBuiltin<"__builtin_tx_nesting_depth">, + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; + + def int_s390_ntstg : Intrinsic<[], [llvm_i64_ty, llvm_ptr64_ty], + [IntrReadWriteArgMem]>; + + def int_s390_ppa_txassist : GCCBuiltin<"__builtin_tx_assist">, + Intrinsic<[], [llvm_i32_ty]>; +} + +//===----------------------------------------------------------------------===// +// +// Vector intrinsics +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "s390" in { + def int_s390_lcbb : GCCBuiltin<"__builtin_s390_lcbb">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_s390_vlbb : GCCBuiltin<"__builtin_s390_vlbb">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_s390_vll : GCCBuiltin<"__builtin_s390_vll">, + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty, llvm_ptr_ty], + [IntrReadArgMem]>; + + def int_s390_vpdi : GCCBuiltin<"__builtin_s390_vpdi">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_s390_vperm : GCCBuiltin<"__builtin_s390_vperm">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + + defm int_s390_vpks : SystemZBinaryTruncHFG<"vpks">; + defm int_s390_vpks : SystemZBinaryTruncCCHFG; + + defm int_s390_vpkls : SystemZBinaryTruncHFG<"vpkls">; + defm int_s390_vpkls : SystemZBinaryTruncCCHFG; + + def int_s390_vstl : GCCBuiltin<"__builtin_s390_vstl">, + Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty], + // In fact write-only but there's no property + // for that. + [IntrReadWriteArgMem]>; + + defm int_s390_vupl : SystemZUnaryExtBHWF<"vupl">; + defm int_s390_vupll : SystemZUnaryExtBHF<"vupll">; + + defm int_s390_vuph : SystemZUnaryExtBHF<"vuph">; + defm int_s390_vuplh : SystemZUnaryExtBHF<"vuplh">; + + defm int_s390_vacc : SystemZBinaryBHFG<"vacc">; + + def int_s390_vaq : SystemZBinary<"vaq", llvm_v16i8_ty>; + def int_s390_vacq : SystemZTernary<"vacq", llvm_v16i8_ty>; + def int_s390_vaccq : SystemZBinary<"vaccq", llvm_v16i8_ty>; + def int_s390_vacccq : SystemZTernary<"vacccq", llvm_v16i8_ty>; + + defm int_s390_vavg : SystemZBinaryBHFG<"vavg">; + defm int_s390_vavgl : SystemZBinaryBHFG<"vavgl">; + + def int_s390_vcksm : SystemZBinary<"vcksm", llvm_v4i32_ty>; + + defm int_s390_vgfm : SystemZBinaryExtBHFG<"vgfm">; + defm int_s390_vgfma : SystemZTernaryExtBHFG<"vgfma">; + + defm int_s390_vmah : SystemZTernaryBHF<"vmah">; + defm int_s390_vmalh : SystemZTernaryBHF<"vmalh">; + defm int_s390_vmae : SystemZTernaryExtBHF<"vmae">; + defm int_s390_vmale : SystemZTernaryExtBHF<"vmale">; + defm int_s390_vmao : SystemZTernaryExtBHF<"vmao">; + defm int_s390_vmalo : SystemZTernaryExtBHF<"vmalo">; + + defm int_s390_vmh : SystemZBinaryBHF<"vmh">; + defm int_s390_vmlh : SystemZBinaryBHF<"vmlh">; + defm int_s390_vme : SystemZBinaryExtBHF<"vme">; + defm int_s390_vmle : SystemZBinaryExtBHF<"vmle">; + defm int_s390_vmo : SystemZBinaryExtBHF<"vmo">; + defm int_s390_vmlo : SystemZBinaryExtBHF<"vmlo">; + + defm int_s390_verllv : SystemZBinaryBHFG<"verllv">; + defm int_s390_verll : SystemZBinaryIntBHFG<"verll">; + defm int_s390_verim : SystemZQuaternaryIntBHFG<"verim">; + + def int_s390_vsl : SystemZBinary<"vsl", llvm_v16i8_ty>; + def int_s390_vslb : SystemZBinary<"vslb", llvm_v16i8_ty>; + def int_s390_vsra : SystemZBinary<"vsra", llvm_v16i8_ty>; + def int_s390_vsrab : SystemZBinary<"vsrab", llvm_v16i8_ty>; + def int_s390_vsrl : SystemZBinary<"vsrl", llvm_v16i8_ty>; + def int_s390_vsrlb : SystemZBinary<"vsrlb", llvm_v16i8_ty>; + + def int_s390_vsldb : GCCBuiltin<"__builtin_s390_vsldb">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + defm int_s390_vscbi : SystemZBinaryBHFG<"vscbi">; + + def int_s390_vsq : SystemZBinary<"vsq", llvm_v16i8_ty>; + def int_s390_vsbiq : SystemZTernary<"vsbiq", llvm_v16i8_ty>; + def int_s390_vscbiq : SystemZBinary<"vscbiq", llvm_v16i8_ty>; + def int_s390_vsbcbiq : SystemZTernary<"vsbcbiq", llvm_v16i8_ty>; + + def int_s390_vsumb : SystemZBinaryConv<"vsumb", llvm_v4i32_ty, llvm_v16i8_ty>; + def int_s390_vsumh : SystemZBinaryConv<"vsumh", llvm_v4i32_ty, llvm_v8i16_ty>; + + def int_s390_vsumgh : SystemZBinaryConv<"vsumgh", llvm_v2i64_ty, + llvm_v8i16_ty>; + def int_s390_vsumgf : SystemZBinaryConv<"vsumgf", llvm_v2i64_ty, + llvm_v4i32_ty>; + + def int_s390_vsumqf : SystemZBinaryConv<"vsumqf", llvm_v16i8_ty, + llvm_v4i32_ty>; + def int_s390_vsumqg : SystemZBinaryConv<"vsumqg", llvm_v16i8_ty, + llvm_v2i64_ty>; + + def int_s390_vtm : SystemZBinaryConv<"vtm", llvm_i32_ty, llvm_v16i8_ty>; + + defm int_s390_vceq : SystemZCompareBHFG<"vceq">; + defm int_s390_vch : SystemZCompareBHFG<"vch">; + defm int_s390_vchl : SystemZCompareBHFG<"vchl">; + + defm int_s390_vfae : SystemZTernaryIntBHF<"vfae">; + defm int_s390_vfae : SystemZTernaryIntCCBHF; + defm int_s390_vfaez : SystemZTernaryIntBHF<"vfaez">; + defm int_s390_vfaez : SystemZTernaryIntCCBHF; + + defm int_s390_vfee : SystemZBinaryBHF<"vfee">; + defm int_s390_vfee : SystemZBinaryCCBHF; + defm int_s390_vfeez : SystemZBinaryBHF<"vfeez">; + defm int_s390_vfeez : SystemZBinaryCCBHF; + + defm int_s390_vfene : SystemZBinaryBHF<"vfene">; + defm int_s390_vfene : SystemZBinaryCCBHF; + defm int_s390_vfenez : SystemZBinaryBHF<"vfenez">; + defm int_s390_vfenez : SystemZBinaryCCBHF; + + defm int_s390_vistr : SystemZUnaryBHF<"vistr">; + defm int_s390_vistr : SystemZUnaryCCBHF; + + defm int_s390_vstrc : SystemZQuaternaryIntBHF<"vstrc">; + defm int_s390_vstrc : SystemZQuaternaryIntCCBHF; + defm int_s390_vstrcz : SystemZQuaternaryIntBHF<"vstrcz">; + defm int_s390_vstrcz : SystemZQuaternaryIntCCBHF; + + def int_s390_vfcedbs : SystemZBinaryConvCC<llvm_v2i64_ty, llvm_v2f64_ty>; + def int_s390_vfchdbs : SystemZBinaryConvCC<llvm_v2i64_ty, llvm_v2f64_ty>; + def int_s390_vfchedbs : SystemZBinaryConvCC<llvm_v2i64_ty, llvm_v2f64_ty>; + + def int_s390_vftcidb : SystemZBinaryConvIntCC<llvm_v2i64_ty, llvm_v2f64_ty>; + + def int_s390_vfidb : Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +} diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 81c729065505..3a8a4a643a43 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -18,6 +18,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //===----------------------------------------------------------------------===// +// SEH LSDA for Windows +let TargetPrefix = "x86" in { + def int_x86_seh_lsda : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// // Read Time Stamp Counter. let TargetPrefix = "x86" in { def int_x86_rdtsc : GCCBuiltin<"__builtin_ia32_rdtsc">, @@ -453,19 +459,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; - - def int_x86_sse2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi128_byteshift">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi128_byteshift">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; } // Conversion ops @@ -895,15 +888,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty], [IntrNoMem]>; @@ -1169,12 +1153,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector blend let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; @@ -1200,32 +1178,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; } -// Vector extract and insert -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_vextractf128_pd_256 : - GCCBuiltin<"__builtin_ia32_vextractf128_pd256">, - Intrinsic<[llvm_v2f64_ty], [llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vextractf128_ps_256 : - GCCBuiltin<"__builtin_ia32_vextractf128_ps256">, - Intrinsic<[llvm_v4f32_ty], [llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vextractf128_si_256 : - GCCBuiltin<"__builtin_ia32_vextractf128_si256">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx_vinsertf128_pd_256 : - GCCBuiltin<"__builtin_ia32_vinsertf128_pd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vinsertf128_ps_256 : - GCCBuiltin<"__builtin_ia32_vinsertf128_ps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vinsertf128_si_256 : - GCCBuiltin<"__builtin_ia32_vinsertf128_si256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; -} - // Vector convert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_cvtdq2_pd_256 : GCCBuiltin<"__builtin_ia32_cvtdq2pd256">, @@ -1363,6 +1315,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_mask_loadu_pd_512 : GCCBuiltin<"__builtin_ia32_loadupd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_load_ps_512 : GCCBuiltin<"__builtin_ia32_loadaps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadArgMem]>; + def int_x86_avx512_mask_load_pd_512 : GCCBuiltin<"__builtin_ia32_loadapd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadArgMem]>; } // Conditional store ops @@ -1389,6 +1347,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_storeupd512_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_ps_512 : + GCCBuiltin<"__builtin_ia32_storeaps512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_pd_512 : + GCCBuiltin<"__builtin_ia32_storeapd512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; def int_x86_avx512_mask_store_ss : GCCBuiltin<"__builtin_ia32_storess_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty], @@ -1448,12 +1414,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw256">, Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem, Commutative]>; - def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Vector min, max @@ -1572,19 +1532,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi256_byteshift">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; @@ -1746,15 +1693,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb256">, Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx2_pblendw : GCCBuiltin<"__builtin_ia32_pblendw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx2_pblendd_128 : GCCBuiltin<"__builtin_ia32_pblendd128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx2_pblendd_256 : GCCBuiltin<"__builtin_ia32_pblendd256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_i8_ty], [IntrNoMem]>; } // Vector load with broadcast @@ -1768,8 +1706,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_vbroadcast_ss_ps_256 : GCCBuiltin<"__builtin_ia32_vbroadcastss_ps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_avx2_vbroadcasti128 : - Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_x86_avx2_pbroadcastb_128 : GCCBuiltin<"__builtin_ia32_pbroadcastb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; @@ -1823,13 +1759,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector extract and insert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_vextracti128 : GCCBuiltin<"__builtin_ia32_extract128i256">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx2_vinserti128 : GCCBuiltin<"__builtin_ia32_insert128i256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextractf32x4_512 : GCCBuiltin<"__builtin_ia32_extractf32x4_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v16f32_ty, llvm_i8_ty, @@ -3068,6 +2997,46 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_i64_ty], [IntrNoMem]>; } +// Pack ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mask_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packsswb_256 : GCCBuiltin<"__builtin_ia32_packsswb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packsswb_512 : GCCBuiltin<"__builtin_ia32_packsswb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packssdw_256 : GCCBuiltin<"__builtin_ia32_packssdw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packssdw_512 : GCCBuiltin<"__builtin_ia32_packssdw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packuswb_256 : GCCBuiltin<"__builtin_ia32_packuswb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packuswb_512 : GCCBuiltin<"__builtin_ia32_packuswb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packusdw_128 : GCCBuiltin<"__builtin_ia32_packusdw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packusdw_256 : GCCBuiltin<"__builtin_ia32_packusdw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packusdw_512 : GCCBuiltin<"__builtin_ia32_packusdw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; +} + // Vector convert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_mask_cvttps2dq_512: GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">, @@ -3164,28 +3133,238 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; } - +//Bitwise Ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mask_pand_d_128 : GCCBuiltin<"__builtin_ia32_pandd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_d_256 : GCCBuiltin<"__builtin_ia32_pandd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_128 : GCCBuiltin<"__builtin_ia32_pandq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_256 : GCCBuiltin<"__builtin_ia32_pandq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_d_128 : GCCBuiltin<"__builtin_ia32_pandnd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_d_256 : GCCBuiltin<"__builtin_ia32_pandnd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_d_512 : GCCBuiltin<"__builtin_ia32_pandnd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_q_128 : GCCBuiltin<"__builtin_ia32_pandnq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_q_256 : GCCBuiltin<"__builtin_ia32_pandnq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_q_512 : GCCBuiltin<"__builtin_ia32_pandnq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_d_128 : GCCBuiltin<"__builtin_ia32_pord128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_d_256 : GCCBuiltin<"__builtin_ia32_pord256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_d_512 : GCCBuiltin<"__builtin_ia32_pord512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_q_128 : GCCBuiltin<"__builtin_ia32_porq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_q_256 : GCCBuiltin<"__builtin_ia32_porq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_q_512 : GCCBuiltin<"__builtin_ia32_porq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_d_128 : GCCBuiltin<"__builtin_ia32_pxord128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_d_256 : GCCBuiltin<"__builtin_ia32_pxord256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_d_512 : GCCBuiltin<"__builtin_ia32_pxord512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_q_128 : GCCBuiltin<"__builtin_ia32_pxorq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_q_256 : GCCBuiltin<"__builtin_ia32_pxorq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_q_512 : GCCBuiltin<"__builtin_ia32_pxorq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; +} // Arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + + def int_x86_avx512_mask_add_ps_128 : GCCBuiltin<"__builtin_ia32_addps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_ps_256 : GCCBuiltin<"__builtin_ia32_addps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_128 : GCCBuiltin<"__builtin_ia32_addpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_256 : GCCBuiltin<"__builtin_ia32_addpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_128 : GCCBuiltin<"__builtin_ia32_subps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_256 : GCCBuiltin<"__builtin_ia32_subps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_128 : GCCBuiltin<"__builtin_ia32_subpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_256 : GCCBuiltin<"__builtin_ia32_subpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_128 : GCCBuiltin<"__builtin_ia32_mulps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_256 : GCCBuiltin<"__builtin_ia32_mulps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_128 : GCCBuiltin<"__builtin_ia32_mulpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_256 : GCCBuiltin<"__builtin_ia32_mulpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_128 : GCCBuiltin<"__builtin_ia32_divps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_256 : GCCBuiltin<"__builtin_ia32_divps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_128 : GCCBuiltin<"__builtin_ia32_divpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_256 : GCCBuiltin<"__builtin_ia32_divpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_ps_128 : GCCBuiltin<"__builtin_ia32_maxps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_ps_256 : GCCBuiltin<"__builtin_ia32_maxps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_pd_128 : GCCBuiltin<"__builtin_ia32_maxpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_pd_256 : GCCBuiltin<"__builtin_ia32_maxpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_ps_128 : GCCBuiltin<"__builtin_ia32_minps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_ps_256 : GCCBuiltin<"__builtin_ia32_minps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_pd_128 : GCCBuiltin<"__builtin_ia32_minpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_pd_256 : GCCBuiltin<"__builtin_ia32_minpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_ss_round : GCCBuiltin<"__builtin_ia32_addss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ss_round : GCCBuiltin<"__builtin_ia32_divss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ss_round : GCCBuiltin<"__builtin_ia32_mulss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ss_round : GCCBuiltin<"__builtin_ia32_subss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_ss_round : GCCBuiltin<"__builtin_ia32_maxss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_ss_round : GCCBuiltin<"__builtin_ia32_minss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_sd_round : GCCBuiltin<"__builtin_ia32_addsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_sd_round : GCCBuiltin<"__builtin_ia32_divsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_sd_round : GCCBuiltin<"__builtin_ia32_mulsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_sd_round : GCCBuiltin<"__builtin_ia32_subsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_sd_round : GCCBuiltin<"__builtin_ia32_maxsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_sd_round : GCCBuiltin<"__builtin_ia32_minsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_avx512_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtrndss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; @@ -3265,21 +3444,273 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; } - -// Integer shift ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi512_byteshift">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi512_byteshift">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; +// FP logical ops +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_and_pd_128 : GCCBuiltin<"__builtin_ia32_andpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_pd_256 : GCCBuiltin<"__builtin_ia32_andpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_pd_512 : GCCBuiltin<"__builtin_ia32_andpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_ps_128 : GCCBuiltin<"__builtin_ia32_andps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_ps_256 : GCCBuiltin<"__builtin_ia32_andps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_ps_512 : GCCBuiltin<"__builtin_ia32_andps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_pd_128 : GCCBuiltin<"__builtin_ia32_andnpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_pd_256 : GCCBuiltin<"__builtin_ia32_andnpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_pd_512 : GCCBuiltin<"__builtin_ia32_andnpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_ps_128 : GCCBuiltin<"__builtin_ia32_andnps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_ps_256 : GCCBuiltin<"__builtin_ia32_andnps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_ps_512 : GCCBuiltin<"__builtin_ia32_andnps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_pd_128 : GCCBuiltin<"__builtin_ia32_orpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_pd_256 : GCCBuiltin<"__builtin_ia32_orpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_pd_512 : GCCBuiltin<"__builtin_ia32_orpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_ps_128 : GCCBuiltin<"__builtin_ia32_orps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_ps_256 : GCCBuiltin<"__builtin_ia32_orps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_ps_512 : GCCBuiltin<"__builtin_ia32_orps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_xor_pd_128 : GCCBuiltin<"__builtin_ia32_xorpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_pd_256 : GCCBuiltin<"__builtin_ia32_xorpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_pd_512 : GCCBuiltin<"__builtin_ia32_xorpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_ps_128 : GCCBuiltin<"__builtin_ia32_xorps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_ps_256 : GCCBuiltin<"__builtin_ia32_xorps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_ps_512 : GCCBuiltin<"__builtin_ia32_xorps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; +} +// Integer arithmetic ops +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_padd_b_128 : GCCBuiltin<"__builtin_ia32_paddb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_b_256 : GCCBuiltin<"__builtin_ia32_paddb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_b_512 : GCCBuiltin<"__builtin_ia32_paddb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_w_128 : GCCBuiltin<"__builtin_ia32_paddw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_w_256 : GCCBuiltin<"__builtin_ia32_paddw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_w_512 : GCCBuiltin<"__builtin_ia32_paddw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_b_128 : GCCBuiltin<"__builtin_ia32_paddsb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_b_256 : GCCBuiltin<"__builtin_ia32_paddsb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_b_512 : GCCBuiltin<"__builtin_ia32_paddsb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_w_128 : GCCBuiltin<"__builtin_ia32_paddsw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_w_256 : GCCBuiltin<"__builtin_ia32_paddsw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_w_512 : GCCBuiltin<"__builtin_ia32_paddsw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_b_128 : GCCBuiltin<"__builtin_ia32_paddusb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_b_256 : GCCBuiltin<"__builtin_ia32_paddusb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_b_512 : GCCBuiltin<"__builtin_ia32_paddusb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_w_128 : GCCBuiltin<"__builtin_ia32_paddusw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_w_256 : GCCBuiltin<"__builtin_ia32_paddusw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_w_512 : GCCBuiltin<"__builtin_ia32_paddusw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_d_128 : GCCBuiltin<"__builtin_ia32_paddd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_d_256 : GCCBuiltin<"__builtin_ia32_paddd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_d_512 : GCCBuiltin<"__builtin_ia32_paddd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_q_128 : GCCBuiltin<"__builtin_ia32_paddq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_q_256 : GCCBuiltin<"__builtin_ia32_paddq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_q_512 : GCCBuiltin<"__builtin_ia32_paddq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_b_128 : GCCBuiltin<"__builtin_ia32_psubb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_b_256 : GCCBuiltin<"__builtin_ia32_psubb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_b_512 : GCCBuiltin<"__builtin_ia32_psubb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_w_128 : GCCBuiltin<"__builtin_ia32_psubw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_w_256 : GCCBuiltin<"__builtin_ia32_psubw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_w_512 : GCCBuiltin<"__builtin_ia32_psubw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_b_128 : GCCBuiltin<"__builtin_ia32_psubsb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_b_256 : GCCBuiltin<"__builtin_ia32_psubsb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_b_512 : GCCBuiltin<"__builtin_ia32_psubsb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_w_128 : GCCBuiltin<"__builtin_ia32_psubsw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_w_256 : GCCBuiltin<"__builtin_ia32_psubsw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_w_512 : GCCBuiltin<"__builtin_ia32_psubsw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_b_128 : GCCBuiltin<"__builtin_ia32_psubusb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_b_256 : GCCBuiltin<"__builtin_ia32_psubusb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_b_512 : GCCBuiltin<"__builtin_ia32_psubusb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_w_128 : GCCBuiltin<"__builtin_ia32_psubusw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_w_256 : GCCBuiltin<"__builtin_ia32_psubusw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_w_512 : GCCBuiltin<"__builtin_ia32_psubusw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_d_128 : GCCBuiltin<"__builtin_ia32_psubd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_d_256 : GCCBuiltin<"__builtin_ia32_psubd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_d_512 : GCCBuiltin<"__builtin_ia32_psubd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_q_128 : GCCBuiltin<"__builtin_ia32_psubq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_q_256 : GCCBuiltin<"__builtin_ia32_psubq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_q_512 : GCCBuiltin<"__builtin_ia32_psubq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulu_dq_128 : GCCBuiltin<"__builtin_ia32_pmuludq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_128 : GCCBuiltin<"__builtin_ia32_pmuldq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulu_dq_256 : GCCBuiltin<"__builtin_ia32_pmuludq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_256 : GCCBuiltin<"__builtin_ia32_pmuldq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_w_128 : GCCBuiltin<"__builtin_ia32_pmullw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_w_256 : GCCBuiltin<"__builtin_ia32_pmullw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_w_512 : GCCBuiltin<"__builtin_ia32_pmullw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_d_128 : GCCBuiltin<"__builtin_ia32_pmulld128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_d_256 : GCCBuiltin<"__builtin_ia32_pmulld256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_d_512 : GCCBuiltin<"__builtin_ia32_pmulld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_q_128 : GCCBuiltin<"__builtin_ia32_pmullq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_q_256 : GCCBuiltin<"__builtin_ia32_pmullq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_q_512 : GCCBuiltin<"__builtin_ia32_pmullq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Gather and Scatter ops @@ -3390,22 +3821,22 @@ let TargetPrefix = "x86" in { GCCBuiltin<"__builtin_ia32_vpconflictsi_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_conflict_q_512 : GCCBuiltin<"__builtin_ia32_vpconflictdi_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_lzcnt_d_512 : GCCBuiltin<"__builtin_ia32_vplzcntd_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_lzcnt_q_512 : GCCBuiltin<"__builtin_ia32_vplzcntq_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - []>; + [IntrNoMem]>; } // Vector blend @@ -3867,21 +4298,33 @@ let TargetPrefix = "x86" in { } // Misc. let TargetPrefix = "x86" in { - def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, + def int_x86_avx512_mask_cmp_ps_512 : + GCCBuiltin<"__builtin_ia32_cmpps512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_pd_512 : + GCCBuiltin<"__builtin_ia32_cmppd512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_ps_256 : + GCCBuiltin<"__builtin_ia32_cmpps256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_pd_256 : + GCCBuiltin<"__builtin_ia32_cmppd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_ps_128 : + GCCBuiltin<"__builtin_ia32_cmpps128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_pd_128 : + GCCBuiltin<"__builtin_ia32_cmppd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_movntdqa : + GCCBuiltin<"__builtin_ia32_movntdqa512">, Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 2f18782a0730..e6c22090ab6d 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -58,7 +58,9 @@ public: MD_noalias = 8, // "noalias", MD_nontemporal = 9, // "nontemporal" MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access" - MD_nonnull = 11 // "nonnull" + MD_nonnull = 11, // "nonnull" + MD_dereferenceable = 12, // "dereferenceable" + MD_dereferenceable_or_null = 13 // "dereferenceable_or_null" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. @@ -176,8 +178,8 @@ public: } private: - LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; - void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; + LLVMContext(LLVMContext&) = delete; + void operator=(LLVMContext&) = delete; /// addModule - Register a module as being instantiated in this context. If /// the context is deleted, the module will be deleted as well. diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index 6c04e9dc3d3f..5257a0eed488 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -50,7 +50,7 @@ class PassManager : public PassManagerBase { public: PassManager(); - ~PassManager(); + ~PassManager() override; void add(Pass *P) override; @@ -70,7 +70,7 @@ public: /// FunctionPassManager ctor - This initializes the pass manager. It needs, /// but does not take ownership of, the specified Module. explicit FunctionPassManager(Module *M); - ~FunctionPassManager(); + ~FunctionPassManager() override; void add(Pass *P) override; diff --git a/include/llvm/IR/LegacyPassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h index e2e4912ef64e..39ae80d797c7 100644 --- a/include/llvm/IR/LegacyPassNameParser.h +++ b/include/llvm/IR/LegacyPassNameParser.h @@ -41,14 +41,12 @@ namespace llvm { // class PassNameParser : public PassRegistrationListener, public cl::parser<const PassInfo*> { - cl::Option *Opt; public: - PassNameParser(); - virtual ~PassNameParser(); + PassNameParser(cl::Option &O); + ~PassNameParser() override; - void initialize(cl::Option &O) { - Opt = &O; - cl::parser<const PassInfo*>::initialize(O); + void initialize() { + cl::parser<const PassInfo*>::initialize(); // Add all of the passes to the map that got initialized before 'this' did. enumeratePasses(); @@ -69,7 +67,7 @@ public: // Implement the PassRegistrationListener callbacks used to populate our map // void passRegistered(const PassInfo *P) override { - if (ignorablePass(P) || !Opt) return; + if (ignorablePass(P)) return; if (findOption(P->getPassArgument()) != getNumOptions()) { errs() << "Two passes with the same argument (-" << P->getPassArgument() << ") attempted to be registered!\n"; diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index 91a6685f6125..ba14457f7185 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -60,6 +60,9 @@ public: /// \brief Return metadata containing a number of branch weights. MDNode *createBranchWeights(ArrayRef<uint32_t> Weights); + /// Return metadata containing the entry count for a function. + MDNode *createFunctionEntryCount(uint64_t Count); + //===------------------------------------------------------------------===// // Range metadata. //===------------------------------------------------------------------===// @@ -67,6 +70,9 @@ public: /// \brief Return metadata describing the range [Lo, Hi). MDNode *createRange(const APInt &Lo, const APInt &Hi); + /// \brief Return metadata describing the range [Lo, Hi). + MDNode *createRange(Constant *Lo, Constant *Hi); + //===------------------------------------------------------------------===// // AA metadata. //===------------------------------------------------------------------===// diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def index 2098bb57eb56..f2abff4752f7 100644 --- a/include/llvm/IR/Metadata.def +++ b/include/llvm/IR/Metadata.def @@ -1,4 +1,4 @@ -//===- llvm/Metadata.def - Metadata definitions -----------------*- C++ -*-===// +//===- llvm/IR/Metadata.def - Metadata definitions --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,10 @@ //===----------------------------------------------------------------------===// #if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \ - defined HANDLE_METADATA_BRANCH || defined HANDLE_UNIQUABLE_LEAF || \ - defined HANDLE_UNIQUABLE_BRANCH) + defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF || \ + defined HANDLE_MDNODE_BRANCH || \ + defined HANDLE_SPECIALIZED_MDNODE_LEAF || \ + defined HANDLE_SPECIALIZED_MDNODE_BRANCH) #error "Missing macro definition of HANDLE_METADATA*" #endif @@ -32,28 +34,67 @@ #define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS) #endif -// Handler for leaf nodes under UniquableMDNode. -#ifndef HANDLE_UNIQUABLE_LEAF -#define HANDLE_UNIQUABLE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) +// Handler for leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_LEAF +#define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) #endif -// Handler for non-leaf nodes under UniquableMDNode. -#ifndef HANDLE_UNIQUABLE_BRANCH -#define HANDLE_UNIQUABLE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) +// Handler for non-leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_BRANCH +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) +#endif + +// Handler for specialized leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#endif + +// Handler for specialized non-leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_BRANCH +#define HANDLE_SPECIALIZED_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_BRANCH(CLASS) #endif HANDLE_METADATA_LEAF(MDString) HANDLE_METADATA_BRANCH(ValueAsMetadata) HANDLE_METADATA_LEAF(ConstantAsMetadata) HANDLE_METADATA_LEAF(LocalAsMetadata) -HANDLE_METADATA_BRANCH(MDNode) -HANDLE_METADATA_LEAF(MDNodeFwdDecl) -HANDLE_UNIQUABLE_BRANCH(UniquableMDNode) -HANDLE_UNIQUABLE_LEAF(MDTuple) -HANDLE_UNIQUABLE_LEAF(MDLocation) +HANDLE_MDNODE_BRANCH(MDNode) +HANDLE_MDNODE_LEAF(MDTuple) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILocation) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIExpression) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode) +HANDLE_SPECIALIZED_MDNODE_LEAF(GenericDINode) +HANDLE_SPECIALIZED_MDNODE_LEAF(DISubrange) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIEnumerator) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIScope) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIBasicType) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIDerivedTypeBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIDerivedType) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DICompositeTypeBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(DICompositeType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DISubroutineType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope) +HANDLE_SPECIALIZED_MDNODE_LEAF(DISubprogram) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILexicalBlock) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILexicalBlockFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(DINamespace) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DITemplateParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(DITemplateTypeParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(DITemplateValueParameter) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIGlobalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILocalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIObjCProperty) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIImportedEntity) #undef HANDLE_METADATA #undef HANDLE_METADATA_LEAF #undef HANDLE_METADATA_BRANCH -#undef HANDLE_UNIQUABLE_LEAF -#undef HANDLE_UNIQUABLE_BRANCH +#undef HANDLE_MDNODE_LEAF +#undef HANDLE_MDNODE_BRANCH +#undef HANDLE_SPECIALIZED_MDNODE_LEAF +#undef HANDLE_SPECIALIZED_MDNODE_BRANCH diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 27a5d6f80041..60718f531bd7 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -1,4 +1,4 @@ -//===-- llvm/Metadata.h - Metadata definitions ------------------*- C++ -*-===// +//===- llvm/IR/Metadata.h - Metadata definitions ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -32,9 +32,8 @@ class Module; template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; - enum LLVMConstants : uint32_t { - DEBUG_METADATA_VERSION = 2 // Current debug info version number. + DEBUG_METADATA_VERSION = 3 // Current debug info version number. }; /// \brief Root of the metadata hierarchy. @@ -47,8 +46,11 @@ class Metadata { const unsigned char SubclassID; protected: + /// \brief Active type of storage. + enum StorageType { Uniqued, Distinct, Temporary }; + /// \brief Storage flag for non-uniqued, otherwise unowned, metadata. - bool IsDistinctInContext : 1; + unsigned Storage : 2; // TODO: expose remaining bits to subclasses. unsigned short SubclassData16; @@ -57,21 +59,37 @@ protected: public: enum MetadataKind { MDTupleKind, - MDLocationKind, - MDNodeFwdDeclKind, + DILocationKind, + GenericDINodeKind, + DISubrangeKind, + DIEnumeratorKind, + DIBasicTypeKind, + DIDerivedTypeKind, + DICompositeTypeKind, + DISubroutineTypeKind, + DIFileKind, + DICompileUnitKind, + DISubprogramKind, + DILexicalBlockKind, + DILexicalBlockFileKind, + DINamespaceKind, + DITemplateTypeParameterKind, + DITemplateValueParameterKind, + DIGlobalVariableKind, + DILocalVariableKind, + DIExpressionKind, + DIObjCPropertyKind, + DIImportedEntityKind, ConstantAsMetadataKind, LocalAsMetadataKind, MDStringKind }; protected: - Metadata(unsigned ID) - : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0), - SubclassData32(0) {} - ~Metadata() {} - - /// \brief Store this in a big non-uniqued untyped bucket. - bool isStoredDistinctInContext() const { return IsDistinctInContext; } + Metadata(unsigned ID, StorageType Storage) + : SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) { + } + ~Metadata() = default; /// \brief Default handling of a changed operand, which asserts. /// @@ -85,15 +103,48 @@ public: unsigned getMetadataID() const { return SubclassID; } /// \brief User-friendly dump. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + /// + /// Note: this uses an explicit overload instead of default arguments so that + /// the nullptr version is easy to call from a debugger. + /// + /// @{ void dump() const; - void print(raw_ostream &OS) const; - void printAsOperand(raw_ostream &OS, bool PrintType = true, - const Module *M = nullptr) const; + void dump(const Module *M) const; + /// @} + + /// \brief Print. + /// + /// Prints definition of \c this. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + void print(raw_ostream &OS, const Module *M = nullptr) const; + + /// \brief Print as operand. + /// + /// Prints reference of \c this. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + void printAsOperand(raw_ostream &OS, const Module *M = nullptr) const; }; #define HANDLE_METADATA(CLASS) class CLASS; #include "llvm/IR/Metadata.def" +// Provide specializations of isa so that we don't need definitions of +// subclasses to see if the metadata is a subclass. +#define HANDLE_METADATA_LEAF(CLASS) \ + template <> struct isa_impl<CLASS, Metadata> { \ + static inline bool doit(const Metadata &MD) { \ + return MD.getMetadataID() == Metadata::CLASS##Kind; \ + } \ + }; +#include "llvm/IR/Metadata.def" + inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { MD.print(OS); return OS; @@ -113,7 +164,7 @@ class MetadataAsValue : public Value { Metadata *MD; MetadataAsValue(Type *Ty, Metadata *MD); - ~MetadataAsValue(); + ~MetadataAsValue() override; /// \brief Drop use of metadata (during teardown). void dropUse() { MD = nullptr; } @@ -145,15 +196,19 @@ public: typedef MetadataTracking::OwnerTy OwnerTy; private: + LLVMContext &Context; uint64_t NextIndex; SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap; public: - ReplaceableMetadataImpl() : NextIndex(0) {} + ReplaceableMetadataImpl(LLVMContext &Context) + : Context(Context), NextIndex(0) {} ~ReplaceableMetadataImpl() { assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata"); } + LLVMContext &getContext() const { return Context; } + /// \brief Replace all uses of this with MD. /// /// Replace all uses of this with \c MD, which is allowed to be null. @@ -162,8 +217,8 @@ public: /// \brief Resolve all uses of this. /// /// Resolve all uses of this, turning off RAUW permanently. If \c - /// ResolveUsers, call \a UniquableMDNode::resolve() on any users whose last - /// operand is resolved. + /// ResolveUsers, call \a MDNode::resolve() on any users whose last operand + /// is resolved. void resolveAllUses(bool ResolveUsers = true); private: @@ -195,10 +250,10 @@ class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl { protected: ValueAsMetadata(unsigned ID, Value *V) - : Metadata(ID), V(V) { + : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) { assert(V && "Expected valid value"); } - ~ValueAsMetadata() {} + ~ValueAsMetadata() = default; public: static ValueAsMetadata *get(Value *V); @@ -441,13 +496,13 @@ dyn_extract_or_null(Y &&MD) { class MDString : public Metadata { friend class StringMapEntry<MDString>; - MDString(const MDString &) LLVM_DELETED_FUNCTION; - MDString &operator=(MDString &&) LLVM_DELETED_FUNCTION; - MDString &operator=(const MDString &) LLVM_DELETED_FUNCTION; + MDString(const MDString &) = delete; + MDString &operator=(MDString &&) = delete; + MDString &operator=(const MDString &) = delete; StringMapEntry<MDString> *Entry; - MDString() : Metadata(MDStringKind), Entry(nullptr) {} - MDString(MDString &&) : Metadata(MDStringKind) {} + MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {} + MDString(MDString &&) : Metadata(MDStringKind, Uniqued) {} public: static MDString *get(LLVMContext &Context, StringRef Str); @@ -489,7 +544,7 @@ struct AAMDNodes { bool operator!=(const AAMDNodes &A) const { return !(*this == A); } - LLVM_EXPLICIT operator bool() const { return TBAA || Scope || NoAlias; } + explicit operator bool() const { return TBAA || Scope || NoAlias; } /// \brief The tag for type-based alias analysis. MDNode *TBAA; @@ -528,10 +583,10 @@ struct DenseMapInfo<AAMDNodes> { /// /// In particular, this is used by \a MDNode. class MDOperand { - MDOperand(MDOperand &&) LLVM_DELETED_FUNCTION; - MDOperand(const MDOperand &) LLVM_DELETED_FUNCTION; - MDOperand &operator=(MDOperand &&) LLVM_DELETED_FUNCTION; - MDOperand &operator=(const MDOperand &) LLVM_DELETED_FUNCTION; + MDOperand(MDOperand &&) = delete; + MDOperand(const MDOperand &) = delete; + MDOperand &operator=(MDOperand &&) = delete; + MDOperand &operator=(const MDOperand &) = delete; Metadata *MD; @@ -580,18 +635,109 @@ template <> struct simplify_type<const MDOperand> { static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); } }; -//===----------------------------------------------------------------------===// -/// \brief Tuple of metadata. +/// \brief Pointer to the context, with optional RAUW support. +/// +/// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer +/// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext). +class ContextAndReplaceableUses { + PointerUnion<LLVMContext *, ReplaceableMetadataImpl *> Ptr; + + ContextAndReplaceableUses() = delete; + ContextAndReplaceableUses(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses(const ContextAndReplaceableUses &) = delete; + ContextAndReplaceableUses &operator=(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses & + operator=(const ContextAndReplaceableUses &) = delete; + +public: + ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {} + ContextAndReplaceableUses( + std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses) + : Ptr(ReplaceableUses.release()) { + assert(getReplaceableUses() && "Expected non-null replaceable uses"); + } + ~ContextAndReplaceableUses() { delete getReplaceableUses(); } + + operator LLVMContext &() { return getContext(); } + + /// \brief Whether this contains RAUW support. + bool hasReplaceableUses() const { + return Ptr.is<ReplaceableMetadataImpl *>(); + } + LLVMContext &getContext() const { + if (hasReplaceableUses()) + return getReplaceableUses()->getContext(); + return *Ptr.get<LLVMContext *>(); + } + ReplaceableMetadataImpl *getReplaceableUses() const { + if (hasReplaceableUses()) + return Ptr.get<ReplaceableMetadataImpl *>(); + return nullptr; + } + + /// \brief Assign RAUW support to this. + /// + /// Make this replaceable, taking ownership of \c ReplaceableUses (which must + /// not be null). + void + makeReplaceable(std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses) { + assert(ReplaceableUses && "Expected non-null replaceable uses"); + assert(&ReplaceableUses->getContext() == &getContext() && + "Expected same context"); + delete getReplaceableUses(); + Ptr = ReplaceableUses.release(); + } + + /// \brief Drop RAUW support. + /// + /// Cede ownership of RAUW support, returning it. + std::unique_ptr<ReplaceableMetadataImpl> takeReplaceableUses() { + assert(hasReplaceableUses() && "Expected to own replaceable uses"); + std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses( + getReplaceableUses()); + Ptr = &ReplaceableUses->getContext(); + return ReplaceableUses; + } +}; + +struct TempMDNodeDeleter { + inline void operator()(MDNode *Node) const; +}; + +#define HANDLE_MDNODE_LEAF(CLASS) \ + typedef std::unique_ptr<CLASS, TempMDNodeDeleter> Temp##CLASS; +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#include "llvm/IR/Metadata.def" + +/// \brief Metadata node. +/// +/// Metadata nodes can be uniqued, like constants, or distinct. Temporary +/// metadata nodes (with full support for RAUW) can be used to delay uniquing +/// until forward references are known. The basic metadata node is an \a +/// MDTuple. +/// +/// There is limited support for RAUW at construction time. At construction +/// time, if any operand is a temporary node (or an unresolved uniqued node, +/// which indicates a transitive temporary operand), the node itself will be +/// unresolved. As soon as all operands become resolved, it will drop RAUW +/// support permanently. +/// +/// If an unresolved node is part of a cycle, \a resolveCycles() needs +/// to be called on some member of the cycle once all temporary nodes have been +/// replaced. class MDNode : public Metadata { - MDNode(const MDNode &) LLVM_DELETED_FUNCTION; - void operator=(const MDNode &) LLVM_DELETED_FUNCTION; - void *operator new(size_t) LLVM_DELETED_FUNCTION; + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + MDNode(const MDNode &) = delete; + void operator=(const MDNode &) = delete; + void *operator new(size_t) = delete; - LLVMContext &Context; unsigned NumOperands; + unsigned NumUnresolved; protected: - unsigned MDNodeSubclassData; + ContextAndReplaceableUses Context; void *operator new(size_t Size, unsigned NumOps); void operator delete(void *Mem); @@ -606,56 +752,163 @@ protected: llvm_unreachable("Constructor throws?"); } - MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs); - ~MDNode() {} + MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, + ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None); + ~MDNode() = default; void dropAllReferences(); MDOperand *mutable_begin() { return mutable_end() - NumOperands; } MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); } -public: - static inline MDNode *get(LLVMContext &Context, ArrayRef<Metadata *> MDs); - static inline MDNode *getIfExists(LLVMContext &Context, - ArrayRef<Metadata *> MDs); - static inline MDNode *getDistinct(LLVMContext &Context, - ArrayRef<Metadata *> MDs); + typedef iterator_range<MDOperand *> mutable_op_range; + mutable_op_range mutable_operands() { + return mutable_op_range(mutable_begin(), mutable_end()); + } - /// \brief Return a temporary MDNode - /// - /// For use in constructing cyclic MDNode structures. A temporary MDNode is - /// not uniqued, may be RAUW'd, and must be manually deleted with - /// deleteTemporary. - static MDNodeFwdDecl *getTemporary(LLVMContext &Context, +public: + static inline MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs); + static inline MDTuple *getIfExists(LLVMContext &Context, + ArrayRef<Metadata *> MDs); + static inline MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs); + static inline TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef<Metadata *> MDs); + + /// \brief Create a (temporary) clone of this. + TempMDNode clone() const; /// \brief Deallocate a node created by getTemporary. /// - /// The node must not have any users. + /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining + /// references will be reset. static void deleteTemporary(MDNode *N); - LLVMContext &getContext() const { return Context; } + LLVMContext &getContext() const { return Context.getContext(); } /// \brief Replace a specific operand. void replaceOperandWith(unsigned I, Metadata *New); /// \brief Check if node is fully resolved. - bool isResolved() const; + /// + /// If \a isTemporary(), this always returns \c false; if \a isDistinct(), + /// this always returns \c true. + /// + /// If \a isUniqued(), returns \c true if this has already dropped RAUW + /// support (because all operands are resolved). + /// + /// As forward declarations are resolved, their containers should get + /// resolved automatically. However, if this (or one of its operands) is + /// involved in a cycle, \a resolveCycles() needs to be called explicitly. + bool isResolved() const { return !Context.hasReplaceableUses(); } + + bool isUniqued() const { return Storage == Uniqued; } + bool isDistinct() const { return Storage == Distinct; } + bool isTemporary() const { return Storage == Temporary; } - /// \brief Check if node is distinct. + /// \brief RAUW a temporary. /// - /// Distinct nodes are not uniqued, and will not be returned by \a - /// MDNode::get(). - bool isDistinct() const { - return isStoredDistinctInContext() || isa<MDNodeFwdDecl>(this); + /// \pre \a isTemporary() must be \c true. + void replaceAllUsesWith(Metadata *MD) { + assert(isTemporary() && "Expected temporary node"); + assert(!isResolved() && "Expected RAUW support"); + Context.getReplaceableUses()->replaceAllUsesWith(MD); } + /// \brief Resolve cycles. + /// + /// Once all forward declarations have been resolved, force cycles to be + /// resolved. + /// + /// \pre No operands (or operands' operands, etc.) have \a isTemporary(). + void resolveCycles(); + + /// \brief Replace a temporary node with a permanent one. + /// + /// Try to create a uniqued version of \c N -- in place, if possible -- and + /// return it. If \c N cannot be uniqued, return a distinct node instead. + template <class T> + static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type + replaceWithPermanent(std::unique_ptr<T, TempMDNodeDeleter> N) { + return cast<T>(N.release()->replaceWithPermanentImpl()); + } + + /// \brief Replace a temporary node with a uniqued one. + /// + /// Create a uniqued version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + /// + /// \pre N does not self-reference. + template <class T> + static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type + replaceWithUniqued(std::unique_ptr<T, TempMDNodeDeleter> N) { + return cast<T>(N.release()->replaceWithUniquedImpl()); + } + + /// \brief Replace a temporary node with a distinct one. + /// + /// Create a distinct version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + template <class T> + static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type + replaceWithDistinct(std::unique_ptr<T, TempMDNodeDeleter> N) { + return cast<T>(N.release()->replaceWithDistinctImpl()); + } + +private: + MDNode *replaceWithPermanentImpl(); + MDNode *replaceWithUniquedImpl(); + MDNode *replaceWithDistinctImpl(); + protected: /// \brief Set an operand. /// /// Sets the operand directly, without worrying about uniquing. void setOperand(unsigned I, Metadata *New); + void storeDistinctInContext(); + template <class T, class StoreT> + static T *storeImpl(T *N, StorageType Storage, StoreT &Store); + +private: + void handleChangedOperand(void *Ref, Metadata *New); + + void resolve(); + void resolveAfterOperandChange(Metadata *Old, Metadata *New); + void decrementUnresolvedOperandCount(); + unsigned countUnresolvedOperands(); + + /// \brief Mutate this to be "uniqued". + /// + /// Mutate this so that \a isUniqued(). + /// \pre \a isTemporary(). + /// \pre already added to uniquing set. + void makeUniqued(); + + /// \brief Mutate this to be "distinct". + /// + /// Mutate this so that \a isDistinct(). + /// \pre \a isTemporary(). + void makeDistinct(); + + void deleteAsSubclass(); + MDNode *uniquify(); + void eraseFromStore(); + + template <class NodeTy> struct HasCachedHash; + template <class NodeTy> + static void dispatchRecalculateHash(NodeTy *N, std::true_type) { + N->recalculateHash(); + } + template <class NodeTy> + static void dispatchRecalculateHash(NodeTy *N, std::false_type) {} + template <class NodeTy> + static void dispatchResetHash(NodeTy *N, std::true_type) { + N->setHash(0); + } + template <class NodeTy> + static void dispatchResetHash(NodeTy *N, std::false_type) {} + public: typedef const MDOperand *op_iterator; typedef iterator_range<op_iterator> op_range; @@ -678,9 +931,14 @@ public: /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDTupleKind || - MD->getMetadataID() == MDLocationKind || - MD->getMetadataID() == MDNodeFwdDeclKind; + switch (MD->getMetadataID()) { + default: + return false; +#define HANDLE_MDNODE_LEAF(CLASS) \ + case CLASS##Kind: \ + return true; +#include "llvm/IR/Metadata.def" + } } /// \brief Check whether MDNode is a vtable access. @@ -690,225 +948,163 @@ public: static MDNode *concatenate(MDNode *A, MDNode *B); static MDNode *intersect(MDNode *A, MDNode *B); static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); - static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); static MDNode *getMostGenericRange(MDNode *A, MDNode *B); static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B); }; -/// \brief Uniquable metadata node. -/// -/// A uniquable metadata node. This contains the basic functionality -/// for implementing sub-types of \a MDNode that can be uniqued like -/// constants. -/// -/// There is limited support for RAUW at construction time. At -/// construction time, if any operands are an instance of \a -/// MDNodeFwdDecl (or another unresolved \a UniquableMDNode, which -/// indicates an \a MDNodeFwdDecl in its path), the node itself will be -/// unresolved. As soon as all operands become resolved, it will drop -/// RAUW support permanently. -/// -/// If an unresolved node is part of a cycle, \a resolveCycles() needs -/// to be called on some member of the cycle when each \a MDNodeFwdDecl -/// has been removed. -class UniquableMDNode : public MDNode { - friend class ReplaceableMetadataImpl; - friend class MDNode; - friend class LLVMContextImpl; - - /// \brief Support RAUW as long as one of its arguments is replaceable. - /// - /// FIXME: Save memory by storing this in a pointer union with the - /// LLVMContext, and adding an LLVMContext reference to RMI. - std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses; - -protected: - /// \brief Create a new node. - /// - /// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW - /// will be dropped once all operands have been resolved (or if \a - /// resolveCycles() is called). - UniquableMDNode(LLVMContext &C, unsigned ID, ArrayRef<Metadata *> Vals, - bool AllowRAUW); - ~UniquableMDNode() {} - - void storeDistinctInContext(); - -public: - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDTupleKind || - MD->getMetadataID() == MDLocationKind; - } - - /// \brief Check whether any operands are forward declarations. - /// - /// Returns \c true as long as any operands (or their operands, etc.) are \a - /// MDNodeFwdDecl. - /// - /// As forward declarations are resolved, their containers should get - /// resolved automatically. However, if this (or one of its operands) is - /// involved in a cycle, \a resolveCycles() needs to be called explicitly. - bool isResolved() const { return !ReplaceableUses; } - - /// \brief Resolve cycles. - /// - /// Once all forward declarations have been resolved, force cycles to be - /// resolved. - /// - /// \pre No operands (or operands' operands, etc.) are \a MDNodeFwdDecl. - void resolveCycles(); - -private: - void handleChangedOperand(void *Ref, Metadata *New); - - void resolve(); - void resolveAfterOperandChange(Metadata *Old, Metadata *New); - void decrementUnresolvedOperandCount(); - - void deleteAsSubclass(); - UniquableMDNode *uniquify(); - void eraseFromStore(); -}; - /// \brief Tuple of metadata. /// /// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by /// default based on their operands. -class MDTuple : public UniquableMDNode { +class MDTuple : public MDNode { friend class LLVMContextImpl; - friend class UniquableMDNode; + friend class MDNode; - MDTuple(LLVMContext &C, ArrayRef<Metadata *> Vals, bool AllowRAUW) - : UniquableMDNode(C, MDTupleKind, Vals, AllowRAUW) {} + MDTuple(LLVMContext &C, StorageType Storage, unsigned Hash, + ArrayRef<Metadata *> Vals) + : MDNode(C, MDTupleKind, Storage, Vals) { + setHash(Hash); + } ~MDTuple() { dropAllReferences(); } - void setHash(unsigned Hash) { MDNodeSubclassData = Hash; } + void setHash(unsigned Hash) { SubclassData32 = Hash; } void recalculateHash(); static MDTuple *getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs, - bool ShouldCreate); + StorageType Storage, bool ShouldCreate = true); + + TempMDTuple cloneImpl() const { + return getTemporary(getContext(), + SmallVector<Metadata *, 4>(op_begin(), op_end())); + } public: /// \brief Get the hash, if any. - unsigned getHash() const { return MDNodeSubclassData; } + unsigned getHash() const { return SubclassData32; } static MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { - return getImpl(Context, MDs, /* ShouldCreate */ true); + return getImpl(Context, MDs, Uniqued); } static MDTuple *getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) { - return getImpl(Context, MDs, /* ShouldCreate */ false); + return getImpl(Context, MDs, Uniqued, /* ShouldCreate */ false); } /// \brief Return a distinct node. /// /// Return a distinct node -- i.e., a node that is not uniqued. - static MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs); + static MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return getImpl(Context, MDs, Distinct); + } + + /// \brief Return a temporary node. + /// + /// For use in constructing cyclic MDNode structures. A temporary MDNode is + /// not uniqued, may be RAUW'd, and must be manually deleted with + /// deleteTemporary. + static TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef<Metadata *> MDs) { + return TempMDTuple(getImpl(Context, MDs, Temporary)); + } + + /// \brief Return a (temporary) clone of this. + TempMDTuple clone() const { return cloneImpl(); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDTupleKind; } - -private: - MDTuple *uniquifyImpl(); - void eraseFromStoreImpl(); }; -MDNode *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { +MDTuple *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { return MDTuple::get(Context, MDs); } -MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) { +MDTuple *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) { return MDTuple::getIfExists(Context, MDs); } -MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { +MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { return MDTuple::getDistinct(Context, MDs); } +TempMDTuple MDNode::getTemporary(LLVMContext &Context, + ArrayRef<Metadata *> MDs) { + return MDTuple::getTemporary(Context, MDs); +} -/// \brief Debug location. -/// -/// A debug location in source code, used for debug info and otherwise. -class MDLocation : public UniquableMDNode { - friend class LLVMContextImpl; - friend class UniquableMDNode; - - MDLocation(LLVMContext &C, unsigned Line, unsigned Column, - ArrayRef<Metadata *> MDs, bool AllowRAUW); - ~MDLocation() { dropAllReferences(); } - - static MDLocation *constructHelper(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt, bool AllowRAUW); - - static MDLocation *getImpl(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt, bool ShouldCreate); +void TempMDNodeDeleter::operator()(MDNode *Node) const { + MDNode::deleteTemporary(Node); +} - // Disallow replacing operands. - void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION; +/// \brief Typed iterator through MDNode operands. +/// +/// An iterator that transforms an \a MDNode::iterator into an iterator over a +/// particular Metadata subclass. +template <class T> +class TypedMDOperandIterator + : std::iterator<std::input_iterator_tag, T *, std::ptrdiff_t, void, T *> { + MDNode::op_iterator I = nullptr; public: - static MDLocation *get(LLVMContext &Context, unsigned Line, unsigned Column, - Metadata *Scope, Metadata *InlinedAt = nullptr) { - return getImpl(Context, Line, Column, Scope, InlinedAt, - /* ShouldCreate */ true); - } - static MDLocation *getIfExists(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt = nullptr) { - return getImpl(Context, Line, Column, Scope, InlinedAt, - /* ShouldCreate */ false); - } - static MDLocation *getDistinct(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt = nullptr); - - unsigned getLine() const { return MDNodeSubclassData; } - unsigned getColumn() const { return SubclassData16; } - Metadata *getScope() const { return getOperand(0); } - Metadata *getInlinedAt() const { - if (getNumOperands() == 2) - return getOperand(1); - return nullptr; + TypedMDOperandIterator() = default; + explicit TypedMDOperandIterator(MDNode::op_iterator I) : I(I) {} + T *operator*() const { return cast_or_null<T>(*I); } + TypedMDOperandIterator &operator++() { + ++I; + return *this; } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDLocationKind; + TypedMDOperandIterator operator++(int) { + TypedMDOperandIterator Temp(*this); + ++I; + return Temp; } - -private: - MDLocation *uniquifyImpl(); - void eraseFromStoreImpl(); + bool operator==(const TypedMDOperandIterator &X) const { return I == X.I; } + bool operator!=(const TypedMDOperandIterator &X) const { return I != X.I; } }; -/// \brief Forward declaration of metadata. +/// \brief Typed, array-like tuple of metadata. /// -/// Forward declaration of metadata, in the form of a basic tuple. Unlike \a -/// MDTuple, this class has full support for RAUW, is not owned, is not -/// uniqued, and is suitable for forward references. -class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl { - friend class Metadata; - friend class ReplaceableMetadataImpl; - - MDNodeFwdDecl(LLVMContext &C, ArrayRef<Metadata *> Vals) - : MDNode(C, MDNodeFwdDeclKind, Vals) {} +/// This is a wrapper for \a MDTuple that makes it act like an array holding a +/// particular type of metadata. +template <class T> class MDTupleTypedArrayWrapper { + const MDTuple *N = nullptr; public: - ~MDNodeFwdDecl() { dropAllReferences(); } - - // MSVC doesn't see the alternative: "using MDNode::operator delete". - void operator delete(void *Mem) { MDNode::operator delete(Mem); } - - static MDNodeFwdDecl *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { - return new (MDs.size()) MDNodeFwdDecl(Context, MDs); - } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDNodeFwdDeclKind; - } - - using ReplaceableMetadataImpl::replaceAllUsesWith; + MDTupleTypedArrayWrapper() = default; + MDTupleTypedArrayWrapper(const MDTuple *N) : N(N) {} + + template <class U> + MDTupleTypedArrayWrapper( + const MDTupleTypedArrayWrapper<U> &Other, + typename std::enable_if<std::is_convertible<U *, T *>::value>::type * = + nullptr) + : N(Other.get()) {} + + template <class U> + explicit MDTupleTypedArrayWrapper( + const MDTupleTypedArrayWrapper<U> &Other, + typename std::enable_if<!std::is_convertible<U *, T *>::value>::type * = + nullptr) + : N(Other.get()) {} + + explicit operator bool() const { return get(); } + explicit operator MDTuple *() const { return get(); } + + MDTuple *get() const { return const_cast<MDTuple *>(N); } + MDTuple *operator->() const { return get(); } + MDTuple &operator*() const { return *get(); } + + // FIXME: Fix callers and remove condition on N. + unsigned size() const { return N ? N->getNumOperands() : 0u; } + T *operator[](unsigned I) const { return cast_or_null<T>(N->getOperand(I)); } + + // FIXME: Fix callers and remove condition on N. + typedef TypedMDOperandIterator<T> iterator; + iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } + iterator end() const { return N ? iterator(N->op_end()) : iterator(); } }; +#define HANDLE_METADATA(CLASS) \ + typedef MDTupleTypedArrayWrapper<CLASS> CLASS##Array; +#include "llvm/IR/Metadata.def" + //===----------------------------------------------------------------------===// /// \brief A tuple of MDNodes. /// @@ -921,7 +1117,7 @@ class NamedMDNode : public ilist_node<NamedMDNode> { friend struct ilist_traits<NamedMDNode>; friend class LLVMContextImpl; friend class Module; - NamedMDNode(const NamedMDNode &) LLVM_DELETED_FUNCTION; + NamedMDNode(const NamedMDNode &) = delete; std::string Name; Module *Parent; diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index b24023b05e4f..d8636dfb123e 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -219,14 +219,7 @@ private: std::string TargetTriple; ///< Platform target triple Module compiled on ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) void *NamedMDSymTab; ///< NamedMDNode names. - - // We need to keep the string because the C API expects us to own the string - // representation. - // Since we have it, we also use an empty string to represent a module without - // a DataLayout. If it has a DataLayout, these variables are in sync and the - // string is just a cache of getDataLayout()->getStringRepresentation(). - std::string DataLayoutStr; - DataLayout DL; + DataLayout DL; ///< DataLayout associated with the module friend class Constant; @@ -256,10 +249,12 @@ public: /// Get the data layout string for the module's target platform. This is /// equivalent to getDataLayout()->getStringRepresentation(). - const std::string &getDataLayoutStr() const { return DataLayoutStr; } + const std::string getDataLayoutStr() const { + return DL.getStringRepresentation(); + } /// Get the data layout for the module's target platform. - const DataLayout *getDataLayout() const; + const DataLayout &getDataLayout() const; /// Get the target triple which is a string describing the target host. /// @returns a string containing the target triple. @@ -293,12 +288,13 @@ public: /// Set the data layout void setDataLayout(StringRef Desc); - void setDataLayout(const DataLayout *Other); + void setDataLayout(const DataLayout &Other); /// Set the target triple. void setTargetTriple(StringRef T) { TargetTriple = T; } /// Set the module-scope inline assembly blocks. + /// A trailing newline is added if the input doesn't have one. void setModuleInlineAsm(StringRef Asm) { GlobalScopeAsm = Asm; if (!GlobalScopeAsm.empty() && @@ -306,8 +302,8 @@ public: GlobalScopeAsm += '\n'; } - /// Append to the module-scope inline assembly blocks, automatically inserting - /// a separating newline if necessary. + /// Append to the module-scope inline assembly blocks. + /// A trailing newline is added if the input doesn't have one. void appendModuleInlineAsm(StringRef Asm) { GlobalScopeAsm += Asm; if (!GlobalScopeAsm.empty() && @@ -496,7 +492,7 @@ public: /// If the GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized /// lazily. If !isDematerializable(), this method is a no-op. - void Dematerialize(GlobalValue *GV); + void dematerialize(GlobalValue *GV); /// Make sure all GlobalValues in this Module are fully read. std::error_code materializeAll(); @@ -506,6 +502,8 @@ public: /// Materializer. std::error_code materializeAllPermanently(); + std::error_code materializeMetadata(); + /// @} /// @name Direct access to the globals list, functions list, and symbol table /// @{ @@ -630,13 +628,25 @@ public: named_metadata_end()); } + /// Destroy ConstantArrays in LLVMContext if they are not used. + /// ConstantArrays constructed during linking can cause quadratic memory + /// explosion. Releasing all unused constants can cause a 20% LTO compile-time + /// slowdown for a large application. + /// + /// NOTE: Constants are currently owned by LLVMContext. This can then only + /// be called where all uses of the LLVMContext are understood. + void dropTriviallyDeadConstantArrays(); + /// @} /// @name Utility functions for printing and dumping Module objects /// @{ /// Print the module to an output stream with an optional - /// AssemblyAnnotationWriter. - void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const; + /// AssemblyAnnotationWriter. If \c ShouldPreserveUseListOrder, then include + /// uselistorder directives so that use-lists can be recreated when reading + /// the assembly. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, + bool ShouldPreserveUseListOrder = false) const; /// Dump the module to stderr (for debugging). void dump() const; diff --git a/include/llvm/IR/NoFolder.h b/include/llvm/IR/NoFolder.h index a9cdfc36fb4a..61f4817a9b62 100644 --- a/include/llvm/IR/NoFolder.h +++ b/include/llvm/IR/NoFolder.h @@ -177,34 +177,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getGetElementPtr(C, Idx); + return ConstantExpr::getGetElementPtr(Ty, C, Idx); } - Instruction *CreateGetElementPtr(Constant *C, + Instruction *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::Create(C, IdxList); + return GetElementPtrInst::Create(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getInBoundsGetElementPtr(C, Idx); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx); } - Instruction *CreateInBoundsGetElementPtr(Constant *C, + Instruction *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::CreateInBounds(C, IdxList); + return GetElementPtrInst::CreateInBounds(Ty, C, IdxList); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 0933f2170236..1b9102ecc7e4 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -18,7 +18,6 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Type.h" @@ -34,15 +33,15 @@ class Operator : public User { private: // The Operator class is intended to be used as a utility, and is never itself // instantiated. - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void *operator new(size_t s) LLVM_DELETED_FUNCTION; - Operator() LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void *operator new(size_t s) = delete; + Operator() = delete; protected: - // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete + // NOTE: Cannot use = delete because it's not legal to delete // an overridden method that's not deleted in the base class. Cannot leave // this unimplemented because that leads to an ODR-violation. - ~Operator(); + ~Operator() override; public: /// Return the opcode for this Instruction or ConstantExpr. @@ -181,17 +180,17 @@ public: { } /// Whether any flag is set - bool any() { return Flags != 0; } + bool any() const { return Flags != 0; } /// Set all the flags to false void clear() { Flags = 0; } /// Flag queries - bool noNaNs() { return 0 != (Flags & NoNaNs); } - bool noInfs() { return 0 != (Flags & NoInfs); } - bool noSignedZeros() { return 0 != (Flags & NoSignedZeros); } - bool allowReciprocal() { return 0 != (Flags & AllowReciprocal); } - bool unsafeAlgebra() { return 0 != (Flags & UnsafeAlgebra); } + bool noNaNs() const { return 0 != (Flags & NoNaNs); } + bool noInfs() const { return 0 != (Flags & NoInfs); } + bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); } + bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); } + bool unsafeAlgebra() const { return 0 != (Flags & UnsafeAlgebra); } /// Flag setters void setNoNaNs() { Flags |= NoNaNs; } @@ -400,6 +399,8 @@ public: return getPointerOperand()->getType(); } + Type *getSourceElementType() const; + /// Method to return the address space of the pointer operand. unsigned getPointerAddressSpace() const { return getPointerOperandType()->getPointerAddressSpace(); @@ -445,36 +446,7 @@ public: /// undefined (it is *not* preserved!). The APInt passed into this routine /// must be at exactly as wide as the IntPtr type for the address space of the /// base GEP pointer. - bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const { - assert(Offset.getBitWidth() == - DL.getPointerSizeInBits(getPointerAddressSpace()) && - "The offset must have exactly as many bits as our pointer."); - - for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); - GTI != GTE; ++GTI) { - ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); - if (!OpC) - return false; - if (OpC->isZero()) - continue; - - // Handle a struct index, which adds its field offset to the pointer. - if (StructType *STy = dyn_cast<StructType>(*GTI)) { - unsigned ElementIdx = OpC->getZExtValue(); - const StructLayout *SL = DL.getStructLayout(STy); - Offset += APInt(Offset.getBitWidth(), - SL->getElementOffset(ElementIdx)); - continue; - } - - // For array or vector indices, scale the index by the size of the type. - APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth()); - Offset += Index * APInt(Offset.getBitWidth(), - DL.getTypeAllocSize(GTI.getIndexedType())); - } - return true; - } - + bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const; }; class PtrToIntOperator @@ -504,6 +476,20 @@ public: } }; +class BitCastOperator + : public ConcreteOperator<Operator, Instruction::BitCast> { + friend class BitCastInst; + friend class ConstantExpr; + +public: + Type *getSrcTy() const { + return getOperand(0)->getType(); + } + + Type *getDestTy() const { + return getType(); + } +}; } // End llvm namespace diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 262576849264..4166babd63e5 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -46,6 +46,7 @@ #include "llvm/IR/PassManagerInternal.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/type_traits.h" #include <list> #include <memory> @@ -241,8 +242,8 @@ public: private: typedef detail::PassConcept<IRUnitT> PassConceptT; - PassManager(const PassManager &) LLVM_DELETED_FUNCTION; - PassManager &operator=(const PassManager &) LLVM_DELETED_FUNCTION; + PassManager(const PassManager &) = delete; + PassManager &operator=(const PassManager &) = delete; std::vector<std::unique_ptr<PassConceptT>> Passes; @@ -281,9 +282,9 @@ template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase { return static_cast<const DerivedT *>(this); } - AnalysisManagerBase(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + AnalysisManagerBase(const AnalysisManagerBase &) = delete; AnalysisManagerBase & - operator=(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + operator=(const AnalysisManagerBase &) = delete; protected: typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT; @@ -453,8 +454,8 @@ public: } private: - AnalysisManager(const AnalysisManager &) LLVM_DELETED_FUNCTION; - AnalysisManager &operator=(const AnalysisManager &) LLVM_DELETED_FUNCTION; + AnalysisManager(const AnalysisManager &) = delete; + AnalysisManager &operator=(const AnalysisManager &) = delete; /// \brief Get an analysis result, running the pass if necessary. ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) { @@ -471,6 +472,12 @@ private: dbgs() << "Running analysis: " << P.name() << "\n"; AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; ResultList.emplace_back(PassID, P.run(IR, this)); + + // P.run may have inserted elements into AnalysisResults and invalidated + // RI. + RI = AnalysisResults.find(std::make_pair(PassID, &IR)); + assert(RI != AnalysisResults.end() && "we just inserted it!"); + RI->second = std::prev(ResultList.end()); } @@ -502,7 +509,7 @@ private: PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) { // Short circuit for a common case of all analyses being preserved. if (PA.areAllPreserved()) - return std::move(PA); + return PA; if (DebugLogging) dbgs() << "Invalidating all non-preserved analyses for: " @@ -542,7 +549,7 @@ private: if (ResultsList.empty()) AnalysisResultLists.erase(&IR); - return std::move(PA); + return PA; } /// \brief List of function analysis pass IDs and associated concept pointers. @@ -782,8 +789,11 @@ public: FAM = &AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { - PreservedAnalyses PassPA = Pass.run(*I, FAM); + for (Function &F : M) { + if (F.isDeclaration()) + continue; + + PreservedAnalyses PassPA = Pass.run(F, FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so @@ -791,7 +801,7 @@ public: // update our preserved set to reflect that these have already been // handled. if (FAM) - PassPA = FAM->invalidate(*I, std::move(PassPA)); + PassPA = FAM->invalidate(F, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -817,7 +827,7 @@ private: template <typename FunctionPassT> ModuleToFunctionPassAdaptor<FunctionPassT> createModuleToFunctionPassAdaptor(FunctionPassT Pass) { - return std::move(ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); + return ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)); } /// \brief A template utility pass to force an analysis result to be available. diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h index 297f5f4e07f4..92de10bcd75b 100644 --- a/include/llvm/IR/PassManagerInternal.h +++ b/include/llvm/IR/PassManagerInternal.h @@ -19,6 +19,7 @@ #define LLVM_IR_PASSMANAGERINTERNAL_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/STLExtras.h" namespace llvm { diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index f94e10576893..41154e6441a9 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -295,6 +295,9 @@ template <typename Class> struct bind_ty { /// \brief Match a value, capturing it if we match. inline bind_ty<Value> m_Value(Value *&V) { return V; } +/// \brief Match an instruction, capturing it if we match. +inline bind_ty<Instruction> m_Instruction(Instruction *&I) { return I; } + /// \brief Match a binary operator, capturing it if we match. inline bind_ty<BinaryOperator> m_BinOp(BinaryOperator *&I) { return I; } @@ -1103,6 +1106,52 @@ m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R); } +//===----------------------------------------------------------------------===// +// Matchers for overflow check patterns: e.g. (a + b) u< a +// + +template <typename LHS_t, typename RHS_t, typename Sum_t> +struct UAddWithOverflow_match { + LHS_t L; + RHS_t R; + Sum_t S; + + UAddWithOverflow_match(const LHS_t &L, const RHS_t &R, const Sum_t &S) + : L(L), R(R), S(S) {} + + template <typename OpTy> bool match(OpTy *V) { + Value *ICmpLHS, *ICmpRHS; + ICmpInst::Predicate Pred; + if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V)) + return false; + + Value *AddLHS, *AddRHS; + auto AddExpr = m_Add(m_Value(AddLHS), m_Value(AddRHS)); + + // (a + b) u< a, (a + b) u< b + if (Pred == ICmpInst::ICMP_ULT) + if (AddExpr.match(ICmpLHS) && (ICmpRHS == AddLHS || ICmpRHS == AddRHS)) + return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpLHS); + + // a >u (a + b), b >u (a + b) + if (Pred == ICmpInst::ICMP_UGT) + if (AddExpr.match(ICmpRHS) && (ICmpLHS == AddLHS || ICmpLHS == AddRHS)) + return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpRHS); + + return false; + } +}; + +/// \brief Match an icmp instruction checking for unsigned overflow on addition. +/// +/// S is matched to the addition whose result is being checked for overflow, and +/// L and R are matched to the LHS and RHS of S. +template <typename LHS_t, typename RHS_t, typename Sum_t> +UAddWithOverflow_match<LHS_t, RHS_t, Sum_t> +m_UAddWithOverflow(const LHS_t &L, const RHS_t &R, const Sum_t &S) { + return UAddWithOverflow_match<LHS_t, RHS_t, Sum_t>(L, R, S); +} + /// \brief Match an 'unordered' floating point minimum function. /// Floating point has one special value 'NaN'. Therefore, there is no total /// order. However, if we can ignore the 'NaN' value (for example, because of a diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h index 5e1be37805ff..118310aed1d0 100644 --- a/include/llvm/IR/PredIteratorCache.h +++ b/include/llvm/IR/PredIteratorCache.h @@ -14,6 +14,7 @@ #ifndef LLVM_IR_PREDITERATORCACHE_H #define LLVM_IR_PREDITERATORCACHE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/CFG.h" @@ -21,50 +22,58 @@ namespace llvm { - /// PredIteratorCache - This class is an extremely trivial cache for - /// predecessor iterator queries. This is useful for code that repeatedly - /// wants the predecessor list for the same blocks. - class PredIteratorCache { - /// BlockToPredsMap - Pointer to null-terminated list. - DenseMap<BasicBlock*, BasicBlock**> BlockToPredsMap; - DenseMap<BasicBlock*, unsigned> BlockToPredCountMap; +/// PredIteratorCache - This class is an extremely trivial cache for +/// predecessor iterator queries. This is useful for code that repeatedly +/// wants the predecessor list for the same blocks. +class PredIteratorCache { + /// BlockToPredsMap - Pointer to null-terminated list. + DenseMap<BasicBlock *, BasicBlock **> BlockToPredsMap; + DenseMap<BasicBlock *, unsigned> BlockToPredCountMap; - /// Memory - This is the space that holds cached preds. - BumpPtrAllocator Memory; - public: + /// Memory - This is the space that holds cached preds. + BumpPtrAllocator Memory; - /// GetPreds - Get a cached list for the null-terminated predecessor list of - /// the specified block. This can be used in a loop like this: - /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) - /// use(*PI); - /// instead of: - /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) - BasicBlock **GetPreds(BasicBlock *BB) { - BasicBlock **&Entry = BlockToPredsMap[BB]; - if (Entry) return Entry; +private: + /// GetPreds - Get a cached list for the null-terminated predecessor list of + /// the specified block. This can be used in a loop like this: + /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) + /// use(*PI); + /// instead of: + /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + BasicBlock **GetPreds(BasicBlock *BB) { + BasicBlock **&Entry = BlockToPredsMap[BB]; + if (Entry) + return Entry; - SmallVector<BasicBlock*, 32> PredCache(pred_begin(BB), pred_end(BB)); - PredCache.push_back(nullptr); // null terminator. - - BlockToPredCountMap[BB] = PredCache.size()-1; + SmallVector<BasicBlock *, 32> PredCache(pred_begin(BB), pred_end(BB)); + PredCache.push_back(nullptr); // null terminator. - Entry = Memory.Allocate<BasicBlock*>(PredCache.size()); - std::copy(PredCache.begin(), PredCache.end(), Entry); - return Entry; - } - - unsigned GetNumPreds(BasicBlock *BB) { - GetPreds(BB); - return BlockToPredCountMap[BB]; - } + BlockToPredCountMap[BB] = PredCache.size() - 1; + + Entry = Memory.Allocate<BasicBlock *>(PredCache.size()); + std::copy(PredCache.begin(), PredCache.end(), Entry); + return Entry; + } + + unsigned GetNumPreds(BasicBlock *BB) { + GetPreds(BB); + return BlockToPredCountMap[BB]; + } + +public: + size_t size(BasicBlock *BB) { return GetNumPreds(BB); } + ArrayRef<BasicBlock *> get(BasicBlock *BB) { + return makeArrayRef(GetPreds(BB), GetNumPreds(BB)); + } + + /// clear - Remove all information. + void clear() { + BlockToPredsMap.clear(); + BlockToPredCountMap.clear(); + Memory.Reset(); + } +}; - /// clear - Remove all information. - void clear() { - BlockToPredsMap.clear(); - BlockToPredCountMap.clear(); - Memory.Reset(); - } - }; } // end namespace llvm #endif diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h index e3c4243e9d81..cd09618e3eee 100644 --- a/include/llvm/IR/Statepoint.h +++ b/include/llvm/IR/Statepoint.h @@ -17,21 +17,35 @@ #define __LLVM_IR_STATEPOINT_H #include "llvm/ADT/iterator_range.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallSite.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/Compiler.h" namespace llvm { +/// The statepoint intrinsic accepts a set of flags as its third argument. +/// Valid values come out of this set. +enum class StatepointFlags { + None = 0, + GCTransition = 1, ///< Indicates that this statepoint is a transition from + ///< GC-aware code to code that is not GC-aware. + + MaskAll = GCTransition ///< A bitmask that includes all valid flags. +}; + +class GCRelocateOperands; +class ImmutableStatepoint; bool isStatepoint(const ImmutableCallSite &CS); -bool isStatepoint(const Instruction *inst); -bool isStatepoint(const Instruction &inst); +bool isStatepoint(const Value *inst); +bool isStatepoint(const Value &inst); -bool isGCRelocate(const Instruction *inst); +bool isGCRelocate(const Value *inst); bool isGCRelocate(const ImmutableCallSite &CS); -bool isGCResult(const Instruction *inst); +bool isGCResult(const Value *inst); bool isGCResult(const ImmutableCallSite &CS); /// Analogous to CallSiteBase, this provides most of the actual @@ -45,10 +59,10 @@ bool isGCResult(const ImmutableCallSite &CS); template <typename InstructionTy, typename ValueTy, typename CallSiteTy> class StatepointBase { CallSiteTy StatepointCS; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void *operator new(size_t s) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void *operator new(size_t s) = delete; - protected: +protected: explicit StatepointBase(InstructionTy *I) : StatepointCS(I) { assert(isStatepoint(I)); } @@ -56,38 +70,68 @@ class StatepointBase { assert(isStatepoint(CS)); } - public: +public: typedef typename CallSiteTy::arg_iterator arg_iterator; + enum { + IDPos = 0, + NumPatchBytesPos = 1, + ActualCalleePos = 2, + NumCallArgsPos = 3, + FlagsPos = 4, + CallArgsBeginPos = 5, + }; + /// Return the underlying CallSite. - CallSiteTy getCallSite() { - return StatepointCS; + CallSiteTy getCallSite() { return StatepointCS; } + + uint64_t getFlags() const { + return cast<ConstantInt>(StatepointCS.getArgument(FlagsPos)) + ->getZExtValue(); + } + + /// Return the ID associated with this statepoint. + uint64_t getID() { + const Value *IDVal = StatepointCS.getArgument(IDPos); + return cast<ConstantInt>(IDVal)->getZExtValue(); + } + + /// Return the number of patchable bytes associated with this statepoint. + uint32_t getNumPatchBytes() { + const Value *NumPatchBytesVal = StatepointCS.getArgument(NumPatchBytesPos); + uint64_t NumPatchBytes = + cast<ConstantInt>(NumPatchBytesVal)->getZExtValue(); + assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!"); + return NumPatchBytes; } /// Return the value actually being called or invoked. - ValueTy *actualCallee() { - return StatepointCS.getArgument(0); + ValueTy *getActualCallee() { + return StatepointCS.getArgument(ActualCalleePos); } - /// Number of arguments to be passed to the actual callee. - int numCallArgs() { - return cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue(); + + /// Return the type of the value returned by the call underlying the + /// statepoint. + Type *getActualReturnType() { + auto *FTy = cast<FunctionType>( + cast<PointerType>(getActualCallee()->getType())->getElementType()); + return FTy->getReturnType(); } - /// Number of additional arguments excluding those intended - /// for garbage collection. - int numTotalVMSArgs() { - return cast<ConstantInt>(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue(); + + /// Number of arguments to be passed to the actual callee. + int getNumCallArgs() { + const Value *NumCallArgsVal = StatepointCS.getArgument(NumCallArgsPos); + return cast<ConstantInt>(NumCallArgsVal)->getZExtValue(); } typename CallSiteTy::arg_iterator call_args_begin() { - // 3 = callTarget, #callArgs, flag - int Offset = 3; - assert(Offset <= (int)StatepointCS.arg_size()); - return StatepointCS.arg_begin() + Offset; + assert(CallArgsBeginPos <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + CallArgsBeginPos; } typename CallSiteTy::arg_iterator call_args_end() { - int Offset = 3 + numCallArgs(); - assert(Offset <= (int)StatepointCS.arg_size()); - return StatepointCS.arg_begin() + Offset; + auto I = call_args_begin() + getNumCallArgs(); + assert((StatepointCS.arg_end() - I) >= 0); + return I; } /// range adapter for call arguments @@ -95,13 +139,44 @@ class StatepointBase { return iterator_range<arg_iterator>(call_args_begin(), call_args_end()); } + /// Number of GC transition args. + int getNumTotalGCTransitionArgs() { + const Value *NumGCTransitionArgs = *call_args_end(); + return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue(); + } + typename CallSiteTy::arg_iterator gc_transition_args_begin() { + auto I = call_args_end() + 1; + assert((StatepointCS.arg_end() - I) >= 0); + return I; + } + typename CallSiteTy::arg_iterator gc_transition_args_end() { + auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs(); + assert((StatepointCS.arg_end() - I) >= 0); + return I; + } + + /// range adapter for GC transition arguments + iterator_range<arg_iterator> gc_transition_args() { + return iterator_range<arg_iterator>(gc_transition_args_begin(), + gc_transition_args_end()); + } + + /// Number of additional arguments excluding those intended + /// for garbage collection. + int getNumTotalVMSArgs() { + const Value *NumVMSArgs = *gc_transition_args_end(); + return cast<ConstantInt>(NumVMSArgs)->getZExtValue(); + } + typename CallSiteTy::arg_iterator vm_state_begin() { - return call_args_end(); + auto I = gc_transition_args_end() + 1; + assert((StatepointCS.arg_end() - I) >= 0); + return I; } typename CallSiteTy::arg_iterator vm_state_end() { - int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs(); - assert(Offset <= (int)StatepointCS.arg_size()); - return StatepointCS.arg_begin() + Offset; + auto I = vm_state_begin() + getNumTotalVMSArgs(); + assert((StatepointCS.arg_end() - I) >= 0); + return I; } /// range adapter for vm state arguments @@ -109,15 +184,7 @@ class StatepointBase { return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end()); } - typename CallSiteTy::arg_iterator first_vm_state_stack_begin() { - // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci, - // 1st_#stack, 1st_#local, 1st_#monitor - return vm_state_begin() + 6; - } - - typename CallSiteTy::arg_iterator gc_args_begin() { - return vm_state_end(); - } + typename CallSiteTy::arg_iterator gc_args_begin() { return vm_state_end(); } typename CallSiteTy::arg_iterator gc_args_end() { return StatepointCS.arg_end(); } @@ -127,18 +194,25 @@ class StatepointBase { return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end()); } + /// Get list of all gc reloactes linked to this statepoint + /// May contain several relocations for the same base/derived pair. + /// For example this could happen due to relocations on unwinding + /// path of invoke. + std::vector<GCRelocateOperands> getRelocates(ImmutableStatepoint &IS); #ifndef NDEBUG /// Asserts if this statepoint is malformed. Common cases for failure /// include incorrect length prefixes for variable length sections or /// illegal values for parameters. void verify() { - assert(numCallArgs() >= 0 && + assert(getNumCallArgs() >= 0 && "number of arguments to actually callee can't be negative"); // The internal asserts in the iterator accessors do the rest. (void)call_args_begin(); (void)call_args_end(); + (void)gc_transition_args_begin(); + (void)gc_transition_args_end(); (void)vm_state_begin(); (void)vm_state_end(); (void)gc_args_begin(); @@ -150,8 +224,7 @@ class StatepointBase { /// A specialization of it's base class for read only access /// to a gc.statepoint. class ImmutableStatepoint - : public StatepointBase<const Instruction, const Value, - ImmutableCallSite> { + : public StatepointBase<const Instruction, const Value, ImmutableCallSite> { typedef StatepointBase<const Instruction, const Value, ImmutableCallSite> Base; @@ -176,40 +249,106 @@ public: class GCRelocateOperands { ImmutableCallSite RelocateCS; - public: - GCRelocateOperands(const User* U) : RelocateCS(U) { - assert(isGCRelocate(U)); - } +public: + GCRelocateOperands(const User *U) : RelocateCS(U) { assert(isGCRelocate(U)); } GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) { assert(isGCRelocate(inst)); } - GCRelocateOperands(CallSite CS) : RelocateCS(CS) { - assert(isGCRelocate(CS)); + GCRelocateOperands(CallSite CS) : RelocateCS(CS) { assert(isGCRelocate(CS)); } + + /// Return true if this relocate is tied to the invoke statepoint. + /// This includes relocates which are on the unwinding path. + bool isTiedToInvoke() const { + const Value *Token = RelocateCS.getArgument(0); + + return isa<ExtractValueInst>(Token) || isa<InvokeInst>(Token); } + /// Get enclosed relocate intrinsic + ImmutableCallSite getUnderlyingCallSite() { return RelocateCS; } + /// The statepoint with which this gc.relocate is associated. - const Instruction *statepoint() { - return cast<Instruction>(RelocateCS.getArgument(0)); + const Instruction *getStatepoint() { + const Value *Token = RelocateCS.getArgument(0); + + // This takes care both of relocates for call statepoints and relocates + // on normal path of invoke statepoint. + if (!isa<ExtractValueInst>(Token)) { + return cast<Instruction>(Token); + } + + // This relocate is on exceptional path of an invoke statepoint + const BasicBlock *InvokeBB = + cast<Instruction>(Token)->getParent()->getUniquePredecessor(); + + assert(InvokeBB && "safepoints should have unique landingpads"); + assert(InvokeBB->getTerminator() && + "safepoint block should be well formed"); + assert(isStatepoint(InvokeBB->getTerminator())); + + return InvokeBB->getTerminator(); } + /// The index into the associate statepoint's argument list /// which contains the base pointer of the pointer whose /// relocation this gc.relocate describes. - int basePtrIndex() { + unsigned getBasePtrIndex() { return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue(); } + /// The index into the associate statepoint's argument list which /// contains the pointer whose relocation this gc.relocate describes. - int derivedPtrIndex() { + unsigned getDerivedPtrIndex() { return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue(); } - Value *basePtr() { - ImmutableCallSite CS(statepoint()); - return *(CS.arg_begin() + basePtrIndex()); + + Value *getBasePtr() { + ImmutableCallSite CS(getStatepoint()); + return *(CS.arg_begin() + getBasePtrIndex()); } - Value *derivedPtr() { - ImmutableCallSite CS(statepoint()); - return *(CS.arg_begin() + derivedPtrIndex()); + + Value *getDerivedPtr() { + ImmutableCallSite CS(getStatepoint()); + return *(CS.arg_begin() + getDerivedPtrIndex()); } }; + +template <typename InstructionTy, typename ValueTy, typename CallSiteTy> +std::vector<GCRelocateOperands> +StatepointBase<InstructionTy, ValueTy, CallSiteTy>::getRelocates( + ImmutableStatepoint &IS) { + + std::vector<GCRelocateOperands> Result; + + ImmutableCallSite StatepointCS = IS.getCallSite(); + + // Search for relocated pointers. Note that working backwards from the + // gc_relocates ensures that we only get pairs which are actually relocated + // and used after the statepoint. + for (const User *U : StatepointCS.getInstruction()->users()) + if (isGCRelocate(U)) + Result.push_back(GCRelocateOperands(U)); + + if (!StatepointCS.isInvoke()) + return Result; + + // We need to scan thorough exceptional relocations if it is invoke statepoint + LandingPadInst *LandingPad = + cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst(); + + // Search for extract value from landingpad instruction to which + // gc relocates will be attached + for (const User *LandingPadUser : LandingPad->users()) { + if (!isa<ExtractValueInst>(LandingPadUser)) + continue; + + // gc relocates should be attached to this extract value + for (const User *U : LandingPadUser->users()) + if (isGCRelocate(U)) + Result.push_back(GCRelocateOperands(U)); + } + return Result; +} } + #endif diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index c2073c7750b2..6ab0bd0631a0 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -91,8 +91,8 @@ protected: NumContainedTys(0), ContainedTys(nullptr) { setTypeID(tid); } - ~Type() {} - + ~Type() = default; + void setTypeID(TypeID ID) { IDAndSubclassData = (ID & 0xFF) | (IDAndSubclassData & 0xFFFFFF00); assert(getTypeID() == ID && "TypeID data too large for field"); @@ -395,7 +395,8 @@ public: static IntegerType *getInt16Ty(LLVMContext &C); static IntegerType *getInt32Ty(LLVMContext &C); static IntegerType *getInt64Ty(LLVMContext &C); - + static IntegerType *getInt128Ty(LLVMContext &C); + //===--------------------------------------------------------------------===// // Convenience methods for getting pointer types with one of the above builtin // types as pointee. diff --git a/include/llvm/IR/TypeBuilder.h b/include/llvm/IR/TypeBuilder.h index 5a29e1e10855..d2c6f00079da 100644 --- a/include/llvm/IR/TypeBuilder.h +++ b/include/llvm/IR/TypeBuilder.h @@ -34,6 +34,8 @@ namespace llvm { /// you'll need to specialize it. For example, say you want to call a /// function defined externally as: /// +/// \code{.cpp} +/// /// struct MyType { /// int32 a; /// int32 *b; @@ -41,12 +43,16 @@ namespace llvm { /// }; /// int8 AFunction(struct MyType *value); /// +/// \endcode +/// /// You'll want to use /// Function::Create(TypeBuilder<types::i<8>(MyType*), true>::get(), ...) /// to declare the function, but when you first try this, your compiler will /// complain that TypeBuilder<MyType, true>::get() doesn't exist. To fix this, /// write: /// +/// \code{.cpp} +/// /// namespace llvm { /// template<bool xcompile> class TypeBuilder<MyType, xcompile> { /// public: @@ -57,7 +63,7 @@ namespace llvm { /// TypeBuilder<types::i<32>, xcompile>::get(Context), /// TypeBuilder<types::i<32>*, xcompile>::get(Context), /// TypeBuilder<types::i<8>*[], xcompile>::get(Context), -/// NULL); +/// nullptr); /// } /// /// // You may find this a convenient place to put some constants @@ -71,6 +77,8 @@ namespace llvm { /// } /// } // namespace llvm /// +/// \endcode +/// /// TypeBuilder cannot handle recursive types or types you only know at runtime. /// If you try to give it a recursive type, it will deadlock, infinitely /// recurse, or do something similarly undesirable. diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 033cd3e2f5da..160d71b03e7f 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -77,7 +77,7 @@ public: typedef PointerIntPair<User *, 1, unsigned> UserRef; private: - Use(const Use &U) LLVM_DELETED_FUNCTION; + Use(const Use &U) = delete; /// Destructor - Only for zap() ~Use() { diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h index 5df459b1bd30..b7c2418d348d 100644 --- a/include/llvm/IR/UseListOrder.h +++ b/include/llvm/IR/UseListOrder.h @@ -45,18 +45,12 @@ struct UseListOrder { } private: - UseListOrder(const UseListOrder &X) LLVM_DELETED_FUNCTION; - UseListOrder &operator=(const UseListOrder &X) LLVM_DELETED_FUNCTION; + UseListOrder(const UseListOrder &X) = delete; + UseListOrder &operator=(const UseListOrder &X) = delete; }; typedef std::vector<UseListOrder> UseListOrderStack; -/// \brief Whether to preserve use-list ordering. -bool shouldPreserveBitcodeUseListOrder(); -bool shouldPreserveAssemblyUseListOrder(); -void setPreserveBitcodeUseListOrder(bool ShouldPreserve); -void setPreserveAssemblyUseListOrder(bool ShouldPreserve); - } // end namespace llvm #endif diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index f578227d6cae..455900566afd 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -33,8 +33,8 @@ template <class> struct OperandTraits; class User : public Value { - User(const User &) LLVM_DELETED_FUNCTION; - void *operator new(size_t) LLVM_DELETED_FUNCTION; + User(const User &) = delete; + void *operator new(size_t) = delete; template <unsigned> friend struct HungoffOperandTraits; virtual void anchor(); @@ -60,9 +60,7 @@ protected: NumOperands = 0; } public: - ~User() { - Use::zap(OperandList, OperandList + NumOperands); - } + ~User() override { Use::zap(OperandList, OperandList + NumOperands); } /// \brief Free memory allocated for User and Use objects. void operator delete(void *Usr); /// \brief Placement delete - required by std, but never called. diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 705fc0f52d58..3bf2943a8980 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -106,17 +106,12 @@ protected: private: template <typename UseT> // UseT == 'Use' or 'const Use' class use_iterator_impl - : public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> { - typedef std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> super; - + : public std::iterator<std::forward_iterator_tag, UseT *> { UseT *U; explicit use_iterator_impl(UseT *u) : U(u) {} friend class Value; public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - use_iterator_impl() : U() {} bool operator==(const use_iterator_impl &x) const { return U == x.U; } @@ -147,17 +142,12 @@ private: template <typename UserTy> // UserTy == 'User' or 'const User' class user_iterator_impl - : public std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> { - typedef std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> super; - + : public std::iterator<std::forward_iterator_tag, UserTy *> { use_iterator_impl<Use> UI; explicit user_iterator_impl(Use *U) : UI(U) {} friend class Value; public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - user_iterator_impl() {} bool operator==(const user_iterator_impl &x) const { return UI == x.UI; } @@ -188,15 +178,10 @@ private: } Use &getUse() const { return *UI; } - - /// \brief Return the operand # of this use in its User. - /// - /// FIXME: Replace all callers with a direct call to Use::getOperandNo. - unsigned getOperandNo() const { return UI->getOperandNo(); } }; - void operator=(const Value &) LLVM_DELETED_FUNCTION; - Value(const Value &) LLVM_DELETED_FUNCTION; + void operator=(const Value &) = delete; + Value(const Value &) = delete; protected: Value(Type *Ty, unsigned scid); @@ -231,6 +216,7 @@ public: private: void destroyValueName(); + void setNameImpl(const Twine &Name); public: /// \brief Return a constant reference to the value's name. @@ -461,12 +447,6 @@ public: return const_cast<Value*>(this)->stripInBoundsOffsets(); } - /// \brief Check if this is always a dereferenceable pointer. - /// - /// Test if this value is always a pointer to allocated and suitably aligned - /// memory for a simple load or store. - bool isDereferenceablePointer(const DataLayout *DL = nullptr) const; - /// \brief Translate PHI node to its predecessor from the given basic block. /// /// If this value is a PHI node with CurBB as its parent, return the value in @@ -484,7 +464,8 @@ public: /// /// This is the greatest alignment value supported by load, store, and alloca /// instructions, and global values. - static const unsigned MaximumAlignment = 1u << 29; + static const unsigned MaxAlignmentExponent = 29; + static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent; /// \brief Mutate the type of this Value to be of the specified type. /// diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index 8fc7fdb03950..355748e05977 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -58,7 +58,7 @@ private: Value* V; - ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; + ValueHandleBase(const ValueHandleBase&) = delete; public: explicit ValueHandleBase(HandleBaseKind Kind) : PrevPair(nullptr, Kind), Next(nullptr), V(nullptr) {} diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index f2ea405f1428..4d00b637609c 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -86,8 +86,8 @@ class ValueMap { MapT Map; std::unique_ptr<MDMapT> MDMap; ExtraData Data; - ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION; - ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION; + ValueMap(const ValueMap&) = delete; + ValueMap& operator=(const ValueMap&) = delete; public: typedef KeyT key_type; typedef ValueT mapped_type; @@ -99,8 +99,6 @@ public: explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) : Map(NumInitBuckets), Data(Data) {} - ~ValueMap() {} - bool hasMD() const { return MDMap; } MDMapT &MD() { if (!MDMap) @@ -149,9 +147,14 @@ public: // If the key is already in the map, it returns false and doesn't update the // value. std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { - std::pair<typename MapT::iterator, bool> map_result= - Map.insert(std::make_pair(Wrap(KV.first), KV.second)); - return std::make_pair(iterator(map_result.first), map_result.second); + auto MapResult = Map.insert(std::make_pair(Wrap(KV.first), KV.second)); + return std::make_pair(iterator(MapResult.first), MapResult.second); + } + + std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { + auto MapResult = + Map.insert(std::make_pair(Wrap(KV.first), std::move(KV.second))); + return std::make_pair(iterator(MapResult.first), MapResult.second); } /// insert - Range insertion of pairs. @@ -258,9 +261,9 @@ public: // I could == Copy.Map->Map.end() if the onRAUW callback already // removed the old mapping. if (I != Copy.Map->Map.end()) { - ValueT Target(I->second); + ValueT Target(std::move(I->second)); Copy.Map->Map.erase(I); // Definitely destroys *this. - Copy.Map->insert(std::make_pair(typed_new_key, Target)); + Copy.Map->insert(std::make_pair(typed_new_key, std::move(Target))); } } } diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h index 43bd123e7f44..89039d24195e 100644 --- a/include/llvm/IR/Verifier.h +++ b/include/llvm/IR/Verifier.h @@ -56,20 +56,9 @@ bool verifyModule(const Module &M, raw_ostream *OS = nullptr); /// printed to stderr, and by default they are fatal. You can override that by /// passing \c false to \p FatalErrors. /// -/// Note that this creates a pass suitable for the legacy pass manager. It has nothing to do with \c VerifierPass. -FunctionPass *createVerifierPass(bool FatalErrors = true); - -/// \brief Create a debug-info verifier pass. -/// -/// Check a module for validity of debug info. This is essentially a pass -/// wrapped around the debug-info parts of \a verifyModule(). When the pass -/// detects a verification error it is always printed to stderr, and by default -/// they are fatal. You can override that by passing \c false to \p -/// FatalErrors. -/// /// Note that this creates a pass suitable for the legacy pass manager. It has /// nothing to do with \c VerifierPass. -ModulePass *createDebugInfoVerifierPass(bool FatalErrors = true); +FunctionPass *createVerifierPass(bool FatalErrors = true); class VerifierPass { bool FatalErrors; |