xref: /llvm-project/clang/lib/AST/ByteCode/InterpBlock.cpp (revision 4e5f8a8f0bf855fdac93fa09b4b82b69339235b9)
1a07aba5dSTimm Baeder //===--- Block.cpp - Allocated blocks for the interpreter -------*- C++ -*-===//
2a07aba5dSTimm Baeder //
3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information.
5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a07aba5dSTimm Baeder //
7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
8a07aba5dSTimm Baeder //
9a07aba5dSTimm Baeder // Defines the classes describing allocated blocks.
10a07aba5dSTimm Baeder //
11a07aba5dSTimm Baeder //===----------------------------------------------------------------------===//
12a07aba5dSTimm Baeder 
13a07aba5dSTimm Baeder #include "InterpBlock.h"
14a07aba5dSTimm Baeder #include "Pointer.h"
15a07aba5dSTimm Baeder 
16a07aba5dSTimm Baeder using namespace clang;
17a07aba5dSTimm Baeder using namespace clang::interp;
18a07aba5dSTimm Baeder 
19a07aba5dSTimm Baeder void Block::addPointer(Pointer *P) {
20a07aba5dSTimm Baeder   assert(P);
21a07aba5dSTimm Baeder   if (IsStatic) {
22a07aba5dSTimm Baeder     assert(!Pointers);
23a07aba5dSTimm Baeder     return;
24a07aba5dSTimm Baeder   }
25a07aba5dSTimm Baeder 
26a07aba5dSTimm Baeder #ifndef NDEBUG
27a07aba5dSTimm Baeder   assert(!hasPointer(P));
28a07aba5dSTimm Baeder #endif
29a07aba5dSTimm Baeder   if (Pointers)
30a07aba5dSTimm Baeder     Pointers->Prev = P;
31a07aba5dSTimm Baeder   P->Next = Pointers;
32a07aba5dSTimm Baeder   P->Prev = nullptr;
33a07aba5dSTimm Baeder   Pointers = P;
34a07aba5dSTimm Baeder #ifndef NDEBUG
35a07aba5dSTimm Baeder   assert(hasPointer(P));
36a07aba5dSTimm Baeder #endif
37a07aba5dSTimm Baeder }
38a07aba5dSTimm Baeder 
39a07aba5dSTimm Baeder void Block::removePointer(Pointer *P) {
40a07aba5dSTimm Baeder   assert(P->isBlockPointer());
41a07aba5dSTimm Baeder   assert(P);
42a07aba5dSTimm Baeder   if (IsStatic) {
43a07aba5dSTimm Baeder     assert(!Pointers);
44a07aba5dSTimm Baeder     return;
45a07aba5dSTimm Baeder   }
46a07aba5dSTimm Baeder 
47a07aba5dSTimm Baeder #ifndef NDEBUG
48a07aba5dSTimm Baeder   assert(hasPointer(P));
49a07aba5dSTimm Baeder #endif
50a07aba5dSTimm Baeder 
51a07aba5dSTimm Baeder   if (Pointers == P)
52a07aba5dSTimm Baeder     Pointers = P->Next;
53a07aba5dSTimm Baeder 
54a07aba5dSTimm Baeder   if (P->Prev)
55a07aba5dSTimm Baeder     P->Prev->Next = P->Next;
56a07aba5dSTimm Baeder   if (P->Next)
57a07aba5dSTimm Baeder     P->Next->Prev = P->Prev;
58a07aba5dSTimm Baeder   P->PointeeStorage.BS.Pointee = nullptr;
59a07aba5dSTimm Baeder #ifndef NDEBUG
60a07aba5dSTimm Baeder   assert(!hasPointer(P));
61a07aba5dSTimm Baeder #endif
62a07aba5dSTimm Baeder }
63a07aba5dSTimm Baeder 
64a07aba5dSTimm Baeder void Block::cleanup() {
65a07aba5dSTimm Baeder   if (Pointers == nullptr && IsDead)
66a07aba5dSTimm Baeder     (reinterpret_cast<DeadBlock *>(this + 1) - 1)->free();
67a07aba5dSTimm Baeder }
68a07aba5dSTimm Baeder 
69a07aba5dSTimm Baeder void Block::replacePointer(Pointer *Old, Pointer *New) {
70a07aba5dSTimm Baeder   assert(Old);
71a07aba5dSTimm Baeder   assert(New);
72a07aba5dSTimm Baeder   if (IsStatic) {
73a07aba5dSTimm Baeder     assert(!Pointers);
74a07aba5dSTimm Baeder     return;
75a07aba5dSTimm Baeder   }
76a07aba5dSTimm Baeder 
77a07aba5dSTimm Baeder #ifndef NDEBUG
78a07aba5dSTimm Baeder   assert(hasPointer(Old));
79a07aba5dSTimm Baeder #endif
80a07aba5dSTimm Baeder 
81a07aba5dSTimm Baeder   removePointer(Old);
82a07aba5dSTimm Baeder   addPointer(New);
83a07aba5dSTimm Baeder 
84a07aba5dSTimm Baeder   Old->PointeeStorage.BS.Pointee = nullptr;
85a07aba5dSTimm Baeder 
86a07aba5dSTimm Baeder #ifndef NDEBUG
87a07aba5dSTimm Baeder   assert(!hasPointer(Old));
88a07aba5dSTimm Baeder   assert(hasPointer(New));
89a07aba5dSTimm Baeder #endif
90a07aba5dSTimm Baeder }
91a07aba5dSTimm Baeder 
92a07aba5dSTimm Baeder #ifndef NDEBUG
93a07aba5dSTimm Baeder bool Block::hasPointer(const Pointer *P) const {
94a07aba5dSTimm Baeder   for (const Pointer *C = Pointers; C; C = C->Next) {
95a07aba5dSTimm Baeder     if (C == P)
96a07aba5dSTimm Baeder       return true;
97a07aba5dSTimm Baeder   }
98a07aba5dSTimm Baeder   return false;
99a07aba5dSTimm Baeder }
100a07aba5dSTimm Baeder #endif
101a07aba5dSTimm Baeder 
102a07aba5dSTimm Baeder DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)
103*4e5f8a8fSTimm Baeder     : Root(Root), B(~0u, Blk->Desc, Blk->IsStatic, Blk->IsExtern, Blk->IsWeak,
104*4e5f8a8fSTimm Baeder                     /*isDead=*/true) {
105a07aba5dSTimm Baeder   // Add the block to the chain of dead blocks.
106a07aba5dSTimm Baeder   if (Root)
107a07aba5dSTimm Baeder     Root->Prev = this;
108a07aba5dSTimm Baeder 
109a07aba5dSTimm Baeder   Next = Root;
110a07aba5dSTimm Baeder   Prev = nullptr;
111a07aba5dSTimm Baeder   Root = this;
112a07aba5dSTimm Baeder 
113df11ee21STimm Baeder   B.IsDynamic = Blk->IsDynamic;
114df11ee21STimm Baeder 
115a07aba5dSTimm Baeder   // Transfer pointers.
116a07aba5dSTimm Baeder   B.Pointers = Blk->Pointers;
117a07aba5dSTimm Baeder   for (Pointer *P = Blk->Pointers; P; P = P->Next)
118a07aba5dSTimm Baeder     P->PointeeStorage.BS.Pointee = &B;
119a07aba5dSTimm Baeder   Blk->Pointers = nullptr;
120a07aba5dSTimm Baeder }
121a07aba5dSTimm Baeder 
122a07aba5dSTimm Baeder void DeadBlock::free() {
123a07aba5dSTimm Baeder   if (B.IsInitialized)
124a07aba5dSTimm Baeder     B.invokeDtor();
125a07aba5dSTimm Baeder 
126a07aba5dSTimm Baeder   if (Prev)
127a07aba5dSTimm Baeder     Prev->Next = Next;
128a07aba5dSTimm Baeder   if (Next)
129a07aba5dSTimm Baeder     Next->Prev = Prev;
130a07aba5dSTimm Baeder   if (Root == this)
131a07aba5dSTimm Baeder     Root = Next;
132a07aba5dSTimm Baeder   std::free(this);
133a07aba5dSTimm Baeder }
134