[ADT] Move allocate_buffer to MemAlloc.h and out of line

There's an ABI breakage here if LLVM is compiled in C++14 without
aligned allocation and a user tries to use the result with aligned
allocation. If DenseMap or unique_function is used across that ABI
boundary it will break (PR45413). Moving it out of line is a bit of
a band-aid and LLVM doesn't really give ABI guarantees at this level,
but given the number of complaints I've received over this it still
seems worth fixing.
This commit is contained in:
Benjamin Kramer 2020-04-24 13:22:40 +02:00
parent b8e12b5ff6
commit f6b6a7722e
6 changed files with 58 additions and 45 deletions

View File

@ -18,6 +18,7 @@
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemAlloc.h"
#include "llvm/Support/ReverseIteration.h"
#include "llvm/Support/type_traits.h"
#include <algorithm>

View File

@ -34,6 +34,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/MemAlloc.h"
#include "llvm/Support/type_traits.h"
#include <memory>

View File

@ -551,48 +551,4 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#define LLVM_ENABLE_EXCEPTIONS 1
#endif
#ifdef __cplusplus
namespace llvm {
/// Allocate a buffer of memory with the given size and alignment.
///
/// When the compiler supports aligned operator new, this will use it to to
/// handle even over-aligned allocations.
///
/// However, this doesn't make any attempt to leverage the fancier techniques
/// like posix_memalign due to portability. It is mostly intended to allow
/// compatibility with platforms that, after aligned allocation was added, use
/// reduced default alignment.
inline void *allocate_buffer(size_t Size, size_t Alignment) {
return ::operator new(Size
#ifdef __cpp_aligned_new
,
std::align_val_t(Alignment)
#endif
);
}
/// Deallocate a buffer of memory with the given size and alignment.
///
/// If supported, this will used the sized delete operator. Also if supported,
/// this will pass the alignment to the delete operator.
///
/// The pointer must have been allocated with the corresponding new operator,
/// most likely using the above helper.
inline void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) {
::operator delete(Ptr
#ifdef __cpp_sized_deallocation
,
Size
#endif
#ifdef __cpp_aligned_new
,
std::align_val_t(Alignment)
#endif
);
}
} // End namespace llvm
#endif // __cplusplus
#endif

View File

@ -62,5 +62,26 @@ LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) {
return Result;
}
}
/// Allocate a buffer of memory with the given size and alignment.
///
/// When the compiler supports aligned operator new, this will use it to to
/// handle even over-aligned allocations.
///
/// However, this doesn't make any attempt to leverage the fancier techniques
/// like posix_memalign due to portability. It is mostly intended to allow
/// compatibility with platforms that, after aligned allocation was added, use
/// reduced default alignment.
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
allocate_buffer(size_t Size, size_t Alignment);
/// Deallocate a buffer of memory with the given size and alignment.
///
/// If supported, this will used the sized delete operator. Also if supported,
/// this will pass the alignment to the delete operator.
///
/// The pointer must have been allocated with the corresponding new operator,
/// most likely using the above helper.
void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment);
} // namespace llvm
#endif

View File

@ -115,6 +115,7 @@ add_llvm_component_library(LLVMSupport
LowLevelType.cpp
ManagedStatic.cpp
MathExtras.cpp
MemAlloc.cpp
MemoryBuffer.cpp
MD5.cpp
NativeFormatting.cpp

33
lib/Support/MemAlloc.cpp Normal file
View File

@ -0,0 +1,33 @@
//===- MemAlloc.cpp - Memory allocation functions -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/MemAlloc.h"
// These are out of line to have __cpp_aligned_new not affect ABI.
void *llvm::allocate_buffer(size_t Size, size_t Alignment) {
return ::operator new(Size
#ifdef __cpp_aligned_new
,
std::align_val_t(Alignment)
#endif
);
}
void llvm::deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) {
::operator delete(Ptr
#ifdef __cpp_sized_deallocation
,
Size
#endif
#ifdef __cpp_aligned_new
,
std::align_val_t(Alignment)
#endif
);
}