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