#ifndef LLVM_SUPPORT_ALLOCATORBASE_H
#define LLVM_SUPPORT_ALLOCATORBASE_H
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemAlloc.h"
#include <type_traits>
namespace llvm {
template <typename DerivedT> class AllocatorBase {
public:
void *Allocate(size_t Size, size_t Alignment) {
#ifdef __clang__
static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>(
&AllocatorBase::Allocate) !=
static_cast<void *(DerivedT::*)(size_t, size_t)>(
&DerivedT::Allocate),
"Class derives from AllocatorBase without implementing the "
"core Allocate(size_t, size_t) overload!");
#endif
return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
}
void Deallocate(const void *Ptr, size_t Size, size_t Alignment) {
#ifdef __clang__
static_assert(
static_cast<void (AllocatorBase::*)(const void *, size_t, size_t)>(
&AllocatorBase::Deallocate) !=
static_cast<void (DerivedT::*)(const void *, size_t, size_t)>(
&DerivedT::Deallocate),
"Class derives from AllocatorBase without implementing the "
"core Deallocate(void *) overload!");
#endif
return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size, Alignment);
}
template <typename T> T *Allocate(size_t Num = 1) {
return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
}
template <typename T>
std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value, void>
Deallocate(T *Ptr, size_t Num = 1) {
Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T), alignof(T));
}
};
class MallocAllocator : public AllocatorBase<MallocAllocator> {
public:
void Reset() {}
LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) {
return allocate_buffer(Size, Alignment);
}
using AllocatorBase<MallocAllocator>::Allocate;
void Deallocate(const void *Ptr, size_t Size, size_t Alignment) {
deallocate_buffer(const_cast<void *>(Ptr), Size, Alignment);
}
using AllocatorBase<MallocAllocator>::Deallocate;
void PrintStats() const {}
};
namespace detail {
template <typename Alloc> class AllocatorHolder : Alloc {
public:
AllocatorHolder() = default;
AllocatorHolder(const Alloc &A) : Alloc(A) {}
AllocatorHolder(Alloc &&A) : Alloc(static_cast<Alloc &&>(A)) {}
Alloc &getAllocator() { return *this; }
const Alloc &getAllocator() const { return *this; }
};
template <typename Alloc> class AllocatorHolder<Alloc &> {
Alloc &A;
public:
AllocatorHolder(Alloc &A) : A(A) {}
Alloc &getAllocator() { return A; }
const Alloc &getAllocator() const { return A; }
};
}
}
#endif