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