brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.9 KiB · ab1058b Raw
121 lines · c
1//==--------- DynamicAllocator.h - Dynamic allocations ------------*- 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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_AST_INTERP_DYNAMIC_ALLOCATOR_H10#define LLVM_CLANG_AST_INTERP_DYNAMIC_ALLOCATOR_H11 12#include "Descriptor.h"13#include "InterpBlock.h"14#include "llvm/ADT/SmallVector.h"15#include "llvm/ADT/iterator_range.h"16#include "llvm/Support/Allocator.h"17 18namespace clang {19class Expr;20namespace interp {21class Block;22class InterpState;23 24/// Manages dynamic memory allocations done during bytecode interpretation.25///26/// We manage allocations as a map from their new-expression to a list27/// of allocations. This is called an AllocationSite. For each site, we28/// record whether it was allocated using new or new[], the29/// IsArrayAllocation flag.30///31/// For all array allocations, we need to allocate new Descriptor instances,32/// so the DynamicAllocator has a llvm::BumpPtrAllocator similar to Program.33class DynamicAllocator final {34public:35  enum class Form : uint8_t {36    NonArray,37    Array,38    Operator,39  };40 41private:42  struct Allocation {43    std::unique_ptr<std::byte[]> Memory;44    Allocation(std::unique_ptr<std::byte[]> Memory)45        : Memory(std::move(Memory)) {}46    Block *block() const { return reinterpret_cast<Block *>(Memory.get()); }47  };48 49  struct AllocationSite {50    llvm::SmallVector<Allocation> Allocations;51    unsigned NumAllocs = 0;52    Form AllocForm;53 54    AllocationSite(std::unique_ptr<std::byte[]> Memory, Form AllocForm)55        : AllocForm(AllocForm) {56      Allocations.push_back({std::move(Memory)});57      ++NumAllocs;58    }59 60    size_t size() const { return Allocations.size(); }61    bool empty() const { return Allocations.empty(); }62  };63 64public:65  DynamicAllocator() = default;66  DynamicAllocator(DynamicAllocator &) = delete;67  DynamicAllocator(DynamicAllocator &&) = delete;68  ~DynamicAllocator();69 70  void cleanup();71 72  /// Allocate ONE element of the given descriptor.73  Block *allocate(const Descriptor *D, unsigned EvalID, Form AllocForm);74  /// Allocate \p NumElements primitive elements of the given type.75  Block *allocate(const Expr *Source, PrimType T, size_t NumElements,76                  unsigned EvalID, Form AllocForm);77  /// Allocate \p NumElements elements of the given descriptor.78  Block *allocate(const Descriptor *D, size_t NumElements, unsigned EvalID,79                  Form AllocForm);80 81  /// Deallocate the given source+block combination.82  /// Returns \c true if anything has been deallocatd, \c false otherwise.83  bool deallocate(const Expr *Source, const Block *BlockToDelete,84                  InterpState &S);85 86  /// Checks whether the allocation done at the given source is an array87  /// allocation.88  std::optional<Form> getAllocationForm(const Expr *Source) const {89    if (auto It = AllocationSites.find(Source); It != AllocationSites.end())90      return It->second.AllocForm;91    return std::nullopt;92  }93 94  /// Allocation site iterator.95  using const_virtual_iter =96      llvm::DenseMap<const Expr *, AllocationSite>::const_iterator;97  llvm::iterator_range<const_virtual_iter> allocation_sites() const {98    return llvm::make_range(AllocationSites.begin(), AllocationSites.end());99  }100 101  bool hasAllocations() const { return !AllocationSites.empty(); }102 103private:104  llvm::DenseMap<const Expr *, AllocationSite> AllocationSites;105  // Allocations that have already been deallocated but had pointers106  // to them.107  llvm::SmallVector<Allocation> DeadAllocations;108 109  using PoolAllocTy = llvm::BumpPtrAllocator;110  PoolAllocTy DescAllocator;111 112  /// Allocates a new descriptor.113  template <typename... Ts> Descriptor *allocateDescriptor(Ts &&...Args) {114    return new (DescAllocator) Descriptor(std::forward<Ts>(Args)...);115  }116};117 118} // namespace interp119} // namespace clang120#endif121