diff options
Diffstat (limited to 'clang/lib/AST/Interp/Block.h')
| -rw-r--r-- | clang/lib/AST/Interp/Block.h | 140 | 
1 files changed, 140 insertions, 0 deletions
| diff --git a/clang/lib/AST/Interp/Block.h b/clang/lib/AST/Interp/Block.h new file mode 100644 index 000000000000..97fb9a3ca096 --- /dev/null +++ b/clang/lib/AST/Interp/Block.h @@ -0,0 +1,140 @@ +//===--- Block.h - Allocated blocks for the interpreter ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines the classes describing allocated blocks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H +#define LLVM_CLANG_AST_INTERP_BLOCK_H + +#include "Descriptor.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ComparisonCategories.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { +namespace interp { +class Block; +class DeadBlock; +class Context; +class InterpState; +class Pointer; +class Function; +enum PrimType : unsigned; + +/// A memory block, either on the stack or in the heap. +/// +/// The storage described by the block immediately follows it in memory. +class Block { +public: +  // Creates a new block. +  Block(const llvm::Optional<unsigned> &DeclID, Descriptor *Desc, +        bool IsStatic = false, bool IsExtern = false) +      : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {} + +  Block(Descriptor *Desc, bool IsStatic = false, bool IsExtern = false) +      : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern), +        Desc(Desc) {} + +  /// Returns the block's descriptor. +  Descriptor *getDescriptor() const { return Desc; } +  /// Checks if the block has any live pointers. +  bool hasPointers() const { return Pointers; } +  /// Checks if the block is extern. +  bool isExtern() const { return IsExtern; } +  /// Checks if the block has static storage duration. +  bool isStatic() const { return IsStatic; } +  /// Checks if the block is temporary. +  bool isTemporary() const { return Desc->IsTemporary; } +  /// Returns the size of the block. +  InterpSize getSize() const { return Desc->getAllocSize(); } +  /// Returns the declaration ID. +  llvm::Optional<unsigned> getDeclID() const { return DeclID; } + +  /// Returns a pointer to the stored data. +  char *data() { return reinterpret_cast<char *>(this + 1); } + +  /// Returns a view over the data. +  template <typename T> +  T &deref() { return *reinterpret_cast<T *>(data()); } + +  /// Invokes the constructor. +  void invokeCtor() { +    std::memset(data(), 0, getSize()); +    if (Desc->CtorFn) +      Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable, +                   /*isActive=*/true, Desc); +  } + +protected: +  friend class Pointer; +  friend class DeadBlock; +  friend class InterpState; + +  Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead) +    : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {} + +  // Deletes a dead block at the end of its lifetime. +  void cleanup(); + +  // Pointer chain management. +  void addPointer(Pointer *P); +  void removePointer(Pointer *P); +  void movePointer(Pointer *From, Pointer *To); + +  /// Start of the chain of pointers. +  Pointer *Pointers = nullptr; +  /// Unique identifier of the declaration. +  llvm::Optional<unsigned> DeclID; +  /// Flag indicating if the block has static storage duration. +  bool IsStatic = false; +  /// Flag indicating if the block is an extern. +  bool IsExtern = false; +  /// Flag indicating if the pointer is dead. +  bool IsDead = false; +  /// Pointer to the stack slot descriptor. +  Descriptor *Desc; +}; + +/// Descriptor for a dead block. +/// +/// Dead blocks are chained in a double-linked list to deallocate them +/// whenever pointers become dead. +class DeadBlock { +public: +  /// Copies the block. +  DeadBlock(DeadBlock *&Root, Block *Blk); + +  /// Returns a pointer to the stored data. +  char *data() { return B.data(); } + +private: +  friend class Block; +  friend class InterpState; + +  void free(); + +  /// Root pointer of the list. +  DeadBlock *&Root; +  /// Previous block in the list. +  DeadBlock *Prev; +  /// Next block in the list. +  DeadBlock *Next; + +  /// Actual block storing data and tracking pointers. +  Block B; +}; + +} // namespace interp +} // namespace clang + +#endif | 
