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