Block.h revision 360784
1289694Sngie//===--- Block.h - Allocated blocks for the interpreter ---------*- C++ -*-===//
2289694Sngie//
3289694Sngie// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4289694Sngie// See https://llvm.org/LICENSE.txt for license information.
5289694Sngie// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6289694Sngie//
7289694Sngie//===----------------------------------------------------------------------===//
8289694Sngie//
9289694Sngie// Defines the classes describing allocated blocks.
10289694Sngie//
11289694Sngie//===----------------------------------------------------------------------===//
12289694Sngie
13289694Sngie#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H
14289694Sngie#define LLVM_CLANG_AST_INTERP_BLOCK_H
15289694Sngie
16289694Sngie#include "Descriptor.h"
17289694Sngie#include "clang/AST/Decl.h"
18289694Sngie#include "clang/AST/DeclCXX.h"
19289694Sngie#include "clang/AST/Expr.h"
20289694Sngie#include "clang/AST/ComparisonCategories.h"
21289694Sngie#include "llvm/ADT/PointerUnion.h"
22289694Sngie#include "llvm/Support/raw_ostream.h"
23289694Sngie
24289694Sngienamespace clang {
25289694Sngienamespace interp {
26289694Sngieclass Block;
27289694Sngieclass DeadBlock;
28289694Sngieclass Context;
29289694Sngieclass InterpState;
30290586Sngieclass Pointer;
31290586Sngieclass Function;
32290594Sngieenum PrimType : unsigned;
33290594Sngie
34290594Sngie/// A memory block, either on the stack or in the heap.
35290594Sngie///
36290594Sngie/// The storage described by the block immediately follows it in memory.
37290594Sngieclass Block {
38290594Sngiepublic:
39290586Sngie  // Creates a new block.
40290586Sngie  Block(const llvm::Optional<unsigned> &DeclID, Descriptor *Desc,
41290586Sngie        bool IsStatic = false, bool IsExtern = false)
42290586Sngie      : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {}
43290586Sngie
44289694Sngie  Block(Descriptor *Desc, bool IsStatic = false, bool IsExtern = false)
45290586Sngie      : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern),
46289694Sngie        Desc(Desc) {}
47290586Sngie
48290586Sngie  /// Returns the block's descriptor.
49290594Sngie  Descriptor *getDescriptor() const { return Desc; }
50289694Sngie  /// Checks if the block has any live pointers.
51290586Sngie  bool hasPointers() const { return Pointers; }
52290586Sngie  /// Checks if the block is extern.
53290586Sngie  bool isExtern() const { return IsExtern; }
54290586Sngie  /// Checks if the block has static storage duration.
55290586Sngie  bool isStatic() const { return IsStatic; }
56290586Sngie  /// Checks if the block is temporary.
57290586Sngie  bool isTemporary() const { return Desc->IsTemporary; }
58290586Sngie  /// Returns the size of the block.
59290586Sngie  InterpSize getSize() const { return Desc->getAllocSize(); }
60290586Sngie  /// Returns the declaration ID.
61290586Sngie  llvm::Optional<unsigned> getDeclID() const { return DeclID; }
62290586Sngie
63290586Sngie  /// Returns a pointer to the stored data.
64290586Sngie  char *data() { return reinterpret_cast<char *>(this + 1); }
65290586Sngie
66290586Sngie  /// Returns a view over the data.
67290586Sngie  template <typename T>
68290586Sngie  T &deref() { return *reinterpret_cast<T *>(data()); }
69290586Sngie
70290586Sngie  /// Invokes the constructor.
71289694Sngie  void invokeCtor() {
72290586Sngie    std::memset(data(), 0, getSize());
73290586Sngie    if (Desc->CtorFn)
74290586Sngie      Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable,
75290586Sngie                   /*isActive=*/true, Desc);
76289694Sngie  }
77290586Sngie
78290586Sngieprotected:
79290586Sngie  friend class Pointer;
80290586Sngie  friend class DeadBlock;
81290586Sngie  friend class InterpState;
82290586Sngie
83289694Sngie  Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead)
84290586Sngie    : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {}
85290586Sngie
86290586Sngie  // Deletes a dead block at the end of its lifetime.
87290586Sngie  void cleanup();
88290586Sngie
89290586Sngie  // Pointer chain management.
90290586Sngie  void addPointer(Pointer *P);
91290586Sngie  void removePointer(Pointer *P);
92290586Sngie  void movePointer(Pointer *From, Pointer *To);
93290586Sngie
94290586Sngie  /// Start of the chain of pointers.
95289694Sngie  Pointer *Pointers = nullptr;
96289694Sngie  /// Unique identifier of the declaration.
97289694Sngie  llvm::Optional<unsigned> DeclID;
98289694Sngie  /// Flag indicating if the block has static storage duration.
99289694Sngie  bool IsStatic = false;
100289694Sngie  /// Flag indicating if the block is an extern.
101290586Sngie  bool IsExtern = false;
102289694Sngie  /// Flag indicating if the pointer is dead.
103290586Sngie  bool IsDead = false;
104290586Sngie  /// Pointer to the stack slot descriptor.
105289694Sngie  Descriptor *Desc;
106289694Sngie};
107289694Sngie
108289694Sngie/// Descriptor for a dead block.
109289694Sngie///
110289694Sngie/// Dead blocks are chained in a double-linked list to deallocate them
111290586Sngie/// whenever pointers become dead.
112290586Sngieclass DeadBlock {
113290586Sngiepublic:
114289694Sngie  /// Copies the block.
115289694Sngie  DeadBlock(DeadBlock *&Root, Block *Blk);
116289694Sngie
117289694Sngie  /// Returns a pointer to the stored data.
118289694Sngie  char *data() { return B.data(); }
119289694Sngie
120289694Sngieprivate:
121289694Sngie  friend class Block;
122289694Sngie  friend class InterpState;
123289694Sngie
124289694Sngie  void free();
125289694Sngie
126289694Sngie  /// Root pointer of the list.
127289694Sngie  DeadBlock *&Root;
128289694Sngie  /// Previous block in the list.
129289694Sngie  DeadBlock *Prev;
130289694Sngie  /// Next block in the list.
131289694Sngie  DeadBlock *Next;
132289694Sngie
133290586Sngie  /// Actual block storing data and tracking pointers.
134290586Sngie  Block B;
135290586Sngie};
136290586Sngie
137290586Sngie} // namespace interp
138290586Sngie} // namespace clang
139290586Sngie
140290586Sngie#endif
141290586Sngie