xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/Interp/InterpBlock.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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