1*5ffd83dbSDimitry Andric //===--- Block.cpp - Allocated blocks for the interpreter -------*- C++ -*-===//
2*5ffd83dbSDimitry Andric //
3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5ffd83dbSDimitry Andric //
7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8*5ffd83dbSDimitry Andric //
9*5ffd83dbSDimitry Andric // Defines the classes describing allocated blocks.
10*5ffd83dbSDimitry Andric //
11*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
12*5ffd83dbSDimitry Andric 
13*5ffd83dbSDimitry Andric #include "InterpBlock.h"
14*5ffd83dbSDimitry Andric #include "Pointer.h"
15*5ffd83dbSDimitry Andric 
16*5ffd83dbSDimitry Andric using namespace clang;
17*5ffd83dbSDimitry Andric using namespace clang::interp;
18*5ffd83dbSDimitry Andric 
19*5ffd83dbSDimitry Andric 
20*5ffd83dbSDimitry Andric 
addPointer(Pointer * P)21*5ffd83dbSDimitry Andric void Block::addPointer(Pointer *P) {
22*5ffd83dbSDimitry Andric   if (IsStatic)
23*5ffd83dbSDimitry Andric     return;
24*5ffd83dbSDimitry Andric   if (Pointers)
25*5ffd83dbSDimitry Andric     Pointers->Prev = P;
26*5ffd83dbSDimitry Andric   P->Next = Pointers;
27*5ffd83dbSDimitry Andric   P->Prev = nullptr;
28*5ffd83dbSDimitry Andric   Pointers = P;
29*5ffd83dbSDimitry Andric }
30*5ffd83dbSDimitry Andric 
removePointer(Pointer * P)31*5ffd83dbSDimitry Andric void Block::removePointer(Pointer *P) {
32*5ffd83dbSDimitry Andric   if (IsStatic)
33*5ffd83dbSDimitry Andric     return;
34*5ffd83dbSDimitry Andric   if (Pointers == P)
35*5ffd83dbSDimitry Andric     Pointers = P->Next;
36*5ffd83dbSDimitry Andric   if (P->Prev)
37*5ffd83dbSDimitry Andric     P->Prev->Next = P->Next;
38*5ffd83dbSDimitry Andric   if (P->Next)
39*5ffd83dbSDimitry Andric     P->Next->Prev = P->Prev;
40*5ffd83dbSDimitry Andric }
41*5ffd83dbSDimitry Andric 
cleanup()42*5ffd83dbSDimitry Andric void Block::cleanup() {
43*5ffd83dbSDimitry Andric   if (Pointers == nullptr && IsDead)
44*5ffd83dbSDimitry Andric     (reinterpret_cast<DeadBlock *>(this + 1) - 1)->free();
45*5ffd83dbSDimitry Andric }
46*5ffd83dbSDimitry Andric 
movePointer(Pointer * From,Pointer * To)47*5ffd83dbSDimitry Andric void Block::movePointer(Pointer *From, Pointer *To) {
48*5ffd83dbSDimitry Andric   if (IsStatic)
49*5ffd83dbSDimitry Andric     return;
50*5ffd83dbSDimitry Andric   To->Prev = From->Prev;
51*5ffd83dbSDimitry Andric   if (To->Prev)
52*5ffd83dbSDimitry Andric     To->Prev->Next = To;
53*5ffd83dbSDimitry Andric   To->Next = From->Next;
54*5ffd83dbSDimitry Andric   if (To->Next)
55*5ffd83dbSDimitry Andric     To->Next->Prev = To;
56*5ffd83dbSDimitry Andric   if (Pointers == From)
57*5ffd83dbSDimitry Andric     Pointers = To;
58*5ffd83dbSDimitry Andric 
59*5ffd83dbSDimitry Andric   From->Prev = nullptr;
60*5ffd83dbSDimitry Andric   From->Next = nullptr;
61*5ffd83dbSDimitry Andric }
62*5ffd83dbSDimitry Andric 
DeadBlock(DeadBlock * & Root,Block * Blk)63*5ffd83dbSDimitry Andric DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)
64*5ffd83dbSDimitry Andric     : Root(Root), B(Blk->Desc, Blk->IsStatic, Blk->IsExtern, /*isDead=*/true) {
65*5ffd83dbSDimitry Andric   // Add the block to the chain of dead blocks.
66*5ffd83dbSDimitry Andric   if (Root)
67*5ffd83dbSDimitry Andric     Root->Prev = this;
68*5ffd83dbSDimitry Andric 
69*5ffd83dbSDimitry Andric   Next = Root;
70*5ffd83dbSDimitry Andric   Prev = nullptr;
71*5ffd83dbSDimitry Andric   Root = this;
72*5ffd83dbSDimitry Andric 
73*5ffd83dbSDimitry Andric   // Transfer pointers.
74*5ffd83dbSDimitry Andric   B.Pointers = Blk->Pointers;
75*5ffd83dbSDimitry Andric   for (Pointer *P = Blk->Pointers; P; P = P->Next)
76*5ffd83dbSDimitry Andric     P->Pointee = &B;
77*5ffd83dbSDimitry Andric }
78*5ffd83dbSDimitry Andric 
free()79*5ffd83dbSDimitry Andric void DeadBlock::free() {
80*5ffd83dbSDimitry Andric   if (Prev)
81*5ffd83dbSDimitry Andric     Prev->Next = Next;
82*5ffd83dbSDimitry Andric   if (Next)
83*5ffd83dbSDimitry Andric     Next->Prev = Prev;
84*5ffd83dbSDimitry Andric   if (Root == this)
85*5ffd83dbSDimitry Andric     Root = Next;
86*5ffd83dbSDimitry Andric   ::free(this);
87*5ffd83dbSDimitry Andric }
88