LLVM 23.0.0git
Allocator.h
Go to the documentation of this file.
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
21#include "llvm/Config/abi-breaking.h"
26#include <algorithm>
27#include <cassert>
28#include <cstddef>
29#include <cstdint>
30#include <iterator>
31#include <optional>
32#include <utility>
33
34namespace llvm {
35
36namespace detail {
37
38// We call out to an external function to actually print the message as the
39// printing code uses Allocator.h in its implementation.
40LLVM_ABI void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t TotalMemory);
41
42} // end namespace detail
43
44/// Allocate memory in an ever growing pool, as if by bump-pointer.
45///
46/// This isn't strictly a bump-pointer allocator as it uses backing slabs of
47/// memory rather than relying on a boundless contiguous heap. However, it has
48/// bump-pointer semantics in that it is a monotonically growing pool of memory
49/// where every allocation is found by merely allocating the next N bytes in
50/// the slab, or the next N bytes in the next slab.
51///
52/// Note that this also has a threshold for forcing allocations above a certain
53/// size into their own slab.
54///
55/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator
56/// object, which wraps malloc, to allocate memory, but it can be changed to
57/// use a custom allocator.
58///
59/// The GrowthDelay specifies after how many allocated slabs the allocator
60/// increases the size of the slabs.
61///
62/// MinAlign keeps the bump pointer aligned between allocations: each size is
63/// rounded up to a multiple of MinAlign so the fast path can skip realigning
64/// CurPtr when the requested alignment is no greater than MinAlign.
65template <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096,
66 size_t SizeThreshold = SlabSize, size_t GrowthDelay = 128,
67 size_t MinAlign = 8>
69 : public AllocatorBase<BumpPtrAllocatorImpl<
70 AllocatorT, SlabSize, SizeThreshold, GrowthDelay, MinAlign>>,
71 private detail::AllocatorHolder<AllocatorT> {
73
74public:
75 static_assert(SizeThreshold <= SlabSize,
76 "The SizeThreshold must be at most the SlabSize to ensure "
77 "that objects larger than a slab go into their own memory "
78 "allocation.");
79 static_assert(GrowthDelay > 0,
80 "GrowthDelay must be at least 1 which already increases the"
81 "slab size after each allocated slab.");
82 static_assert(MinAlign > 0 && (MinAlign & (MinAlign - 1)) == 0,
83 "MinAlign must be a power of two");
84 static_assert(MinAlign <= alignof(std::max_align_t),
85 "MinAlign must not exceed the alignment of fresh slabs");
86
88
89 template <typename T>
91 : AllocTy(std::forward<T &&>(Allocator)) {}
92
93 // Manually implement a move constructor as we must clear the old allocator's
94 // slabs as a matter of correctness.
96 : AllocTy(std::move(Old.getAllocator())), CurPtr(Old.CurPtr),
97 EndSentinel(Old.EndSentinel), Slabs(std::move(Old.Slabs)),
98 CustomSizedSlabs(std::move(Old.CustomSizedSlabs)) {
99#if LLVM_ENABLE_ABI_BREAKING_CHECKS
100 RedZoneSize = Old.RedZoneSize;
101#endif
102 Old.CurPtr = nullptr;
103 Old.EndSentinel = 0;
104 Old.Slabs.clear();
105 Old.CustomSizedSlabs.clear();
106 }
107
109 DeallocateSlabs(Slabs.begin(), Slabs.end());
110 DeallocateCustomSizedSlabs();
111 }
112
114 DeallocateSlabs(Slabs.begin(), Slabs.end());
115 DeallocateCustomSizedSlabs();
116
117 CurPtr = RHS.CurPtr;
118 EndSentinel = RHS.EndSentinel;
119#if LLVM_ENABLE_ABI_BREAKING_CHECKS
120 RedZoneSize = RHS.RedZoneSize;
121#endif
122 Slabs = std::move(RHS.Slabs);
123 CustomSizedSlabs = std::move(RHS.CustomSizedSlabs);
124 AllocTy::operator=(std::move(RHS.getAllocator()));
125
126 RHS.CurPtr = nullptr;
127 RHS.EndSentinel = 0;
128 RHS.Slabs.clear();
129 RHS.CustomSizedSlabs.clear();
130 return *this;
131 }
132
133 /// Deallocate all but the current slab and reset the current pointer
134 /// to the beginning of it, freeing all memory allocated so far.
135 void Reset() {
136 // Deallocate all but the first slab, and deallocate all custom-sized slabs.
137 DeallocateCustomSizedSlabs();
138 CustomSizedSlabs.clear();
139
140 if (Slabs.empty())
141 return;
142
143 // Reset the state.
144 CurPtr = (char *)Slabs.front();
145 EndSentinel = uintptr_t(CurPtr) + SlabSize + 1;
146
147 __asan_poison_memory_region(*Slabs.begin(), computeSlabSize(0));
148 DeallocateSlabs(std::next(Slabs.begin()), Slabs.end());
149 Slabs.erase(std::next(Slabs.begin()), Slabs.end());
150 }
151
152 /// Allocate space at the specified alignment.
153 // This method is *not* marked noalias, because
154 // SpecificBumpPtrAllocator::DestroyAll() loops over all allocations, and
155 // that loop is not based on the Allocate() return value.
156 //
157 // Allocate(0, N) is valid, it returns a non-null pointer (which should not
158 // be dereferenced).
160 size_t SizeToAllocate = Size;
161#if LLVM_ADDRESS_SANITIZER_BUILD && LLVM_ENABLE_ABI_BREAKING_CHECKS
162 // Add trailing bytes as a "red zone" under ASan. RedZoneSize only exists
163 // when both conditions are true.
164 SizeToAllocate += RedZoneSize;
165#endif
166 SizeToAllocate = alignToPowerOf2(SizeToAllocate, MinAlign);
167
168 // CurPtr is already MinAlign-aligned, so only a stricter request realigns.
169 uintptr_t AlignedPtr = uintptr_t(CurPtr);
170 if (Alignment.value() > MinAlign)
171 AlignedPtr = alignAddr(CurPtr, Alignment);
172 uintptr_t AllocEndPtr = AlignedPtr + SizeToAllocate;
173 assert(AllocEndPtr >= uintptr_t(CurPtr) &&
174 "Alignment + Size must not overflow");
175
176 // Check if we have enough space. `EndSentinel` is 0 for an empty allocator,
177 // so this also rejects a null CurPtr when `SizeToAllocate` is 0.
178 if (LLVM_LIKELY(AllocEndPtr < EndSentinel)) {
179 CurPtr = reinterpret_cast<char *>(AllocEndPtr);
180 // Update the allocation point of this memory block in MemorySanitizer.
181 // Without this, MemorySanitizer messages for values originated from here
182 // will point to the allocation of the entire slab.
183 __msan_allocated_memory(reinterpret_cast<char *>(AlignedPtr), Size);
184 // Similarly, tell ASan about this space.
185 __asan_unpoison_memory_region(reinterpret_cast<char *>(AlignedPtr), Size);
186 return reinterpret_cast<char *>(AlignedPtr);
187 }
188
189 return AllocateSlow(Size, SizeToAllocate, Alignment);
190 }
191
193 AllocateSlow(size_t Size, size_t SizeToAllocate, Align Alignment) {
194 // If Size is really big, allocate a separate slab for it.
195 size_t PaddedSize = SizeToAllocate + Alignment.value() - 1;
196 if (PaddedSize > SizeThreshold) {
197 void *NewSlab =
198 this->getAllocator().Allocate(PaddedSize, alignof(std::max_align_t));
199 // We own the new slab and don't want anyone reading anyting other than
200 // pieces returned from this method. So poison the whole slab.
201 __asan_poison_memory_region(NewSlab, PaddedSize);
202 CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize));
203
204 uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment);
205 assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize);
206 char *AlignedPtr = (char*)AlignedAddr;
207 __msan_allocated_memory(AlignedPtr, Size);
209 return AlignedPtr;
210 }
211
212 // Otherwise, start a new slab and try again.
213 StartNewSlab();
214 uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment);
215 assert(AlignedAddr + SizeToAllocate < EndSentinel &&
216 "Unable to allocate memory!");
217 char *AlignedPtr = (char*)AlignedAddr;
218 CurPtr = AlignedPtr + SizeToAllocate;
219 __msan_allocated_memory(AlignedPtr, Size);
221 return AlignedPtr;
222 }
223
225 Allocate(size_t Size, size_t Alignment) {
226 assert(Alignment > 0 && "0-byte alignment is not allowed. Use 1 instead.");
227 return Allocate(Size, Align(Alignment));
228 }
229
230 // Pull in base class overloads.
232
233 // Bump pointer allocators are expected to never free their storage; and
234 // clients expect pointers to remain valid for non-dereferencing uses even
235 // after deallocation.
236 void Deallocate(const void *Ptr, size_t Size, size_t /*Alignment*/) {
238 }
239
240 // Pull in base class overloads.
242
243 size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); }
244
245 /// \return An index uniquely and reproducibly identifying
246 /// an input pointer \p Ptr in the given allocator.
247 /// The returned value is negative iff the object is inside a custom-size
248 /// slab.
249 /// Returns an empty optional if the pointer is not found in the allocator.
250 std::optional<int64_t> identifyObject(const void *Ptr) {
251 const char *P = static_cast<const char *>(Ptr);
252 int64_t InSlabIdx = 0;
253 for (size_t Idx = 0, E = Slabs.size(); Idx < E; Idx++) {
254 const char *S = static_cast<const char *>(Slabs[Idx]);
255 if (P >= S && P < S + computeSlabSize(Idx))
256 return InSlabIdx + static_cast<int64_t>(P - S);
257 InSlabIdx += static_cast<int64_t>(computeSlabSize(Idx));
258 }
259
260 // Use negative index to denote custom sized slabs.
261 int64_t InCustomSizedSlabIdx = -1;
262 for (const auto &Slab : CustomSizedSlabs) {
263 const char *S = static_cast<const char *>(Slab.first);
264 size_t Size = Slab.second;
265 if (P >= S && P < S + Size)
266 return InCustomSizedSlabIdx - static_cast<int64_t>(P - S);
267 InCustomSizedSlabIdx -= static_cast<int64_t>(Size);
268 }
269 return std::nullopt;
270 }
271
272 /// A wrapper around identifyObject that additionally asserts that
273 /// the object is indeed within the allocator.
274 /// \return An index uniquely and reproducibly identifying
275 /// an input pointer \p Ptr in the given allocator.
276 int64_t identifyKnownObject(const void *Ptr) {
277 std::optional<int64_t> Out = identifyObject(Ptr);
278 assert(Out && "Wrong allocator used");
279 return *Out;
280 }
281
282 /// A wrapper around identifyKnownObject. Accepts type information
283 /// about the object and produces a smaller identifier by relying on
284 /// the alignment information. Note that sub-classes may have different
285 /// alignment, so the most base class should be passed as template parameter
286 /// in order to obtain correct results. For that reason automatic template
287 /// parameter deduction is disabled.
288 /// \return An index uniquely and reproducibly identifying
289 /// an input pointer \p Ptr in the given allocator. This identifier is
290 /// different from the ones produced by identifyObject and
291 /// identifyAlignedObject.
292 template <typename T>
293 int64_t identifyKnownAlignedObject(const void *Ptr) {
294 int64_t Out = identifyKnownObject(Ptr);
295 assert(Out % alignof(T) == 0 && "Wrong alignment information");
296 return Out / alignof(T);
297 }
298
299 size_t getTotalMemory() const {
300 size_t TotalMemory = 0;
301 for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I)
302 TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I));
303 for (const auto &PtrAndSize : CustomSizedSlabs)
304 TotalMemory += PtrAndSize.second;
305 return TotalMemory;
306 }
307
308 void setRedZoneSize([[maybe_unused]] size_t NewSize) {
309#if LLVM_ENABLE_ABI_BREAKING_CHECKS
310 RedZoneSize = NewSize;
311#endif
312 }
313
314 void PrintStats() const {
316 }
317
318private:
319 /// The current pointer into the current slab.
320 ///
321 /// This points to the next free byte in the slab.
322 char *CurPtr = nullptr;
323
324 /// One past the slab end (0 when there is no slab). +1 is so that the fast
325 /// path condition also rejects a empty allocator with a 0-size allocation.
326 uintptr_t EndSentinel = 0;
327
328 /// The slabs allocated so far.
330
331 /// Custom-sized slabs allocated for too-large allocation requests.
332 SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs;
333
334#if LLVM_ENABLE_ABI_BREAKING_CHECKS
335 /// The number of bytes to put between allocations when running under a
336 /// sanitizer.
337 size_t RedZoneSize = 1;
338#endif
339
340 static size_t computeSlabSize(unsigned SlabIdx) {
341 // Scale the actual allocated slab size based on the number of slabs
342 // allocated. Every GrowthDelay slabs allocated, we double
343 // the allocated size to reduce allocation frequency, but saturate at
344 // multiplying the slab size by 2^30.
345 return SlabSize *
346 ((size_t)1 << std::min<size_t>(30, SlabIdx / GrowthDelay));
347 }
348
349 /// Allocate a new slab and move the bump pointers over into the new
350 /// slab, modifying CurPtr and EndSentinel.
351 void StartNewSlab() {
352 size_t AllocatedSlabSize = computeSlabSize(Slabs.size());
353
354 void *NewSlab = this->getAllocator().Allocate(AllocatedSlabSize,
355 alignof(std::max_align_t));
356 // We own the new slab and don't want anyone reading anything other than
357 // pieces returned from this method. So poison the whole slab.
358 __asan_poison_memory_region(NewSlab, AllocatedSlabSize);
359
360 Slabs.push_back(NewSlab);
361 CurPtr = (char *)(NewSlab);
362 EndSentinel = uintptr_t(NewSlab) + AllocatedSlabSize + 1;
363 }
364
365 /// Deallocate a sequence of slabs.
366 void DeallocateSlabs(SmallVectorImpl<void *>::iterator I,
368 for (; I != E; ++I) {
369 size_t AllocatedSlabSize =
370 computeSlabSize(std::distance(Slabs.begin(), I));
371 this->getAllocator().Deallocate(*I, AllocatedSlabSize,
372 alignof(std::max_align_t));
373 }
374 }
375
376 /// Deallocate all memory for custom sized slabs.
377 void DeallocateCustomSizedSlabs() {
378 for (auto &PtrAndSize : CustomSizedSlabs) {
379 void *Ptr = PtrAndSize.first;
380 size_t Size = PtrAndSize.second;
381 this->getAllocator().Deallocate(Ptr, Size, alignof(std::max_align_t));
382 }
383 }
384
385 template <typename T> friend class SpecificBumpPtrAllocator;
386};
387
388/// The standard BumpPtrAllocator which just uses the default template
389/// parameters.
390using BumpPtrAllocator = BumpPtrAllocatorImpl<>;
391
392/// A BumpPtrAllocator that allows only elements of a specific type to be
393/// allocated.
394///
395/// This allows calling the destructor in DestroyAll() and when the allocator is
396/// destroyed.
397template <typename T> class SpecificBumpPtrAllocator {
398 // DestroyAll() walks objects at a fixed sizeof(T) stride, so it needs tight
399 // packing: MinAlign=1 disables the size rounding. (alignof(T) would pack just
400 // as tightly and reuse the default instantiation, but T may be incomplete
401 // here, e.g. SpecificBumpPtrAllocator<MCSectionELF>.)
402 using BumpPtrAllocatorTy =
403 BumpPtrAllocatorImpl<MallocAllocator, 4096, 4096, 128, /*MinAlign=*/1>;
404 BumpPtrAllocatorTy Allocator;
405
406public:
408 // Because SpecificBumpPtrAllocator walks the memory to call destructors,
409 // it can't have red zones between allocations.
410 Allocator.setRedZoneSize(0);
411 }
413 : Allocator(std::move(Old.Allocator)) {}
415
417 Allocator = std::move(RHS.Allocator);
418 return *this;
419 }
420
421 /// Call the destructor of each allocated object and deallocate all but the
422 /// current slab and reset the current pointer to the beginning of it, freeing
423 /// all memory allocated so far.
424 void DestroyAll() {
425 auto DestroyElements = [](char *Begin, char *End) {
426 assert(Begin == (char *)alignAddr(Begin, Align::Of<T>()));
427 for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T))
428 reinterpret_cast<T *>(Ptr)->~T();
429 };
430
431 for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E;
432 ++I) {
433 size_t AllocatedSlabSize = BumpPtrAllocatorTy::computeSlabSize(
434 std::distance(Allocator.Slabs.begin(), I));
435 char *Begin = (char *)alignAddr(*I, Align::Of<T>());
436 char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr
437 : (char *)*I + AllocatedSlabSize;
438
439 DestroyElements(Begin, End);
440 }
441
442 for (auto &PtrAndSize : Allocator.CustomSizedSlabs) {
443 void *Ptr = PtrAndSize.first;
444 size_t Size = PtrAndSize.second;
445 DestroyElements((char *)alignAddr(Ptr, Align::Of<T>()),
446 (char *)Ptr + Size);
447 }
448
449 Allocator.Reset();
450 }
451
452 /// Allocate space for an array of objects without constructing them.
453 T *Allocate(size_t num = 1) {
454 // Slabs are max_align_t-aligned and every size is a multiple of alignof(T),
455 // so the bump pointer is already alignof(T)-aligned. Request alignment 1 so
456 // the fast path skips realigning CurPtr; over-aligned T still needs it.
457 if constexpr (alignof(T) <= alignof(std::max_align_t))
458 return static_cast<T *>(Allocator.Allocate(num * sizeof(T), Align()));
459 return Allocator.Allocate<T>(num);
460 }
461
462 /// \return An index uniquely and reproducibly identifying
463 /// an input pointer \p Ptr in the given allocator.
464 /// Returns an empty optional if the pointer is not found in the allocator.
465 std::optional<int64_t> identifyObject(const void *Ptr) {
466 return Allocator.identifyObject(Ptr);
467 }
468};
469
470} // end namespace llvm
471
472template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold,
473 size_t GrowthDelay, size_t MinAlign>
474void *
475operator new(size_t Size,
476 llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold,
477 GrowthDelay, MinAlign> &Allocator) {
478 return Allocator.Allocate(
479 Size, std::min(llvm::bit_ceil(Size), alignof(std::max_align_t)));
480}
481
482template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold,
483 size_t GrowthDelay, size_t MinAlign>
484void operator delete(
485 void *, llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold,
486 GrowthDelay, MinAlign> &) {}
487
488#endif // LLVM_SUPPORT_ALLOCATOR_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines MallocAllocator.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
#define __asan_poison_memory_region(p, size)
Definition Compiler.h:593
#define __asan_unpoison_memory_region(p, size)
Definition Compiler.h:594
#define LLVM_ATTRIBUTE_NOINLINE
LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, mark a method "not for inl...
Definition Compiler.h:348
#define LLVM_ATTRIBUTE_RETURNS_NONNULL
Definition Compiler.h:375
#define __msan_allocated_memory(p, size)
Definition Compiler.h:568
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:337
#define I(x, y, z)
Definition MD5.cpp:57
#define T
#define P(N)
Basic Register Allocator
This file defines the SmallVector class.
Value * RHS
CRTP base class providing obvious overloads for the core Allocate() methods of LLVM-style allocators.
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition Allocator.h:71
int64_t identifyKnownObject(const void *Ptr)
A wrapper around identifyObject that additionally asserts that the object is indeed within the alloca...
Definition Allocator.h:276
BumpPtrAllocatorImpl(T &&Allocator)
Definition Allocator.h:90
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_NOINLINE void * AllocateSlow(size_t Size, size_t SizeToAllocate, Align Alignment)
Definition Allocator.h:193
BumpPtrAllocatorImpl & operator=(BumpPtrAllocatorImpl &&RHS)
Definition Allocator.h:113
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
Definition Allocator.h:159
void Deallocate(const void *Ptr, size_t Size, size_t)
Definition Allocator.h:236
BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old)
Definition Allocator.h:95
size_t GetNumSlabs() const
Definition Allocator.h:243
void Reset()
Deallocate all but the current slab and reset the current pointer to the beginning of it,...
Definition Allocator.h:135
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, size_t Alignment)
Definition Allocator.h:225
void setRedZoneSize(size_t NewSize)
Definition Allocator.h:308
int64_t identifyKnownAlignedObject(const void *Ptr)
A wrapper around identifyKnownObject.
Definition Allocator.h:293
size_t getTotalMemory() const
Definition Allocator.h:299
std::optional< int64_t > identifyObject(const void *Ptr)
Definition Allocator.h:250
void Deallocate(const void *Ptr, size_t Size, size_t Alignment)
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, size_t Alignment)
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
std::optional< int64_t > identifyObject(const void *Ptr)
Definition Allocator.h:465
SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old)
Definition Allocator.h:412
T * Allocate(size_t num=1)
Allocate space for an array of objects without constructing them.
Definition Allocator.h:453
void DestroyAll()
Call the destructor of each allocated object and deallocate all but the current slab and reset the cu...
Definition Allocator.h:424
SpecificBumpPtrAllocator & operator=(SpecificBumpPtrAllocator &&RHS)
Definition Allocator.h:416
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
Definition ADL.h:123
LLVM_ABI void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t TotalMemory)
Definition Allocator.cpp:20
This is an optimization pass for GlobalISel generic memory operations.
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
Definition bit.h:362
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
Definition MathExtras.h:357
constexpr T alignToPowerOf2(U Value, V Align)
Will overflow only if result is not representable in T.
Definition MathExtras.h:493
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:390
uintptr_t alignAddr(const void *Addr, Align Alignment)
Aligns Addr to Alignment bytes, rounding up.
Definition Alignment.h:176
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:860
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
static constexpr Align Of()
Allow constructions of constexpr Align from types.
Definition Alignment.h:94
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77