• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
DeclID(DeclID)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.
getDescriptor()49   Descriptor *getDescriptor() const { return Desc; }
50   /// Checks if the block has any live pointers.
hasPointers()51   bool hasPointers() const { return Pointers; }
52   /// Checks if the block is extern.
isExtern()53   bool isExtern() const { return IsExtern; }
54   /// Checks if the block has static storage duration.
isStatic()55   bool isStatic() const { return IsStatic; }
56   /// Checks if the block is temporary.
isTemporary()57   bool isTemporary() const { return Desc->IsTemporary; }
58   /// Returns the size of the block.
getSize()59   InterpSize getSize() const { return Desc->getAllocSize(); }
60   /// Returns the declaration ID.
getDeclID()61   llvm::Optional<unsigned> getDeclID() const { return DeclID; }
62 
63   /// Returns a pointer to the stored data.
data()64   char *data() { return reinterpret_cast<char *>(this + 1); }
65 
66   /// Returns a view over the data.
67   template <typename T>
deref()68   T &deref() { return *reinterpret_cast<T *>(data()); }
69 
70   /// Invokes the constructor.
invokeCtor()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 
Block(Descriptor * Desc,bool IsExtern,bool IsStatic,bool IsDead)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.
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