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