Bug Summary

File:src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support/Alignment.h
Warning:line 85, column 47
The result of the left shift is undefined due to shifting by '255', which is greater or equal to the width of type 'uint64_t'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name Attributes.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Analysis -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ASMParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/BinaryFormat -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitstream -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /include/llvm/CodeGen -I /include/llvm/CodeGen/PBQP -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Coroutines -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData/Coverage -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/CodeView -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/DWARF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/MSF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/PDB -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Demangle -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/JITLink -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/Orc -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenACC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenMP -I /include/llvm/CodeGen/GlobalISel -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IRReader -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/LTO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Linker -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC/MCParser -I /include/llvm/CodeGen/MIRParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Object -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Option -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Passes -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Scalar -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ADT -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/Symbolize -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Target -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Utils -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Vectorize -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/IPO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libLLVM/../include -I /usr/src/gnu/usr.bin/clang/libLLVM/obj -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/IR/Attributes.cpp

/usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/IR/Attributes.cpp

1//===- Attributes.cpp - Implement AttributesList --------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// \file
10// This file implements the Attribute, AttributeImpl, AttrBuilder,
11// AttributeListImpl, and AttributeList classes.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/IR/Attributes.h"
16#include "AttributeImpl.h"
17#include "LLVMContextImpl.h"
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/FoldingSet.h"
20#include "llvm/ADT/Optional.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/ADT/StringSwitch.h"
26#include "llvm/ADT/Twine.h"
27#include "llvm/Config/llvm-config.h"
28#include "llvm/IR/Function.h"
29#include "llvm/IR/LLVMContext.h"
30#include "llvm/IR/Type.h"
31#include "llvm/Support/Compiler.h"
32#include "llvm/Support/Debug.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/MathExtras.h"
35#include "llvm/Support/raw_ostream.h"
36#include <algorithm>
37#include <cassert>
38#include <climits>
39#include <cstddef>
40#include <cstdint>
41#include <limits>
42#include <string>
43#include <tuple>
44#include <utility>
45
46using namespace llvm;
47
48//===----------------------------------------------------------------------===//
49// Attribute Construction Methods
50//===----------------------------------------------------------------------===//
51
52// allocsize has two integer arguments, but because they're both 32 bits, we can
53// pack them into one 64-bit value, at the cost of making said value
54// nonsensical.
55//
56// In order to do this, we need to reserve one value of the second (optional)
57// allocsize argument to signify "not present."
58static const unsigned AllocSizeNumElemsNotPresent = -1;
59
60static uint64_t packAllocSizeArgs(unsigned ElemSizeArg,
61 const Optional<unsigned> &NumElemsArg) {
62 assert((!NumElemsArg.hasValue() ||((void)0)
63 *NumElemsArg != AllocSizeNumElemsNotPresent) &&((void)0)
64 "Attempting to pack a reserved value")((void)0);
65
66 return uint64_t(ElemSizeArg) << 32 |
67 NumElemsArg.getValueOr(AllocSizeNumElemsNotPresent);
68}
69
70static std::pair<unsigned, Optional<unsigned>>
71unpackAllocSizeArgs(uint64_t Num) {
72 unsigned NumElems = Num & std::numeric_limits<unsigned>::max();
73 unsigned ElemSizeArg = Num >> 32;
74
75 Optional<unsigned> NumElemsArg;
76 if (NumElems != AllocSizeNumElemsNotPresent)
77 NumElemsArg = NumElems;
78 return std::make_pair(ElemSizeArg, NumElemsArg);
79}
80
81static uint64_t packVScaleRangeArgs(unsigned MinValue, unsigned MaxValue) {
82 return uint64_t(MinValue) << 32 | MaxValue;
83}
84
85static std::pair<unsigned, unsigned> unpackVScaleRangeArgs(uint64_t Value) {
86 unsigned MaxValue = Value & std::numeric_limits<unsigned>::max();
87 unsigned MinValue = Value >> 32;
88
89 return std::make_pair(MinValue, MaxValue);
90}
91
92Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
93 uint64_t Val) {
94 if (Val)
95 assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute")((void)0);
96 else
97 assert(Attribute::isEnumAttrKind(Kind) && "Not an enum attribute")((void)0);
98
99 LLVMContextImpl *pImpl = Context.pImpl;
100 FoldingSetNodeID ID;
101 ID.AddInteger(Kind);
102 if (Val) ID.AddInteger(Val);
103
104 void *InsertPoint;
105 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
106
107 if (!PA) {
108 // If we didn't find any existing attributes of the same shape then create a
109 // new one and insert it.
110 if (!Val)
111 PA = new (pImpl->Alloc) EnumAttributeImpl(Kind);
112 else
113 PA = new (pImpl->Alloc) IntAttributeImpl(Kind, Val);
114 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
115 }
116
117 // Return the Attribute that we found or created.
118 return Attribute(PA);
119}
120
121Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
122 LLVMContextImpl *pImpl = Context.pImpl;
123 FoldingSetNodeID ID;
124 ID.AddString(Kind);
125 if (!Val.empty()) ID.AddString(Val);
126
127 void *InsertPoint;
128 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
129
130 if (!PA) {
131 // If we didn't find any existing attributes of the same shape then create a
132 // new one and insert it.
133 void *Mem =
134 pImpl->Alloc.Allocate(StringAttributeImpl::totalSizeToAlloc(Kind, Val),
135 alignof(StringAttributeImpl));
136 PA = new (Mem) StringAttributeImpl(Kind, Val);
137 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
138 }
139
140 // Return the Attribute that we found or created.
141 return Attribute(PA);
142}
143
144Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
145 Type *Ty) {
146 assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute")((void)0);
147 LLVMContextImpl *pImpl = Context.pImpl;
148 FoldingSetNodeID ID;
149 ID.AddInteger(Kind);
150 ID.AddPointer(Ty);
151
152 void *InsertPoint;
153 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
154
155 if (!PA) {
2
Assuming 'PA' is null
3
Taking true branch
156 // If we didn't find any existing attributes of the same shape then create a
157 // new one and insert it.
158 PA = new (pImpl->Alloc) TypeAttributeImpl(Kind, Ty);
4
Calling 'operator new<llvm::MallocAllocator, 4096UL, 4096UL, 128UL>'
159 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
160 }
161
162 // Return the Attribute that we found or created.
163 return Attribute(PA);
164}
165
166Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) {
167 assert(A <= llvm::Value::MaximumAlignment && "Alignment too large.")((void)0);
168 return get(Context, Alignment, A.value());
169}
170
171Attribute Attribute::getWithStackAlignment(LLVMContext &Context, Align A) {
172 assert(A <= 0x100 && "Alignment too large.")((void)0);
173 return get(Context, StackAlignment, A.value());
174}
175
176Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
177 uint64_t Bytes) {
178 assert(Bytes && "Bytes must be non-zero.")((void)0);
179 return get(Context, Dereferenceable, Bytes);
180}
181
182Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
183 uint64_t Bytes) {
184 assert(Bytes && "Bytes must be non-zero.")((void)0);
185 return get(Context, DereferenceableOrNull, Bytes);
186}
187
188Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
189 return get(Context, ByVal, Ty);
190}
191
192Attribute Attribute::getWithStructRetType(LLVMContext &Context, Type *Ty) {
193 return get(Context, StructRet, Ty);
194}
195
196Attribute Attribute::getWithByRefType(LLVMContext &Context, Type *Ty) {
197 return get(Context, ByRef, Ty);
198}
199
200Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
201 return get(Context, Preallocated, Ty);
202}
203
204Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
205 return get(Context, InAlloca, Ty);
1
Calling 'Attribute::get'
206}
207
208Attribute
209Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
210 const Optional<unsigned> &NumElemsArg) {
211 assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) &&((void)0)
212 "Invalid allocsize arguments -- given allocsize(0, 0)")((void)0);
213 return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
214}
215
216Attribute Attribute::getWithVScaleRangeArgs(LLVMContext &Context,
217 unsigned MinValue,
218 unsigned MaxValue) {
219 return get(Context, VScaleRange, packVScaleRangeArgs(MinValue, MaxValue));
220}
221
222Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
223 return StringSwitch<Attribute::AttrKind>(AttrName)
224#define GET_ATTR_NAMES
225#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
226 .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
227#include "llvm/IR/Attributes.inc"
228 .Default(Attribute::None);
229}
230
231StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
232 switch (AttrKind) {
233#define GET_ATTR_NAMES
234#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
235 case Attribute::ENUM_NAME: \
236 return #DISPLAY_NAME;
237#include "llvm/IR/Attributes.inc"
238 case Attribute::None:
239 return "none";
240 default:
241 llvm_unreachable("invalid Kind")__builtin_unreachable();
242 }
243}
244
245bool Attribute::isExistingAttribute(StringRef Name) {
246 return StringSwitch<bool>(Name)
247#define GET_ATTR_NAMES
248#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true)
249#include "llvm/IR/Attributes.inc"
250 .Default(false);
251}
252
253//===----------------------------------------------------------------------===//
254// Attribute Accessor Methods
255//===----------------------------------------------------------------------===//
256
257bool Attribute::isEnumAttribute() const {
258 return pImpl && pImpl->isEnumAttribute();
259}
260
261bool Attribute::isIntAttribute() const {
262 return pImpl && pImpl->isIntAttribute();
263}
264
265bool Attribute::isStringAttribute() const {
266 return pImpl && pImpl->isStringAttribute();
267}
268
269bool Attribute::isTypeAttribute() const {
270 return pImpl && pImpl->isTypeAttribute();
271}
272
273Attribute::AttrKind Attribute::getKindAsEnum() const {
274 if (!pImpl) return None;
275 assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&((void)0)
276 "Invalid attribute type to get the kind as an enum!")((void)0);
277 return pImpl->getKindAsEnum();
278}
279
280uint64_t Attribute::getValueAsInt() const {
281 if (!pImpl) return 0;
282 assert(isIntAttribute() &&((void)0)
283 "Expected the attribute to be an integer attribute!")((void)0);
284 return pImpl->getValueAsInt();
285}
286
287bool Attribute::getValueAsBool() const {
288 if (!pImpl) return false;
289 assert(isStringAttribute() &&((void)0)
290 "Expected the attribute to be a string attribute!")((void)0);
291 return pImpl->getValueAsBool();
292}
293
294StringRef Attribute::getKindAsString() const {
295 if (!pImpl) return {};
296 assert(isStringAttribute() &&((void)0)
297 "Invalid attribute type to get the kind as a string!")((void)0);
298 return pImpl->getKindAsString();
299}
300
301StringRef Attribute::getValueAsString() const {
302 if (!pImpl) return {};
303 assert(isStringAttribute() &&((void)0)
304 "Invalid attribute type to get the value as a string!")((void)0);
305 return pImpl->getValueAsString();
306}
307
308Type *Attribute::getValueAsType() const {
309 if (!pImpl) return {};
310 assert(isTypeAttribute() &&((void)0)
311 "Invalid attribute type to get the value as a type!")((void)0);
312 return pImpl->getValueAsType();
313}
314
315
316bool Attribute::hasAttribute(AttrKind Kind) const {
317 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
318}
319
320bool Attribute::hasAttribute(StringRef Kind) const {
321 if (!isStringAttribute()) return false;
322 return pImpl && pImpl->hasAttribute(Kind);
323}
324
325MaybeAlign Attribute::getAlignment() const {
326 assert(hasAttribute(Attribute::Alignment) &&((void)0)
327 "Trying to get alignment from non-alignment attribute!")((void)0);
328 return MaybeAlign(pImpl->getValueAsInt());
329}
330
331MaybeAlign Attribute::getStackAlignment() const {
332 assert(hasAttribute(Attribute::StackAlignment) &&((void)0)
333 "Trying to get alignment from non-alignment attribute!")((void)0);
334 return MaybeAlign(pImpl->getValueAsInt());
335}
336
337uint64_t Attribute::getDereferenceableBytes() const {
338 assert(hasAttribute(Attribute::Dereferenceable) &&((void)0)
339 "Trying to get dereferenceable bytes from "((void)0)
340 "non-dereferenceable attribute!")((void)0);
341 return pImpl->getValueAsInt();
342}
343
344uint64_t Attribute::getDereferenceableOrNullBytes() const {
345 assert(hasAttribute(Attribute::DereferenceableOrNull) &&((void)0)
346 "Trying to get dereferenceable bytes from "((void)0)
347 "non-dereferenceable attribute!")((void)0);
348 return pImpl->getValueAsInt();
349}
350
351std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
352 assert(hasAttribute(Attribute::AllocSize) &&((void)0)
353 "Trying to get allocsize args from non-allocsize attribute")((void)0);
354 return unpackAllocSizeArgs(pImpl->getValueAsInt());
355}
356
357std::pair<unsigned, unsigned> Attribute::getVScaleRangeArgs() const {
358 assert(hasAttribute(Attribute::VScaleRange) &&((void)0)
359 "Trying to get vscale args from non-vscale attribute")((void)0);
360 return unpackVScaleRangeArgs(pImpl->getValueAsInt());
361}
362
363std::string Attribute::getAsString(bool InAttrGrp) const {
364 if (!pImpl) return {};
365
366 if (isEnumAttribute())
367 return getNameFromAttrKind(getKindAsEnum()).str();
368
369 if (isTypeAttribute()) {
370 std::string Result = getNameFromAttrKind(getKindAsEnum()).str();
371 Result += '(';
372 raw_string_ostream OS(Result);
373 getValueAsType()->print(OS, false, true);
374 OS.flush();
375 Result += ')';
376 return Result;
377 }
378
379 // FIXME: These should be output like this:
380 //
381 // align=4
382 // alignstack=8
383 //
384 if (hasAttribute(Attribute::Alignment)) {
385 std::string Result;
386 Result += "align";
387 Result += (InAttrGrp) ? "=" : " ";
388 Result += utostr(getValueAsInt());
389 return Result;
390 }
391
392 auto AttrWithBytesToString = [&](const char *Name) {
393 std::string Result;
394 Result += Name;
395 if (InAttrGrp) {
396 Result += "=";
397 Result += utostr(getValueAsInt());
398 } else {
399 Result += "(";
400 Result += utostr(getValueAsInt());
401 Result += ")";
402 }
403 return Result;
404 };
405
406 if (hasAttribute(Attribute::StackAlignment))
407 return AttrWithBytesToString("alignstack");
408
409 if (hasAttribute(Attribute::Dereferenceable))
410 return AttrWithBytesToString("dereferenceable");
411
412 if (hasAttribute(Attribute::DereferenceableOrNull))
413 return AttrWithBytesToString("dereferenceable_or_null");
414
415 if (hasAttribute(Attribute::AllocSize)) {
416 unsigned ElemSize;
417 Optional<unsigned> NumElems;
418 std::tie(ElemSize, NumElems) = getAllocSizeArgs();
419
420 std::string Result = "allocsize(";
421 Result += utostr(ElemSize);
422 if (NumElems.hasValue()) {
423 Result += ',';
424 Result += utostr(*NumElems);
425 }
426 Result += ')';
427 return Result;
428 }
429
430 if (hasAttribute(Attribute::VScaleRange)) {
431 unsigned MinValue, MaxValue;
432 std::tie(MinValue, MaxValue) = getVScaleRangeArgs();
433
434 std::string Result = "vscale_range(";
435 Result += utostr(MinValue);
436 Result += ',';
437 Result += utostr(MaxValue);
438 Result += ')';
439 return Result;
440 }
441
442 // Convert target-dependent attributes to strings of the form:
443 //
444 // "kind"
445 // "kind" = "value"
446 //
447 if (isStringAttribute()) {
448 std::string Result;
449 {
450 raw_string_ostream OS(Result);
451 OS << '"' << getKindAsString() << '"';
452
453 // Since some attribute strings contain special characters that cannot be
454 // printable, those have to be escaped to make the attribute value
455 // printable as is. e.g. "\01__gnu_mcount_nc"
456 const auto &AttrVal = pImpl->getValueAsString();
457 if (!AttrVal.empty()) {
458 OS << "=\"";
459 printEscapedString(AttrVal, OS);
460 OS << "\"";
461 }
462 }
463 return Result;
464 }
465
466 llvm_unreachable("Unknown attribute")__builtin_unreachable();
467}
468
469bool Attribute::hasParentContext(LLVMContext &C) const {
470 assert(isValid() && "invalid Attribute doesn't refer to any context")((void)0);
471 FoldingSetNodeID ID;
472 pImpl->Profile(ID);
473 void *Unused;
474 return C.pImpl->AttrsSet.FindNodeOrInsertPos(ID, Unused) == pImpl;
475}
476
477bool Attribute::operator<(Attribute A) const {
478 if (!pImpl && !A.pImpl) return false;
479 if (!pImpl) return true;
480 if (!A.pImpl) return false;
481 return *pImpl < *A.pImpl;
482}
483
484void Attribute::Profile(FoldingSetNodeID &ID) const {
485 ID.AddPointer(pImpl);
486}
487
488enum AttributeProperty {
489 FnAttr = (1 << 0),
490 ParamAttr = (1 << 1),
491 RetAttr = (1 << 2),
492};
493
494#define GET_ATTR_PROP_TABLE
495#include "llvm/IR/Attributes.inc"
496
497static bool hasAttributeProperty(Attribute::AttrKind Kind,
498 AttributeProperty Prop) {
499 unsigned Index = Kind - 1;
500 assert(Index < sizeof(AttrPropTable) / sizeof(AttrPropTable[0]) &&((void)0)
501 "Invalid attribute kind")((void)0);
502 return AttrPropTable[Index] & Prop;
503}
504
505bool Attribute::canUseAsFnAttr(AttrKind Kind) {
506 return hasAttributeProperty(Kind, AttributeProperty::FnAttr);
507}
508
509bool Attribute::canUseAsParamAttr(AttrKind Kind) {
510 return hasAttributeProperty(Kind, AttributeProperty::ParamAttr);
511}
512
513bool Attribute::canUseAsRetAttr(AttrKind Kind) {
514 return hasAttributeProperty(Kind, AttributeProperty::RetAttr);
515}
516
517//===----------------------------------------------------------------------===//
518// AttributeImpl Definition
519//===----------------------------------------------------------------------===//
520
521bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
522 if (isStringAttribute()) return false;
523 return getKindAsEnum() == A;
524}
525
526bool AttributeImpl::hasAttribute(StringRef Kind) const {
527 if (!isStringAttribute()) return false;
528 return getKindAsString() == Kind;
529}
530
531Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
532 assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute())((void)0);
533 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
534}
535
536uint64_t AttributeImpl::getValueAsInt() const {
537 assert(isIntAttribute())((void)0);
538 return static_cast<const IntAttributeImpl *>(this)->getValue();
539}
540
541bool AttributeImpl::getValueAsBool() const {
542 assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true")((void)0);
543 return getValueAsString() == "true";
544}
545
546StringRef AttributeImpl::getKindAsString() const {
547 assert(isStringAttribute())((void)0);
548 return static_cast<const StringAttributeImpl *>(this)->getStringKind();
549}
550
551StringRef AttributeImpl::getValueAsString() const {
552 assert(isStringAttribute())((void)0);
553 return static_cast<const StringAttributeImpl *>(this)->getStringValue();
554}
555
556Type *AttributeImpl::getValueAsType() const {
557 assert(isTypeAttribute())((void)0);
558 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
559}
560
561bool AttributeImpl::operator<(const AttributeImpl &AI) const {
562 if (this == &AI)
563 return false;
564
565 // This sorts the attributes with Attribute::AttrKinds coming first (sorted
566 // relative to their enum value) and then strings.
567 if (!isStringAttribute()) {
568 if (AI.isStringAttribute())
569 return true;
570 if (getKindAsEnum() != AI.getKindAsEnum())
571 return getKindAsEnum() < AI.getKindAsEnum();
572 assert(!AI.isEnumAttribute() && "Non-unique attribute")((void)0);
573 assert(!AI.isTypeAttribute() && "Comparison of types would be unstable")((void)0);
574 // TODO: Is this actually needed?
575 assert(AI.isIntAttribute() && "Only possibility left")((void)0);
576 return getValueAsInt() < AI.getValueAsInt();
577 }
578
579 if (!AI.isStringAttribute())
580 return false;
581 if (getKindAsString() == AI.getKindAsString())
582 return getValueAsString() < AI.getValueAsString();
583 return getKindAsString() < AI.getKindAsString();
584}
585
586//===----------------------------------------------------------------------===//
587// AttributeSet Definition
588//===----------------------------------------------------------------------===//
589
590AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) {
591 return AttributeSet(AttributeSetNode::get(C, B));
592}
593
594AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
595 return AttributeSet(AttributeSetNode::get(C, Attrs));
596}
597
598AttributeSet AttributeSet::addAttribute(LLVMContext &C,
599 Attribute::AttrKind Kind) const {
600 if (hasAttribute(Kind)) return *this;
601 AttrBuilder B;
602 B.addAttribute(Kind);
603 return addAttributes(C, AttributeSet::get(C, B));
604}
605
606AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
607 StringRef Value) const {
608 AttrBuilder B;
609 B.addAttribute(Kind, Value);
610 return addAttributes(C, AttributeSet::get(C, B));
611}
612
613AttributeSet AttributeSet::addAttributes(LLVMContext &C,
614 const AttributeSet AS) const {
615 if (!hasAttributes())
616 return AS;
617
618 if (!AS.hasAttributes())
619 return *this;
620
621 AttrBuilder B(AS);
622 for (const auto &I : *this)
623 B.addAttribute(I);
624
625 return get(C, B);
626}
627
628AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
629 Attribute::AttrKind Kind) const {
630 if (!hasAttribute(Kind)) return *this;
631 AttrBuilder B(*this);
632 B.removeAttribute(Kind);
633 return get(C, B);
634}
635
636AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
637 StringRef Kind) const {
638 if (!hasAttribute(Kind)) return *this;
639 AttrBuilder B(*this);
640 B.removeAttribute(Kind);
641 return get(C, B);
642}
643
644AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
645 const AttrBuilder &Attrs) const {
646 AttrBuilder B(*this);
647 // If there is nothing to remove, directly return the original set.
648 if (!B.overlaps(Attrs))
649 return *this;
650
651 B.remove(Attrs);
652 return get(C, B);
653}
654
655unsigned AttributeSet::getNumAttributes() const {
656 return SetNode ? SetNode->getNumAttributes() : 0;
657}
658
659bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const {
660 return SetNode ? SetNode->hasAttribute(Kind) : false;
661}
662
663bool AttributeSet::hasAttribute(StringRef Kind) const {
664 return SetNode ? SetNode->hasAttribute(Kind) : false;
665}
666
667Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const {
668 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
669}
670
671Attribute AttributeSet::getAttribute(StringRef Kind) const {
672 return SetNode ? SetNode->getAttribute(Kind) : Attribute();
673}
674
675MaybeAlign AttributeSet::getAlignment() const {
676 return SetNode ? SetNode->getAlignment() : None;
677}
678
679MaybeAlign AttributeSet::getStackAlignment() const {
680 return SetNode ? SetNode->getStackAlignment() : None;
681}
682
683uint64_t AttributeSet::getDereferenceableBytes() const {
684 return SetNode ? SetNode->getDereferenceableBytes() : 0;
685}
686
687uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
688 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
689}
690
691Type *AttributeSet::getByRefType() const {
692 return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr;
693}
694
695Type *AttributeSet::getByValType() const {
696 return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr;
697}
698
699Type *AttributeSet::getStructRetType() const {
700 return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr;
701}
702
703Type *AttributeSet::getPreallocatedType() const {
704 return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr;
705}
706
707Type *AttributeSet::getInAllocaType() const {
708 return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr;
709}
710
711Type *AttributeSet::getElementType() const {
712 return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr;
713}
714
715std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
716 return SetNode ? SetNode->getAllocSizeArgs()
717 : std::pair<unsigned, Optional<unsigned>>(0, 0);
718}
719
720std::pair<unsigned, unsigned> AttributeSet::getVScaleRangeArgs() const {
721 return SetNode ? SetNode->getVScaleRangeArgs()
722 : std::pair<unsigned, unsigned>(0, 0);
723}
724
725std::string AttributeSet::getAsString(bool InAttrGrp) const {
726 return SetNode ? SetNode->getAsString(InAttrGrp) : "";
727}
728
729bool AttributeSet::hasParentContext(LLVMContext &C) const {
730 assert(hasAttributes() && "empty AttributeSet doesn't refer to any context")((void)0);
731 FoldingSetNodeID ID;
732 SetNode->Profile(ID);
733 void *Unused;
734 return C.pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, Unused) == SetNode;
735}
736
737AttributeSet::iterator AttributeSet::begin() const {
738 return SetNode ? SetNode->begin() : nullptr;
739}
740
741AttributeSet::iterator AttributeSet::end() const {
742 return SetNode ? SetNode->end() : nullptr;
743}
744
745#if !defined(NDEBUG1) || defined(LLVM_ENABLE_DUMP)
746LLVM_DUMP_METHOD__attribute__((noinline)) void AttributeSet::dump() const {
747 dbgs() << "AS =\n";
748 dbgs() << " { ";
749 dbgs() << getAsString(true) << " }\n";
750}
751#endif
752
753//===----------------------------------------------------------------------===//
754// AttributeSetNode Definition
755//===----------------------------------------------------------------------===//
756
757AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
758 : NumAttrs(Attrs.size()) {
759 // There's memory after the node where we can store the entries in.
760 llvm::copy(Attrs, getTrailingObjects<Attribute>());
761
762 for (const auto &I : *this) {
763 if (I.isStringAttribute())
764 StringAttrs.insert({ I.getKindAsString(), I });
765 else
766 AvailableAttrs.addAttribute(I.getKindAsEnum());
767 }
768}
769
770AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
771 ArrayRef<Attribute> Attrs) {
772 SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
773 llvm::sort(SortedAttrs);
774 return getSorted(C, SortedAttrs);
775}
776
777AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
778 ArrayRef<Attribute> SortedAttrs) {
779 if (SortedAttrs.empty())
780 return nullptr;
781
782 // Build a key to look up the existing attributes.
783 LLVMContextImpl *pImpl = C.pImpl;
784 FoldingSetNodeID ID;
785
786 assert(llvm::is_sorted(SortedAttrs) && "Expected sorted attributes!")((void)0);
787 for (const auto &Attr : SortedAttrs)
788 Attr.Profile(ID);
789
790 void *InsertPoint;
791 AttributeSetNode *PA =
792 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint);
793
794 // If we didn't find any existing attributes of the same shape then create a
795 // new one and insert it.
796 if (!PA) {
797 // Coallocate entries after the AttributeSetNode itself.
798 void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size()));
799 PA = new (Mem) AttributeSetNode(SortedAttrs);
800 pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint);
801 }
802
803 // Return the AttributeSetNode that we found or created.
804 return PA;
805}
806
807AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
808 // Add target-independent attributes.
809 SmallVector<Attribute, 8> Attrs;
810 for (Attribute::AttrKind Kind = Attribute::None;
811 Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {
812 if (!B.contains(Kind))
813 continue;
814
815 if (Attribute::isTypeAttrKind(Kind)) {
816 Attrs.push_back(Attribute::get(C, Kind, B.getTypeAttr(Kind)));
817 continue;
818 }
819
820 Attribute Attr;
821 switch (Kind) {
822 case Attribute::Alignment:
823 assert(B.getAlignment() && "Alignment must be set")((void)0);
824 Attr = Attribute::getWithAlignment(C, *B.getAlignment());
825 break;
826 case Attribute::StackAlignment:
827 assert(B.getStackAlignment() && "StackAlignment must be set")((void)0);
828 Attr = Attribute::getWithStackAlignment(C, *B.getStackAlignment());
829 break;
830 case Attribute::Dereferenceable:
831 Attr = Attribute::getWithDereferenceableBytes(
832 C, B.getDereferenceableBytes());
833 break;
834 case Attribute::DereferenceableOrNull:
835 Attr = Attribute::getWithDereferenceableOrNullBytes(
836 C, B.getDereferenceableOrNullBytes());
837 break;
838 case Attribute::AllocSize: {
839 auto A = B.getAllocSizeArgs();
840 Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second);
841 break;
842 }
843 case Attribute::VScaleRange: {
844 auto A = B.getVScaleRangeArgs();
845 Attr = Attribute::getWithVScaleRangeArgs(C, A.first, A.second);
846 break;
847 }
848 default:
849 Attr = Attribute::get(C, Kind);
850 }
851 Attrs.push_back(Attr);
852 }
853
854 // Add target-dependent (string) attributes.
855 for (const auto &TDA : B.td_attrs())
856 Attrs.emplace_back(Attribute::get(C, TDA.first, TDA.second));
857
858 return getSorted(C, Attrs);
859}
860
861bool AttributeSetNode::hasAttribute(StringRef Kind) const {
862 return StringAttrs.count(Kind);
863}
864
865Optional<Attribute>
866AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const {
867 // Do a quick presence check.
868 if (!hasAttribute(Kind))
869 return None;
870
871 // Attributes in a set are sorted by enum value, followed by string
872 // attributes. Binary search the one we want.
873 const Attribute *I =
874 std::lower_bound(begin(), end() - StringAttrs.size(), Kind,
875 [](Attribute A, Attribute::AttrKind Kind) {
876 return A.getKindAsEnum() < Kind;
877 });
878 assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?")((void)0);
879 return *I;
880}
881
882Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
883 if (auto A = findEnumAttribute(Kind))
884 return *A;
885 return {};
886}
887
888Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
889 return StringAttrs.lookup(Kind);
890}
891
892MaybeAlign AttributeSetNode::getAlignment() const {
893 if (auto A = findEnumAttribute(Attribute::Alignment))
894 return A->getAlignment();
895 return None;
896}
897
898MaybeAlign AttributeSetNode::getStackAlignment() const {
899 if (auto A = findEnumAttribute(Attribute::StackAlignment))
900 return A->getStackAlignment();
901 return None;
902}
903
904Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const {
905 if (auto A = findEnumAttribute(Kind))
906 return A->getValueAsType();
907 return nullptr;
908}
909
910uint64_t AttributeSetNode::getDereferenceableBytes() const {
911 if (auto A = findEnumAttribute(Attribute::Dereferenceable))
912 return A->getDereferenceableBytes();
913 return 0;
914}
915
916uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
917 if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
918 return A->getDereferenceableOrNullBytes();
919 return 0;
920}
921
922std::pair<unsigned, Optional<unsigned>>
923AttributeSetNode::getAllocSizeArgs() const {
924 if (auto A = findEnumAttribute(Attribute::AllocSize))
925 return A->getAllocSizeArgs();
926 return std::make_pair(0, 0);
927}
928
929std::pair<unsigned, unsigned> AttributeSetNode::getVScaleRangeArgs() const {
930 if (auto A = findEnumAttribute(Attribute::VScaleRange))
931 return A->getVScaleRangeArgs();
932 return std::make_pair(0, 0);
933}
934
935std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
936 std::string Str;
937 for (iterator I = begin(), E = end(); I != E; ++I) {
938 if (I != begin())
939 Str += ' ';
940 Str += I->getAsString(InAttrGrp);
941 }
942 return Str;
943}
944
945//===----------------------------------------------------------------------===//
946// AttributeListImpl Definition
947//===----------------------------------------------------------------------===//
948
949/// Map from AttributeList index to the internal array index. Adding one happens
950/// to work, because -1 wraps around to 0.
951static unsigned attrIdxToArrayIdx(unsigned Index) {
952 return Index + 1;
953}
954
955AttributeListImpl::AttributeListImpl(ArrayRef<AttributeSet> Sets)
956 : NumAttrSets(Sets.size()) {
957 assert(!Sets.empty() && "pointless AttributeListImpl")((void)0);
958
959 // There's memory after the node where we can store the entries in.
960 llvm::copy(Sets, getTrailingObjects<AttributeSet>());
961
962 // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
963 // summary bitsets.
964 for (const auto &I : Sets[attrIdxToArrayIdx(AttributeList::FunctionIndex)])
965 if (!I.isStringAttribute())
966 AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
967
968 for (const auto &Set : Sets)
969 for (const auto &I : Set)
970 if (!I.isStringAttribute())
971 AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
972}
973
974void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
975 Profile(ID, makeArrayRef(begin(), end()));
976}
977
978void AttributeListImpl::Profile(FoldingSetNodeID &ID,
979 ArrayRef<AttributeSet> Sets) {
980 for (const auto &Set : Sets)
981 ID.AddPointer(Set.SetNode);
982}
983
984bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
985 unsigned *Index) const {
986 if (!AvailableSomewhereAttrs.hasAttribute(Kind))
987 return false;
988
989 if (Index) {
990 for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
991 if (begin()[I].hasAttribute(Kind)) {
992 *Index = I - 1;
993 break;
994 }
995 }
996 }
997
998 return true;
999}
1000
1001
1002#if !defined(NDEBUG1) || defined(LLVM_ENABLE_DUMP)
1003LLVM_DUMP_METHOD__attribute__((noinline)) void AttributeListImpl::dump() const {
1004 AttributeList(const_cast<AttributeListImpl *>(this)).dump();
1005}
1006#endif
1007
1008//===----------------------------------------------------------------------===//
1009// AttributeList Construction and Mutation Methods
1010//===----------------------------------------------------------------------===//
1011
1012AttributeList AttributeList::getImpl(LLVMContext &C,
1013 ArrayRef<AttributeSet> AttrSets) {
1014 assert(!AttrSets.empty() && "pointless AttributeListImpl")((void)0);
1015
1016 LLVMContextImpl *pImpl = C.pImpl;
1017 FoldingSetNodeID ID;
1018 AttributeListImpl::Profile(ID, AttrSets);
1019
1020 void *InsertPoint;
1021 AttributeListImpl *PA =
1022 pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint);
1023
1024 // If we didn't find any existing attributes of the same shape then
1025 // create a new one and insert it.
1026 if (!PA) {
1027 // Coallocate entries after the AttributeListImpl itself.
1028 void *Mem = pImpl->Alloc.Allocate(
1029 AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size()),
1030 alignof(AttributeListImpl));
1031 PA = new (Mem) AttributeListImpl(AttrSets);
1032 pImpl->AttrsLists.InsertNode(PA, InsertPoint);
1033 }
1034
1035 // Return the AttributesList that we found or created.
1036 return AttributeList(PA);
1037}
1038
1039AttributeList
1040AttributeList::get(LLVMContext &C,
1041 ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
1042 // If there are no attributes then return a null AttributesList pointer.
1043 if (Attrs.empty())
1044 return {};
1045
1046 assert(llvm::is_sorted(Attrs,((void)0)
1047 [](const std::pair<unsigned, Attribute> &LHS,((void)0)
1048 const std::pair<unsigned, Attribute> &RHS) {((void)0)
1049 return LHS.first < RHS.first;((void)0)
1050 }) &&((void)0)
1051 "Misordered Attributes list!")((void)0);
1052 assert(llvm::all_of(Attrs,((void)0)
1053 [](const std::pair<unsigned, Attribute> &Pair) {((void)0)
1054 return Pair.second.isValid();((void)0)
1055 }) &&((void)0)
1056 "Pointless attribute!")((void)0);
1057
1058 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
1059 // list.
1060 SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec;
1061 for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(),
1062 E = Attrs.end(); I != E; ) {
1063 unsigned Index = I->first;
1064 SmallVector<Attribute, 4> AttrVec;
1065 while (I != E && I->first == Index) {
1066 AttrVec.push_back(I->second);
1067 ++I;
1068 }
1069
1070 AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec));
1071 }
1072
1073 return get(C, AttrPairVec);
1074}
1075
1076AttributeList
1077AttributeList::get(LLVMContext &C,
1078 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
1079 // If there are no attributes then return a null AttributesList pointer.
1080 if (Attrs.empty())
1081 return {};
1082
1083 assert(llvm::is_sorted(Attrs,((void)0)
1084 [](const std::pair<unsigned, AttributeSet> &LHS,((void)0)
1085 const std::pair<unsigned, AttributeSet> &RHS) {((void)0)
1086 return LHS.first < RHS.first;((void)0)
1087 }) &&((void)0)
1088 "Misordered Attributes list!")((void)0);
1089 assert(llvm::none_of(Attrs,((void)0)
1090 [](const std::pair<unsigned, AttributeSet> &Pair) {((void)0)
1091 return !Pair.second.hasAttributes();((void)0)
1092 }) &&((void)0)
1093 "Pointless attribute!")((void)0);
1094
1095 unsigned MaxIndex = Attrs.back().first;
1096 // If the MaxIndex is FunctionIndex and there are other indices in front
1097 // of it, we need to use the largest of those to get the right size.
1098 if (MaxIndex == FunctionIndex && Attrs.size() > 1)
1099 MaxIndex = Attrs[Attrs.size() - 2].first;
1100
1101 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
1102 for (const auto &Pair : Attrs)
1103 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
1104
1105 return getImpl(C, AttrVec);
1106}
1107
1108AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
1109 AttributeSet RetAttrs,
1110 ArrayRef<AttributeSet> ArgAttrs) {
1111 // Scan from the end to find the last argument with attributes. Most
1112 // arguments don't have attributes, so it's nice if we can have fewer unique
1113 // AttributeListImpls by dropping empty attribute sets at the end of the list.
1114 unsigned NumSets = 0;
1115 for (size_t I = ArgAttrs.size(); I != 0; --I) {
1116 if (ArgAttrs[I - 1].hasAttributes()) {
1117 NumSets = I + 2;
1118 break;
1119 }
1120 }
1121 if (NumSets == 0) {
1122 // Check function and return attributes if we didn't have argument
1123 // attributes.
1124 if (RetAttrs.hasAttributes())
1125 NumSets = 2;
1126 else if (FnAttrs.hasAttributes())
1127 NumSets = 1;
1128 }
1129
1130 // If all attribute sets were empty, we can use the empty attribute list.
1131 if (NumSets == 0)
1132 return {};
1133
1134 SmallVector<AttributeSet, 8> AttrSets;
1135 AttrSets.reserve(NumSets);
1136 // If we have any attributes, we always have function attributes.
1137 AttrSets.push_back(FnAttrs);
1138 if (NumSets > 1)
1139 AttrSets.push_back(RetAttrs);
1140 if (NumSets > 2) {
1141 // Drop the empty argument attribute sets at the end.
1142 ArgAttrs = ArgAttrs.take_front(NumSets - 2);
1143 llvm::append_range(AttrSets, ArgAttrs);
1144 }
1145
1146 return getImpl(C, AttrSets);
1147}
1148
1149AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1150 const AttrBuilder &B) {
1151 if (!B.hasAttributes())
1152 return {};
1153 Index = attrIdxToArrayIdx(Index);
1154 SmallVector<AttributeSet, 8> AttrSets(Index + 1);
1155 AttrSets[Index] = AttributeSet::get(C, B);
1156 return getImpl(C, AttrSets);
1157}
1158
1159AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1160 ArrayRef<Attribute::AttrKind> Kinds) {
1161 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1162 for (const auto K : Kinds)
1163 Attrs.emplace_back(Index, Attribute::get(C, K));
1164 return get(C, Attrs);
1165}
1166
1167AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1168 ArrayRef<Attribute::AttrKind> Kinds,
1169 ArrayRef<uint64_t> Values) {
1170 assert(Kinds.size() == Values.size() && "Mismatched attribute values.")((void)0);
1171 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1172 auto VI = Values.begin();
1173 for (const auto K : Kinds)
1174 Attrs.emplace_back(Index, Attribute::get(C, K, *VI++));
1175 return get(C, Attrs);
1176}
1177
1178AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
1179 ArrayRef<StringRef> Kinds) {
1180 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
1181 for (const auto &K : Kinds)
1182 Attrs.emplace_back(Index, Attribute::get(C, K));
1183 return get(C, Attrs);
1184}
1185
1186AttributeList AttributeList::get(LLVMContext &C,
1187 ArrayRef<AttributeList> Attrs) {
1188 if (Attrs.empty())
1189 return {};
1190 if (Attrs.size() == 1)
1191 return Attrs[0];
1192
1193 unsigned MaxSize = 0;
1194 for (const auto &List : Attrs)
1195 MaxSize = std::max(MaxSize, List.getNumAttrSets());
1196
1197 // If every list was empty, there is no point in merging the lists.
1198 if (MaxSize == 0)
1199 return {};
1200
1201 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
1202 for (unsigned I = 0; I < MaxSize; ++I) {
1203 AttrBuilder CurBuilder;
1204 for (const auto &List : Attrs)
1205 CurBuilder.merge(List.getAttributes(I - 1));
1206 NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
1207 }
1208
1209 return getImpl(C, NewAttrSets);
1210}
1211
1212AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
1213 Attribute::AttrKind Kind) const {
1214 if (hasAttribute(Index, Kind)) return *this;
1215 AttributeSet Attrs = getAttributes(Index);
1216 // TODO: Insert at correct position and avoid sort.
1217 SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end());
1218 NewAttrs.push_back(Attribute::get(C, Kind));
1219 return setAttributes(C, Index, AttributeSet::get(C, NewAttrs));
1220}
1221
1222AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
1223 StringRef Kind,
1224 StringRef Value) const {
1225 AttrBuilder B;
1226 B.addAttribute(Kind, Value);
1227 return addAttributes(C, Index, B);
1228}
1229
1230AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index,
1231 Attribute A) const {
1232 AttrBuilder B;
1233 B.addAttribute(A);
1234 return addAttributes(C, Index, B);
1235}
1236
1237AttributeList AttributeList::setAttributes(LLVMContext &C, unsigned Index,
1238 AttributeSet Attrs) const {
1239 Index = attrIdxToArrayIdx(Index);
1240 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1241 if (Index >= AttrSets.size())
1242 AttrSets.resize(Index + 1);
1243 AttrSets[Index] = Attrs;
1244 return AttributeList::getImpl(C, AttrSets);
1245}
1246
1247AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
1248 const AttrBuilder &B) const {
1249 if (!B.hasAttributes())
1250 return *this;
1251
1252 if (!pImpl)
1253 return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
1254
1255#ifndef NDEBUG1
1256 // FIXME it is not obvious how this should work for alignment. For now, say
1257 // we can't change a known alignment.
1258 const MaybeAlign OldAlign = getAttributes(Index).getAlignment();
1259 const MaybeAlign NewAlign = B.getAlignment();
1260 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&((void)0)
1261 "Attempt to change alignment!")((void)0);
1262#endif
1263
1264 AttrBuilder Merged(getAttributes(Index));
1265 Merged.merge(B);
1266 return setAttributes(C, Index, AttributeSet::get(C, Merged));
1267}
1268
1269AttributeList AttributeList::addParamAttribute(LLVMContext &C,
1270 ArrayRef<unsigned> ArgNos,
1271 Attribute A) const {
1272 assert(llvm::is_sorted(ArgNos))((void)0);
1273
1274 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1275 unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex);
1276 if (MaxIndex >= AttrSets.size())
1277 AttrSets.resize(MaxIndex + 1);
1278
1279 for (unsigned ArgNo : ArgNos) {
1280 unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
1281 AttrBuilder B(AttrSets[Index]);
1282 B.addAttribute(A);
1283 AttrSets[Index] = AttributeSet::get(C, B);
1284 }
1285
1286 return getImpl(C, AttrSets);
1287}
1288
1289AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
1290 Attribute::AttrKind Kind) const {
1291 if (!hasAttribute(Index, Kind)) return *this;
1292
1293 Index = attrIdxToArrayIdx(Index);
1294 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1295 assert(Index < AttrSets.size())((void)0);
1296
1297 AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
1298
1299 return getImpl(C, AttrSets);
1300}
1301
1302AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
1303 StringRef Kind) const {
1304 if (!hasAttribute(Index, Kind)) return *this;
1305
1306 Index = attrIdxToArrayIdx(Index);
1307 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1308 assert(Index < AttrSets.size())((void)0);
1309
1310 AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
1311
1312 return getImpl(C, AttrSets);
1313}
1314
1315AttributeList
1316AttributeList::removeAttributes(LLVMContext &C, unsigned Index,
1317 const AttrBuilder &AttrsToRemove) const {
1318 AttributeSet Attrs = getAttributes(Index);
1319 AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
1320 // If nothing was removed, return the original list.
1321 if (Attrs == NewAttrs)
1322 return *this;
1323 return setAttributes(C, Index, NewAttrs);
1324}
1325
1326AttributeList AttributeList::removeAttributes(LLVMContext &C,
1327 unsigned WithoutIndex) const {
1328 if (!pImpl)
1329 return {};
1330 WithoutIndex = attrIdxToArrayIdx(WithoutIndex);
1331 if (WithoutIndex >= getNumAttrSets())
1332 return *this;
1333 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1334 AttrSets[WithoutIndex] = AttributeSet();
1335 return getImpl(C, AttrSets);
1336}
1337
1338AttributeList AttributeList::addDereferenceableAttr(LLVMContext &C,
1339 unsigned Index,
1340 uint64_t Bytes) const {
1341 AttrBuilder B;
1342 B.addDereferenceableAttr(Bytes);
1343 return addAttributes(C, Index, B);
1344}
1345
1346AttributeList
1347AttributeList::addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
1348 uint64_t Bytes) const {
1349 AttrBuilder B;
1350 B.addDereferenceableOrNullAttr(Bytes);
1351 return addAttributes(C, Index, B);
1352}
1353
1354AttributeList
1355AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index,
1356 unsigned ElemSizeArg,
1357 const Optional<unsigned> &NumElemsArg) {
1358 AttrBuilder B;
1359 B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
1360 return addAttributes(C, Index, B);
1361}
1362
1363AttributeList AttributeList::addVScaleRangeAttr(LLVMContext &C, unsigned Index,
1364 unsigned MinValue,
1365 unsigned MaxValue) {
1366 AttrBuilder B;
1367 B.addVScaleRangeAttr(MinValue, MaxValue);
1368 return addAttributes(C, Index, B);
1369}
1370
1371//===----------------------------------------------------------------------===//
1372// AttributeList Accessor Methods
1373//===----------------------------------------------------------------------===//
1374
1375AttributeSet AttributeList::getParamAttributes(unsigned ArgNo) const {
1376 return getAttributes(ArgNo + FirstArgIndex);
1377}
1378
1379AttributeSet AttributeList::getRetAttributes() const {
1380 return getAttributes(ReturnIndex);
1381}
1382
1383AttributeSet AttributeList::getFnAttributes() const {
1384 return getAttributes(FunctionIndex);
1385}
1386
1387bool AttributeList::hasAttribute(unsigned Index,
1388 Attribute::AttrKind Kind) const {
1389 return getAttributes(Index).hasAttribute(Kind);
1390}
1391
1392bool AttributeList::hasAttribute(unsigned Index, StringRef Kind) const {
1393 return getAttributes(Index).hasAttribute(Kind);
1394}
1395
1396bool AttributeList::hasAttributes(unsigned Index) const {
1397 return getAttributes(Index).hasAttributes();
1398}
1399
1400bool AttributeList::hasFnAttribute(Attribute::AttrKind Kind) const {
1401 return pImpl && pImpl->hasFnAttribute(Kind);
1402}
1403
1404bool AttributeList::hasFnAttribute(StringRef Kind) const {
1405 return hasAttribute(AttributeList::FunctionIndex, Kind);
1406}
1407
1408bool AttributeList::hasParamAttribute(unsigned ArgNo,
1409 Attribute::AttrKind Kind) const {
1410 return hasAttribute(ArgNo + FirstArgIndex, Kind);
1411}
1412
1413bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
1414 unsigned *Index) const {
1415 return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
1416}
1417
1418Attribute AttributeList::getAttribute(unsigned Index,
1419 Attribute::AttrKind Kind) const {
1420 return getAttributes(Index).getAttribute(Kind);
1421}
1422
1423Attribute AttributeList::getAttribute(unsigned Index, StringRef Kind) const {
1424 return getAttributes(Index).getAttribute(Kind);
1425}
1426
1427MaybeAlign AttributeList::getRetAlignment() const {
1428 return getAttributes(ReturnIndex).getAlignment();
1429}
1430
1431MaybeAlign AttributeList::getParamAlignment(unsigned ArgNo) const {
1432 return getAttributes(ArgNo + FirstArgIndex).getAlignment();
1433}
1434
1435MaybeAlign AttributeList::getParamStackAlignment(unsigned ArgNo) const {
1436 return getAttributes(ArgNo + FirstArgIndex).getStackAlignment();
1437}
1438
1439Type *AttributeList::getParamByValType(unsigned Index) const {
1440 return getAttributes(Index+FirstArgIndex).getByValType();
1441}
1442
1443Type *AttributeList::getParamStructRetType(unsigned Index) const {
1444 return getAttributes(Index + FirstArgIndex).getStructRetType();
1445}
1446
1447Type *AttributeList::getParamByRefType(unsigned Index) const {
1448 return getAttributes(Index + FirstArgIndex).getByRefType();
1449}
1450
1451Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
1452 return getAttributes(Index + FirstArgIndex).getPreallocatedType();
1453}
1454
1455Type *AttributeList::getParamInAllocaType(unsigned Index) const {
1456 return getAttributes(Index + FirstArgIndex).getInAllocaType();
1457}
1458
1459Type *AttributeList::getParamElementType(unsigned Index) const {
1460 return getAttributes(Index + FirstArgIndex).getElementType();
1461}
1462
1463MaybeAlign AttributeList::getStackAlignment(unsigned Index) const {
1464 return getAttributes(Index).getStackAlignment();
1465}
1466
1467uint64_t AttributeList::getDereferenceableBytes(unsigned Index) const {
1468 return getAttributes(Index).getDereferenceableBytes();
1469}
1470
1471uint64_t AttributeList::getDereferenceableOrNullBytes(unsigned Index) const {
1472 return getAttributes(Index).getDereferenceableOrNullBytes();
1473}
1474
1475std::pair<unsigned, Optional<unsigned>>
1476AttributeList::getAllocSizeArgs(unsigned Index) const {
1477 return getAttributes(Index).getAllocSizeArgs();
1478}
1479
1480std::pair<unsigned, unsigned>
1481AttributeList::getVScaleRangeArgs(unsigned Index) const {
1482 return getAttributes(Index).getVScaleRangeArgs();
1483}
1484
1485std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
1486 return getAttributes(Index).getAsString(InAttrGrp);
1487}
1488
1489AttributeSet AttributeList::getAttributes(unsigned Index) const {
1490 Index = attrIdxToArrayIdx(Index);
1491 if (!pImpl || Index >= getNumAttrSets())
1492 return {};
1493 return pImpl->begin()[Index];
1494}
1495
1496bool AttributeList::hasParentContext(LLVMContext &C) const {
1497 assert(!isEmpty() && "an empty attribute list has no parent context")((void)0);
1498 FoldingSetNodeID ID;
1499 pImpl->Profile(ID);
1500 void *Unused;
1501 return C.pImpl->AttrsLists.FindNodeOrInsertPos(ID, Unused) == pImpl;
1502}
1503
1504AttributeList::iterator AttributeList::begin() const {
1505 return pImpl ? pImpl->begin() : nullptr;
1506}
1507
1508AttributeList::iterator AttributeList::end() const {
1509 return pImpl ? pImpl->end() : nullptr;
1510}
1511
1512//===----------------------------------------------------------------------===//
1513// AttributeList Introspection Methods
1514//===----------------------------------------------------------------------===//
1515
1516unsigned AttributeList::getNumAttrSets() const {
1517 return pImpl ? pImpl->NumAttrSets : 0;
1518}
1519
1520void AttributeList::print(raw_ostream &O) const {
1521 O << "AttributeList[\n";
1522
1523 for (unsigned i = index_begin(), e = index_end(); i != e; ++i) {
1524 if (!getAttributes(i).hasAttributes())
1525 continue;
1526 O << " { ";
1527 switch (i) {
1528 case AttrIndex::ReturnIndex:
1529 O << "return";
1530 break;
1531 case AttrIndex::FunctionIndex:
1532 O << "function";
1533 break;
1534 default:
1535 O << "arg(" << i - AttrIndex::FirstArgIndex << ")";
1536 }
1537 O << " => " << getAsString(i) << " }\n";
1538 }
1539
1540 O << "]\n";
1541}
1542
1543#if !defined(NDEBUG1) || defined(LLVM_ENABLE_DUMP)
1544LLVM_DUMP_METHOD__attribute__((noinline)) void AttributeList::dump() const { print(dbgs()); }
1545#endif
1546
1547//===----------------------------------------------------------------------===//
1548// AttrBuilder Method Implementations
1549//===----------------------------------------------------------------------===//
1550
1551// FIXME: Remove this ctor, use AttributeSet.
1552AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) {
1553 AttributeSet AS = AL.getAttributes(Index);
1554 for (const auto &A : AS)
1555 addAttribute(A);
1556}
1557
1558AttrBuilder::AttrBuilder(AttributeSet AS) {
1559 for (const auto &A : AS)
1560 addAttribute(A);
1561}
1562
1563void AttrBuilder::clear() {
1564 Attrs.reset();
1565 TargetDepAttrs.clear();
1566 Alignment.reset();
1567 StackAlignment.reset();
1568 DerefBytes = DerefOrNullBytes = 0;
1569 AllocSizeArgs = 0;
1570 VScaleRangeArgs = 0;
1571 TypeAttrs = {};
1572}
1573
1574Optional<unsigned>
1575AttrBuilder::kindToTypeIndex(Attribute::AttrKind Kind) const {
1576 if (Attribute::isTypeAttrKind(Kind))
1577 return Kind - Attribute::FirstTypeAttr;
1578 return None;
1579}
1580
1581AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
1582 if (Attr.isStringAttribute()) {
1583 addAttribute(Attr.getKindAsString(), Attr.getValueAsString());
1584 return *this;
1585 }
1586
1587 Attribute::AttrKind Kind = Attr.getKindAsEnum();
1588 Attrs[Kind] = true;
1589
1590 if (Optional<unsigned> TypeIndex = kindToTypeIndex(Kind))
1591 TypeAttrs[*TypeIndex] = Attr.getValueAsType();
1592 else if (Kind == Attribute::Alignment)
1593 Alignment = Attr.getAlignment();
1594 else if (Kind == Attribute::StackAlignment)
1595 StackAlignment = Attr.getStackAlignment();
1596 else if (Kind == Attribute::Dereferenceable)
1597 DerefBytes = Attr.getDereferenceableBytes();
1598 else if (Kind == Attribute::DereferenceableOrNull)
1599 DerefOrNullBytes = Attr.getDereferenceableOrNullBytes();
1600 else if (Kind == Attribute::AllocSize)
1601 AllocSizeArgs = Attr.getValueAsInt();
1602 else if (Kind == Attribute::VScaleRange)
1603 VScaleRangeArgs = Attr.getValueAsInt();
1604
1605 return *this;
1606}
1607
1608AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
1609 TargetDepAttrs[A] = V;
1610 return *this;
1611}
1612
1613AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
1614 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!")((void)0);
1615 Attrs[Val] = false;
1616
1617 if (Optional<unsigned> TypeIndex = kindToTypeIndex(Val))
1618 TypeAttrs[*TypeIndex] = nullptr;
1619 else if (Val == Attribute::Alignment)
1620 Alignment.reset();
1621 else if (Val == Attribute::StackAlignment)
1622 StackAlignment.reset();
1623 else if (Val == Attribute::Dereferenceable)
1624 DerefBytes = 0;
1625 else if (Val == Attribute::DereferenceableOrNull)
1626 DerefOrNullBytes = 0;
1627 else if (Val == Attribute::AllocSize)
1628 AllocSizeArgs = 0;
1629 else if (Val == Attribute::VScaleRange)
1630 VScaleRangeArgs = 0;
1631
1632 return *this;
1633}
1634
1635AttrBuilder &AttrBuilder::removeAttributes(AttributeList A, uint64_t Index) {
1636 remove(A.getAttributes(Index));
1637 return *this;
1638}
1639
1640AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
1641 auto I = TargetDepAttrs.find(A);
1642 if (I != TargetDepAttrs.end())
1643 TargetDepAttrs.erase(I);
1644 return *this;
1645}
1646
1647std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
1648 return unpackAllocSizeArgs(AllocSizeArgs);
1649}
1650
1651std::pair<unsigned, unsigned> AttrBuilder::getVScaleRangeArgs() const {
1652 return unpackVScaleRangeArgs(VScaleRangeArgs);
1653}
1654
1655AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) {
1656 if (!Align)
1657 return *this;
1658
1659 assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large.")((void)0);
1660
1661 Attrs[Attribute::Alignment] = true;
1662 Alignment = Align;
1663 return *this;
1664}
1665
1666AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) {
1667 // Default alignment, allow the target to define how to align it.
1668 if (!Align)
1669 return *this;
1670
1671 assert(*Align <= 0x100 && "Alignment too large.")((void)0);
1672
1673 Attrs[Attribute::StackAlignment] = true;
1674 StackAlignment = Align;
1675 return *this;
1676}
1677
1678AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
1679 if (Bytes == 0) return *this;
1680
1681 Attrs[Attribute::Dereferenceable] = true;
1682 DerefBytes = Bytes;
1683 return *this;
1684}
1685
1686AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
1687 if (Bytes == 0)
1688 return *this;
1689
1690 Attrs[Attribute::DereferenceableOrNull] = true;
1691 DerefOrNullBytes = Bytes;
1692 return *this;
1693}
1694
1695AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize,
1696 const Optional<unsigned> &NumElems) {
1697 return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems));
1698}
1699
1700AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
1701 // (0, 0) is our "not present" value, so we need to check for it here.
1702 assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)")((void)0);
1703
1704 Attrs[Attribute::AllocSize] = true;
1705 // Reuse existing machinery to store this as a single 64-bit integer so we can
1706 // save a few bytes over using a pair<unsigned, Optional<unsigned>>.
1707 AllocSizeArgs = RawArgs;
1708 return *this;
1709}
1710
1711AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue,
1712 unsigned MaxValue) {
1713 return addVScaleRangeAttrFromRawRepr(packVScaleRangeArgs(MinValue, MaxValue));
1714}
1715
1716AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
1717 // (0, 0) is not present hence ignore this case
1718 if (RawArgs == 0)
1719 return *this;
1720
1721 Attrs[Attribute::VScaleRange] = true;
1722 // Reuse existing machinery to store this as a single 64-bit integer so we can
1723 // save a few bytes over using a pair<unsigned, unsigned>.
1724 VScaleRangeArgs = RawArgs;
1725 return *this;
1726}
1727
1728Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
1729 Optional<unsigned> TypeIndex = kindToTypeIndex(Kind);
1730 assert(TypeIndex && "Not a type attribute")((void)0);
1731 return TypeAttrs[*TypeIndex];
1732}
1733
1734AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
1735 Optional<unsigned> TypeIndex = kindToTypeIndex(Kind);
1736 assert(TypeIndex && "Not a type attribute")((void)0);
1737 Attrs[Kind] = true;
1738 TypeAttrs[*TypeIndex] = Ty;
1739 return *this;
1740}
1741
1742AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
1743 return addTypeAttr(Attribute::ByVal, Ty);
1744}
1745
1746AttrBuilder &AttrBuilder::addStructRetAttr(Type *Ty) {
1747 return addTypeAttr(Attribute::StructRet, Ty);
1748}
1749
1750AttrBuilder &AttrBuilder::addByRefAttr(Type *Ty) {
1751 return addTypeAttr(Attribute::ByRef, Ty);
1752}
1753
1754AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
1755 return addTypeAttr(Attribute::Preallocated, Ty);
1756}
1757
1758AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
1759 return addTypeAttr(Attribute::InAlloca, Ty);
1760}
1761
1762AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
1763 // FIXME: What if both have alignments, but they don't match?!
1764 if (!Alignment)
1765 Alignment = B.Alignment;
1766
1767 if (!StackAlignment)
1768 StackAlignment = B.StackAlignment;
1769
1770 if (!DerefBytes)
1771 DerefBytes = B.DerefBytes;
1772
1773 if (!DerefOrNullBytes)
1774 DerefOrNullBytes = B.DerefOrNullBytes;
1775
1776 if (!AllocSizeArgs)
1777 AllocSizeArgs = B.AllocSizeArgs;
1778
1779 if (!VScaleRangeArgs)
1780 VScaleRangeArgs = B.VScaleRangeArgs;
1781
1782 for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index)
1783 if (!TypeAttrs[Index])
1784 TypeAttrs[Index] = B.TypeAttrs[Index];
1785
1786 Attrs |= B.Attrs;
1787
1788 for (const auto &I : B.td_attrs())
1789 TargetDepAttrs[I.first] = I.second;
1790
1791 return *this;
1792}
1793
1794AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
1795 // FIXME: What if both have alignments, but they don't match?!
1796 if (B.Alignment)
1797 Alignment.reset();
1798
1799 if (B.StackAlignment)
1800 StackAlignment.reset();
1801
1802 if (B.DerefBytes)
1803 DerefBytes = 0;
1804
1805 if (B.DerefOrNullBytes)
1806 DerefOrNullBytes = 0;
1807
1808 if (B.AllocSizeArgs)
1809 AllocSizeArgs = 0;
1810
1811 if (B.VScaleRangeArgs)
1812 VScaleRangeArgs = 0;
1813
1814 for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index)
1815 if (B.TypeAttrs[Index])
1816 TypeAttrs[Index] = nullptr;
1817
1818 Attrs &= ~B.Attrs;
1819
1820 for (const auto &I : B.td_attrs())
1821 TargetDepAttrs.erase(I.first);
1822
1823 return *this;
1824}
1825
1826bool AttrBuilder::overlaps(const AttrBuilder &B) const {
1827 // First check if any of the target independent attributes overlap.
1828 if ((Attrs & B.Attrs).any())
1829 return true;
1830
1831 // Then check if any target dependent ones do.
1832 for (const auto &I : td_attrs())
1833 if (B.contains(I.first))
1834 return true;
1835
1836 return false;
1837}
1838
1839bool AttrBuilder::contains(StringRef A) const {
1840 return TargetDepAttrs.find(A) != TargetDepAttrs.end();
1841}
1842
1843bool AttrBuilder::hasAttributes() const {
1844 return !Attrs.none() || !TargetDepAttrs.empty();
1845}
1846
1847bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const {
1848 AttributeSet AS = AL.getAttributes(Index);
1849
1850 for (const auto &Attr : AS) {
1851 if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
1852 if (contains(Attr.getKindAsEnum()))
1853 return true;
1854 } else {
1855 assert(Attr.isStringAttribute() && "Invalid attribute kind!")((void)0);
1856 return contains(Attr.getKindAsString());
1857 }
1858 }
1859
1860 return false;
1861}
1862
1863bool AttrBuilder::hasAlignmentAttr() const {
1864 return Alignment != 0;
1865}
1866
1867bool AttrBuilder::operator==(const AttrBuilder &B) const {
1868 if (Attrs != B.Attrs)
1869 return false;
1870
1871 for (const auto &TDA : TargetDepAttrs)
1872 if (B.TargetDepAttrs.find(TDA.first) == B.TargetDepAttrs.end())
1873 return false;
1874
1875 return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
1876 DerefBytes == B.DerefBytes && TypeAttrs == B.TypeAttrs &&
1877 VScaleRangeArgs == B.VScaleRangeArgs;
1878}
1879
1880//===----------------------------------------------------------------------===//
1881// AttributeFuncs Function Defintions
1882//===----------------------------------------------------------------------===//
1883
1884/// Which attributes cannot be applied to a type.
1885AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
1886 AttrBuilder Incompatible;
1887
1888 if (!Ty->isIntegerTy())
1889 // Attribute that only apply to integers.
1890 Incompatible.addAttribute(Attribute::SExt)
1891 .addAttribute(Attribute::ZExt);
1892
1893 if (!Ty->isPointerTy())
1894 // Attribute that only apply to pointers.
1895 Incompatible.addAttribute(Attribute::Nest)
1896 .addAttribute(Attribute::NoAlias)
1897 .addAttribute(Attribute::NoCapture)
1898 .addAttribute(Attribute::NonNull)
1899 .addAttribute(Attribute::ReadNone)
1900 .addAttribute(Attribute::ReadOnly)
1901 .addAttribute(Attribute::SwiftError)
1902 .addAlignmentAttr(1) // the int here is ignored
1903 .addDereferenceableAttr(1) // the int here is ignored
1904 .addDereferenceableOrNullAttr(1) // the int here is ignored
1905 .addPreallocatedAttr(Ty)
1906 .addInAllocaAttr(Ty)
1907 .addByValAttr(Ty)
1908 .addStructRetAttr(Ty)
1909 .addByRefAttr(Ty)
1910 .addTypeAttr(Attribute::ElementType, Ty);
1911
1912 // Some attributes can apply to all "values" but there are no `void` values.
1913 if (Ty->isVoidTy())
1914 Incompatible.addAttribute(Attribute::NoUndef);
1915
1916 return Incompatible;
1917}
1918
1919AttrBuilder AttributeFuncs::getUBImplyingAttributes() {
1920 AttrBuilder B;
1921 B.addAttribute(Attribute::NoUndef);
1922 B.addDereferenceableAttr(1);
1923 B.addDereferenceableOrNullAttr(1);
1924 return B;
1925}
1926
1927template<typename AttrClass>
1928static bool isEqual(const Function &Caller, const Function &Callee) {
1929 return Caller.getFnAttribute(AttrClass::getKind()) ==
1930 Callee.getFnAttribute(AttrClass::getKind());
1931}
1932
1933/// Compute the logical AND of the attributes of the caller and the
1934/// callee.
1935///
1936/// This function sets the caller's attribute to false if the callee's attribute
1937/// is false.
1938template<typename AttrClass>
1939static void setAND(Function &Caller, const Function &Callee) {
1940 if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
1941 !AttrClass::isSet(Callee, AttrClass::getKind()))
1942 AttrClass::set(Caller, AttrClass::getKind(), false);
1943}
1944
1945/// Compute the logical OR of the attributes of the caller and the
1946/// callee.
1947///
1948/// This function sets the caller's attribute to true if the callee's attribute
1949/// is true.
1950template<typename AttrClass>
1951static void setOR(Function &Caller, const Function &Callee) {
1952 if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
1953 AttrClass::isSet(Callee, AttrClass::getKind()))
1954 AttrClass::set(Caller, AttrClass::getKind(), true);
1955}
1956
1957/// If the inlined function had a higher stack protection level than the
1958/// calling function, then bump up the caller's stack protection level.
1959static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
1960 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
1961 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
1962 // clutter to the IR.
1963 AttrBuilder OldSSPAttr;
1964 OldSSPAttr.addAttribute(Attribute::StackProtect)
1965 .addAttribute(Attribute::StackProtectStrong)
1966 .addAttribute(Attribute::StackProtectReq);
1967
1968 if (Callee.hasFnAttribute(Attribute::StackProtectReq)) {
1969 Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr);
1970 Caller.addFnAttr(Attribute::StackProtectReq);
1971 } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
1972 !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
1973 Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr);
1974 Caller.addFnAttr(Attribute::StackProtectStrong);
1975 } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
1976 !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
1977 !Caller.hasFnAttribute(Attribute::StackProtectStrong))
1978 Caller.addFnAttr(Attribute::StackProtect);
1979}
1980
1981/// If the inlined function required stack probes, then ensure that
1982/// the calling function has those too.
1983static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
1984 if (!Caller.hasFnAttribute("probe-stack") &&
1985 Callee.hasFnAttribute("probe-stack")) {
1986 Caller.addFnAttr(Callee.getFnAttribute("probe-stack"));
1987 }
1988}
1989
1990/// If the inlined function defines the size of guard region
1991/// on the stack, then ensure that the calling function defines a guard region
1992/// that is no larger.
1993static void
1994adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
1995 Attribute CalleeAttr = Callee.getFnAttribute("stack-probe-size");
1996 if (CalleeAttr.isValid()) {
1997 Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
1998 if (CallerAttr.isValid()) {
1999 uint64_t CallerStackProbeSize, CalleeStackProbeSize;
2000 CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
2001 CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
2002
2003 if (CallerStackProbeSize > CalleeStackProbeSize) {
2004 Caller.addFnAttr(CalleeAttr);
2005 }
2006 } else {
2007 Caller.addFnAttr(CalleeAttr);
2008 }
2009 }
2010}
2011
2012/// If the inlined function defines a min legal vector width, then ensure
2013/// the calling function has the same or larger min legal vector width. If the
2014/// caller has the attribute, but the callee doesn't, we need to remove the
2015/// attribute from the caller since we can't make any guarantees about the
2016/// caller's requirements.
2017/// This function is called after the inlining decision has been made so we have
2018/// to merge the attribute this way. Heuristics that would use
2019/// min-legal-vector-width to determine inline compatibility would need to be
2020/// handled as part of inline cost analysis.
2021static void
2022adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
2023 Attribute CallerAttr = Caller.getFnAttribute("min-legal-vector-width");
2024 if (CallerAttr.isValid()) {
2025 Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
2026 if (CalleeAttr.isValid()) {
2027 uint64_t CallerVectorWidth, CalleeVectorWidth;
2028 CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
2029 CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
2030 if (CallerVectorWidth < CalleeVectorWidth)
2031 Caller.addFnAttr(CalleeAttr);
2032 } else {
2033 // If the callee doesn't have the attribute then we don't know anything
2034 // and must drop the attribute from the caller.
2035 Caller.removeFnAttr("min-legal-vector-width");
2036 }
2037 }
2038}
2039
2040/// If the inlined function has null_pointer_is_valid attribute,
2041/// set this attribute in the caller post inlining.
2042static void
2043adjustNullPointerValidAttr(Function &Caller, const Function &Callee) {
2044 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) {
2045 Caller.addFnAttr(Attribute::NullPointerIsValid);
2046 }
2047}
2048
2049struct EnumAttr {
2050 static bool isSet(const Function &Fn,
2051 Attribute::AttrKind Kind) {
2052 return Fn.hasFnAttribute(Kind);
2053 }
2054
2055 static void set(Function &Fn,
2056 Attribute::AttrKind Kind, bool Val) {
2057 if (Val)
2058 Fn.addFnAttr(Kind);
2059 else
2060 Fn.removeFnAttr(Kind);
2061 }
2062};
2063
2064struct StrBoolAttr {
2065 static bool isSet(const Function &Fn,
2066 StringRef Kind) {
2067 auto A = Fn.getFnAttribute(Kind);
2068 return A.getValueAsString().equals("true");
2069 }
2070
2071 static void set(Function &Fn,
2072 StringRef Kind, bool Val) {
2073 Fn.addFnAttr(Kind, Val ? "true" : "false");
2074 }
2075};
2076
2077#define GET_ATTR_NAMES
2078#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
2079 struct ENUM_NAME##Attr : EnumAttr { \
2080 static enum Attribute::AttrKind getKind() { \
2081 return llvm::Attribute::ENUM_NAME; \
2082 } \
2083 };
2084#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
2085 struct ENUM_NAME##Attr : StrBoolAttr { \
2086 static StringRef getKind() { return #DISPLAY_NAME; } \
2087 };
2088#include "llvm/IR/Attributes.inc"
2089
2090#define GET_ATTR_COMPAT_FUNC
2091#include "llvm/IR/Attributes.inc"
2092
2093bool AttributeFuncs::areInlineCompatible(const Function &Caller,
2094 const Function &Callee) {
2095 return hasCompatibleFnAttrs(Caller, Callee);
2096}
2097
2098bool AttributeFuncs::areOutlineCompatible(const Function &A,
2099 const Function &B) {
2100 return hasCompatibleFnAttrs(A, B);
2101}
2102
2103void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
2104 const Function &Callee) {
2105 mergeFnAttrs(Caller, Callee);
2106}
2107
2108void AttributeFuncs::mergeAttributesForOutlining(Function &Base,
2109 const Function &ToMerge) {
2110
2111 // We merge functions so that they meet the most general case.
2112 // For example, if the NoNansFPMathAttr is set in one function, but not in
2113 // the other, in the merged function we can say that the NoNansFPMathAttr
2114 // is not set.
2115 // However if we have the SpeculativeLoadHardeningAttr set true in one
2116 // function, but not the other, we make sure that the function retains
2117 // that aspect in the merged function.
2118 mergeFnAttrs(Base, ToMerge);
2119}

/usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support/Allocator.h

1//===- Allocator.h - Simple memory allocation abstraction -------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8/// \file
9///
10/// This file defines the BumpPtrAllocator interface. BumpPtrAllocator conforms
11/// to the LLVM "Allocator" concept and is similar to MallocAllocator, but
12/// objects cannot be deallocated. Their lifetime is tied to the lifetime of the
13/// allocator.
14///
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_SUPPORT_ALLOCATOR_H
18#define LLVM_SUPPORT_ALLOCATOR_H
19
20#include "llvm/ADT/Optional.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/Support/Alignment.h"
23#include "llvm/Support/AllocatorBase.h"
24#include "llvm/Support/Compiler.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/MathExtras.h"
27#include "llvm/Support/MemAlloc.h"
28#include <algorithm>
29#include <cassert>
30#include <cstddef>
31#include <cstdint>
32#include <cstdlib>
33#include <iterator>
34#include <type_traits>
35#include <utility>
36
37namespace llvm {
38
39namespace detail {
40
41// We call out to an external function to actually print the message as the
42// printing code uses Allocator.h in its implementation.
43void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
44 size_t TotalMemory);
45
46} // end namespace detail
47
48/// Allocate memory in an ever growing pool, as if by bump-pointer.
49///
50/// This isn't strictly a bump-pointer allocator as it uses backing slabs of
51/// memory rather than relying on a boundless contiguous heap. However, it has
52/// bump-pointer semantics in that it is a monotonically growing pool of memory
53/// where every allocation is found by merely allocating the next N bytes in
54/// the slab, or the next N bytes in the next slab.
55///
56/// Note that this also has a threshold for forcing allocations above a certain
57/// size into their own slab.
58///
59/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator
60/// object, which wraps malloc, to allocate memory, but it can be changed to
61/// use a custom allocator.
62///
63/// The GrowthDelay specifies after how many allocated slabs the allocator
64/// increases the size of the slabs.
65template <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096,
66 size_t SizeThreshold = SlabSize, size_t GrowthDelay = 128>
67class BumpPtrAllocatorImpl
68 : public AllocatorBase<BumpPtrAllocatorImpl<AllocatorT, SlabSize,
69 SizeThreshold, GrowthDelay>>,
70 private AllocatorT {
71public:
72 static_assert(SizeThreshold <= SlabSize,
73 "The SizeThreshold must be at most the SlabSize to ensure "
74 "that objects larger than a slab go into their own memory "
75 "allocation.");
76 static_assert(GrowthDelay > 0,
77 "GrowthDelay must be at least 1 which already increases the"
78 "slab size after each allocated slab.");
79
80 BumpPtrAllocatorImpl() = default;
81
82 template <typename T>
83 BumpPtrAllocatorImpl(T &&Allocator)
84 : AllocatorT(std::forward<T &&>(Allocator)) {}
85
86 // Manually implement a move constructor as we must clear the old allocator's
87 // slabs as a matter of correctness.
88 BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old)
89 : AllocatorT(static_cast<AllocatorT &&>(Old)), CurPtr(Old.CurPtr),
90 End(Old.End), Slabs(std::move(Old.Slabs)),
91 CustomSizedSlabs(std::move(Old.CustomSizedSlabs)),
92 BytesAllocated(Old.BytesAllocated), RedZoneSize(Old.RedZoneSize) {
93 Old.CurPtr = Old.End = nullptr;
94 Old.BytesAllocated = 0;
95 Old.Slabs.clear();
96 Old.CustomSizedSlabs.clear();
97 }
98
99 ~BumpPtrAllocatorImpl() {
100 DeallocateSlabs(Slabs.begin(), Slabs.end());
101 DeallocateCustomSizedSlabs();
102 }
103
104 BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) {
105 DeallocateSlabs(Slabs.begin(), Slabs.end());
106 DeallocateCustomSizedSlabs();
107
108 CurPtr = RHS.CurPtr;
109 End = RHS.End;
110 BytesAllocated = RHS.BytesAllocated;
111 RedZoneSize = RHS.RedZoneSize;
112 Slabs = std::move(RHS.Slabs);
113 CustomSizedSlabs = std::move(RHS.CustomSizedSlabs);
114 AllocatorT::operator=(static_cast<AllocatorT &&>(RHS));
115
116 RHS.CurPtr = RHS.End = nullptr;
117 RHS.BytesAllocated = 0;
118 RHS.Slabs.clear();
119 RHS.CustomSizedSlabs.clear();
120 return *this;
121 }
122
123 /// Deallocate all but the current slab and reset the current pointer
124 /// to the beginning of it, freeing all memory allocated so far.
125 void Reset() {
126 // Deallocate all but the first slab, and deallocate all custom-sized slabs.
127 DeallocateCustomSizedSlabs();
128 CustomSizedSlabs.clear();
129
130 if (Slabs.empty())
131 return;
132
133 // Reset the state.
134 BytesAllocated = 0;
135 CurPtr = (char *)Slabs.front();
136 End = CurPtr + SlabSize;
137
138 __asan_poison_memory_region(*Slabs.begin(), computeSlabSize(0));
139 DeallocateSlabs(std::next(Slabs.begin()), Slabs.end());
140 Slabs.erase(std::next(Slabs.begin()), Slabs.end());
141 }
142
143 /// Allocate space at the specified alignment.
144 LLVM_ATTRIBUTE_RETURNS_NONNULL__attribute__((returns_nonnull)) LLVM_ATTRIBUTE_RETURNS_NOALIAS__attribute__((__malloc__)) void *
145 Allocate(size_t Size, Align Alignment) {
146 // Keep track of how many bytes we've allocated.
147 BytesAllocated += Size;
148
149 size_t Adjustment = offsetToAlignedAddr(CurPtr, Alignment);
7
Calling 'offsetToAlignedAddr'
150 assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow")((void)0);
151
152 size_t SizeToAllocate = Size;
153#if LLVM_ADDRESS_SANITIZER_BUILD0
154 // Add trailing bytes as a "red zone" under ASan.
155 SizeToAllocate += RedZoneSize;
156#endif
157
158 // Check if we have enough space.
159 if (Adjustment + SizeToAllocate <= size_t(End - CurPtr)) {
160 char *AlignedPtr = CurPtr + Adjustment;
161 CurPtr = AlignedPtr + SizeToAllocate;
162 // Update the allocation point of this memory block in MemorySanitizer.
163 // Without this, MemorySanitizer messages for values originated from here
164 // will point to the allocation of the entire slab.
165 __msan_allocated_memory(AlignedPtr, Size);
166 // Similarly, tell ASan about this space.
167 __asan_unpoison_memory_region(AlignedPtr, Size);
168 return AlignedPtr;
169 }
170
171 // If Size is really big, allocate a separate slab for it.
172 size_t PaddedSize = SizeToAllocate + Alignment.value() - 1;
173 if (PaddedSize > SizeThreshold) {
174 void *NewSlab =
175 AllocatorT::Allocate(PaddedSize, alignof(std::max_align_t));
176 // We own the new slab and don't want anyone reading anyting other than
177 // pieces returned from this method. So poison the whole slab.
178 __asan_poison_memory_region(NewSlab, PaddedSize);
179 CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize));
180
181 uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment);
182 assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize)((void)0);
183 char *AlignedPtr = (char*)AlignedAddr;
184 __msan_allocated_memory(AlignedPtr, Size);
185 __asan_unpoison_memory_region(AlignedPtr, Size);
186 return AlignedPtr;
187 }
188
189 // Otherwise, start a new slab and try again.
190 StartNewSlab();
191 uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment);
192 assert(AlignedAddr + SizeToAllocate <= (uintptr_t)End &&((void)0)
193 "Unable to allocate memory!")((void)0);
194 char *AlignedPtr = (char*)AlignedAddr;
195 CurPtr = AlignedPtr + SizeToAllocate;
196 __msan_allocated_memory(AlignedPtr, Size);
197 __asan_unpoison_memory_region(AlignedPtr, Size);
198 return AlignedPtr;
199 }
200
201 inline LLVM_ATTRIBUTE_RETURNS_NONNULL__attribute__((returns_nonnull)) LLVM_ATTRIBUTE_RETURNS_NOALIAS__attribute__((__malloc__)) void *
202 Allocate(size_t Size, size_t Alignment) {
203 assert(Alignment > 0 && "0-byte alignment is not allowed. Use 1 instead.")((void)0);
204 return Allocate(Size, Align(Alignment));
6
Calling 'BumpPtrAllocatorImpl::Allocate'
205 }
206
207 // Pull in base class overloads.
208 using AllocatorBase<BumpPtrAllocatorImpl>::Allocate;
209
210 // Bump pointer allocators are expected to never free their storage; and
211 // clients expect pointers to remain valid for non-dereferencing uses even
212 // after deallocation.
213 void Deallocate(const void *Ptr, size_t Size, size_t /*Alignment*/) {
214 __asan_poison_memory_region(Ptr, Size);
215 }
216
217 // Pull in base class overloads.
218 using AllocatorBase<BumpPtrAllocatorImpl>::Deallocate;
219
220 size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); }
221
222 /// \return An index uniquely and reproducibly identifying
223 /// an input pointer \p Ptr in the given allocator.
224 /// The returned value is negative iff the object is inside a custom-size
225 /// slab.
226 /// Returns an empty optional if the pointer is not found in the allocator.
227 llvm::Optional<int64_t> identifyObject(const void *Ptr) {
228 const char *P = static_cast<const char *>(Ptr);
229 int64_t InSlabIdx = 0;
230 for (size_t Idx = 0, E = Slabs.size(); Idx < E; Idx++) {
231 const char *S = static_cast<const char *>(Slabs[Idx]);
232 if (P >= S && P < S + computeSlabSize(Idx))
233 return InSlabIdx + static_cast<int64_t>(P - S);
234 InSlabIdx += static_cast<int64_t>(computeSlabSize(Idx));
235 }
236
237 // Use negative index to denote custom sized slabs.
238 int64_t InCustomSizedSlabIdx = -1;
239 for (size_t Idx = 0, E = CustomSizedSlabs.size(); Idx < E; Idx++) {
240 const char *S = static_cast<const char *>(CustomSizedSlabs[Idx].first);
241 size_t Size = CustomSizedSlabs[Idx].second;
242 if (P >= S && P < S + Size)
243 return InCustomSizedSlabIdx - static_cast<int64_t>(P - S);
244 InCustomSizedSlabIdx -= static_cast<int64_t>(Size);
245 }
246 return None;
247 }
248
249 /// A wrapper around identifyObject that additionally asserts that
250 /// the object is indeed within the allocator.
251 /// \return An index uniquely and reproducibly identifying
252 /// an input pointer \p Ptr in the given allocator.
253 int64_t identifyKnownObject(const void *Ptr) {
254 Optional<int64_t> Out = identifyObject(Ptr);
255 assert(Out && "Wrong allocator used")((void)0);
256 return *Out;
257 }
258
259 /// A wrapper around identifyKnownObject. Accepts type information
260 /// about the object and produces a smaller identifier by relying on
261 /// the alignment information. Note that sub-classes may have different
262 /// alignment, so the most base class should be passed as template parameter
263 /// in order to obtain correct results. For that reason automatic template
264 /// parameter deduction is disabled.
265 /// \return An index uniquely and reproducibly identifying
266 /// an input pointer \p Ptr in the given allocator. This identifier is
267 /// different from the ones produced by identifyObject and
268 /// identifyAlignedObject.
269 template <typename T>
270 int64_t identifyKnownAlignedObject(const void *Ptr) {
271 int64_t Out = identifyKnownObject(Ptr);
272 assert(Out % alignof(T) == 0 && "Wrong alignment information")((void)0);
273 return Out / alignof(T);
274 }
275
276 size_t getTotalMemory() const {
277 size_t TotalMemory = 0;
278 for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I)
279 TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I));
280 for (auto &PtrAndSize : CustomSizedSlabs)
281 TotalMemory += PtrAndSize.second;
282 return TotalMemory;
283 }
284
285 size_t getBytesAllocated() const { return BytesAllocated; }
286
287 void setRedZoneSize(size_t NewSize) {
288 RedZoneSize = NewSize;
289 }
290
291 void PrintStats() const {
292 detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated,
293 getTotalMemory());
294 }
295
296private:
297 /// The current pointer into the current slab.
298 ///
299 /// This points to the next free byte in the slab.
300 char *CurPtr = nullptr;
301
302 /// The end of the current slab.
303 char *End = nullptr;
304
305 /// The slabs allocated so far.
306 SmallVector<void *, 4> Slabs;
307
308 /// Custom-sized slabs allocated for too-large allocation requests.
309 SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs;
310
311 /// How many bytes we've allocated.
312 ///
313 /// Used so that we can compute how much space was wasted.
314 size_t BytesAllocated = 0;
315
316 /// The number of bytes to put between allocations when running under
317 /// a sanitizer.
318 size_t RedZoneSize = 1;
319
320 static size_t computeSlabSize(unsigned SlabIdx) {
321 // Scale the actual allocated slab size based on the number of slabs
322 // allocated. Every GrowthDelay slabs allocated, we double
323 // the allocated size to reduce allocation frequency, but saturate at
324 // multiplying the slab size by 2^30.
325 return SlabSize *
326 ((size_t)1 << std::min<size_t>(30, SlabIdx / GrowthDelay));
327 }
328
329 /// Allocate a new slab and move the bump pointers over into the new
330 /// slab, modifying CurPtr and End.
331 void StartNewSlab() {
332 size_t AllocatedSlabSize = computeSlabSize(Slabs.size());
333
334 void *NewSlab =
335 AllocatorT::Allocate(AllocatedSlabSize, alignof(std::max_align_t));
336 // We own the new slab and don't want anyone reading anything other than
337 // pieces returned from this method. So poison the whole slab.
338 __asan_poison_memory_region(NewSlab, AllocatedSlabSize);
339
340 Slabs.push_back(NewSlab);
341 CurPtr = (char *)(NewSlab);
342 End = ((char *)NewSlab) + AllocatedSlabSize;
343 }
344
345 /// Deallocate a sequence of slabs.
346 void DeallocateSlabs(SmallVectorImpl<void *>::iterator I,
347 SmallVectorImpl<void *>::iterator E) {
348 for (; I != E; ++I) {
349 size_t AllocatedSlabSize =
350 computeSlabSize(std::distance(Slabs.begin(), I));
351 AllocatorT::Deallocate(*I, AllocatedSlabSize, alignof(std::max_align_t));
352 }
353 }
354
355 /// Deallocate all memory for custom sized slabs.
356 void DeallocateCustomSizedSlabs() {
357 for (auto &PtrAndSize : CustomSizedSlabs) {
358 void *Ptr = PtrAndSize.first;
359 size_t Size = PtrAndSize.second;
360 AllocatorT::Deallocate(Ptr, Size, alignof(std::max_align_t));
361 }
362 }
363
364 template <typename T> friend class SpecificBumpPtrAllocator;
365};
366
367/// The standard BumpPtrAllocator which just uses the default template
368/// parameters.
369typedef BumpPtrAllocatorImpl<> BumpPtrAllocator;
370
371/// A BumpPtrAllocator that allows only elements of a specific type to be
372/// allocated.
373///
374/// This allows calling the destructor in DestroyAll() and when the allocator is
375/// destroyed.
376template <typename T> class SpecificBumpPtrAllocator {
377 BumpPtrAllocator Allocator;
378
379public:
380 SpecificBumpPtrAllocator() {
381 // Because SpecificBumpPtrAllocator walks the memory to call destructors,
382 // it can't have red zones between allocations.
383 Allocator.setRedZoneSize(0);
384 }
385 SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old)
386 : Allocator(std::move(Old.Allocator)) {}
387 ~SpecificBumpPtrAllocator() { DestroyAll(); }
388
389 SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) {
390 Allocator = std::move(RHS.Allocator);
391 return *this;
392 }
393
394 /// Call the destructor of each allocated object and deallocate all but the
395 /// current slab and reset the current pointer to the beginning of it, freeing
396 /// all memory allocated so far.
397 void DestroyAll() {
398 auto DestroyElements = [](char *Begin, char *End) {
399 assert(Begin == (char *)alignAddr(Begin, Align::Of<T>()))((void)0);
400 for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T))
401 reinterpret_cast<T *>(Ptr)->~T();
402 };
403
404 for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E;
405 ++I) {
406 size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize(
407 std::distance(Allocator.Slabs.begin(), I));
408 char *Begin = (char *)alignAddr(*I, Align::Of<T>());
409 char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr
410 : (char *)*I + AllocatedSlabSize;
411
412 DestroyElements(Begin, End);
413 }
414
415 for (auto &PtrAndSize : Allocator.CustomSizedSlabs) {
416 void *Ptr = PtrAndSize.first;
417 size_t Size = PtrAndSize.second;
418 DestroyElements((char *)alignAddr(Ptr, Align::Of<T>()),
419 (char *)Ptr + Size);
420 }
421
422 Allocator.Reset();
423 }
424
425 /// Allocate space for an array of objects without constructing them.
426 T *Allocate(size_t num = 1) { return Allocator.Allocate<T>(num); }
427};
428
429} // end namespace llvm
430
431template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold,
432 size_t GrowthDelay>
433void *
434operator new(size_t Size,
435 llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold,
436 GrowthDelay> &Allocator) {
437 return Allocator.Allocate(Size, std::min((size_t)llvm::NextPowerOf2(Size),
5
Calling 'BumpPtrAllocatorImpl::Allocate'
438 alignof(std::max_align_t)));
439}
440
441template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold,
442 size_t GrowthDelay>
443void operator delete(void *,
444 llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize,
445 SizeThreshold, GrowthDelay> &) {
446}
447
448#endif // LLVM_SUPPORT_ALLOCATOR_H

/usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support/Alignment.h

1//===-- llvm/Support/Alignment.h - Useful alignment functions ---*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains types to represent alignments.
10// They are instrumented to guarantee some invariants are preserved and prevent
11// invalid manipulations.
12//
13// - Align represents an alignment in bytes, it is always set and always a valid
14// power of two, its minimum value is 1 which means no alignment requirements.
15//
16// - MaybeAlign is an optional type, it may be undefined or set. When it's set
17// you can get the underlying Align type by using the getValue() method.
18//
19//===----------------------------------------------------------------------===//
20
21#ifndef LLVM_SUPPORT_ALIGNMENT_H_
22#define LLVM_SUPPORT_ALIGNMENT_H_
23
24#include "llvm/ADT/Optional.h"
25#include "llvm/Support/MathExtras.h"
26#include <cassert>
27#ifndef NDEBUG1
28#include <string>
29#endif // NDEBUG
30
31namespace llvm {
32
33#define ALIGN_CHECK_ISPOSITIVE(decl) \
34 assert(decl > 0 && (#decl " should be defined"))((void)0)
35
36/// This struct is a compact representation of a valid (non-zero power of two)
37/// alignment.
38/// It is suitable for use as static global constants.
39struct Align {
40private:
41 uint8_t ShiftValue = 0; /// The log2 of the required alignment.
42 /// ShiftValue is less than 64 by construction.
43
44 friend struct MaybeAlign;
45 friend unsigned Log2(Align);
46 friend bool operator==(Align Lhs, Align Rhs);
47 friend bool operator!=(Align Lhs, Align Rhs);
48 friend bool operator<=(Align Lhs, Align Rhs);
49 friend bool operator>=(Align Lhs, Align Rhs);
50 friend bool operator<(Align Lhs, Align Rhs);
51 friend bool operator>(Align Lhs, Align Rhs);
52 friend unsigned encode(struct MaybeAlign A);
53 friend struct MaybeAlign decodeMaybeAlign(unsigned Value);
54
55 /// A trivial type to allow construction of constexpr Align.
56 /// This is currently needed to workaround a bug in GCC 5.3 which prevents
57 /// definition of constexpr assign operators.
58 /// https://stackoverflow.com/questions/46756288/explicitly-defaulted-function-cannot-be-declared-as-constexpr-because-the-implic
59 /// FIXME: Remove this, make all assign operators constexpr and introduce user
60 /// defined literals when we don't have to support GCC 5.3 anymore.
61 /// https://llvm.org/docs/GettingStarted.html#getting-a-modern-host-c-toolchain
62 struct LogValue {
63 uint8_t Log;
64 };
65
66public:
67 /// Default is byte-aligned.
68 constexpr Align() = default;
69 /// Do not perform checks in case of copy/move construct/assign, because the
70 /// checks have been performed when building `Other`.
71 constexpr Align(const Align &Other) = default;
72 constexpr Align(Align &&Other) = default;
73 Align &operator=(const Align &Other) = default;
74 Align &operator=(Align &&Other) = default;
75
76 explicit Align(uint64_t Value) {
77 assert(Value > 0 && "Value must not be 0")((void)0);
78 assert(llvm::isPowerOf2_64(Value) && "Alignment is not a power of 2")((void)0);
79 ShiftValue = Log2_64(Value);
80 assert(ShiftValue < 64 && "Broken invariant")((void)0);
81 }
82
83 /// This is a hole in the type system and should not be abused.
84 /// Needed to interact with C for instance.
85 uint64_t value() const { return uint64_t(1) << ShiftValue; }
12
The result of the left shift is undefined due to shifting by '255', which is greater or equal to the width of type 'uint64_t'
86
87 /// Allow constructions of constexpr Align.
88 template <size_t kValue> constexpr static LogValue Constant() {
89 return LogValue{static_cast<uint8_t>(CTLog2<kValue>())};
90 }
91
92 /// Allow constructions of constexpr Align from types.
93 /// Compile time equivalent to Align(alignof(T)).
94 template <typename T> constexpr static LogValue Of() {
95 return Constant<std::alignment_of<T>::value>();
96 }
97
98 /// Constexpr constructor from LogValue type.
99 constexpr Align(LogValue CA) : ShiftValue(CA.Log) {}
100};
101
102/// Treats the value 0 as a 1, so Align is always at least 1.
103inline Align assumeAligned(uint64_t Value) {
104 return Value ? Align(Value) : Align();
105}
106
107/// This struct is a compact representation of a valid (power of two) or
108/// undefined (0) alignment.
109struct MaybeAlign : public llvm::Optional<Align> {
110private:
111 using UP = llvm::Optional<Align>;
112
113public:
114 /// Default is undefined.
115 MaybeAlign() = default;
116 /// Do not perform checks in case of copy/move construct/assign, because the
117 /// checks have been performed when building `Other`.
118 MaybeAlign(const MaybeAlign &Other) = default;
119 MaybeAlign &operator=(const MaybeAlign &Other) = default;
120 MaybeAlign(MaybeAlign &&Other) = default;
121 MaybeAlign &operator=(MaybeAlign &&Other) = default;
122
123 /// Use llvm::Optional<Align> constructor.
124 using UP::UP;
125
126 explicit MaybeAlign(uint64_t Value) {
127 assert((Value == 0 || llvm::isPowerOf2_64(Value)) &&((void)0)
128 "Alignment is neither 0 nor a power of 2")((void)0);
129 if (Value)
130 emplace(Value);
131 }
132
133 /// For convenience, returns a valid alignment or 1 if undefined.
134 Align valueOrOne() const { return hasValue() ? getValue() : Align(); }
135};
136
137/// Checks that SizeInBytes is a multiple of the alignment.
138inline bool isAligned(Align Lhs, uint64_t SizeInBytes) {
139 return SizeInBytes % Lhs.value() == 0;
140}
141
142/// Checks that Addr is a multiple of the alignment.
143inline bool isAddrAligned(Align Lhs, const void *Addr) {
144 return isAligned(Lhs, reinterpret_cast<uintptr_t>(Addr));
145}
146
147/// Returns a multiple of A needed to store `Size` bytes.
148inline uint64_t alignTo(uint64_t Size, Align A) {
149 const uint64_t Value = A.value();
11
Calling 'Align::value'
150 // The following line is equivalent to `(Size + Value - 1) / Value * Value`.
151
152 // The division followed by a multiplication can be thought of as a right
153 // shift followed by a left shift which zeros out the extra bits produced in
154 // the bump; `~(Value - 1)` is a mask where all those bits being zeroed out
155 // are just zero.
156
157 // Most compilers can generate this code but the pattern may be missed when
158 // multiple functions gets inlined.
159 return (Size + Value - 1) & ~(Value - 1U);
160}
161
162/// If non-zero \p Skew is specified, the return value will be a minimal integer
163/// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
164/// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
165/// Skew mod \p A'.
166///
167/// Examples:
168/// \code
169/// alignTo(5, Align(8), 7) = 7
170/// alignTo(17, Align(8), 1) = 17
171/// alignTo(~0LL, Align(8), 3) = 3
172/// \endcode
173inline uint64_t alignTo(uint64_t Size, Align A, uint64_t Skew) {
174 const uint64_t Value = A.value();
175 Skew %= Value;
176 return ((Size + Value - 1 - Skew) & ~(Value - 1U)) + Skew;
177}
178
179/// Returns a multiple of A needed to store `Size` bytes.
180/// Returns `Size` if current alignment is undefined.
181inline uint64_t alignTo(uint64_t Size, MaybeAlign A) {
182 return A ? alignTo(Size, A.getValue()) : Size;
183}
184
185/// Aligns `Addr` to `Alignment` bytes, rounding up.
186inline uintptr_t alignAddr(const void *Addr, Align Alignment) {
187 uintptr_t ArithAddr = reinterpret_cast<uintptr_t>(Addr);
188 assert(static_cast<uintptr_t>(ArithAddr + Alignment.value() - 1) >=((void)0)
189 ArithAddr &&((void)0)
190 "Overflow")((void)0);
191 return alignTo(ArithAddr, Alignment);
192}
193
194/// Returns the offset to the next integer (mod 2**64) that is greater than
195/// or equal to \p Value and is a multiple of \p Align.
196inline uint64_t offsetToAlignment(uint64_t Value, Align Alignment) {
197 return alignTo(Value, Alignment) - Value;
9
The value 255 is assigned to 'A.ShiftValue'
10
Calling 'alignTo'
198}
199
200/// Returns the necessary adjustment for aligning `Addr` to `Alignment`
201/// bytes, rounding up.
202inline uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment) {
203 return offsetToAlignment(reinterpret_cast<uintptr_t>(Addr), Alignment);
8
Calling 'offsetToAlignment'
204}
205
206/// Returns the log2 of the alignment.
207inline unsigned Log2(Align A) { return A.ShiftValue; }
208
209/// Returns the alignment that satisfies both alignments.
210/// Same semantic as MinAlign.
211inline Align commonAlignment(Align A, Align B) { return std::min(A, B); }
212
213/// Returns the alignment that satisfies both alignments.
214/// Same semantic as MinAlign.
215inline Align commonAlignment(Align A, uint64_t Offset) {
216 return Align(MinAlign(A.value(), Offset));
217}
218
219/// Returns the alignment that satisfies both alignments.
220/// Same semantic as MinAlign.
221inline MaybeAlign commonAlignment(MaybeAlign A, MaybeAlign B) {
222 return A && B ? commonAlignment(*A, *B) : A ? A : B;
223}
224
225/// Returns the alignment that satisfies both alignments.
226/// Same semantic as MinAlign.
227inline MaybeAlign commonAlignment(MaybeAlign A, uint64_t Offset) {
228 return MaybeAlign(MinAlign((*A).value(), Offset));
229}
230
231/// Returns a representation of the alignment that encodes undefined as 0.
232inline unsigned encode(MaybeAlign A) { return A ? A->ShiftValue + 1 : 0; }
233
234/// Dual operation of the encode function above.
235inline MaybeAlign decodeMaybeAlign(unsigned Value) {
236 if (Value == 0)
237 return MaybeAlign();
238 Align Out;
239 Out.ShiftValue = Value - 1;
240 return Out;
241}
242
243/// Returns a representation of the alignment, the encoded value is positive by
244/// definition.
245inline unsigned encode(Align A) { return encode(MaybeAlign(A)); }
246
247/// Comparisons between Align and scalars. Rhs must be positive.
248inline bool operator==(Align Lhs, uint64_t Rhs) {
249 ALIGN_CHECK_ISPOSITIVE(Rhs);
250 return Lhs.value() == Rhs;
251}
252inline bool operator!=(Align Lhs, uint64_t Rhs) {
253 ALIGN_CHECK_ISPOSITIVE(Rhs);
254 return Lhs.value() != Rhs;
255}
256inline bool operator<=(Align Lhs, uint64_t Rhs) {
257 ALIGN_CHECK_ISPOSITIVE(Rhs);
258 return Lhs.value() <= Rhs;
259}
260inline bool operator>=(Align Lhs, uint64_t Rhs) {
261 ALIGN_CHECK_ISPOSITIVE(Rhs);
262 return Lhs.value() >= Rhs;
263}
264inline bool operator<(Align Lhs, uint64_t Rhs) {
265 ALIGN_CHECK_ISPOSITIVE(Rhs);
266 return Lhs.value() < Rhs;
267}
268inline bool operator>(Align Lhs, uint64_t Rhs) {
269 ALIGN_CHECK_ISPOSITIVE(Rhs);
270 return Lhs.value() > Rhs;
271}
272
273/// Comparisons between MaybeAlign and scalars.
274inline bool operator==(MaybeAlign Lhs, uint64_t Rhs) {
275 return Lhs ? (*Lhs).value() == Rhs : Rhs == 0;
276}
277inline bool operator!=(MaybeAlign Lhs, uint64_t Rhs) {
278 return Lhs ? (*Lhs).value() != Rhs : Rhs != 0;
279}
280
281/// Comparisons operators between Align.
282inline bool operator==(Align Lhs, Align Rhs) {
283 return Lhs.ShiftValue == Rhs.ShiftValue;
284}
285inline bool operator!=(Align Lhs, Align Rhs) {
286 return Lhs.ShiftValue != Rhs.ShiftValue;
287}
288inline bool operator<=(Align Lhs, Align Rhs) {
289 return Lhs.ShiftValue <= Rhs.ShiftValue;
290}
291inline bool operator>=(Align Lhs, Align Rhs) {
292 return Lhs.ShiftValue >= Rhs.ShiftValue;
293}
294inline bool operator<(Align Lhs, Align Rhs) {
295 return Lhs.ShiftValue < Rhs.ShiftValue;
296}
297inline bool operator>(Align Lhs, Align Rhs) {
298 return Lhs.ShiftValue > Rhs.ShiftValue;
299}
300
301// Don't allow relational comparisons with MaybeAlign.
302bool operator<=(Align Lhs, MaybeAlign Rhs) = delete;
303bool operator>=(Align Lhs, MaybeAlign Rhs) = delete;
304bool operator<(Align Lhs, MaybeAlign Rhs) = delete;
305bool operator>(Align Lhs, MaybeAlign Rhs) = delete;
306
307bool operator<=(MaybeAlign Lhs, Align Rhs) = delete;
308bool operator>=(MaybeAlign Lhs, Align Rhs) = delete;
309bool operator<(MaybeAlign Lhs, Align Rhs) = delete;
310bool operator>(MaybeAlign Lhs, Align Rhs) = delete;
311
312bool operator<=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
313bool operator>=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
314bool operator<(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
315bool operator>(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
316
317inline Align operator*(Align Lhs, uint64_t Rhs) {
318 assert(Rhs > 0 && "Rhs must be positive")((void)0);
319 return Align(Lhs.value() * Rhs);
320}
321
322inline MaybeAlign operator*(MaybeAlign Lhs, uint64_t Rhs) {
323 assert(Rhs > 0 && "Rhs must be positive")((void)0);
324 return Lhs ? Lhs.getValue() * Rhs : MaybeAlign();
325}
326
327inline Align operator/(Align Lhs, uint64_t Divisor) {
328 assert(llvm::isPowerOf2_64(Divisor) &&((void)0)
329 "Divisor must be positive and a power of 2")((void)0);
330 assert(Lhs != 1 && "Can't halve byte alignment")((void)0);
331 return Align(Lhs.value() / Divisor);
332}
333
334inline MaybeAlign operator/(MaybeAlign Lhs, uint64_t Divisor) {
335 assert(llvm::isPowerOf2_64(Divisor) &&((void)0)
336 "Divisor must be positive and a power of 2")((void)0);
337 return Lhs ? Lhs.getValue() / Divisor : MaybeAlign();
338}
339
340inline Align max(MaybeAlign Lhs, Align Rhs) {
341 return Lhs && *Lhs > Rhs ? *Lhs : Rhs;
342}
343
344inline Align max(Align Lhs, MaybeAlign Rhs) {
345 return Rhs && *Rhs > Lhs ? *Rhs : Lhs;
346}
347
348#ifndef NDEBUG1
349// For usage in LLVM_DEBUG macros.
350inline std::string DebugStr(const Align &A) {
351 return std::to_string(A.value());
352}
353// For usage in LLVM_DEBUG macros.
354inline std::string DebugStr(const MaybeAlign &MA) {
355 if (MA)
356 return std::to_string(MA->value());
357 return "None";
358}
359#endif // NDEBUG
360
361#undef ALIGN_CHECK_ISPOSITIVE
362
363} // namespace llvm
364
365#endif // LLVM_SUPPORT_ALIGNMENT_H_