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