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 } 35 36 void Block::removePointer(Pointer *P) { 37 assert(P); 38 if (IsStatic) { 39 assert(!Pointers); 40 return; 41 } 42 43 #ifndef NDEBUG 44 assert(hasPointer(P)); 45 #endif 46 47 if (Pointers == P) 48 Pointers = P->Next; 49 50 if (P->Prev) 51 P->Prev->Next = P->Next; 52 if (P->Next) 53 P->Next->Prev = P->Prev; 54 } 55 56 void Block::cleanup() { 57 if (Pointers == nullptr && IsDead) 58 (reinterpret_cast<DeadBlock *>(this + 1) - 1)->free(); 59 } 60 61 void Block::replacePointer(Pointer *Old, Pointer *New) { 62 assert(Old); 63 assert(New); 64 if (IsStatic) { 65 assert(!Pointers); 66 return; 67 } 68 69 #ifndef NDEBUG 70 assert(hasPointer(Old)); 71 #endif 72 73 removePointer(Old); 74 addPointer(New); 75 76 Old->Pointee = nullptr; 77 78 #ifndef NDEBUG 79 assert(!hasPointer(Old)); 80 assert(hasPointer(New)); 81 #endif 82 } 83 84 #ifndef NDEBUG 85 bool Block::hasPointer(const Pointer *P) const { 86 for (const Pointer *C = Pointers; C; C = C->Next) { 87 if (C == P) 88 return true; 89 } 90 return false; 91 } 92 #endif 93 94 DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk) 95 : Root(Root), B(Blk->Desc, Blk->IsStatic, Blk->IsExtern, /*isDead=*/true) { 96 // Add the block to the chain of dead blocks. 97 if (Root) 98 Root->Prev = this; 99 100 Next = Root; 101 Prev = nullptr; 102 Root = this; 103 104 // Transfer pointers. 105 B.Pointers = Blk->Pointers; 106 for (Pointer *P = Blk->Pointers; P; P = P->Next) 107 P->Pointee = &B; 108 } 109 110 void DeadBlock::free() { 111 if (Prev) 112 Prev->Next = Next; 113 if (Next) 114 Next->Prev = Prev; 115 if (Root == this) 116 Root = Next; 117 std::free(this); 118 } 119