brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.8 KiB · 73fdc8d Raw
233 lines · c
1//===-- InterpBlock.h - Allocated blocks for the interpreter -*- 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// Defines the classes describing allocated blocks.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H14#define LLVM_CLANG_AST_INTERP_BLOCK_H15 16#include "Descriptor.h"17#include "llvm/Support/raw_ostream.h"18 19namespace clang {20namespace interp {21class Block;22class DeadBlock;23class InterpState;24class Pointer;25enum PrimType : uint8_t;26 27/// A memory block, either on the stack or in the heap.28///29/// The storage described by the block is immediately followed by30/// optional metadata, which is followed by the actual data.31///32/// Block*        rawData()                  data()33/// │               │                         │34/// │               │                         │35/// ▼               ▼                         ▼36/// ┌───────────────┬─────────────────────────┬─────────────────┐37/// │ Block         │ Metadata                │ Data            │38/// │ sizeof(Block) │ Desc->getMetadataSize() │ Desc->getSize() │39/// └───────────────┴─────────────────────────┴─────────────────┘40///41/// Desc->getAllocSize() describes the size after the Block, i.e.42/// the data size and the metadata size.43///44class Block final {45private:46  static constexpr uint8_t ExternFlag = 1 << 0;47  static constexpr uint8_t DeadFlag = 1 << 1;48  static constexpr uint8_t WeakFlag = 1 << 2;49  static constexpr uint8_t DummyFlag = 1 << 3;50 51public:52  /// Creates a new block.53  Block(unsigned EvalID, UnsignedOrNone DeclID, const Descriptor *Desc,54        bool IsStatic = false, bool IsExtern = false, bool IsWeak = false,55        bool IsDummy = false)56      : Desc(Desc), DeclID(DeclID), EvalID(EvalID), IsStatic(IsStatic) {57    assert(Desc);58    AccessFlags |= (ExternFlag * IsExtern);59    AccessFlags |= (WeakFlag * IsWeak);60    AccessFlags |= (DummyFlag * IsDummy);61  }62 63  Block(unsigned EvalID, const Descriptor *Desc, bool IsStatic = false,64        bool IsExtern = false, bool IsWeak = false, bool IsDummy = false)65      : Desc(Desc), EvalID(EvalID), IsStatic(IsStatic) {66    assert(Desc);67    AccessFlags |= (ExternFlag * IsExtern);68    AccessFlags |= (WeakFlag * IsWeak);69    AccessFlags |= (DummyFlag * IsDummy);70  }71 72  /// Returns the block's descriptor.73  const Descriptor *getDescriptor() const { return Desc; }74  /// Checks if the block has any live pointers.75  bool hasPointers() const { return Pointers; }76  /// Checks if the block is extern.77  bool isExtern() const { return AccessFlags & ExternFlag; }78  /// Checks if the block has static storage duration.79  bool isStatic() const { return IsStatic; }80  /// Checks if the block is temporary.81  bool isTemporary() const { return Desc->IsTemporary; }82  bool isWeak() const { return AccessFlags & WeakFlag; }83  bool isDynamic() const { return (DynAllocId != std::nullopt); }84  bool isDummy() const { return AccessFlags & DummyFlag; }85  bool isDead() const { return AccessFlags & DeadFlag; }86  /// Returns the size of the block.87  unsigned getSize() const { return Desc->getAllocSize(); }88  /// Returns the declaration ID.89  UnsignedOrNone getDeclID() const { return DeclID; }90  /// Returns whether the data of this block has been initialized via91  /// invoking the Ctor func.92  bool isInitialized() const { return IsInitialized; }93  /// The Evaluation ID this block was created in.94  unsigned getEvalID() const { return EvalID; }95  /// Move all pointers from this block to \param B.96  void movePointersTo(Block *B);97 98  /// Returns a pointer to the stored data.99  /// You are allowed to read Desc->getSize() bytes from this address.100  std::byte *data() {101    // rawData might contain metadata as well.102    size_t DataOffset = Desc->getMetadataSize();103    return rawData() + DataOffset;104  }105  const std::byte *data() const {106    // rawData might contain metadata as well.107    size_t DataOffset = Desc->getMetadataSize();108    return rawData() + DataOffset;109  }110 111  /// Returns a pointer to the raw data, including metadata.112  /// You are allowed to read Desc->getAllocSize() bytes from this address.113  std::byte *rawData() {114    return reinterpret_cast<std::byte *>(this) + sizeof(Block);115  }116  const std::byte *rawData() const {117    return reinterpret_cast<const std::byte *>(this) + sizeof(Block);118  }119 120  template <typename T> const T &deref() const {121    return *reinterpret_cast<const T *>(data());122  }123  template <typename T> T &deref() { return *reinterpret_cast<T *>(data()); }124 125  /// Invokes the constructor.126  void invokeCtor() {127    assert(!IsInitialized);128    std::memset(rawData(), 0, Desc->getAllocSize());129    if (Desc->CtorFn) {130      Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable,131                   Desc->IsVolatile,132                   /*isActive=*/true, /*InUnion=*/false, Desc);133    }134    IsInitialized = true;135  }136 137  /// Invokes the Destructor.138  void invokeDtor() {139    assert(IsInitialized);140    if (Desc->DtorFn)141      Desc->DtorFn(this, data(), Desc);142    IsInitialized = false;143  }144 145  void dump() const { dump(llvm::errs()); }146  void dump(llvm::raw_ostream &OS) const;147 148  bool isAccessible() const { return AccessFlags == 0; }149 150private:151  friend class Pointer;152  friend class DeadBlock;153  friend class InterpState;154  friend class DynamicAllocator;155  friend class Program;156 157  Block(unsigned EvalID, const Descriptor *Desc, bool IsExtern, bool IsStatic,158        bool IsWeak, bool IsDummy, bool IsDead)159      : Desc(Desc), EvalID(EvalID), IsStatic(IsStatic) {160    assert(Desc);161    AccessFlags |= (ExternFlag * IsExtern);162    AccessFlags |= (DeadFlag * IsDead);163    AccessFlags |= (WeakFlag * IsWeak);164    AccessFlags |= (DummyFlag * IsDummy);165  }166 167  /// To be called by DynamicAllocator.168  void setDynAllocId(unsigned ID) { DynAllocId = ID; }169 170  /// Deletes a dead block at the end of its lifetime.171  void cleanup();172 173  /// Pointer chain management.174  void addPointer(Pointer *P);175  void removePointer(Pointer *P);176  void replacePointer(Pointer *Old, Pointer *New);177#ifndef NDEBUG178  bool hasPointer(const Pointer *P) const;179#endif180 181  /// Pointer to the stack slot descriptor.182  const Descriptor *Desc;183  /// Start of the chain of pointers.184  Pointer *Pointers = nullptr;185  /// Unique identifier of the declaration.186  UnsignedOrNone DeclID = std::nullopt;187  const unsigned EvalID = ~0u;188  /// Flag indicating if the block has static storage duration.189  bool IsStatic = false;190  /// Flag indicating if the block contents have been initialized191  /// via invokeCtor.192  bool IsInitialized = false;193  /// Allocation ID for this dynamic allocation, if it is one.194  UnsignedOrNone DynAllocId = std::nullopt;195  /// AccessFlags containing IsExtern, IsDead, IsWeak, and IsDummy bits.196  uint8_t AccessFlags = 0;197};198 199/// Descriptor for a dead block.200///201/// Dead blocks are chained in a double-linked list to deallocate them202/// whenever pointers become dead.203class DeadBlock final {204public:205  /// Copies the block.206  DeadBlock(DeadBlock *&Root, Block *Blk);207 208  /// Returns a pointer to the stored data.209  std::byte *data() { return B.data(); }210  std::byte *rawData() { return B.rawData(); }211 212private:213  friend class Block;214  friend class InterpState;215 216  void free();217 218  /// Root pointer of the list.219  DeadBlock *&Root;220  /// Previous block in the list.221  DeadBlock *Prev;222  /// Next block in the list.223  DeadBlock *Next;224 225  /// Actual block storing data and tracking pointers.226  Block B;227};228 229} // namespace interp230} // namespace clang231 232#endif233