Block.h revision 353942
1//===--- Block.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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Defines the classes describing allocated blocks.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H
14#define LLVM_CLANG_AST_INTERP_BLOCK_H
15
16#include "Descriptor.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/ComparisonCategories.h"
21#include "llvm/ADT/PointerUnion.h"
22#include "llvm/Support/raw_ostream.h"
23
24namespace clang {
25namespace interp {
26class Block;
27class DeadBlock;
28class Context;
29class InterpState;
30class Pointer;
31class Function;
32enum PrimType : unsigned;
33
34/// A memory block, either on the stack or in the heap.
35///
36/// The storage described by the block immediately follows it in memory.
37class Block {
38public:
39  // Creates a new block.
40  Block(const llvm::Optional<unsigned> &DeclID, Descriptor *Desc,
41        bool IsStatic = false, bool IsExtern = false)
42      : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {}
43
44  Block(Descriptor *Desc, bool IsStatic = false, bool IsExtern = false)
45      : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern),
46        Desc(Desc) {}
47
48  /// Returns the block's descriptor.
49  Descriptor *getDescriptor() const { return Desc; }
50  /// Checks if the block has any live pointers.
51  bool hasPointers() const { return Pointers; }
52  /// Checks if the block is extern.
53  bool isExtern() const { return IsExtern; }
54  /// Checks if the block has static storage duration.
55  bool isStatic() const { return IsStatic; }
56  /// Checks if the block is temporary.
57  bool isTemporary() const { return Desc->IsTemporary; }
58  /// Returns the size of the block.
59  InterpSize getSize() const { return Desc->getAllocSize(); }
60  /// Returns the declaration ID.
61  llvm::Optional<unsigned> getDeclID() const { return DeclID; }
62
63  /// Returns a pointer to the stored data.
64  char *data() { return reinterpret_cast<char *>(this + 1); }
65
66  /// Returns a view over the data.
67  template <typename T>
68  T &deref() { return *reinterpret_cast<T *>(data()); }
69
70  /// Invokes the constructor.
71  void invokeCtor() {
72    std::memset(data(), 0, getSize());
73    if (Desc->CtorFn)
74      Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable,
75                   /*isActive=*/true, Desc);
76  }
77
78protected:
79  friend class Pointer;
80  friend class DeadBlock;
81  friend class InterpState;
82
83  Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead)
84    : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {}
85
86  // Deletes a dead block at the end of its lifetime.
87  void cleanup();
88
89  // Pointer chain management.
90  void addPointer(Pointer *P);
91  void removePointer(Pointer *P);
92  void movePointer(Pointer *From, Pointer *To);
93
94  /// Start of the chain of pointers.
95  Pointer *Pointers = nullptr;
96  /// Unique identifier of the declaration.
97  llvm::Optional<unsigned> DeclID;
98  /// Flag indicating if the block has static storage duration.
99  bool IsStatic = false;
100  /// Flag indicating if the block is an extern.
101  bool IsExtern = false;
102  /// Flag indicating if the pointer is dead.
103  bool IsDead = false;
104  /// Pointer to the stack slot descriptor.
105  Descriptor *Desc;
106};
107
108/// Descriptor for a dead block.
109///
110/// Dead blocks are chained in a double-linked list to deallocate them
111/// whenever pointers become dead.
112class DeadBlock {
113public:
114  /// Copies the block.
115  DeadBlock(DeadBlock *&Root, Block *Blk);
116
117  /// Returns a pointer to the stored data.
118  char *data() { return B.data(); }
119
120private:
121  friend class Block;
122  friend class InterpState;
123
124  void free();
125
126  /// Root pointer of the list.
127  DeadBlock *&Root;
128  /// Previous block in the list.
129  DeadBlock *Prev;
130  /// Next block in the list.
131  DeadBlock *Next;
132
133  /// Actual block storing data and tracking pointers.
134  Block B;
135};
136
137} // namespace interp
138} // namespace clang
139
140#endif
141