Home | History | Annotate | Line # | Download | only in Interp
InterpBlock.h revision 1.1.1.1
      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 Context;
     29 class InterpState;
     30 class Pointer;
     31 class Function;
     32 enum 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.
     37 class Block {
     38 public:
     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 
     78 protected:
     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.
    112 class DeadBlock {
    113 public:
    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 
    120 private:
    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