1 //===- AttributeImpl.h - Attribute Internals --------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file defines various helper methods and classes used by
11 /// LLVMContextImpl for creating and managing attributes.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H
16 #define LLVM_LIB_IR_ATTRIBUTEIMPL_H
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/FoldingSet.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/IR/Attributes.h"
23 #include "llvm/IR/ConstantRange.h"
24 #include "llvm/IR/ConstantRangeList.h"
25 #include "llvm/Support/TrailingObjects.h"
38 //===----------------------------------------------------------------------===//
40 /// This class represents a single, uniqued attribute. That attribute
41 /// could be a single enum, a tuple, or a string.
42 class AttributeImpl
: public FoldingSetNode
{
43 unsigned char KindID
; ///< Holds the AttrEntryKind of the attribute
51 ConstantRangeAttrEntry
,
52 ConstantRangeListAttrEntry
,
55 AttributeImpl(AttrEntryKind KindID
) : KindID(KindID
) {}
58 // AttributesImpl is uniqued, these should not be available.
59 AttributeImpl(const AttributeImpl
&) = delete;
60 AttributeImpl
&operator=(const AttributeImpl
&) = delete;
62 bool isEnumAttribute() const { return KindID
== EnumAttrEntry
; }
63 bool isIntAttribute() const { return KindID
== IntAttrEntry
; }
64 bool isStringAttribute() const { return KindID
== StringAttrEntry
; }
65 bool isTypeAttribute() const { return KindID
== TypeAttrEntry
; }
66 bool isConstantRangeAttribute() const {
67 return KindID
== ConstantRangeAttrEntry
;
69 bool isConstantRangeListAttribute() const {
70 return KindID
== ConstantRangeListAttrEntry
;
73 bool hasAttribute(Attribute::AttrKind A
) const;
74 bool hasAttribute(StringRef Kind
) const;
76 Attribute::AttrKind
getKindAsEnum() const;
77 uint64_t getValueAsInt() const;
78 bool getValueAsBool() const;
80 StringRef
getKindAsString() const;
81 StringRef
getValueAsString() const;
83 Type
*getValueAsType() const;
85 const ConstantRange
&getValueAsConstantRange() const;
87 ArrayRef
<ConstantRange
> getValueAsConstantRangeList() const;
89 /// Used to sort attributes. KindOnly controls if the sort includes the
90 /// attributes' values or just the kind.
91 int cmp(const AttributeImpl
&AI
, bool KindOnly
) const;
92 /// Used when sorting the attributes.
93 bool operator<(const AttributeImpl
&AI
) const;
95 void Profile(FoldingSetNodeID
&ID
) const {
96 if (isEnumAttribute())
97 Profile(ID
, getKindAsEnum());
98 else if (isIntAttribute())
99 Profile(ID
, getKindAsEnum(), getValueAsInt());
100 else if (isStringAttribute())
101 Profile(ID
, getKindAsString(), getValueAsString());
102 else if (isTypeAttribute())
103 Profile(ID
, getKindAsEnum(), getValueAsType());
104 else if (isConstantRangeAttribute())
105 Profile(ID
, getKindAsEnum(), getValueAsConstantRange());
107 Profile(ID
, getKindAsEnum(), getValueAsConstantRangeList());
110 static void Profile(FoldingSetNodeID
&ID
, Attribute::AttrKind Kind
) {
111 assert(Attribute::isEnumAttrKind(Kind
) && "Expected enum attribute");
115 static void Profile(FoldingSetNodeID
&ID
, Attribute::AttrKind Kind
,
117 assert(Attribute::isIntAttrKind(Kind
) && "Expected int attribute");
122 static void Profile(FoldingSetNodeID
&ID
, StringRef Kind
, StringRef Values
) {
124 if (!Values
.empty()) ID
.AddString(Values
);
127 static void Profile(FoldingSetNodeID
&ID
, Attribute::AttrKind Kind
,
133 static void Profile(FoldingSetNodeID
&ID
, Attribute::AttrKind Kind
,
134 const ConstantRange
&CR
) {
136 CR
.getLower().Profile(ID
);
137 CR
.getUpper().Profile(ID
);
140 static void Profile(FoldingSetNodeID
&ID
, Attribute::AttrKind Kind
,
141 ArrayRef
<ConstantRange
> Val
) {
143 ID
.AddInteger(Val
.size());
144 for (auto &CR
: Val
) {
145 CR
.getLower().Profile(ID
);
146 CR
.getUpper().Profile(ID
);
151 static_assert(std::is_trivially_destructible
<AttributeImpl
>::value
,
152 "AttributeImpl should be trivially destructible");
154 //===----------------------------------------------------------------------===//
156 /// A set of classes that contain the value of the
157 /// attribute object. There are three main categories: enum attribute entries,
158 /// represented by Attribute::AttrKind; alignment attribute entries; and string
159 /// attribute enties, which are for target-dependent attributes.
161 class EnumAttributeImpl
: public AttributeImpl
{
162 Attribute::AttrKind Kind
;
165 EnumAttributeImpl(AttrEntryKind ID
, Attribute::AttrKind Kind
)
166 : AttributeImpl(ID
), Kind(Kind
) {}
169 EnumAttributeImpl(Attribute::AttrKind Kind
)
170 : AttributeImpl(EnumAttrEntry
), Kind(Kind
) {
171 assert(Kind
!= Attribute::AttrKind::None
&&
172 "Can't create a None attribute!");
175 Attribute::AttrKind
getEnumKind() const { return Kind
; }
178 class IntAttributeImpl
: public EnumAttributeImpl
{
182 IntAttributeImpl(Attribute::AttrKind Kind
, uint64_t Val
)
183 : EnumAttributeImpl(IntAttrEntry
, Kind
), Val(Val
) {
184 assert(Attribute::isIntAttrKind(Kind
) &&
185 "Wrong kind for int attribute!");
188 uint64_t getValue() const { return Val
; }
191 class StringAttributeImpl final
192 : public AttributeImpl
,
193 private TrailingObjects
<StringAttributeImpl
, char> {
194 friend TrailingObjects
;
198 size_t numTrailingObjects(OverloadToken
<char>) const {
199 return KindSize
+ 1 + ValSize
+ 1;
203 StringAttributeImpl(StringRef Kind
, StringRef Val
= StringRef())
204 : AttributeImpl(StringAttrEntry
), KindSize(Kind
.size()),
205 ValSize(Val
.size()) {
206 char *TrailingString
= getTrailingObjects
<char>();
207 // Some users rely on zero-termination.
208 llvm::copy(Kind
, TrailingString
);
209 TrailingString
[KindSize
] = '\0';
210 llvm::copy(Val
, &TrailingString
[KindSize
+ 1]);
211 TrailingString
[KindSize
+ 1 + ValSize
] = '\0';
214 StringRef
getStringKind() const {
215 return StringRef(getTrailingObjects
<char>(), KindSize
);
217 StringRef
getStringValue() const {
218 return StringRef(getTrailingObjects
<char>() + KindSize
+ 1, ValSize
);
221 static size_t totalSizeToAlloc(StringRef Kind
, StringRef Val
) {
222 return TrailingObjects::totalSizeToAlloc
<char>(Kind
.size() + 1 +
227 class TypeAttributeImpl
: public EnumAttributeImpl
{
231 TypeAttributeImpl(Attribute::AttrKind Kind
, Type
*Ty
)
232 : EnumAttributeImpl(TypeAttrEntry
, Kind
), Ty(Ty
) {}
234 Type
*getTypeValue() const { return Ty
; }
237 class ConstantRangeAttributeImpl
: public EnumAttributeImpl
{
241 ConstantRangeAttributeImpl(Attribute::AttrKind Kind
, const ConstantRange
&CR
)
242 : EnumAttributeImpl(ConstantRangeAttrEntry
, Kind
), CR(CR
) {}
244 const ConstantRange
&getConstantRangeValue() const { return CR
; }
247 class ConstantRangeListAttributeImpl final
248 : public EnumAttributeImpl
,
249 private TrailingObjects
<ConstantRangeListAttributeImpl
, ConstantRange
> {
250 friend TrailingObjects
;
253 size_t numTrailingObjects(OverloadToken
<ConstantRange
>) const { return Size
; }
256 ConstantRangeListAttributeImpl(Attribute::AttrKind Kind
,
257 ArrayRef
<ConstantRange
> Val
)
258 : EnumAttributeImpl(ConstantRangeListAttrEntry
, Kind
), Size(Val
.size()) {
260 ConstantRange
*TrailingCR
= getTrailingObjects
<ConstantRange
>();
261 std::uninitialized_copy(Val
.begin(), Val
.end(), TrailingCR
);
264 ~ConstantRangeListAttributeImpl() {
265 ConstantRange
*TrailingCR
= getTrailingObjects
<ConstantRange
>();
266 for (unsigned I
= 0; I
!= Size
; ++I
)
267 TrailingCR
[I
].~ConstantRange();
270 ArrayRef
<ConstantRange
> getConstantRangeListValue() const {
271 return ArrayRef(getTrailingObjects
<ConstantRange
>(), Size
);
274 static size_t totalSizeToAlloc(ArrayRef
<ConstantRange
> Val
) {
275 return TrailingObjects::totalSizeToAlloc
<ConstantRange
>(Val
.size());
279 class AttributeBitSet
{
280 /// Bitset with a bit for each available attribute Attribute::AttrKind.
281 uint8_t AvailableAttrs
[16] = {};
282 static_assert(Attribute::EndAttrKinds
<= sizeof(AvailableAttrs
) * CHAR_BIT
,
283 "Too many attributes");
286 bool hasAttribute(Attribute::AttrKind Kind
) const {
287 return AvailableAttrs
[Kind
/ 8] & (1 << (Kind
% 8));
290 void addAttribute(Attribute::AttrKind Kind
) {
291 AvailableAttrs
[Kind
/ 8] |= 1 << (Kind
% 8);
295 //===----------------------------------------------------------------------===//
297 /// This class represents a group of attributes that apply to one
298 /// element: function, return type, or parameter.
299 class AttributeSetNode final
300 : public FoldingSetNode
,
301 private TrailingObjects
<AttributeSetNode
, Attribute
> {
302 friend TrailingObjects
;
304 unsigned NumAttrs
; ///< Number of attributes in this node.
305 AttributeBitSet AvailableAttrs
; ///< Available enum attributes.
307 DenseMap
<StringRef
, Attribute
> StringAttrs
;
309 AttributeSetNode(ArrayRef
<Attribute
> Attrs
);
311 static AttributeSetNode
*getSorted(LLVMContext
&C
,
312 ArrayRef
<Attribute
> SortedAttrs
);
313 std::optional
<Attribute
> findEnumAttribute(Attribute::AttrKind Kind
) const;
316 // AttributesSetNode is uniqued, these should not be available.
317 AttributeSetNode(const AttributeSetNode
&) = delete;
318 AttributeSetNode
&operator=(const AttributeSetNode
&) = delete;
320 void operator delete(void *p
) { ::operator delete(p
); }
322 static AttributeSetNode
*get(LLVMContext
&C
, const AttrBuilder
&B
);
324 static AttributeSetNode
*get(LLVMContext
&C
, ArrayRef
<Attribute
> Attrs
);
326 /// Return the number of attributes this AttributeList contains.
327 unsigned getNumAttributes() const { return NumAttrs
; }
329 bool hasAttribute(Attribute::AttrKind Kind
) const {
330 return AvailableAttrs
.hasAttribute(Kind
);
332 bool hasAttribute(StringRef Kind
) const;
333 bool hasAttributes() const { return NumAttrs
!= 0; }
335 Attribute
getAttribute(Attribute::AttrKind Kind
) const;
336 Attribute
getAttribute(StringRef Kind
) const;
338 MaybeAlign
getAlignment() const;
339 MaybeAlign
getStackAlignment() const;
340 uint64_t getDereferenceableBytes() const;
341 uint64_t getDereferenceableOrNullBytes() const;
342 std::optional
<std::pair
<unsigned, std::optional
<unsigned>>> getAllocSizeArgs()
344 unsigned getVScaleRangeMin() const;
345 std::optional
<unsigned> getVScaleRangeMax() const;
346 UWTableKind
getUWTableKind() const;
347 AllocFnKind
getAllocKind() const;
348 MemoryEffects
getMemoryEffects() const;
349 CaptureInfo
getCaptureInfo() const;
350 FPClassTest
getNoFPClass() const;
351 std::string
getAsString(bool InAttrGrp
) const;
352 Type
*getAttributeType(Attribute::AttrKind Kind
) const;
354 using iterator
= const Attribute
*;
356 iterator
begin() const { return getTrailingObjects
<Attribute
>(); }
357 iterator
end() const { return begin() + NumAttrs
; }
359 void Profile(FoldingSetNodeID
&ID
) const {
360 Profile(ID
, ArrayRef(begin(), end()));
363 static void Profile(FoldingSetNodeID
&ID
, ArrayRef
<Attribute
> AttrList
) {
364 for (const auto &Attr
: AttrList
)
369 //===----------------------------------------------------------------------===//
371 /// This class represents a set of attributes that apply to the function,
372 /// return type, and parameters.
373 class AttributeListImpl final
374 : public FoldingSetNode
,
375 private TrailingObjects
<AttributeListImpl
, AttributeSet
> {
376 friend class AttributeList
;
377 friend TrailingObjects
;
380 unsigned NumAttrSets
; ///< Number of entries in this set.
381 /// Available enum function attributes.
382 AttributeBitSet AvailableFunctionAttrs
;
383 /// Union of enum attributes available at any index.
384 AttributeBitSet AvailableSomewhereAttrs
;
386 // Helper fn for TrailingObjects class.
387 size_t numTrailingObjects(OverloadToken
<AttributeSet
>) { return NumAttrSets
; }
390 AttributeListImpl(ArrayRef
<AttributeSet
> Sets
);
392 // AttributesSetImpt is uniqued, these should not be available.
393 AttributeListImpl(const AttributeListImpl
&) = delete;
394 AttributeListImpl
&operator=(const AttributeListImpl
&) = delete;
396 /// Return true if the AttributeSet or the FunctionIndex has an
397 /// enum attribute of the given kind.
398 bool hasFnAttribute(Attribute::AttrKind Kind
) const {
399 return AvailableFunctionAttrs
.hasAttribute(Kind
);
402 /// Return true if the specified attribute is set for at least one
403 /// parameter or for the return value. If Index is not nullptr, the index
404 /// of a parameter with the specified attribute is provided.
405 bool hasAttrSomewhere(Attribute::AttrKind Kind
,
406 unsigned *Index
= nullptr) const;
408 using iterator
= const AttributeSet
*;
410 iterator
begin() const { return getTrailingObjects
<AttributeSet
>(); }
411 iterator
end() const { return begin() + NumAttrSets
; }
413 void Profile(FoldingSetNodeID
&ID
) const;
414 static void Profile(FoldingSetNodeID
&ID
, ArrayRef
<AttributeSet
> Nodes
);
419 static_assert(std::is_trivially_destructible
<AttributeListImpl
>::value
,
420 "AttributeListImpl should be trivially destructible");
422 } // end namespace llvm
424 #endif // LLVM_LIB_IR_ATTRIBUTEIMPL_H