Block.h revision 353942
1//===--- Block.h - 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#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H 14#define LLVM_CLANG_AST_INTERP_BLOCK_H 15 16#include "Descriptor.h" 17#include "clang/AST/Decl.h" 18#include "clang/AST/DeclCXX.h" 19#include "clang/AST/Expr.h" 20#include "clang/AST/ComparisonCategories.h" 21#include "llvm/ADT/PointerUnion.h" 22#include "llvm/Support/raw_ostream.h" 23 24namespace clang { 25namespace interp { 26class Block; 27class DeadBlock; 28class Context; 29class InterpState; 30class Pointer; 31class Function; 32enum PrimType : unsigned; 33 34/// A memory block, either on the stack or in the heap. 35/// 36/// The storage described by the block immediately follows it in memory. 37class Block { 38public: 39 // Creates a new block. 40 Block(const llvm::Optional<unsigned> &DeclID, Descriptor *Desc, 41 bool IsStatic = false, bool IsExtern = false) 42 : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {} 43 44 Block(Descriptor *Desc, bool IsStatic = false, bool IsExtern = false) 45 : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern), 46 Desc(Desc) {} 47 48 /// Returns the block's descriptor. 49 Descriptor *getDescriptor() const { return Desc; } 50 /// Checks if the block has any live pointers. 51 bool hasPointers() const { return Pointers; } 52 /// Checks if the block is extern. 53 bool isExtern() const { return IsExtern; } 54 /// Checks if the block has static storage duration. 55 bool isStatic() const { return IsStatic; } 56 /// Checks if the block is temporary. 57 bool isTemporary() const { return Desc->IsTemporary; } 58 /// Returns the size of the block. 59 InterpSize getSize() const { return Desc->getAllocSize(); } 60 /// Returns the declaration ID. 61 llvm::Optional<unsigned> getDeclID() const { return DeclID; } 62 63 /// Returns a pointer to the stored data. 64 char *data() { return reinterpret_cast<char *>(this + 1); } 65 66 /// Returns a view over the data. 67 template <typename T> 68 T &deref() { return *reinterpret_cast<T *>(data()); } 69 70 /// Invokes the constructor. 71 void invokeCtor() { 72 std::memset(data(), 0, getSize()); 73 if (Desc->CtorFn) 74 Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable, 75 /*isActive=*/true, Desc); 76 } 77 78protected: 79 friend class Pointer; 80 friend class DeadBlock; 81 friend class InterpState; 82 83 Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead) 84 : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {} 85 86 // Deletes a dead block at the end of its lifetime. 87 void cleanup(); 88 89 // Pointer chain management. 90 void addPointer(Pointer *P); 91 void removePointer(Pointer *P); 92 void movePointer(Pointer *From, Pointer *To); 93 94 /// Start of the chain of pointers. 95 Pointer *Pointers = nullptr; 96 /// Unique identifier of the declaration. 97 llvm::Optional<unsigned> DeclID; 98 /// Flag indicating if the block has static storage duration. 99 bool IsStatic = false; 100 /// Flag indicating if the block is an extern. 101 bool IsExtern = false; 102 /// Flag indicating if the pointer is dead. 103 bool IsDead = false; 104 /// Pointer to the stack slot descriptor. 105 Descriptor *Desc; 106}; 107 108/// Descriptor for a dead block. 109/// 110/// Dead blocks are chained in a double-linked list to deallocate them 111/// whenever pointers become dead. 112class DeadBlock { 113public: 114 /// Copies the block. 115 DeadBlock(DeadBlock *&Root, Block *Blk); 116 117 /// Returns a pointer to the stored data. 118 char *data() { return B.data(); } 119 120private: 121 friend class Block; 122 friend class InterpState; 123 124 void free(); 125 126 /// Root pointer of the list. 127 DeadBlock *&Root; 128 /// Previous block in the list. 129 DeadBlock *Prev; 130 /// Next block in the list. 131 DeadBlock *Next; 132 133 /// Actual block storing data and tracking pointers. 134 Block B; 135}; 136 137} // namespace interp 138} // namespace clang 139 140#endif 141