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