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 when sorting the attributes.
90 bool operator<(const AttributeImpl
&AI
) const;
92 void Profile(FoldingSetNodeID
&ID
) const {
93 if (isEnumAttribute())
94 Profile(ID
, getKindAsEnum());
95 else if (isIntAttribute())
96 Profile(ID
, getKindAsEnum(), getValueAsInt());
97 else if (isStringAttribute())
98 Profile(ID
, getKindAsString(), getValueAsString());
99 else if (isTypeAttribute())
100 Profile(ID
, getKindAsEnum(), getValueAsType());
101 else if (isConstantRangeAttribute())
102 Profile(ID
, getKindAsEnum(), getValueAsConstantRange());
104 Profile(ID
, getKindAsEnum(), getValueAsConstantRangeList());
107 static void Profile(FoldingSetNodeID
&ID
, Attribute::AttrKind Kind
) {
108 assert(Attribute::isEnumAttrKind(Kind
) && "Expected enum attribute");
112 static void Profile(FoldingSetNodeID
&ID
, Attribute::AttrKind Kind
,
114 assert(Attribute::isIntAttrKind(Kind
) && "Expected int attribute");
119 static void Profile(FoldingSetNodeID
&ID
, StringRef Kind
, StringRef Values
) {
121 if (!Values
.empty()) ID
.AddString(Values
);
124 static void Profile(FoldingSetNodeID
&ID
, Attribute::AttrKind Kind
,
130 static void Profile(FoldingSetNodeID
&ID
, Attribute::AttrKind Kind
,
131 const ConstantRange
&CR
) {
133 CR
.getLower().Profile(ID
);
134 CR
.getUpper().Profile(ID
);
137 static void Profile(FoldingSetNodeID
&ID
, Attribute::AttrKind Kind
,
138 ArrayRef
<ConstantRange
> Val
) {
140 ID
.AddInteger(Val
.size());
141 for (auto &CR
: Val
) {
142 CR
.getLower().Profile(ID
);
143 CR
.getUpper().Profile(ID
);
148 static_assert(std::is_trivially_destructible
<AttributeImpl
>::value
,
149 "AttributeImpl should be trivially destructible");
151 //===----------------------------------------------------------------------===//
153 /// A set of classes that contain the value of the
154 /// attribute object. There are three main categories: enum attribute entries,
155 /// represented by Attribute::AttrKind; alignment attribute entries; and string
156 /// attribute enties, which are for target-dependent attributes.
158 class EnumAttributeImpl
: public AttributeImpl
{
159 Attribute::AttrKind Kind
;
162 EnumAttributeImpl(AttrEntryKind ID
, Attribute::AttrKind Kind
)
163 : AttributeImpl(ID
), Kind(Kind
) {}
166 EnumAttributeImpl(Attribute::AttrKind Kind
)
167 : AttributeImpl(EnumAttrEntry
), Kind(Kind
) {
168 assert(Kind
!= Attribute::AttrKind::None
&&
169 "Can't create a None attribute!");
172 Attribute::AttrKind
getEnumKind() const { return Kind
; }
175 class IntAttributeImpl
: public EnumAttributeImpl
{
179 IntAttributeImpl(Attribute::AttrKind Kind
, uint64_t Val
)
180 : EnumAttributeImpl(IntAttrEntry
, Kind
), Val(Val
) {
181 assert(Attribute::isIntAttrKind(Kind
) &&
182 "Wrong kind for int attribute!");
185 uint64_t getValue() const { return Val
; }
188 class StringAttributeImpl final
189 : public AttributeImpl
,
190 private TrailingObjects
<StringAttributeImpl
, char> {
191 friend TrailingObjects
;
195 size_t numTrailingObjects(OverloadToken
<char>) const {
196 return KindSize
+ 1 + ValSize
+ 1;
200 StringAttributeImpl(StringRef Kind
, StringRef Val
= StringRef())
201 : AttributeImpl(StringAttrEntry
), KindSize(Kind
.size()),
202 ValSize(Val
.size()) {
203 char *TrailingString
= getTrailingObjects
<char>();
204 // Some users rely on zero-termination.
205 llvm::copy(Kind
, TrailingString
);
206 TrailingString
[KindSize
] = '\0';
207 llvm::copy(Val
, &TrailingString
[KindSize
+ 1]);
208 TrailingString
[KindSize
+ 1 + ValSize
] = '\0';
211 StringRef
getStringKind() const {
212 return StringRef(getTrailingObjects
<char>(), KindSize
);
214 StringRef
getStringValue() const {
215 return StringRef(getTrailingObjects
<char>() + KindSize
+ 1, ValSize
);
218 static size_t totalSizeToAlloc(StringRef Kind
, StringRef Val
) {
219 return TrailingObjects::totalSizeToAlloc
<char>(Kind
.size() + 1 +
224 class TypeAttributeImpl
: public EnumAttributeImpl
{
228 TypeAttributeImpl(Attribute::AttrKind Kind
, Type
*Ty
)
229 : EnumAttributeImpl(TypeAttrEntry
, Kind
), Ty(Ty
) {}
231 Type
*getTypeValue() const { return Ty
; }
234 class ConstantRangeAttributeImpl
: public EnumAttributeImpl
{
238 ConstantRangeAttributeImpl(Attribute::AttrKind Kind
, const ConstantRange
&CR
)
239 : EnumAttributeImpl(ConstantRangeAttrEntry
, Kind
), CR(CR
) {}
241 const ConstantRange
&getConstantRangeValue() const { return CR
; }
244 class ConstantRangeListAttributeImpl final
245 : public EnumAttributeImpl
,
246 private TrailingObjects
<ConstantRangeListAttributeImpl
, ConstantRange
> {
247 friend TrailingObjects
;
250 size_t numTrailingObjects(OverloadToken
<ConstantRange
>) const { return Size
; }
253 ConstantRangeListAttributeImpl(Attribute::AttrKind Kind
,
254 ArrayRef
<ConstantRange
> Val
)
255 : EnumAttributeImpl(ConstantRangeListAttrEntry
, Kind
), Size(Val
.size()) {
257 ConstantRange
*TrailingCR
= getTrailingObjects
<ConstantRange
>();
258 std::uninitialized_copy(Val
.begin(), Val
.end(), TrailingCR
);
261 ~ConstantRangeListAttributeImpl() {
262 ConstantRange
*TrailingCR
= getTrailingObjects
<ConstantRange
>();
263 for (unsigned I
= 0; I
!= Size
; ++I
)
264 TrailingCR
[I
].~ConstantRange();
267 ArrayRef
<ConstantRange
> getConstantRangeListValue() const {
268 return ArrayRef(getTrailingObjects
<ConstantRange
>(), Size
);
271 static size_t totalSizeToAlloc(ArrayRef
<ConstantRange
> Val
) {
272 return TrailingObjects::totalSizeToAlloc
<ConstantRange
>(Val
.size());
276 class AttributeBitSet
{
277 /// Bitset with a bit for each available attribute Attribute::AttrKind.
278 uint8_t AvailableAttrs
[12] = {};
279 static_assert(Attribute::EndAttrKinds
<= sizeof(AvailableAttrs
) * CHAR_BIT
,
280 "Too many attributes");
283 bool hasAttribute(Attribute::AttrKind Kind
) const {
284 return AvailableAttrs
[Kind
/ 8] & (1 << (Kind
% 8));
287 void addAttribute(Attribute::AttrKind Kind
) {
288 AvailableAttrs
[Kind
/ 8] |= 1 << (Kind
% 8);
292 //===----------------------------------------------------------------------===//
294 /// This class represents a group of attributes that apply to one
295 /// element: function, return type, or parameter.
296 class AttributeSetNode final
297 : public FoldingSetNode
,
298 private TrailingObjects
<AttributeSetNode
, Attribute
> {
299 friend TrailingObjects
;
301 unsigned NumAttrs
; ///< Number of attributes in this node.
302 AttributeBitSet AvailableAttrs
; ///< Available enum attributes.
304 DenseMap
<StringRef
, Attribute
> StringAttrs
;
306 AttributeSetNode(ArrayRef
<Attribute
> Attrs
);
308 static AttributeSetNode
*getSorted(LLVMContext
&C
,
309 ArrayRef
<Attribute
> SortedAttrs
);
310 std::optional
<Attribute
> findEnumAttribute(Attribute::AttrKind Kind
) const;
313 // AttributesSetNode is uniqued, these should not be available.
314 AttributeSetNode(const AttributeSetNode
&) = delete;
315 AttributeSetNode
&operator=(const AttributeSetNode
&) = delete;
317 void operator delete(void *p
) { ::operator delete(p
); }
319 static AttributeSetNode
*get(LLVMContext
&C
, const AttrBuilder
&B
);
321 static AttributeSetNode
*get(LLVMContext
&C
, ArrayRef
<Attribute
> Attrs
);
323 /// Return the number of attributes this AttributeList contains.
324 unsigned getNumAttributes() const { return NumAttrs
; }
326 bool hasAttribute(Attribute::AttrKind Kind
) const {
327 return AvailableAttrs
.hasAttribute(Kind
);
329 bool hasAttribute(StringRef Kind
) const;
330 bool hasAttributes() const { return NumAttrs
!= 0; }
332 Attribute
getAttribute(Attribute::AttrKind Kind
) const;
333 Attribute
getAttribute(StringRef Kind
) const;
335 MaybeAlign
getAlignment() const;
336 MaybeAlign
getStackAlignment() const;
337 uint64_t getDereferenceableBytes() const;
338 uint64_t getDereferenceableOrNullBytes() const;
339 std::optional
<std::pair
<unsigned, std::optional
<unsigned>>> getAllocSizeArgs()
341 unsigned getVScaleRangeMin() const;
342 std::optional
<unsigned> getVScaleRangeMax() const;
343 UWTableKind
getUWTableKind() const;
344 AllocFnKind
getAllocKind() const;
345 MemoryEffects
getMemoryEffects() const;
346 FPClassTest
getNoFPClass() const;
347 std::string
getAsString(bool InAttrGrp
) const;
348 Type
*getAttributeType(Attribute::AttrKind Kind
) const;
350 using iterator
= const Attribute
*;
352 iterator
begin() const { return getTrailingObjects
<Attribute
>(); }
353 iterator
end() const { return begin() + NumAttrs
; }
355 void Profile(FoldingSetNodeID
&ID
) const {
356 Profile(ID
, ArrayRef(begin(), end()));
359 static void Profile(FoldingSetNodeID
&ID
, ArrayRef
<Attribute
> AttrList
) {
360 for (const auto &Attr
: AttrList
)
365 //===----------------------------------------------------------------------===//
367 /// This class represents a set of attributes that apply to the function,
368 /// return type, and parameters.
369 class AttributeListImpl final
370 : public FoldingSetNode
,
371 private TrailingObjects
<AttributeListImpl
, AttributeSet
> {
372 friend class AttributeList
;
373 friend TrailingObjects
;
376 unsigned NumAttrSets
; ///< Number of entries in this set.
377 /// Available enum function attributes.
378 AttributeBitSet AvailableFunctionAttrs
;
379 /// Union of enum attributes available at any index.
380 AttributeBitSet AvailableSomewhereAttrs
;
382 // Helper fn for TrailingObjects class.
383 size_t numTrailingObjects(OverloadToken
<AttributeSet
>) { return NumAttrSets
; }
386 AttributeListImpl(ArrayRef
<AttributeSet
> Sets
);
388 // AttributesSetImpt is uniqued, these should not be available.
389 AttributeListImpl(const AttributeListImpl
&) = delete;
390 AttributeListImpl
&operator=(const AttributeListImpl
&) = delete;
392 /// Return true if the AttributeSet or the FunctionIndex has an
393 /// enum attribute of the given kind.
394 bool hasFnAttribute(Attribute::AttrKind Kind
) const {
395 return AvailableFunctionAttrs
.hasAttribute(Kind
);
398 /// Return true if the specified attribute is set for at least one
399 /// parameter or for the return value. If Index is not nullptr, the index
400 /// of a parameter with the specified attribute is provided.
401 bool hasAttrSomewhere(Attribute::AttrKind Kind
,
402 unsigned *Index
= nullptr) const;
404 using iterator
= const AttributeSet
*;
406 iterator
begin() const { return getTrailingObjects
<AttributeSet
>(); }
407 iterator
end() const { return begin() + NumAttrSets
; }
409 void Profile(FoldingSetNodeID
&ID
) const;
410 static void Profile(FoldingSetNodeID
&ID
, ArrayRef
<AttributeSet
> Nodes
);
415 static_assert(std::is_trivially_destructible
<AttributeListImpl
>::value
,
416 "AttributeListImpl should be trivially destructible");
418 } // end namespace llvm
420 #endif // LLVM_LIB_IR_ATTRIBUTEIMPL_H