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->PointeeStorage.BS.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), 96 B(~0u, Blk->Desc, Blk->IsStatic, Blk->IsExtern, /*isDead=*/true) { 97 // Add the block to the chain of dead blocks. 98 if (Root) 99 Root->Prev = this; 100 101 Next = Root; 102 Prev = nullptr; 103 Root = this; 104 105 // Transfer pointers. 106 B.Pointers = Blk->Pointers; 107 for (Pointer *P = Blk->Pointers; P; P = P->Next) 108 P->PointeeStorage.BS.Pointee = &B; 109 Blk->Pointers = nullptr; 110 } 111 112 void DeadBlock::free() { 113 if (B.IsInitialized) 114 B.invokeDtor(); 115 116 if (Prev) 117 Prev->Next = Next; 118 if (Next) 119 Next->Prev = Prev; 120 if (Root == this) 121 Root = Next; 122 std::free(this); 123 } 124