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