[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang / lib / AST / Interp / InterpBlock.h
blob9d0c4859fd06c158450f63b7c8b59b2367a31da2
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines the classes describing allocated blocks.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_AST_INTERP_BLOCK_H
14 #define LLVM_CLANG_AST_INTERP_BLOCK_H
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"
24 namespace clang {
25 namespace interp {
26 class Block;
27 class DeadBlock;
28 class InterpState;
29 class Pointer;
30 enum PrimType : unsigned;
32 /// A memory block, either on the stack or in the heap.
33 ///
34 /// The storage described by the block is immediately followed by
35 /// optional metadata, which is followed by the actual data.
36 ///
37 /// Block* rawData() data()
38 /// │ │ │
39 /// │ │ │
40 /// ▼ ▼ ▼
41 /// ┌───────────────┬─────────────────────────┬─────────────────┐
42 /// │ Block │ Metadata │ Data │
43 /// │ sizeof(Block) │ Desc->getMetadataSize() │ Desc->getSize() │
44 /// └───────────────┴─────────────────────────┴─────────────────┘
45 ///
46 /// Desc->getAllocSize() describes the size after the Block, i.e.
47 /// the data size and the metadata size.
48 ///
49 class Block final {
50 public:
51 /// Creates a new block.
52 Block(const std::optional<unsigned> &DeclID, const Descriptor *Desc,
53 bool IsStatic = false, bool IsExtern = false)
54 : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {}
56 Block(const Descriptor *Desc, bool IsStatic = false, bool IsExtern = false)
57 : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern),
58 Desc(Desc) {}
60 /// Returns the block's descriptor.
61 const Descriptor *getDescriptor() const { return Desc; }
62 /// Checks if the block has any live pointers.
63 bool hasPointers() const { return Pointers; }
64 /// Checks if the block is extern.
65 bool isExtern() const { return IsExtern; }
66 /// Checks if the block has static storage duration.
67 bool isStatic() const { return IsStatic; }
68 /// Checks if the block is temporary.
69 bool isTemporary() const { return Desc->IsTemporary; }
70 /// Returns the size of the block.
71 unsigned getSize() const { return Desc->getAllocSize(); }
72 /// Returns the declaration ID.
73 std::optional<unsigned> getDeclID() const { return DeclID; }
74 bool isInitialized() const { return IsInitialized; }
76 /// Returns a pointer to the stored data.
77 /// You are allowed to read Desc->getSize() bytes from this address.
78 std::byte *data() {
79 // rawData might contain metadata as well.
80 size_t DataOffset = Desc->getMetadataSize();
81 return rawData() + DataOffset;
83 const std::byte *data() const {
84 // rawData might contain metadata as well.
85 size_t DataOffset = Desc->getMetadataSize();
86 return rawData() + DataOffset;
89 /// Returns a pointer to the raw data, including metadata.
90 /// You are allowed to read Desc->getAllocSize() bytes from this address.
91 std::byte *rawData() {
92 return reinterpret_cast<std::byte *>(this) + sizeof(Block);
94 const std::byte *rawData() const {
95 return reinterpret_cast<const std::byte *>(this) + sizeof(Block);
98 /// Returns a view over the data.
99 template <typename T>
100 T &deref() { return *reinterpret_cast<T *>(data()); }
102 /// Invokes the constructor.
103 void invokeCtor() {
104 std::memset(rawData(), 0, Desc->getAllocSize());
105 if (Desc->CtorFn)
106 Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable,
107 /*isActive=*/true, Desc);
108 IsInitialized = true;
111 /// Invokes the Destructor.
112 void invokeDtor() {
113 if (Desc->DtorFn)
114 Desc->DtorFn(this, data(), Desc);
115 IsInitialized = false;
118 protected:
119 friend class Pointer;
120 friend class DeadBlock;
121 friend class InterpState;
123 Block(const Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead)
124 : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {}
126 /// Deletes a dead block at the end of its lifetime.
127 void cleanup();
129 /// Pointer chain management.
130 void addPointer(Pointer *P);
131 void removePointer(Pointer *P);
132 void replacePointer(Pointer *Old, Pointer *New);
133 #ifndef NDEBUG
134 bool hasPointer(const Pointer *P) const;
135 #endif
137 /// Start of the chain of pointers.
138 Pointer *Pointers = nullptr;
139 /// Unique identifier of the declaration.
140 std::optional<unsigned> DeclID;
141 /// Flag indicating if the block has static storage duration.
142 bool IsStatic = false;
143 /// Flag indicating if the block is an extern.
144 bool IsExtern = false;
145 /// Flag indicating if the pointer is dead. This is only ever
146 /// set once, when converting the Block to a DeadBlock.
147 bool IsDead = false;
148 /// Flag indicating if the block contents have been initialized
149 /// via invokeCtor.
150 bool IsInitialized = false;
151 /// Pointer to the stack slot descriptor.
152 const Descriptor *Desc;
155 /// Descriptor for a dead block.
157 /// Dead blocks are chained in a double-linked list to deallocate them
158 /// whenever pointers become dead.
159 class DeadBlock final {
160 public:
161 /// Copies the block.
162 DeadBlock(DeadBlock *&Root, Block *Blk);
164 /// Returns a pointer to the stored data.
165 std::byte *data() { return B.data(); }
166 std::byte *rawData() { return B.rawData(); }
168 private:
169 friend class Block;
170 friend class InterpState;
172 void free();
174 /// Root pointer of the list.
175 DeadBlock *&Root;
176 /// Previous block in the list.
177 DeadBlock *Prev;
178 /// Next block in the list.
179 DeadBlock *Next;
181 /// Actual block storing data and tracking pointers.
182 Block B;
185 } // namespace interp
186 } // namespace clang
188 #endif