Block.h revision 360784
1289694Sngie//===--- Block.h - Allocated blocks for the interpreter ---------*- C++ -*-===// 2289694Sngie// 3289694Sngie// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4289694Sngie// See https://llvm.org/LICENSE.txt for license information. 5289694Sngie// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6289694Sngie// 7289694Sngie//===----------------------------------------------------------------------===// 8289694Sngie// 9289694Sngie// Defines the classes describing allocated blocks. 10289694Sngie// 11289694Sngie//===----------------------------------------------------------------------===// 12289694Sngie 13289694Sngie#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H 14289694Sngie#define LLVM_CLANG_AST_INTERP_BLOCK_H 15289694Sngie 16289694Sngie#include "Descriptor.h" 17289694Sngie#include "clang/AST/Decl.h" 18289694Sngie#include "clang/AST/DeclCXX.h" 19289694Sngie#include "clang/AST/Expr.h" 20289694Sngie#include "clang/AST/ComparisonCategories.h" 21289694Sngie#include "llvm/ADT/PointerUnion.h" 22289694Sngie#include "llvm/Support/raw_ostream.h" 23289694Sngie 24289694Sngienamespace clang { 25289694Sngienamespace interp { 26289694Sngieclass Block; 27289694Sngieclass DeadBlock; 28289694Sngieclass Context; 29289694Sngieclass InterpState; 30290586Sngieclass Pointer; 31290586Sngieclass Function; 32290594Sngieenum PrimType : unsigned; 33290594Sngie 34290594Sngie/// A memory block, either on the stack or in the heap. 35290594Sngie/// 36290594Sngie/// The storage described by the block immediately follows it in memory. 37290594Sngieclass Block { 38290594Sngiepublic: 39290586Sngie // Creates a new block. 40290586Sngie Block(const llvm::Optional<unsigned> &DeclID, Descriptor *Desc, 41290586Sngie bool IsStatic = false, bool IsExtern = false) 42290586Sngie : DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern), Desc(Desc) {} 43290586Sngie 44289694Sngie Block(Descriptor *Desc, bool IsStatic = false, bool IsExtern = false) 45290586Sngie : DeclID((unsigned)-1), IsStatic(IsStatic), IsExtern(IsExtern), 46289694Sngie Desc(Desc) {} 47290586Sngie 48290586Sngie /// Returns the block's descriptor. 49290594Sngie Descriptor *getDescriptor() const { return Desc; } 50289694Sngie /// Checks if the block has any live pointers. 51290586Sngie bool hasPointers() const { return Pointers; } 52290586Sngie /// Checks if the block is extern. 53290586Sngie bool isExtern() const { return IsExtern; } 54290586Sngie /// Checks if the block has static storage duration. 55290586Sngie bool isStatic() const { return IsStatic; } 56290586Sngie /// Checks if the block is temporary. 57290586Sngie bool isTemporary() const { return Desc->IsTemporary; } 58290586Sngie /// Returns the size of the block. 59290586Sngie InterpSize getSize() const { return Desc->getAllocSize(); } 60290586Sngie /// Returns the declaration ID. 61290586Sngie llvm::Optional<unsigned> getDeclID() const { return DeclID; } 62290586Sngie 63290586Sngie /// Returns a pointer to the stored data. 64290586Sngie char *data() { return reinterpret_cast<char *>(this + 1); } 65290586Sngie 66290586Sngie /// Returns a view over the data. 67290586Sngie template <typename T> 68290586Sngie T &deref() { return *reinterpret_cast<T *>(data()); } 69290586Sngie 70290586Sngie /// Invokes the constructor. 71289694Sngie void invokeCtor() { 72290586Sngie std::memset(data(), 0, getSize()); 73290586Sngie if (Desc->CtorFn) 74290586Sngie Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable, 75290586Sngie /*isActive=*/true, Desc); 76289694Sngie } 77290586Sngie 78290586Sngieprotected: 79290586Sngie friend class Pointer; 80290586Sngie friend class DeadBlock; 81290586Sngie friend class InterpState; 82290586Sngie 83289694Sngie Block(Descriptor *Desc, bool IsExtern, bool IsStatic, bool IsDead) 84290586Sngie : IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true), Desc(Desc) {} 85290586Sngie 86290586Sngie // Deletes a dead block at the end of its lifetime. 87290586Sngie void cleanup(); 88290586Sngie 89290586Sngie // Pointer chain management. 90290586Sngie void addPointer(Pointer *P); 91290586Sngie void removePointer(Pointer *P); 92290586Sngie void movePointer(Pointer *From, Pointer *To); 93290586Sngie 94290586Sngie /// Start of the chain of pointers. 95289694Sngie Pointer *Pointers = nullptr; 96289694Sngie /// Unique identifier of the declaration. 97289694Sngie llvm::Optional<unsigned> DeclID; 98289694Sngie /// Flag indicating if the block has static storage duration. 99289694Sngie bool IsStatic = false; 100289694Sngie /// Flag indicating if the block is an extern. 101290586Sngie bool IsExtern = false; 102289694Sngie /// Flag indicating if the pointer is dead. 103290586Sngie bool IsDead = false; 104290586Sngie /// Pointer to the stack slot descriptor. 105289694Sngie Descriptor *Desc; 106289694Sngie}; 107289694Sngie 108289694Sngie/// Descriptor for a dead block. 109289694Sngie/// 110289694Sngie/// Dead blocks are chained in a double-linked list to deallocate them 111290586Sngie/// whenever pointers become dead. 112290586Sngieclass DeadBlock { 113290586Sngiepublic: 114289694Sngie /// Copies the block. 115289694Sngie DeadBlock(DeadBlock *&Root, Block *Blk); 116289694Sngie 117289694Sngie /// Returns a pointer to the stored data. 118289694Sngie char *data() { return B.data(); } 119289694Sngie 120289694Sngieprivate: 121289694Sngie friend class Block; 122289694Sngie friend class InterpState; 123289694Sngie 124289694Sngie void free(); 125289694Sngie 126289694Sngie /// Root pointer of the list. 127289694Sngie DeadBlock *&Root; 128289694Sngie /// Previous block in the list. 129289694Sngie DeadBlock *Prev; 130289694Sngie /// Next block in the list. 131289694Sngie DeadBlock *Next; 132289694Sngie 133290586Sngie /// Actual block storing data and tracking pointers. 134290586Sngie Block B; 135290586Sngie}; 136290586Sngie 137290586Sngie} // namespace interp 138290586Sngie} // namespace clang 139290586Sngie 140290586Sngie#endif 141290586Sngie