#ifndef LLVM_CLANG_AST_INTERP_DYNAMIC_ALLOCATOR_H
#define LLVM_CLANG_AST_INTERP_DYNAMIC_ALLOCATOR_H
#include "Descriptor.h"
#include "InterpBlock.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
namespace clang {
class Expr;
namespace interp {
class Block;
class InterpState;
class DynamicAllocator final {
struct Allocation {
std::unique_ptr<std::byte[]> Memory;
Allocation(std::unique_ptr<std::byte[]> Memory)
: Memory(std::move(Memory)) {}
};
struct AllocationSite {
llvm::SmallVector<Allocation> Allocations;
bool IsArrayAllocation = false;
AllocationSite(std::unique_ptr<std::byte[]> Memory, bool Array)
: IsArrayAllocation(Array) {
Allocations.push_back({std::move(Memory)});
}
size_t size() const { return Allocations.size(); }
};
public:
DynamicAllocator() = default;
~DynamicAllocator();
void cleanup();
unsigned getNumAllocations() const { return AllocationSites.size(); }
Block *allocate(const Descriptor *D, unsigned EvalID);
Block *allocate(const Expr *Source, PrimType T, size_t NumElements,
unsigned EvalID);
Block *allocate(const Descriptor *D, size_t NumElements, unsigned EvalID);
bool deallocate(const Expr *Source, const Block *BlockToDelete,
InterpState &S);
bool isArrayAllocation(const Expr *Source) const {
if (auto It = AllocationSites.find(Source); It != AllocationSites.end())
return It->second.IsArrayAllocation;
return false;
}
using const_virtual_iter =
llvm::DenseMap<const Expr *, AllocationSite>::const_iterator;
llvm::iterator_range<const_virtual_iter> allocation_sites() const {
return llvm::make_range(AllocationSites.begin(), AllocationSites.end());
}
private:
llvm::DenseMap<const Expr *, AllocationSite> AllocationSites;
using PoolAllocTy = llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator>;
PoolAllocTy DescAllocator;
template <typename... Ts> Descriptor *allocateDescriptor(Ts &&...Args) {
return new (DescAllocator) Descriptor(std::forward<Ts>(Args)...);
}
};
}
}
#endif