brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.5 KiB · dc0178a Raw
156 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// Defines the classes describing allocated blocks.10//11//===----------------------------------------------------------------------===//12 13#include "InterpBlock.h"14#include "Pointer.h"15 16using namespace clang;17using namespace clang::interp;18 19void Block::addPointer(Pointer *P) {20  assert(P);21 22#ifndef NDEBUG23  assert(!hasPointer(P));24#endif25  if (Pointers)26    Pointers->BS.Prev = P;27  P->BS.Next = Pointers;28  P->BS.Prev = nullptr;29  Pointers = P;30#ifndef NDEBUG31  assert(hasPointer(P));32#endif33}34 35void Block::removePointer(Pointer *P) {36  assert(P->isBlockPointer());37  assert(P);38 39#ifndef NDEBUG40  assert(hasPointer(P));41#endif42 43  BlockPointer &BP = P->BS;44 45  if (Pointers == P)46    Pointers = BP.Next;47 48  if (BP.Prev)49    BP.Prev->BS.Next = BP.Next;50  if (BP.Next)51    BP.Next->BS.Prev = BP.Prev;52  P->BS.Pointee = nullptr;53#ifndef NDEBUG54  assert(!hasPointer(P));55#endif56}57 58void Block::cleanup() {59  if (Pointers == nullptr && !isDynamic() && isDead())60    (reinterpret_cast<DeadBlock *>(this + 1) - 1)->free();61}62 63void Block::replacePointer(Pointer *Old, Pointer *New) {64  assert(Old);65  assert(Old->isBlockPointer());66  assert(New);67  assert(New->isBlockPointer());68  assert(Old != New);69#ifndef NDEBUG70  assert(hasPointer(Old));71#endif72 73  BlockPointer &OldBP = Old->BS;74  BlockPointer &NewBP = New->BS;75 76  if (OldBP.Prev)77    OldBP.Prev->BS.Next = New;78  if (OldBP.Next)79    OldBP.Next->BS.Prev = New;80  NewBP.Prev = OldBP.Prev;81  NewBP.Next = OldBP.Next;82  if (Pointers == Old)83    Pointers = New;84 85  OldBP.Pointee = nullptr;86  NewBP.Pointee = this;87#ifndef NDEBUG88  assert(!hasPointer(Old));89  assert(hasPointer(New));90#endif91}92 93#ifndef NDEBUG94bool Block::hasPointer(const Pointer *P) const {95  for (const Pointer *C = Pointers; C; C = C->asBlockPointer().Next) {96    if (C == P)97      return true;98  }99  return false;100}101#endif102 103void Block::movePointersTo(Block *B) {104  assert(B != this);105  unsigned MDDiff = static_cast<int>(B->Desc->getMetadataSize()) -106                    static_cast<int>(Desc->getMetadataSize());107 108  while (Pointers) {109    Pointer *P = Pointers;110 111    this->removePointer(P);112    P->BS.Pointee = B;113 114    // If the metadata size changed between the two blocks, move the pointer115    // base/offset. Realistically, this should only happen when we move pointers116    // from a dummy pointer to a global one.117    P->BS.Base += MDDiff;118    P->Offset += MDDiff;119 120    B->addPointer(P);121  }122  assert(!this->hasPointers());123}124 125DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)126    : Root(Root), B(~0u, Blk->Desc, Blk->isExtern(), Blk->IsStatic,127                    Blk->isWeak(), Blk->isDummy(), /*IsDead=*/true) {128  // Add the block to the chain of dead blocks.129  if (Root)130    Root->Prev = this;131 132  Next = Root;133  Prev = nullptr;134  Root = this;135 136  B.DynAllocId = Blk->DynAllocId;137 138  // Transfer pointers.139  B.Pointers = Blk->Pointers;140  for (Pointer *P = Blk->Pointers; P; P = P->asBlockPointer().Next)141    P->BS.Pointee = &B;142  Blk->Pointers = nullptr;143}144 145void DeadBlock::free() {146  assert(!B.isInitialized());147 148  if (Prev)149    Prev->Next = Next;150  if (Next)151    Next->Prev = Prev;152  if (Root == this)153    Root = Next;154  std::free(this);155}156