15ffd83dbSDimitry Andric //===--- Block.cpp - Allocated blocks for the interpreter -------*- C++ -*-===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric // Defines the classes describing allocated blocks. 105ffd83dbSDimitry Andric // 115ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 125ffd83dbSDimitry Andric 135ffd83dbSDimitry Andric #include "InterpBlock.h" 145ffd83dbSDimitry Andric #include "Pointer.h" 155ffd83dbSDimitry Andric 165ffd83dbSDimitry Andric using namespace clang; 175ffd83dbSDimitry Andric using namespace clang::interp; 185ffd83dbSDimitry Andric 195ffd83dbSDimitry Andric void Block::addPointer(Pointer *P) { 2006c3fb27SDimitry Andric assert(P); 2106c3fb27SDimitry Andric if (IsStatic) { 2206c3fb27SDimitry Andric assert(!Pointers); 235ffd83dbSDimitry Andric return; 2406c3fb27SDimitry Andric } 2506c3fb27SDimitry Andric 2606c3fb27SDimitry Andric #ifndef NDEBUG 2706c3fb27SDimitry Andric assert(!hasPointer(P)); 2806c3fb27SDimitry Andric #endif 295ffd83dbSDimitry Andric if (Pointers) 305ffd83dbSDimitry Andric Pointers->Prev = P; 315ffd83dbSDimitry Andric P->Next = Pointers; 325ffd83dbSDimitry Andric P->Prev = nullptr; 335ffd83dbSDimitry Andric Pointers = P; 345ffd83dbSDimitry Andric } 355ffd83dbSDimitry Andric 365ffd83dbSDimitry Andric void Block::removePointer(Pointer *P) { 3706c3fb27SDimitry Andric assert(P); 3806c3fb27SDimitry Andric if (IsStatic) { 3906c3fb27SDimitry Andric assert(!Pointers); 405ffd83dbSDimitry Andric return; 4106c3fb27SDimitry Andric } 4206c3fb27SDimitry Andric 4306c3fb27SDimitry Andric #ifndef NDEBUG 4406c3fb27SDimitry Andric assert(hasPointer(P)); 4506c3fb27SDimitry Andric #endif 4606c3fb27SDimitry Andric 475ffd83dbSDimitry Andric if (Pointers == P) 485ffd83dbSDimitry Andric Pointers = P->Next; 4906c3fb27SDimitry Andric 505ffd83dbSDimitry Andric if (P->Prev) 515ffd83dbSDimitry Andric P->Prev->Next = P->Next; 525ffd83dbSDimitry Andric if (P->Next) 535ffd83dbSDimitry Andric P->Next->Prev = P->Prev; 545ffd83dbSDimitry Andric } 555ffd83dbSDimitry Andric 565ffd83dbSDimitry Andric void Block::cleanup() { 575ffd83dbSDimitry Andric if (Pointers == nullptr && IsDead) 585ffd83dbSDimitry Andric (reinterpret_cast<DeadBlock *>(this + 1) - 1)->free(); 595ffd83dbSDimitry Andric } 605ffd83dbSDimitry Andric 6106c3fb27SDimitry Andric void Block::replacePointer(Pointer *Old, Pointer *New) { 6206c3fb27SDimitry Andric assert(Old); 6306c3fb27SDimitry Andric assert(New); 6406c3fb27SDimitry Andric if (IsStatic) { 6506c3fb27SDimitry Andric assert(!Pointers); 665ffd83dbSDimitry Andric return; 675ffd83dbSDimitry Andric } 685ffd83dbSDimitry Andric 6906c3fb27SDimitry Andric #ifndef NDEBUG 7006c3fb27SDimitry Andric assert(hasPointer(Old)); 7106c3fb27SDimitry Andric #endif 7206c3fb27SDimitry Andric 7306c3fb27SDimitry Andric removePointer(Old); 7406c3fb27SDimitry Andric addPointer(New); 7506c3fb27SDimitry Andric 76*0fca6ea1SDimitry Andric Old->PointeeStorage.BS.Pointee = nullptr; 7706c3fb27SDimitry Andric 7806c3fb27SDimitry Andric #ifndef NDEBUG 7906c3fb27SDimitry Andric assert(!hasPointer(Old)); 8006c3fb27SDimitry Andric assert(hasPointer(New)); 8106c3fb27SDimitry Andric #endif 8206c3fb27SDimitry Andric } 8306c3fb27SDimitry Andric 8406c3fb27SDimitry Andric #ifndef NDEBUG 8506c3fb27SDimitry Andric bool Block::hasPointer(const Pointer *P) const { 8606c3fb27SDimitry Andric for (const Pointer *C = Pointers; C; C = C->Next) { 8706c3fb27SDimitry Andric if (C == P) 8806c3fb27SDimitry Andric return true; 8906c3fb27SDimitry Andric } 9006c3fb27SDimitry Andric return false; 9106c3fb27SDimitry Andric } 9206c3fb27SDimitry Andric #endif 9306c3fb27SDimitry Andric 945ffd83dbSDimitry Andric DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk) 95*0fca6ea1SDimitry Andric : Root(Root), 96*0fca6ea1SDimitry Andric B(~0u, Blk->Desc, Blk->IsStatic, Blk->IsExtern, /*isDead=*/true) { 975ffd83dbSDimitry Andric // Add the block to the chain of dead blocks. 985ffd83dbSDimitry Andric if (Root) 995ffd83dbSDimitry Andric Root->Prev = this; 1005ffd83dbSDimitry Andric 1015ffd83dbSDimitry Andric Next = Root; 1025ffd83dbSDimitry Andric Prev = nullptr; 1035ffd83dbSDimitry Andric Root = this; 1045ffd83dbSDimitry Andric 1055ffd83dbSDimitry Andric // Transfer pointers. 1065ffd83dbSDimitry Andric B.Pointers = Blk->Pointers; 1075ffd83dbSDimitry Andric for (Pointer *P = Blk->Pointers; P; P = P->Next) 108*0fca6ea1SDimitry Andric P->PointeeStorage.BS.Pointee = &B; 109*0fca6ea1SDimitry Andric Blk->Pointers = nullptr; 1105ffd83dbSDimitry Andric } 1115ffd83dbSDimitry Andric 1125ffd83dbSDimitry Andric void DeadBlock::free() { 113*0fca6ea1SDimitry Andric if (B.IsInitialized) 114*0fca6ea1SDimitry Andric B.invokeDtor(); 115*0fca6ea1SDimitry Andric 1165ffd83dbSDimitry Andric if (Prev) 1175ffd83dbSDimitry Andric Prev->Next = Next; 1185ffd83dbSDimitry Andric if (Next) 1195ffd83dbSDimitry Andric Next->Prev = Prev; 1205ffd83dbSDimitry Andric if (Root == this) 1215ffd83dbSDimitry Andric Root = Next; 12206c3fb27SDimitry Andric std::free(this); 1235ffd83dbSDimitry Andric } 124