1 //===--- Block.h - Allocated blocks for the interpreter ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
32 enum PrimType : unsigned;
34 /// A memory block, either on the stack or in the heap.
36 /// The storage described by the block immediately follows it in memory.
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) {}
44 Block(Descriptor *Desc, bool IsStatic = false, bool IsExtern = false)
45 : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern),
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; }
63 /// Returns a pointer to the stored data.
64 char *data() { return reinterpret_cast<char *>(this + 1); }
66 /// Returns a view over the data.
68 T &deref() { return *reinterpret_cast<T *>(data()); }
70 /// Invokes the constructor.
72 std::memset(data(), 0, getSize());
74 Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable,
75 /*isActive=*/true, Desc);
80 friend class DeadBlock;
81 friend class InterpState;
83 Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead)
84 : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {}
86 // Deletes a dead block at the end of its lifetime.
89 // Pointer chain management.
90 void addPointer(Pointer *P);
91 void removePointer(Pointer *P);
92 void movePointer(Pointer *From, Pointer *To);
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.
104 /// Pointer to the stack slot descriptor.
108 /// Descriptor for a dead block.
110 /// Dead blocks are chained in a double-linked list to deallocate them
111 /// whenever pointers become dead.
114 /// Copies the block.
115 DeadBlock(DeadBlock *&Root, Block *Blk);
117 /// Returns a pointer to the stored data.
118 char *data() { return B.data(); }
122 friend class InterpState;
126 /// Root pointer of the list.
128 /// Previous block in the list.
130 /// Next block in the list.
133 /// Actual block storing data and tracking pointers.
137 } // namespace interp