blob: fbfe5854594fdca58daafc69c0596894e7e219b5 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- llvm/Attributes.h - Container for Attributes -------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8//
9/// \file
Andrew Scullcdfcccc2018-10-05 20:58:37 +010010/// This file contains the simple types necessary to represent the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010011/// attributes associated with functions and their calls.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_IR_ATTRIBUTES_H
16#define LLVM_IR_ATTRIBUTES_H
17
18#include "llvm-c/Types.h"
19#include "llvm/ADT/ArrayRef.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010020#include "llvm/ADT/Optional.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/ADT/iterator_range.h"
Andrew Scullcdfcccc2018-10-05 20:58:37 +010023#include "llvm/Config/llvm-config.h"
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020024#include "llvm/Support/Alignment.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010025#include "llvm/Support/PointerLikeTypeTraits.h"
26#include <bitset>
27#include <cassert>
28#include <cstdint>
29#include <map>
30#include <string>
31#include <utility>
32
33namespace llvm {
34
35class AttrBuilder;
36class AttributeImpl;
37class AttributeListImpl;
38class AttributeSetNode;
39template<typename T> struct DenseMapInfo;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020040class FoldingSetNodeID;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010041class Function;
42class LLVMContext;
43class Type;
44
45//===----------------------------------------------------------------------===//
46/// \class
Andrew Scullcdfcccc2018-10-05 20:58:37 +010047/// Functions, function parameters, and return types can have attributes
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010048/// to indicate how they should be treated by optimizations and code
49/// generation. This class represents one of those attributes. It's light-weight
50/// and should be passed around by-value.
51class Attribute {
52public:
53 /// This enumeration lists the attributes that can be associated with
54 /// parameters, function results, or the function itself.
55 ///
56 /// Note: The `uwtable' attribute is about the ABI or the user mandating an
57 /// entry in the unwind table. The `nounwind' attribute is about an exception
58 /// passing by the function.
59 ///
60 /// In a theoretical system that uses tables for profiling and SjLj for
61 /// exceptions, they would be fully independent. In a normal system that uses
62 /// tables for both, the semantics are:
63 ///
64 /// nil = Needs an entry because an exception might pass by.
65 /// nounwind = No need for an entry
66 /// uwtable = Needs an entry because the ABI says so and because
67 /// an exception might pass by.
68 /// uwtable + nounwind = Needs an entry because the ABI says so.
69
70 enum AttrKind {
71 // IR-Level Attributes
72 None, ///< No attributes have been set
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020073 #define GET_ATTR_NAMES
74 #define ATTRIBUTE_ENUM(ENUM_NAME, OTHER) ENUM_NAME,
Andrew Scullcdfcccc2018-10-05 20:58:37 +010075 #include "llvm/IR/Attributes.inc"
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020076 EndAttrKinds, ///< Sentinal value useful for loops
77 EmptyKey, ///< Use as Empty key for DenseMap of AttrKind
78 TombstoneKey, ///< Use as Tombstone key for DenseMap of AttrKind
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010079 };
80
81private:
82 AttributeImpl *pImpl = nullptr;
83
84 Attribute(AttributeImpl *A) : pImpl(A) {}
85
86public:
87 Attribute() = default;
88
89 //===--------------------------------------------------------------------===//
90 // Attribute Construction
91 //===--------------------------------------------------------------------===//
92
Andrew Scullcdfcccc2018-10-05 20:58:37 +010093 /// Return a uniquified Attribute object.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010094 static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0);
95 static Attribute get(LLVMContext &Context, StringRef Kind,
96 StringRef Val = StringRef());
Andrew Walbran3d2c1972020-04-07 12:24:26 +010097 static Attribute get(LLVMContext &Context, AttrKind Kind, Type *Ty);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010098
Andrew Scullcdfcccc2018-10-05 20:58:37 +010099 /// Return a uniquified Attribute object that has the specific
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100100 /// alignment set.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200101 static Attribute getWithAlignment(LLVMContext &Context, Align Alignment);
102 static Attribute getWithStackAlignment(LLVMContext &Context, Align Alignment);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100103 static Attribute getWithDereferenceableBytes(LLVMContext &Context,
104 uint64_t Bytes);
105 static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context,
106 uint64_t Bytes);
107 static Attribute getWithAllocSizeArgs(LLVMContext &Context,
108 unsigned ElemSizeArg,
109 const Optional<unsigned> &NumElemsArg);
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100110 static Attribute getWithByValType(LLVMContext &Context, Type *Ty);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200111 static Attribute getWithStructRetType(LLVMContext &Context, Type *Ty);
112 static Attribute getWithByRefType(LLVMContext &Context, Type *Ty);
113 static Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty);
114
115 /// For a typed attribute, return the equivalent attribute with the type
116 /// changed to \p ReplacementTy.
117 Attribute getWithNewType(LLVMContext &Context, Type *ReplacementTy) {
118 assert(isTypeAttribute() && "this requires a typed attribute");
119 return get(Context, getKindAsEnum(), ReplacementTy);
120 }
121
122 static Attribute::AttrKind getAttrKindFromName(StringRef AttrName);
123
124 static StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind);
125
126 /// Return true if and only if the attribute has an Argument.
127 static bool doesAttrKindHaveArgument(Attribute::AttrKind AttrKind);
128
129 /// Return true if the provided string matches the IR name of an attribute.
130 /// example: "noalias" return true but not "NoAlias"
131 static bool isExistingAttribute(StringRef Name);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100132
133 //===--------------------------------------------------------------------===//
134 // Attribute Accessors
135 //===--------------------------------------------------------------------===//
136
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100137 /// Return true if the attribute is an Attribute::AttrKind type.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100138 bool isEnumAttribute() const;
139
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100140 /// Return true if the attribute is an integer attribute.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100141 bool isIntAttribute() const;
142
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100143 /// Return true if the attribute is a string (target-dependent)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100144 /// attribute.
145 bool isStringAttribute() const;
146
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100147 /// Return true if the attribute is a type attribute.
148 bool isTypeAttribute() const;
149
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200150 /// Return true if the attribute is any kind of attribute.
151 bool isValid() const { return pImpl; }
152
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100153 /// Return true if the attribute is present.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100154 bool hasAttribute(AttrKind Val) const;
155
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100156 /// Return true if the target-dependent attribute is present.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100157 bool hasAttribute(StringRef Val) const;
158
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100159 /// Return the attribute's kind as an enum (Attribute::AttrKind). This
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100160 /// requires the attribute to be an enum or integer attribute.
161 Attribute::AttrKind getKindAsEnum() const;
162
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100163 /// Return the attribute's value as an integer. This requires that the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100164 /// attribute be an integer attribute.
165 uint64_t getValueAsInt() const;
166
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100167 /// Return the attribute's kind as a string. This requires the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100168 /// attribute to be a string attribute.
169 StringRef getKindAsString() const;
170
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100171 /// Return the attribute's value as a string. This requires the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100172 /// attribute to be a string attribute.
173 StringRef getValueAsString() const;
174
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100175 /// Return the attribute's value as a Type. This requires the attribute to be
176 /// a type attribute.
177 Type *getValueAsType() const;
178
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100179 /// Returns the alignment field of an attribute as a byte alignment
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100180 /// value.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200181 MaybeAlign getAlignment() const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100182
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100183 /// Returns the stack alignment field of an attribute as a byte
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100184 /// alignment value.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200185 MaybeAlign getStackAlignment() const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100186
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100187 /// Returns the number of dereferenceable bytes from the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100188 /// dereferenceable attribute.
189 uint64_t getDereferenceableBytes() const;
190
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100191 /// Returns the number of dereferenceable_or_null bytes from the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100192 /// dereferenceable_or_null attribute.
193 uint64_t getDereferenceableOrNullBytes() const;
194
195 /// Returns the argument numbers for the allocsize attribute (or pair(0, 0)
196 /// if not known).
197 std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
198
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100199 /// The Attribute is converted to a string of equivalent mnemonic. This
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100200 /// is, presumably, for writing out the mnemonics for the assembly writer.
201 std::string getAsString(bool InAttrGrp = false) const;
202
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100203 /// Equality and non-equality operators.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100204 bool operator==(Attribute A) const { return pImpl == A.pImpl; }
205 bool operator!=(Attribute A) const { return pImpl != A.pImpl; }
206
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100207 /// Less-than operator. Useful for sorting the attributes list.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100208 bool operator<(Attribute A) const;
209
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200210 void Profile(FoldingSetNodeID &ID) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100211
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100212 /// Return a raw pointer that uniquely identifies this attribute.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100213 void *getRawPointer() const {
214 return pImpl;
215 }
216
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100217 /// Get an attribute from a raw pointer created by getRawPointer.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100218 static Attribute fromRawPointer(void *RawPtr) {
219 return Attribute(reinterpret_cast<AttributeImpl*>(RawPtr));
220 }
221};
222
223// Specialized opaque value conversions.
224inline LLVMAttributeRef wrap(Attribute Attr) {
225 return reinterpret_cast<LLVMAttributeRef>(Attr.getRawPointer());
226}
227
228// Specialized opaque value conversions.
229inline Attribute unwrap(LLVMAttributeRef Attr) {
230 return Attribute::fromRawPointer(Attr);
231}
232
233//===----------------------------------------------------------------------===//
234/// \class
235/// This class holds the attributes for a particular argument, parameter,
236/// function, or return value. It is an immutable value type that is cheap to
237/// copy. Adding and removing enum attributes is intended to be fast, but adding
238/// and removing string or integer attributes involves a FoldingSet lookup.
239class AttributeSet {
240 friend AttributeListImpl;
241 template <typename Ty> friend struct DenseMapInfo;
242
243 // TODO: Extract AvailableAttrs from AttributeSetNode and store them here.
244 // This will allow an efficient implementation of addAttribute and
245 // removeAttribute for enum attrs.
246
247 /// Private implementation pointer.
248 AttributeSetNode *SetNode = nullptr;
249
250private:
251 explicit AttributeSet(AttributeSetNode *ASN) : SetNode(ASN) {}
252
253public:
254 /// AttributeSet is a trivially copyable value type.
255 AttributeSet() = default;
256 AttributeSet(const AttributeSet &) = default;
257 ~AttributeSet() = default;
258
259 static AttributeSet get(LLVMContext &C, const AttrBuilder &B);
260 static AttributeSet get(LLVMContext &C, ArrayRef<Attribute> Attrs);
261
262 bool operator==(const AttributeSet &O) const { return SetNode == O.SetNode; }
263 bool operator!=(const AttributeSet &O) const { return !(*this == O); }
264
265 /// Add an argument attribute. Returns a new set because attribute sets are
266 /// immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100267 LLVM_NODISCARD AttributeSet addAttribute(LLVMContext &C,
268 Attribute::AttrKind Kind) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100269
270 /// Add a target-dependent attribute. Returns a new set because attribute sets
271 /// are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100272 LLVM_NODISCARD AttributeSet addAttribute(LLVMContext &C, StringRef Kind,
273 StringRef Value = StringRef()) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100274
275 /// Add attributes to the attribute set. Returns a new set because attribute
276 /// sets are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100277 LLVM_NODISCARD AttributeSet addAttributes(LLVMContext &C,
278 AttributeSet AS) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100279
280 /// Remove the specified attribute from this set. Returns a new set because
281 /// attribute sets are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100282 LLVM_NODISCARD AttributeSet removeAttribute(LLVMContext &C,
283 Attribute::AttrKind Kind) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100284
285 /// Remove the specified attribute from this set. Returns a new set because
286 /// attribute sets are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100287 LLVM_NODISCARD AttributeSet removeAttribute(LLVMContext &C,
288 StringRef Kind) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100289
290 /// Remove the specified attributes from this set. Returns a new set because
291 /// attribute sets are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100292 LLVM_NODISCARD AttributeSet
293 removeAttributes(LLVMContext &C, const AttrBuilder &AttrsToRemove) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100294
295 /// Return the number of attributes in this set.
296 unsigned getNumAttributes() const;
297
298 /// Return true if attributes exists in this set.
299 bool hasAttributes() const { return SetNode != nullptr; }
300
301 /// Return true if the attribute exists in this set.
302 bool hasAttribute(Attribute::AttrKind Kind) const;
303
304 /// Return true if the attribute exists in this set.
305 bool hasAttribute(StringRef Kind) const;
306
307 /// Return the attribute object.
308 Attribute getAttribute(Attribute::AttrKind Kind) const;
309
310 /// Return the target-dependent attribute object.
311 Attribute getAttribute(StringRef Kind) const;
312
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200313 MaybeAlign getAlignment() const;
314 MaybeAlign getStackAlignment() const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100315 uint64_t getDereferenceableBytes() const;
316 uint64_t getDereferenceableOrNullBytes() const;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100317 Type *getByValType() const;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200318 Type *getStructRetType() const;
319 Type *getByRefType() const;
320 Type *getPreallocatedType() const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100321 std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
322 std::string getAsString(bool InAttrGrp = false) const;
323
324 using iterator = const Attribute *;
325
326 iterator begin() const;
327 iterator end() const;
328#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
329 void dump() const;
330#endif
331};
332
333//===----------------------------------------------------------------------===//
334/// \class
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100335/// Provide DenseMapInfo for AttributeSet.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100336template <> struct DenseMapInfo<AttributeSet> {
337 static AttributeSet getEmptyKey() {
338 auto Val = static_cast<uintptr_t>(-1);
339 Val <<= PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
340 return AttributeSet(reinterpret_cast<AttributeSetNode *>(Val));
341 }
342
343 static AttributeSet getTombstoneKey() {
344 auto Val = static_cast<uintptr_t>(-2);
345 Val <<= PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
346 return AttributeSet(reinterpret_cast<AttributeSetNode *>(Val));
347 }
348
349 static unsigned getHashValue(AttributeSet AS) {
350 return (unsigned((uintptr_t)AS.SetNode) >> 4) ^
351 (unsigned((uintptr_t)AS.SetNode) >> 9);
352 }
353
354 static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; }
355};
356
357//===----------------------------------------------------------------------===//
358/// \class
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100359/// This class holds the attributes for a function, its return value, and
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100360/// its parameters. You access the attributes for each of them via an index into
361/// the AttributeList object. The function attributes are at index
362/// `AttributeList::FunctionIndex', the return value is at index
363/// `AttributeList::ReturnIndex', and the attributes for the parameters start at
364/// index `AttributeList::FirstArgIndex'.
365class AttributeList {
366public:
367 enum AttrIndex : unsigned {
368 ReturnIndex = 0U,
369 FunctionIndex = ~0U,
370 FirstArgIndex = 1,
371 };
372
373private:
374 friend class AttrBuilder;
375 friend class AttributeListImpl;
376 friend class AttributeSet;
377 friend class AttributeSetNode;
378 template <typename Ty> friend struct DenseMapInfo;
379
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100380 /// The attributes that we are managing. This can be null to represent
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100381 /// the empty attributes list.
382 AttributeListImpl *pImpl = nullptr;
383
384public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100385 /// Create an AttributeList with the specified parameters in it.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100386 static AttributeList get(LLVMContext &C,
387 ArrayRef<std::pair<unsigned, Attribute>> Attrs);
388 static AttributeList get(LLVMContext &C,
389 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs);
390
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100391 /// Create an AttributeList from attribute sets for a function, its
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100392 /// return value, and all of its arguments.
393 static AttributeList get(LLVMContext &C, AttributeSet FnAttrs,
394 AttributeSet RetAttrs,
395 ArrayRef<AttributeSet> ArgAttrs);
396
397private:
398 explicit AttributeList(AttributeListImpl *LI) : pImpl(LI) {}
399
400 static AttributeList getImpl(LLVMContext &C, ArrayRef<AttributeSet> AttrSets);
401
402public:
403 AttributeList() = default;
404
405 //===--------------------------------------------------------------------===//
406 // AttributeList Construction and Mutation
407 //===--------------------------------------------------------------------===//
408
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100409 /// Return an AttributeList with the specified parameters in it.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100410 static AttributeList get(LLVMContext &C, ArrayRef<AttributeList> Attrs);
411 static AttributeList get(LLVMContext &C, unsigned Index,
412 ArrayRef<Attribute::AttrKind> Kinds);
413 static AttributeList get(LLVMContext &C, unsigned Index,
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200414 ArrayRef<Attribute::AttrKind> Kinds,
415 ArrayRef<uint64_t> Values);
416 static AttributeList get(LLVMContext &C, unsigned Index,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100417 ArrayRef<StringRef> Kind);
418 static AttributeList get(LLVMContext &C, unsigned Index,
419 const AttrBuilder &B);
420
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100421 /// Add an attribute to the attribute set at the given index.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100422 /// Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100423 LLVM_NODISCARD AttributeList addAttribute(LLVMContext &C, unsigned Index,
424 Attribute::AttrKind Kind) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100425
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100426 /// Add an attribute to the attribute set at the given index.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100427 /// Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100428 LLVM_NODISCARD AttributeList
429 addAttribute(LLVMContext &C, unsigned Index, StringRef Kind,
430 StringRef Value = StringRef()) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100431
432 /// Add an attribute to the attribute set at the given index.
433 /// Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100434 LLVM_NODISCARD AttributeList addAttribute(LLVMContext &C, unsigned Index,
435 Attribute A) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100436
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100437 /// Add attributes to the attribute set at the given index.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100438 /// Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100439 LLVM_NODISCARD AttributeList addAttributes(LLVMContext &C, unsigned Index,
440 const AttrBuilder &B) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100441
442 /// Add an argument attribute to the list. Returns a new list because
443 /// attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100444 LLVM_NODISCARD AttributeList addParamAttribute(
445 LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind) const {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100446 return addAttribute(C, ArgNo + FirstArgIndex, Kind);
447 }
448
449 /// Add an argument attribute to the list. Returns a new list because
450 /// attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100451 LLVM_NODISCARD AttributeList
452 addParamAttribute(LLVMContext &C, unsigned ArgNo, StringRef Kind,
453 StringRef Value = StringRef()) const {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100454 return addAttribute(C, ArgNo + FirstArgIndex, Kind, Value);
455 }
456
457 /// Add an attribute to the attribute list at the given arg indices. Returns a
458 /// new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100459 LLVM_NODISCARD AttributeList addParamAttribute(LLVMContext &C,
460 ArrayRef<unsigned> ArgNos,
461 Attribute A) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100462
463 /// Add an argument attribute to the list. Returns a new list because
464 /// attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100465 LLVM_NODISCARD AttributeList addParamAttributes(LLVMContext &C,
466 unsigned ArgNo,
467 const AttrBuilder &B) const {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100468 return addAttributes(C, ArgNo + FirstArgIndex, B);
469 }
470
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100471 /// Remove the specified attribute at the specified index from this
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100472 /// attribute list. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100473 LLVM_NODISCARD AttributeList removeAttribute(LLVMContext &C, unsigned Index,
474 Attribute::AttrKind Kind) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100475
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100476 /// Remove the specified attribute at the specified index from this
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100477 /// attribute list. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100478 LLVM_NODISCARD AttributeList removeAttribute(LLVMContext &C, unsigned Index,
479 StringRef Kind) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100480
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100481 /// Remove the specified attributes at the specified index from this
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100482 /// attribute list. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100483 LLVM_NODISCARD AttributeList removeAttributes(
484 LLVMContext &C, unsigned Index, const AttrBuilder &AttrsToRemove) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100485
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100486 /// Remove all attributes at the specified index from this
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100487 /// attribute list. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100488 LLVM_NODISCARD AttributeList removeAttributes(LLVMContext &C,
489 unsigned Index) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100490
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100491 /// Remove the specified attribute at the specified arg index from this
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100492 /// attribute list. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100493 LLVM_NODISCARD AttributeList removeParamAttribute(
494 LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind) const {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100495 return removeAttribute(C, ArgNo + FirstArgIndex, Kind);
496 }
497
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100498 /// Remove the specified attribute at the specified arg index from this
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100499 /// attribute list. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100500 LLVM_NODISCARD AttributeList removeParamAttribute(LLVMContext &C,
501 unsigned ArgNo,
502 StringRef Kind) const {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100503 return removeAttribute(C, ArgNo + FirstArgIndex, Kind);
504 }
505
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100506 /// Remove the specified attribute at the specified arg index from this
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100507 /// attribute list. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100508 LLVM_NODISCARD AttributeList removeParamAttributes(
509 LLVMContext &C, unsigned ArgNo, const AttrBuilder &AttrsToRemove) const {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100510 return removeAttributes(C, ArgNo + FirstArgIndex, AttrsToRemove);
511 }
512
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100513 /// Remove all attributes at the specified arg index from this
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100514 /// attribute list. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100515 LLVM_NODISCARD AttributeList removeParamAttributes(LLVMContext &C,
516 unsigned ArgNo) const {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100517 return removeAttributes(C, ArgNo + FirstArgIndex);
518 }
519
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200520 /// Replace the type contained by attribute \p AttrKind at index \p ArgNo wih
521 /// \p ReplacementTy, preserving all other attributes.
522 LLVM_NODISCARD AttributeList replaceAttributeType(LLVMContext &C,
523 unsigned ArgNo,
524 Attribute::AttrKind Kind,
525 Type *ReplacementTy) const {
526 Attribute Attr = getAttribute(ArgNo, Kind);
527 auto Attrs = removeAttribute(C, ArgNo, Kind);
528 return Attrs.addAttribute(C, ArgNo, Attr.getWithNewType(C, ReplacementTy));
529 }
530
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100531 /// \brief Add the dereferenceable attribute to the attribute set at the given
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100532 /// index. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100533 LLVM_NODISCARD AttributeList addDereferenceableAttr(LLVMContext &C,
534 unsigned Index,
535 uint64_t Bytes) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100536
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100537 /// \brief Add the dereferenceable attribute to the attribute set at the given
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100538 /// arg index. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100539 LLVM_NODISCARD AttributeList addDereferenceableParamAttr(
540 LLVMContext &C, unsigned ArgNo, uint64_t Bytes) const {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100541 return addDereferenceableAttr(C, ArgNo + FirstArgIndex, Bytes);
542 }
543
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100544 /// Add the dereferenceable_or_null attribute to the attribute set at
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100545 /// the given index. Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100546 LLVM_NODISCARD AttributeList addDereferenceableOrNullAttr(
547 LLVMContext &C, unsigned Index, uint64_t Bytes) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100548
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100549 /// Add the dereferenceable_or_null attribute to the attribute set at
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100550 /// the given arg index. Returns a new list because attribute lists are
551 /// immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100552 LLVM_NODISCARD AttributeList addDereferenceableOrNullParamAttr(
553 LLVMContext &C, unsigned ArgNo, uint64_t Bytes) const {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100554 return addDereferenceableOrNullAttr(C, ArgNo + FirstArgIndex, Bytes);
555 }
556
557 /// Add the allocsize attribute to the attribute set at the given index.
558 /// Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100559 LLVM_NODISCARD AttributeList
560 addAllocSizeAttr(LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
561 const Optional<unsigned> &NumElemsArg);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100562
563 /// Add the allocsize attribute to the attribute set at the given arg index.
564 /// Returns a new list because attribute lists are immutable.
Andrew Walbran16937d02019-10-22 13:54:20 +0100565 LLVM_NODISCARD AttributeList
566 addAllocSizeParamAttr(LLVMContext &C, unsigned ArgNo, unsigned ElemSizeArg,
567 const Optional<unsigned> &NumElemsArg) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100568 return addAllocSizeAttr(C, ArgNo + FirstArgIndex, ElemSizeArg, NumElemsArg);
569 }
570
571 //===--------------------------------------------------------------------===//
572 // AttributeList Accessors
573 //===--------------------------------------------------------------------===//
574
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100575 /// The attributes for the specified index are returned.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100576 AttributeSet getAttributes(unsigned Index) const;
577
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100578 /// The attributes for the argument or parameter at the given index are
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100579 /// returned.
580 AttributeSet getParamAttributes(unsigned ArgNo) const;
581
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100582 /// The attributes for the ret value are returned.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100583 AttributeSet getRetAttributes() const;
584
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100585 /// The function attributes are returned.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100586 AttributeSet getFnAttributes() const;
587
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100588 /// Return true if the attribute exists at the given index.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100589 bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const;
590
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100591 /// Return true if the attribute exists at the given index.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100592 bool hasAttribute(unsigned Index, StringRef Kind) const;
593
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100594 /// Return true if attribute exists at the given index.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100595 bool hasAttributes(unsigned Index) const;
596
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100597 /// Return true if the attribute exists for the given argument
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100598 bool hasParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
599 return hasAttribute(ArgNo + FirstArgIndex, Kind);
600 }
601
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100602 /// Return true if the attribute exists for the given argument
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100603 bool hasParamAttr(unsigned ArgNo, StringRef Kind) const {
604 return hasAttribute(ArgNo + FirstArgIndex, Kind);
605 }
606
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100607 /// Return true if attributes exists for the given argument
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100608 bool hasParamAttrs(unsigned ArgNo) const {
609 return hasAttributes(ArgNo + FirstArgIndex);
610 }
611
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100612 /// Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100613 /// may be faster.
614 bool hasFnAttribute(Attribute::AttrKind Kind) const;
615
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100616 /// Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100617 /// may be faster.
618 bool hasFnAttribute(StringRef Kind) const;
619
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100620 /// Equivalent to hasAttribute(ArgNo + FirstArgIndex, Kind).
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100621 bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const;
622
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100623 /// Return true if the specified attribute is set for at least one
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100624 /// parameter or for the return value. If Index is not nullptr, the index
625 /// of a parameter with the specified attribute is provided.
626 bool hasAttrSomewhere(Attribute::AttrKind Kind,
627 unsigned *Index = nullptr) const;
628
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100629 /// Return the attribute object that exists at the given index.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100630 Attribute getAttribute(unsigned Index, Attribute::AttrKind Kind) const;
631
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100632 /// Return the attribute object that exists at the given index.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100633 Attribute getAttribute(unsigned Index, StringRef Kind) const;
634
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100635 /// Return the attribute object that exists at the arg index.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100636 Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
637 return getAttribute(ArgNo + FirstArgIndex, Kind);
638 }
639
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100640 /// Return the attribute object that exists at the given index.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100641 Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const {
642 return getAttribute(ArgNo + FirstArgIndex, Kind);
643 }
644
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100645 /// Return the alignment of the return value.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200646 MaybeAlign getRetAlignment() const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100647
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100648 /// Return the alignment for the specified function parameter.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200649 MaybeAlign getParamAlignment(unsigned ArgNo) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100650
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100651 /// Return the byval type for the specified function parameter.
652 Type *getParamByValType(unsigned ArgNo) const;
653
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200654 /// Return the sret type for the specified function parameter.
655 Type *getParamStructRetType(unsigned ArgNo) const;
656
657 /// Return the byref type for the specified function parameter.
658 Type *getParamByRefType(unsigned ArgNo) const;
659
660 /// Return the preallocated type for the specified function parameter.
661 Type *getParamPreallocatedType(unsigned ArgNo) const;
662
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100663 /// Get the stack alignment.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200664 MaybeAlign getStackAlignment(unsigned Index) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100665
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100666 /// Get the number of dereferenceable bytes (or zero if unknown).
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100667 uint64_t getDereferenceableBytes(unsigned Index) const;
668
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100669 /// Get the number of dereferenceable bytes (or zero if unknown) of an
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100670 /// arg.
671 uint64_t getParamDereferenceableBytes(unsigned ArgNo) const {
672 return getDereferenceableBytes(ArgNo + FirstArgIndex);
673 }
674
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100675 /// Get the number of dereferenceable_or_null bytes (or zero if
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100676 /// unknown).
677 uint64_t getDereferenceableOrNullBytes(unsigned Index) const;
678
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100679 /// Get the number of dereferenceable_or_null bytes (or zero if
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100680 /// unknown) of an arg.
681 uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const {
682 return getDereferenceableOrNullBytes(ArgNo + FirstArgIndex);
683 }
684
685 /// Get the allocsize argument numbers (or pair(0, 0) if unknown).
686 std::pair<unsigned, Optional<unsigned>>
687 getAllocSizeArgs(unsigned Index) const;
688
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100689 /// Return the attributes at the index as a string.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100690 std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
691
692 //===--------------------------------------------------------------------===//
693 // AttributeList Introspection
694 //===--------------------------------------------------------------------===//
695
696 using iterator = const AttributeSet *;
697
698 iterator begin() const;
699 iterator end() const;
700
701 unsigned getNumAttrSets() const;
702
703 /// Use these to iterate over the valid attribute indices.
704 unsigned index_begin() const { return AttributeList::FunctionIndex; }
705 unsigned index_end() const { return getNumAttrSets() - 1; }
706
707 /// operator==/!= - Provide equality predicates.
708 bool operator==(const AttributeList &RHS) const { return pImpl == RHS.pImpl; }
709 bool operator!=(const AttributeList &RHS) const { return pImpl != RHS.pImpl; }
710
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100711 /// Return a raw pointer that uniquely identifies this attribute list.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100712 void *getRawPointer() const {
713 return pImpl;
714 }
715
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100716 /// Return true if there are no attributes.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100717 bool isEmpty() const { return pImpl == nullptr; }
718
719 void dump() const;
720};
721
722//===----------------------------------------------------------------------===//
723/// \class
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100724/// Provide DenseMapInfo for AttributeList.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100725template <> struct DenseMapInfo<AttributeList> {
726 static AttributeList getEmptyKey() {
727 auto Val = static_cast<uintptr_t>(-1);
728 Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
729 return AttributeList(reinterpret_cast<AttributeListImpl *>(Val));
730 }
731
732 static AttributeList getTombstoneKey() {
733 auto Val = static_cast<uintptr_t>(-2);
734 Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
735 return AttributeList(reinterpret_cast<AttributeListImpl *>(Val));
736 }
737
738 static unsigned getHashValue(AttributeList AS) {
739 return (unsigned((uintptr_t)AS.pImpl) >> 4) ^
740 (unsigned((uintptr_t)AS.pImpl) >> 9);
741 }
742
743 static bool isEqual(AttributeList LHS, AttributeList RHS) {
744 return LHS == RHS;
745 }
746};
747
748//===----------------------------------------------------------------------===//
749/// \class
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100750/// This class is used in conjunction with the Attribute::get method to
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100751/// create an Attribute object. The object itself is uniquified. The Builder's
752/// value, however, is not. So this can be used as a quick way to test for
753/// equality, presence of attributes, etc.
754class AttrBuilder {
755 std::bitset<Attribute::EndAttrKinds> Attrs;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200756 std::map<std::string, std::string, std::less<>> TargetDepAttrs;
757 MaybeAlign Alignment;
758 MaybeAlign StackAlignment;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100759 uint64_t DerefBytes = 0;
760 uint64_t DerefOrNullBytes = 0;
761 uint64_t AllocSizeArgs = 0;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100762 Type *ByValType = nullptr;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200763 Type *StructRetType = nullptr;
764 Type *ByRefType = nullptr;
765 Type *PreallocatedType = nullptr;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100766
767public:
768 AttrBuilder() = default;
769
770 AttrBuilder(const Attribute &A) {
771 addAttribute(A);
772 }
773
774 AttrBuilder(AttributeList AS, unsigned Idx);
775 AttrBuilder(AttributeSet AS);
776
777 void clear();
778
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100779 /// Add an attribute to the builder.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200780 AttrBuilder &addAttribute(Attribute::AttrKind Val) {
781 assert((unsigned)Val < Attribute::EndAttrKinds &&
782 "Attribute out of range!");
783 assert(!Attribute::doesAttrKindHaveArgument(Val) &&
784 "Adding integer attribute without adding a value!");
785 Attrs[Val] = true;
786 return *this;
787 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100788
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100789 /// Add the Attribute object to the builder.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100790 AttrBuilder &addAttribute(Attribute A);
791
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100792 /// Add the target-dependent attribute to the builder.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100793 AttrBuilder &addAttribute(StringRef A, StringRef V = StringRef());
794
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100795 /// Remove an attribute from the builder.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100796 AttrBuilder &removeAttribute(Attribute::AttrKind Val);
797
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100798 /// Remove the attributes from the builder.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100799 AttrBuilder &removeAttributes(AttributeList A, uint64_t WithoutIndex);
800
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100801 /// Remove the target-dependent attribute to the builder.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100802 AttrBuilder &removeAttribute(StringRef A);
803
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100804 /// Add the attributes from the builder.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100805 AttrBuilder &merge(const AttrBuilder &B);
806
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100807 /// Remove the attributes from the builder.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100808 AttrBuilder &remove(const AttrBuilder &B);
809
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100810 /// Return true if the builder has any attribute that's in the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100811 /// specified builder.
812 bool overlaps(const AttrBuilder &B) const;
813
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100814 /// Return true if the builder has the specified attribute.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100815 bool contains(Attribute::AttrKind A) const {
816 assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
817 return Attrs[A];
818 }
819
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100820 /// Return true if the builder has the specified target-dependent
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100821 /// attribute.
822 bool contains(StringRef A) const;
823
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100824 /// Return true if the builder has IR-level attributes.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100825 bool hasAttributes() const;
826
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100827 /// Return true if the builder has any attribute that's in the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100828 /// specified attribute.
829 bool hasAttributes(AttributeList A, uint64_t Index) const;
830
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100831 /// Return true if the builder has an alignment attribute.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100832 bool hasAlignmentAttr() const;
833
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100834 /// Retrieve the alignment attribute, if it exists.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200835 MaybeAlign getAlignment() const { return Alignment; }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100836
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100837 /// Retrieve the stack alignment attribute, if it exists.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200838 MaybeAlign getStackAlignment() const { return StackAlignment; }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100839
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100840 /// Retrieve the number of dereferenceable bytes, if the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100841 /// dereferenceable attribute exists (zero is returned otherwise).
842 uint64_t getDereferenceableBytes() const { return DerefBytes; }
843
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100844 /// Retrieve the number of dereferenceable_or_null bytes, if the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100845 /// dereferenceable_or_null attribute exists (zero is returned otherwise).
846 uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; }
847
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100848 /// Retrieve the byval type.
849 Type *getByValType() const { return ByValType; }
850
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200851 /// Retrieve the sret type.
852 Type *getStructRetType() const { return StructRetType; }
853
854 /// Retrieve the byref type.
855 Type *getByRefType() const { return ByRefType; }
856
857 /// Retrieve the preallocated type.
858 Type *getPreallocatedType() const { return PreallocatedType; }
859
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100860 /// Retrieve the allocsize args, if the allocsize attribute exists. If it
861 /// doesn't exist, pair(0, 0) is returned.
862 std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
863
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200864 /// This turns an alignment into the form used internally in Attribute.
865 /// This call has no effect if Align is not set.
866 AttrBuilder &addAlignmentAttr(MaybeAlign Align);
867
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100868 /// This turns an int alignment (which must be a power of 2) into the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100869 /// form used internally in Attribute.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200870 /// This call has no effect if Align is 0.
871 /// Deprecated, use the version using a MaybeAlign.
872 inline AttrBuilder &addAlignmentAttr(unsigned Align) {
873 return addAlignmentAttr(MaybeAlign(Align));
874 }
875
876 /// This turns a stack alignment into the form used internally in Attribute.
877 /// This call has no effect if Align is not set.
878 AttrBuilder &addStackAlignmentAttr(MaybeAlign Align);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100879
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100880 /// This turns an int stack alignment (which must be a power of 2) into
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100881 /// the form used internally in Attribute.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200882 /// This call has no effect if Align is 0.
883 /// Deprecated, use the version using a MaybeAlign.
884 inline AttrBuilder &addStackAlignmentAttr(unsigned Align) {
885 return addStackAlignmentAttr(MaybeAlign(Align));
886 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100887
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100888 /// This turns the number of dereferenceable bytes into the form used
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100889 /// internally in Attribute.
890 AttrBuilder &addDereferenceableAttr(uint64_t Bytes);
891
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100892 /// This turns the number of dereferenceable_or_null bytes into the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100893 /// form used internally in Attribute.
894 AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes);
895
896 /// This turns one (or two) ints into the form used internally in Attribute.
897 AttrBuilder &addAllocSizeAttr(unsigned ElemSizeArg,
898 const Optional<unsigned> &NumElemsArg);
899
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100900 /// This turns a byval type into the form used internally in Attribute.
901 AttrBuilder &addByValAttr(Type *Ty);
902
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200903 /// This turns a sret type into the form used internally in Attribute.
904 AttrBuilder &addStructRetAttr(Type *Ty);
905
906 /// This turns a byref type into the form used internally in Attribute.
907 AttrBuilder &addByRefAttr(Type *Ty);
908
909 /// This turns a preallocated type into the form used internally in Attribute.
910 AttrBuilder &addPreallocatedAttr(Type *Ty);
911
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100912 /// Add an allocsize attribute, using the representation returned by
913 /// Attribute.getIntValue().
914 AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr);
915
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100916 /// Return true if the builder contains no target-independent
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100917 /// attributes.
918 bool empty() const { return Attrs.none(); }
919
920 // Iterators for target-dependent attributes.
921 using td_type = std::pair<std::string, std::string>;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200922 using td_iterator = decltype(TargetDepAttrs)::iterator;
923 using td_const_iterator = decltype(TargetDepAttrs)::const_iterator;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100924 using td_range = iterator_range<td_iterator>;
925 using td_const_range = iterator_range<td_const_iterator>;
926
927 td_iterator td_begin() { return TargetDepAttrs.begin(); }
928 td_iterator td_end() { return TargetDepAttrs.end(); }
929
930 td_const_iterator td_begin() const { return TargetDepAttrs.begin(); }
931 td_const_iterator td_end() const { return TargetDepAttrs.end(); }
932
933 td_range td_attrs() { return td_range(td_begin(), td_end()); }
934
935 td_const_range td_attrs() const {
936 return td_const_range(td_begin(), td_end());
937 }
938
939 bool td_empty() const { return TargetDepAttrs.empty(); }
940
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200941 bool operator==(const AttrBuilder &B) const;
942 bool operator!=(const AttrBuilder &B) const { return !(*this == B); }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100943};
944
945namespace AttributeFuncs {
946
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100947/// Which attributes cannot be applied to a type.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100948AttrBuilder typeIncompatible(Type *Ty);
949
950/// \returns Return true if the two functions have compatible target-independent
951/// attributes for inlining purposes.
952bool areInlineCompatible(const Function &Caller, const Function &Callee);
953
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200954
955/// Checks if there are any incompatible function attributes between
956/// \p A and \p B.
957///
958/// \param [in] A - The first function to be compared with.
959/// \param [in] B - The second function to be compared with.
960/// \returns true if the functions have compatible attributes.
961bool areOutlineCompatible(const Function &A, const Function &B);
962
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100963/// Merge caller's and callee's attributes.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100964void mergeAttributesForInlining(Function &Caller, const Function &Callee);
965
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200966/// Merges the functions attributes from \p ToMerge into function \p Base.
967///
968/// \param [in,out] Base - The function being merged into.
969/// \param [in] ToMerge - The function to merge attributes from.
970void mergeAttributesForOutlining(Function &Base, const Function &ToMerge);
971
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100972} // end namespace AttributeFuncs
973
974} // end namespace llvm
975
976#endif // LLVM_IR_ATTRIBUTES_H