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