/// \brief Return true if attribute exists at the given index.
bool hasAttributes(unsigned Index) const;
+ /// \brief Equivalent to hasAttribute(AttributeSet::FunctionIndex, Kind) but
+ /// may be faster.
+ bool hasFnAttribute(Attribute::AttrKind Kind) const;
+
/// \brief Return true if the specified attribute is set for at least one
/// parameter or for the return value.
bool hasAttrSomewhere(Attribute::AttrKind Attr) const;
/// @brief Return true if the function has the attribute.
bool hasFnAttribute(Attribute::AttrKind Kind) const {
- return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind);
+ return AttributeSets.hasFnAttribute(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 {
+ if (!hasFnAttribute(Kind))
+ return Attribute();
return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind);
}
Attribute getFnAttribute(StringRef Kind) const {
/// \brief Return the stack alignment for the function.
unsigned getFnStackAlignment() const {
+ if (!hasFnAttribute(Attribute::StackAlignment))
+ return 0;
return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex);
}
private:
LLVMContext &Context;
unsigned NumAttrs; ///< Number of entries in this set.
+ /// Bitset with a bit for each available attribute Attribute::AttrKind.
+ uint64_t AvailableFunctionAttrs;
+ static_assert(Attribute::EndAttrKinds
+ <= sizeof(AvailableFunctionAttrs)*CHAR_BIT,
+ "Too many attributes");
// Helper fn for TrailingObjects class.
size_t numTrailingObjects(OverloadToken<IndexAttrPair>) { return NumAttrs; }
public:
AttributeSetImpl(LLVMContext &C,
ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs)
- : Context(C), NumAttrs(Attrs.size()) {
+ : Context(C), NumAttrs(Attrs.size()), AvailableFunctionAttrs(0) {
#ifndef NDEBUG
if (Attrs.size() >= 2) {
#endif
// There's memory after the node where we can store the entries in.
std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<IndexAttrPair>());
+
+ // Initialize AvailableFunctionAttrs summary bitset.
+ if (NumAttrs > 0) {
+ static_assert(AttributeSet::FunctionIndex == ~0u,
+ "FunctionIndex should be biggest possible index");
+ const std::pair<unsigned, AttributeSetNode *> &Last = Attrs.back();
+ if (Last.first == AttributeSet::FunctionIndex) {
+ const AttributeSetNode *Node = Last.second;
+ for (AttributeSetNode::iterator I = Node->begin(), E = Node->end();
+ I != E; ++I) {
+ if (!I->isStringAttribute())
+ AvailableFunctionAttrs |= ((uint64_t)1) << I->getKindAsEnum();
+ }
+ }
+ }
}
/// \brief Get the context that created this AttributeSetImpl.
return getNode(Slot)->second;
}
+ /// \brief Return true if the AttributeSetNode for the FunctionIndex has an
+ /// enum attribute of the given kind.
+ bool hasFnAttribute(Attribute::AttrKind Kind) const {
+ return AvailableFunctionAttrs & ((uint64_t)1) << Kind;
+ }
+
typedef AttributeSetNode::iterator iterator;
iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); }
iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); }