X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FIR%2FFunction.h;h=71822a462daa68da562c178c4932d99ac321966a;hb=9ac3ec43b3eb2c18007542c1fe43d93519606c32;hp=1762b2c10acb1435e6a516b37151854df93df3e6;hpb=0b8c9a80f20772c3793201ab5b251d3520b9cea3;p=oota-llvm.git diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 1762b2c10ac..71822a462da 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -15,63 +15,33 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_FUNCTION_H -#define LLVM_FUNCTION_H +#ifndef LLVM_IR_FUNCTION_H +#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" #include "llvm/IR/CallingConv.h" -#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/GlobalObject.h" +#include "llvm/IR/OperandTraits.h" #include "llvm/Support/Compiler.h" namespace llvm { class FunctionType; class LLVMContext; +class DISubprogram; -// Traits for intrusive list of basic blocks... -template<> struct ilist_traits - : public SymbolTableListTraits { +template <> +struct SymbolTableListSentinelTraits + : public ilist_half_embedded_sentinel_traits {}; - // createSentinel is used to get hold of the node that marks the end of the - // list... (same trick used here as in ilist_traits) - BasicBlock *createSentinel() const { - return static_cast(&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 Sentinel; -}; - -template<> struct ilist_traits - : public SymbolTableListTraits { - - Argument *createSentinel() const { - return static_cast(&Sentinel); - } - static void destroySentinel(Argument*) {} - - Argument *provideInitialHead() const { return createSentinel(); } - Argument *ensureHead(Argument*) const { return createSentinel(); } - static void noteHead(Argument*, Argument*) {} - - static ValueSymbolTable *getSymTab(Function *ItemParent); -private: - mutable ilist_half_node Sentinel; -}; - -class Function : public GlobalValue, - public ilist_node { +class Function : public GlobalObject, public ilist_node { public: - typedef iplist ArgumentListType; - typedef iplist BasicBlockListType; + typedef SymbolTableList ArgumentListType; + typedef SymbolTableList BasicBlockListType; // BasicBlock iterators... typedef BasicBlockListType::iterator iterator; @@ -85,15 +55,32 @@ private: BasicBlockListType BasicBlocks; ///< The basic blocks mutable ArgumentListType ArgumentList; ///< The formal arguments ValueSymbolTable *SymTab; ///< Symbol table of args/instructions - AttributeSet AttributeList; ///< Parameter attributes - - // HasLazyArguments is stored in Value::SubclassData. - /*bool HasLazyArguments;*/ - - // The Calling Convention is stored in Value::SubclassData. - /*CallingConv::ID CallingConvention;*/ - - friend class SymbolTableListTraits; + AttributeSet AttributeSets; ///< Parameter attributes + FunctionType *Ty; + + /* + * Value::SubclassData + * + * bit 0 : HasLazyArguments + * bit 1 : HasPrefixData + * bit 2 : HasPrologueData + * bit 3 : [reserved] + * bits 4-13 : CallingConvention + * bits 14-15 : [reserved] + */ + + /// 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; void setParent(Module *parent); @@ -102,7 +89,7 @@ private: /// needs it. The hasLazyArguments predicate returns true if the arg list /// hasn't been set up yet. bool hasLazyArguments() const { - return getSubclassDataFromValue() & 1; + return getSubclassDataFromValue() & (1<<0); } void CheckLazyArguments() const { if (hasLazyArguments()) @@ -110,76 +97,133 @@ private: } void BuildLazyArguments() const; - Function(const Function&) LLVM_DELETED_FUNCTION; - void operator=(const Function&) LLVM_DELETED_FUNCTION; + 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 /// the module. /// Function(FunctionType *Ty, LinkageTypes Linkage, - const Twine &N = "", Module *M = 0); + const Twine &N = "", Module *M = nullptr); public: static Function *Create(FunctionType *Ty, LinkageTypes Linkage, - const Twine &N = "", Module *M = 0) { - return new(0) Function(Ty, Linkage, N, M); + const Twine &N = "", Module *M = nullptr) { + return new(1) Function(Ty, Linkage, N, M); } - ~Function(); + ~Function() override; + + /// \brief Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// \brief Get the personality function associated with this function. + bool hasPersonalityFn() const { return getNumOperands() != 0; } + Constant *getPersonalityFn() const { + assert(hasPersonalityFn()); + return cast(Op<0>()); + } + void setPersonalityFn(Constant *C); 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 /// arguments. bool isVarArg() const; + bool isMaterializable() const; + void setIsMaterializable(bool V); + /// getIntrinsicID - This method returns the ID number of the specified /// function, or Intrinsic::not_intrinsic if the function is not an - /// instrinsic, or if the pointer is null. This value is always defined to be + /// 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. - /// - unsigned getIntrinsicID() const LLVM_READONLY; + 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. CallingConv::ID getCallingConv() const { - return static_cast(getSubclassDataFromValue() >> 1); + return static_cast((getSubclassDataFromValue() >> 4) & + CallingConv::MaxID); } void setCallingConv(CallingConv::ID CC) { - setValueSubclassData((getSubclassDataFromValue() & 1) | - (static_cast(CC) << 1)); + auto ID = static_cast(CC); + assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); + setValueSubclassData((getSubclassDataFromValue() & 0xc00f) | (ID << 4)); } - /// getAttributes - Return the attribute list for this Function. - /// - const AttributeSet &getAttributes() const { return AttributeList; } + /// @brief Return the attribute list for this Function. + AttributeSet getAttributes() const { return AttributeSets; } - /// setAttributes - Set the attribute list for this Function. - /// - void setAttributes(const AttributeSet &attrs) { AttributeList = attrs; } + /// @brief Set the attribute list for this Function. + void setAttributes(AttributeSet attrs) { AttributeSets = attrs; } - /// addFnAttr - Add function attributes to this function. - /// + /// @brief Add function attributes to this function. void addFnAttr(Attribute::AttrKind N) { - // Function Attribute are stored at ~0 index - addAttribute(AttributeSet::FunctionIndex, Attribute::get(getContext(), N)); + setAttributes(AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, N)); } - /// removeFnAttr - Remove function attributes from this function. - /// - void removeFnAttr(Attribute N) { - // Function Attribute are stored at ~0 index - removeAttribute(~0U, N); + /// @brief Remove function attributes from this function. + void removeFnAttr(Attribute::AttrKind N) { + setAttributes(AttributeSets.removeAttribute( + getContext(), AttributeSet::FunctionIndex, N)); + } + + /// @brief Add function attributes to this function. + void addFnAttr(StringRef Kind) { + setAttributes( + AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, Kind)); + } + void addFnAttr(StringRef Kind, StringRef Value) { + setAttributes( + AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, Kind, Value)); + } + + /// Set the entry count for this function. + void setEntryCount(uint64_t Count); + + /// Get the entry count for this function. + Optional getEntryCount() const; + + /// @brief Return true if the function has the attribute. + bool hasFnAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); + } + bool hasFnAttribute(StringRef Kind) const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); + } + + /// @brief Return the attribute for the given attribute kind. + Attribute getFnAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); + } + Attribute getFnAttribute(StringRef Kind) const { + 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 @@ -189,20 +233,42 @@ public: void setGC(const char *Str); void clearGC(); - /// addAttribute - adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attribute attr); + /// @brief adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attribute::AttrKind attr); + + /// @brief adds the attributes to the list of attributes. + void addAttributes(unsigned i, AttributeSet attrs); + + /// @brief removes the attributes from the list of attributes. + void removeAttributes(unsigned i, AttributeSet attr); - /// 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 Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { - return AttributeList.getParamAlignment(i); + return AttributeSets.getParamAlignment(i); + } + + /// @brief Extract the number of dereferenceable bytes for a call or + /// parameter (0=unknown). + 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 AttributeList.hasAttribute(AttributeSet::FunctionIndex, + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); } void setDoesNotAccessMemory() { @@ -212,16 +278,24 @@ public: /// @brief Determine if the function does not access or only reads memory. bool onlyReadsMemory() const { return doesNotAccessMemory() || - AttributeList.hasAttribute(AttributeSet::FunctionIndex, + AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly); } void setOnlyReadsMemory() { addFnAttr(Attribute::ReadOnly); } + /// @brief Determine if the call can access memmory only using pointers based + /// on its arguments. + bool onlyAccessesArgMemory() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::ArgMemOnly); + } + void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); } + /// @brief Determine if the function cannot return. bool doesNotReturn() const { - return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoReturn); } void setDoesNotReturn() { @@ -230,7 +304,7 @@ public: /// @brief Determine if the function cannot unwind. bool doesNotThrow() const { - return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); } void setDoesNotThrow() { @@ -239,17 +313,36 @@ public: /// @brief Determine if the call cannot be duplicated. bool cannotDuplicate() const { - return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoDuplicate); } void setCannotDuplicate() { 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); + } + + /// Determine if the function is known not to recurse, directly or + /// indirectly. + bool doesNotRecurse() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::NoRecurse); + } + void setDoesNotRecurse() { + addFnAttr(Attribute::NoRecurse); + } + /// @brief True if the ABI mandates (or the user requested) that this /// function be in a unwind table. bool hasUWTable() const { - return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::UWTable); } void setHasUWTable() { @@ -264,30 +357,55 @@ public: /// @brief Determine if the function returns a structure through first /// pointer argument. bool hasStructRetAttr() const { - return AttributeList.hasAttribute(1, Attribute::StructRet); + return AttributeSets.hasAttribute(1, Attribute::StructRet) || + AttributeSets.hasAttribute(2, Attribute::StructRet); } - /// @brief Determine if the parameter does not alias other parameters. + /// @brief Determine if the parameter or return value is marked with NoAlias + /// attribute. /// @param n The parameter to check. 1 is the first parameter, 0 is the return bool doesNotAlias(unsigned n) const { - return AttributeList.hasAttribute(n, Attribute::NoAlias); + return AttributeSets.hasAttribute(n, Attribute::NoAlias); } void setDoesNotAlias(unsigned n) { - addAttribute(n, Attribute::get(getContext(), Attribute::NoAlias)); + addAttribute(n, Attribute::NoAlias); } /// @brief Determine if the parameter can be captured. /// @param n The parameter to check. 1 is the first parameter, 0 is the return bool doesNotCapture(unsigned n) const { - return AttributeList.hasAttribute(n, Attribute::NoCapture); + return AttributeSets.hasAttribute(n, Attribute::NoCapture); } void setDoesNotCapture(unsigned n) { - addAttribute(n, Attribute::get(getContext(), Attribute::NoCapture)); + addAttribute(n, Attribute::NoCapture); + } + + bool doesNotAccessMemory(unsigned n) const { + return AttributeSets.hasAttribute(n, Attribute::ReadNone); + } + void setDoesNotAccessMemory(unsigned n) { + addAttribute(n, Attribute::ReadNone); + } + + bool onlyReadsMemory(unsigned n) const { + return doesNotAccessMemory(n) || + AttributeSets.hasAttribute(n, Attribute::ReadOnly); + } + void setOnlyReadsMemory(unsigned n) { + addAttribute(n, Attribute::ReadOnly); + } + + /// Optimize this function for minimum size (-Oz). + bool optForMinSize() const { return hasFnAttribute(Attribute::MinSize); }; + + /// Optimize this function for size (-Os) or minimum size (-Oz). + bool optForSize() const { + return hasFnAttribute(Attribute::OptimizeForSize) || optForMinSize(); } /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a Function) from the Function Src to this one. - void copyAttributesFrom(const GlobalValue *Src); + void copyAttributesFrom(const GlobalValue *Src) override; /// deleteBody - This method deletes the body of the function, and converts /// the linkage to external. @@ -300,13 +418,12 @@ public: /// removeFromParent - This method unlinks 'this' from the containing module, /// but does not delete it. /// - virtual void removeFromParent(); + void removeFromParent() override; /// eraseFromParent - This method unlinks 'this' from the containing module /// and deletes it. /// - virtual void eraseFromParent(); - + void eraseFromParent() override; /// Get the underlying elements of the Function... the basic block list is /// empty for external functions. @@ -319,13 +436,13 @@ public: CheckLazyArguments(); return ArgumentList; } - static iplist Function::*getSublistAccess(Argument*) { + static ArgumentListType Function::*getSublistAccess(Argument*) { return &Function::ArgumentList; } const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; } BasicBlockListType &getBasicBlockList() { return BasicBlocks; } - static iplist Function::*getSublistAccess(BasicBlock*) { + static BasicBlockListType Function::*getSublistAccess(BasicBlock*) { return &Function::BasicBlocks; } @@ -340,7 +457,6 @@ public: inline ValueSymbolTable &getValueSymbolTable() { return *SymTab; } inline const ValueSymbolTable &getValueSymbolTable() const { return *SymTab; } - //===--------------------------------------------------------------------===// // BasicBlock iterator forwarding functions // @@ -356,9 +472,9 @@ public: const BasicBlock &back() const { return BasicBlocks.back(); } BasicBlock &back() { return BasicBlocks.back(); } - //===--------------------------------------------------------------------===// - // Argument iterator forwarding functions - // +/// @name Function Argument Iteration +/// @{ + arg_iterator arg_begin() { CheckLazyArguments(); return ArgumentList.begin(); @@ -376,9 +492,33 @@ public: return ArgumentList.end(); } + iterator_range args() { + return iterator_range(arg_begin(), arg_end()); + } + + iterator_range args() const { + return iterator_range(arg_begin(), arg_end()); + } + +/// @} + size_t arg_size() const; bool arg_empty() const; + bool hasPrefixData() const { + return getSubclassDataFromValue() & (1<<1); + } + + Constant *getPrefixData() const; + void setPrefixData(Constant *PrefixData); + + bool hasPrologueData() const { + return getSubclassDataFromValue() & (1<<2); + } + + Constant *getPrologueData() const; + void setPrologueData(Constant *PrologueData); + /// 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 @@ -417,7 +557,7 @@ public: /// other than direct calls or invokes to it, or blockaddress expressions. /// Optionally passes back an offending user for diagnostic purposes. /// - bool hasAddressTaken(const User** = 0) const; + bool hasAddressTaken(const User** = nullptr) const; /// isDefTriviallyDead - Return true if it is trivially safe to remove /// this function definition from the module (because it isn't externally @@ -429,23 +569,67 @@ 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> &MDs) const; + + /// \brief Drop metadata not in the given list. + /// + /// Drop all metadata from \c this not included in \c KnownIDs. + void dropUnknownMetadata(ArrayRef KnownIDs); + + /// \brief Set the attached subprogram. + /// + /// Calls \a setMetadata() with \a LLVMContext::MD_dbg. + void setSubprogram(DISubprogram *SP); + + /// \brief Get the attached subprogram. + /// + /// Calls \a getMetadata() with \a LLVMContext::MD_dbg and casts the result + /// to \a DISubprogram. + DISubprogram *getSubprogram() const; + 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 * -ilist_traits::getSymTab(Function *F) { - return F ? &F->getValueSymbolTable() : 0; -} +template <> +struct OperandTraits : public OptionalOperandTraits {}; -inline ValueSymbolTable * -ilist_traits::getSymTab(Function *F) { - return F ? &F->getValueSymbolTable() : 0; -} +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Function, Value) } // End llvm namespace