Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/DynamicAllocator.h
213799 views
//==--------- DynamicAllocator.h - Dynamic allocations ------------*- C++ -*-=//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_CLANG_AST_INTERP_DYNAMIC_ALLOCATOR_H9#define LLVM_CLANG_AST_INTERP_DYNAMIC_ALLOCATOR_H1011#include "Descriptor.h"12#include "InterpBlock.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/ADT/iterator_range.h"15#include "llvm/Support/Allocator.h"1617namespace clang {18class Expr;19namespace interp {20class Block;21class InterpState;2223/// Manages dynamic memory allocations done during bytecode interpretation.24///25/// We manage allocations as a map from their new-expression to a list26/// of allocations. This is called an AllocationSite. For each site, we27/// record whether it was allocated using new or new[], the28/// IsArrayAllocation flag.29///30/// For all array allocations, we need to allocate new Descriptor instances,31/// so the DynamicAllocator has a llvm::BumpPtrAllocator similar to Program.32class DynamicAllocator final {33public:34enum class Form : uint8_t {35NonArray,36Array,37Operator,38};3940private:41struct Allocation {42std::unique_ptr<std::byte[]> Memory;43Allocation(std::unique_ptr<std::byte[]> Memory)44: Memory(std::move(Memory)) {}45};4647struct AllocationSite {48llvm::SmallVector<Allocation> Allocations;49Form AllocForm;5051AllocationSite(std::unique_ptr<std::byte[]> Memory, Form AllocForm)52: AllocForm(AllocForm) {53Allocations.push_back({std::move(Memory)});54}5556size_t size() const { return Allocations.size(); }57};5859public:60DynamicAllocator() = default;61DynamicAllocator(DynamicAllocator &) = delete;62DynamicAllocator(DynamicAllocator &&) = delete;63~DynamicAllocator();6465void cleanup();6667unsigned getNumAllocations() const { return AllocationSites.size(); }6869/// Allocate ONE element of the given descriptor.70Block *allocate(const Descriptor *D, unsigned EvalID, Form AllocForm);71/// Allocate \p NumElements primitive elements of the given type.72Block *allocate(const Expr *Source, PrimType T, size_t NumElements,73unsigned EvalID, Form AllocForm);74/// Allocate \p NumElements elements of the given descriptor.75Block *allocate(const Descriptor *D, size_t NumElements, unsigned EvalID,76Form AllocForm);7778/// Deallocate the given source+block combination.79/// Returns \c true if anything has been deallocatd, \c false otherwise.80bool deallocate(const Expr *Source, const Block *BlockToDelete,81InterpState &S);8283/// Checks whether the allocation done at the given source is an array84/// allocation.85std::optional<Form> getAllocationForm(const Expr *Source) const {86if (auto It = AllocationSites.find(Source); It != AllocationSites.end())87return It->second.AllocForm;88return std::nullopt;89}9091/// Allocation site iterator.92using const_virtual_iter =93llvm::DenseMap<const Expr *, AllocationSite>::const_iterator;94llvm::iterator_range<const_virtual_iter> allocation_sites() const {95return llvm::make_range(AllocationSites.begin(), AllocationSites.end());96}9798private:99llvm::DenseMap<const Expr *, AllocationSite> AllocationSites;100101using PoolAllocTy = llvm::BumpPtrAllocator;102PoolAllocTy DescAllocator;103104/// Allocates a new descriptor.105template <typename... Ts> Descriptor *allocateDescriptor(Ts &&...Args) {106return new (DescAllocator) Descriptor(std::forward<Ts>(Args)...);107}108};109110} // namespace interp111} // namespace clang112#endif113114115