xref: /freebsd/contrib/llvm-project/clang/lib/AST/ByteCode/InterpBlock.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
addPointer(Pointer * P)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 
removePointer(Pointer * P)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 
cleanup()64 void Block::cleanup() {
65   if (Pointers == nullptr && IsDead)
66     (reinterpret_cast<DeadBlock *>(this + 1) - 1)->free();
67 }
68 
replacePointer(Pointer * Old,Pointer * New)69 void Block::replacePointer(Pointer *Old, Pointer *New) {
70   assert(Old);
71   assert(New);
72   assert(Old != New);
73   if (IsStatic) {
74     assert(!Pointers);
75     return;
76   }
77 #ifndef NDEBUG
78   assert(hasPointer(Old));
79 #endif
80 
81   if (Old->Prev)
82     Old->Prev->Next = New;
83   if (Old->Next)
84     Old->Next->Prev = New;
85   New->Prev = Old->Prev;
86   New->Next = Old->Next;
87   if (Pointers == Old)
88     Pointers = New;
89 
90   Old->PointeeStorage.BS.Pointee = nullptr;
91   New->PointeeStorage.BS.Pointee = this;
92 #ifndef NDEBUG
93   assert(!hasPointer(Old));
94   assert(hasPointer(New));
95 #endif
96 }
97 
98 #ifndef NDEBUG
hasPointer(const Pointer * P) const99 bool Block::hasPointer(const Pointer *P) const {
100   for (const Pointer *C = Pointers; C; C = C->Next) {
101     if (C == P)
102       return true;
103   }
104   return false;
105 }
106 #endif
107 
DeadBlock(DeadBlock * & Root,Block * Blk)108 DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)
109     : Root(Root), B(~0u, Blk->Desc, Blk->IsStatic, Blk->IsExtern, Blk->IsWeak,
110                     /*isDead=*/true) {
111   // Add the block to the chain of dead blocks.
112   if (Root)
113     Root->Prev = this;
114 
115   Next = Root;
116   Prev = nullptr;
117   Root = this;
118 
119   B.IsDynamic = Blk->IsDynamic;
120 
121   // Transfer pointers.
122   B.Pointers = Blk->Pointers;
123   for (Pointer *P = Blk->Pointers; P; P = P->Next)
124     P->PointeeStorage.BS.Pointee = &B;
125   Blk->Pointers = nullptr;
126 }
127 
free()128 void DeadBlock::free() {
129   if (B.IsInitialized)
130     B.invokeDtor();
131 
132   if (Prev)
133     Prev->Next = Next;
134   if (Next)
135     Next->Prev = Prev;
136   if (Root == this)
137     Root = Next;
138   std::free(this);
139 }
140