clang  19.0.0git
Descriptor.h
Go to the documentation of this file.
1 //===--- Descriptor.h - Types for the constexpr VM --------------*- 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 descriptors which characterise allocations.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_AST_INTERP_DESCRIPTOR_H
14 #define LLVM_CLANG_AST_INTERP_DESCRIPTOR_H
15 
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/Expr.h"
18 
19 namespace clang {
20 namespace interp {
21 class Block;
22 class Record;
23 struct InitMap;
24 struct Descriptor;
25 enum PrimType : unsigned;
26 
27 using DeclTy = llvm::PointerUnion<const Decl *, const Expr *>;
28 using InitMapPtr = std::optional<std::pair<bool, std::shared_ptr<InitMap>>>;
29 
30 /// Invoked whenever a block is created. The constructor method fills in the
31 /// inline descriptors of all fields and array elements. It also initializes
32 /// all the fields which contain non-trivial types.
33 using BlockCtorFn = void (*)(Block *Storage, std::byte *FieldPtr, bool IsConst,
34  bool IsMutable, bool IsActive,
35  const Descriptor *FieldDesc);
36 
37 /// Invoked when a block is destroyed. Invokes the destructors of all
38 /// non-trivial nested fields of arrays and records.
39 using BlockDtorFn = void (*)(Block *Storage, std::byte *FieldPtr,
40  const Descriptor *FieldDesc);
41 
42 /// Invoked when a block with pointers referencing it goes out of scope. Such
43 /// blocks are persisted: the move function copies all inline descriptors and
44 /// non-trivial fields, as existing pointers might need to reference those
45 /// descriptors. Data is not copied since it cannot be legally read.
46 using BlockMoveFn = void (*)(Block *Storage, const std::byte *SrcFieldPtr,
47  std::byte *DstFieldPtr,
48  const Descriptor *FieldDesc);
49 
50 /// Inline descriptor embedded in structures and arrays.
51 ///
52 /// Such descriptors precede all composite array elements and structure fields.
53 /// If the base of a pointer is not zero, the base points to the end of this
54 /// structure. The offset field is used to traverse the pointer chain up
55 /// to the root structure which allocated the object.
57  /// Offset inside the structure/array.
58  unsigned Offset;
59 
60  /// Flag indicating if the storage is constant or not.
61  /// Relevant for primitive fields.
62  LLVM_PREFERRED_TYPE(bool)
64  /// For primitive fields, it indicates if the field was initialized.
65  /// Primitive fields in static storage are always initialized.
66  /// Arrays are always initialized, even though their elements might not be.
67  /// Base classes are initialized after the constructor is invoked.
68  LLVM_PREFERRED_TYPE(bool)
69  unsigned IsInitialized : 1;
70  /// Flag indicating if the field is an embedded base class.
71  LLVM_PREFERRED_TYPE(bool)
72  unsigned IsBase : 1;
73  /// Flag indicating if the field is the active member of a union.
74  LLVM_PREFERRED_TYPE(bool)
75  unsigned IsActive : 1;
76  /// Flag indicating if the field is mutable (if in a record).
77  LLVM_PREFERRED_TYPE(bool)
78  unsigned IsFieldMutable : 1;
79 
80  const Descriptor *Desc;
81 
85 
86  void dump() const { dump(llvm::errs()); }
87  void dump(llvm::raw_ostream &OS) const;
88 };
89 
90 /// Describes a memory block created by an allocation site.
91 struct Descriptor final {
92 private:
93  /// Original declaration, used to emit the error message.
94  const DeclTy Source;
95  /// Size of an element, in host bytes.
96  const unsigned ElemSize;
97  /// Size of the storage, in host bytes.
98  const unsigned Size;
99  /// Size of the metadata.
100  const unsigned MDSize;
101  /// Size of the allocation (storage + metadata), in host bytes.
102  const unsigned AllocSize;
103 
104  /// Value to denote arrays of unknown size.
105  static constexpr unsigned UnknownSizeMark = (unsigned)-1;
106 
107 public:
108  /// Token to denote structures of unknown size.
109  struct UnknownSize {};
110 
111  using MetadataSize = std::optional<unsigned>;
112  static constexpr MetadataSize InlineDescMD = sizeof(InlineDescriptor);
113 
114  /// Pointer to the record, if block contains records.
115  const Record *const ElemRecord = nullptr;
116  /// Descriptor of the array element.
117  const Descriptor *const ElemDesc = nullptr;
118  /// The primitive type this descriptor was created for,
119  /// or the primitive element type in case this is
120  /// a primitive array.
121  const std::optional<PrimType> PrimT = std::nullopt;
122  /// Flag indicating if the block is mutable.
123  const bool IsConst = false;
124  /// Flag indicating if a field is mutable.
125  const bool IsMutable = false;
126  /// Flag indicating if the block is a temporary.
127  const bool IsTemporary = false;
128  /// Flag indicating if the block is an array.
129  const bool IsArray = false;
130  /// Flag indicating if this is a dummy descriptor.
131  bool IsDummy = false;
132 
133  /// Storage management methods.
134  const BlockCtorFn CtorFn = nullptr;
135  const BlockDtorFn DtorFn = nullptr;
136  const BlockMoveFn MoveFn = nullptr;
137 
138  /// Allocates a descriptor for a primitive.
139  Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, bool IsConst,
140  bool IsTemporary, bool IsMutable);
141 
142  /// Allocates a descriptor for an array of primitives.
143  Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, size_t NumElems,
144  bool IsConst, bool IsTemporary, bool IsMutable);
145 
146  /// Allocates a descriptor for an array of primitives of unknown size.
147  Descriptor(const DeclTy &D, PrimType Type, MetadataSize MDSize,
148  bool IsTemporary, UnknownSize);
149 
150  /// Allocates a descriptor for an array of composites.
151  Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD,
152  unsigned NumElems, bool IsConst, bool IsTemporary, bool IsMutable);
153 
154  /// Allocates a descriptor for an array of composites of unknown size.
155  Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD,
156  bool IsTemporary, UnknownSize);
157 
158  /// Allocates a descriptor for a record.
159  Descriptor(const DeclTy &D, const Record *R, MetadataSize MD, bool IsConst,
160  bool IsTemporary, bool IsMutable);
161 
162  /// Allocates a dummy descriptor.
163  Descriptor(const DeclTy &D);
164 
165  /// Make this descriptor a dummy descriptor.
166  void makeDummy() { IsDummy = true; }
167 
168  QualType getType() const;
169  QualType getElemQualType() const;
170  SourceLocation getLocation() const;
171 
172  const Decl *asDecl() const { return Source.dyn_cast<const Decl *>(); }
173  const Expr *asExpr() const { return Source.dyn_cast<const Expr *>(); }
174  const DeclTy &getSource() const { return Source; }
175 
176  const ValueDecl *asValueDecl() const {
177  return dyn_cast_if_present<ValueDecl>(asDecl());
178  }
179 
180  const VarDecl *asVarDecl() const {
181  return dyn_cast_if_present<VarDecl>(asDecl());
182  }
183 
184  const FieldDecl *asFieldDecl() const {
185  return dyn_cast_if_present<FieldDecl>(asDecl());
186  }
187 
188  const RecordDecl *asRecordDecl() const {
189  return dyn_cast_if_present<RecordDecl>(asDecl());
190  }
191 
192  /// Returns the size of the object without metadata.
193  unsigned getSize() const {
194  assert(!isUnknownSizeArray() && "Array of unknown size");
195  return Size;
196  }
197 
199  assert(isPrimitiveArray() || isPrimitive());
200  return *PrimT;
201  }
202 
203  /// Returns the allocated size, including metadata.
204  unsigned getAllocSize() const { return AllocSize; }
205  /// returns the size of an element when the structure is viewed as an array.
206  unsigned getElemSize() const { return ElemSize; }
207  /// Returns the size of the metadata.
208  unsigned getMetadataSize() const { return MDSize; }
209 
210  /// Returns the number of elements stored in the block.
211  unsigned getNumElems() const {
212  return Size == UnknownSizeMark ? 0 : (getSize() / getElemSize());
213  }
214 
215  /// Checks if the descriptor is of an array of primitives.
216  bool isPrimitiveArray() const { return IsArray && !ElemDesc; }
217  /// Checks if the descriptor is of an array of composites.
218  bool isCompositeArray() const { return IsArray && ElemDesc; }
219  /// Checks if the descriptor is of an array of zero size.
220  bool isZeroSizeArray() const { return Size == 0; }
221  /// Checks if the descriptor is of an array of unknown size.
222  bool isUnknownSizeArray() const { return Size == UnknownSizeMark; }
223 
224  /// Checks if the descriptor is of a primitive.
225  bool isPrimitive() const { return !IsArray && !ElemRecord; }
226 
227  /// Checks if the descriptor is of an array.
228  bool isArray() const { return IsArray; }
229  /// Checks if the descriptor is of a record.
230  bool isRecord() const { return !IsArray && ElemRecord; }
231  /// Checks if this is a dummy descriptor.
232  bool isDummy() const { return IsDummy; }
233 
234  void dump() const;
235  void dump(llvm::raw_ostream &OS) const;
236 };
237 
238 /// Bitfield tracking the initialisation status of elements of primitive arrays.
239 struct InitMap final {
240 private:
241  /// Type packing bits.
242  using T = uint64_t;
243  /// Bits stored in a single field.
244  static constexpr uint64_t PER_FIELD = sizeof(T) * CHAR_BIT;
245 
246 public:
247  /// Initializes the map with no fields set.
248  explicit InitMap(unsigned N);
249 
250 private:
251  friend class Pointer;
252 
253  /// Returns a pointer to storage.
254  T *data() { return Data.get(); }
255  const T *data() const { return Data.get(); }
256 
257  /// Initializes an element. Returns true when object if fully initialized.
258  bool initializeElement(unsigned I);
259 
260  /// Checks if an element was initialized.
261  bool isElementInitialized(unsigned I) const;
262 
263  static constexpr size_t numFields(unsigned N) {
264  return (N + PER_FIELD - 1) / PER_FIELD;
265  }
266  /// Number of fields not initialized.
267  unsigned UninitFields;
268  std::unique_ptr<T[]> Data;
269 };
270 
271 } // namespace interp
272 } // namespace clang
273 
274 #endif
const CFGBlock * Block
Definition: HTMLLogger.cpp:153
llvm::MachO::Record Record
Definition: MachO.h:31
const char * Data
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
This represents one expression.
Definition: Expr.h:110
Represents a member of a struct/union/class.
Definition: Decl.h:3060
A (possibly-)qualified type.
Definition: Type.h:940
Represents a struct/union/class.
Definition: Decl.h:4171
Encodes a location in the source.
The base class of the type hierarchy.
Definition: Type.h:1813
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:707
Represents a variable declaration or definition.
Definition: Decl.h:919
A memory block, either on the stack or in the heap.
Definition: InterpBlock.h:49
A pointer to a memory block, live or dead.
Definition: Pointer.h:80
Structure/Class descriptor.
Definition: Record.h:25
#define CHAR_BIT
Definition: limits.h:71
std::optional< std::pair< bool, std::shared_ptr< InitMap > >> InitMapPtr
Definition: Descriptor.h:28
void(*)(Block *Storage, std::byte *FieldPtr, const Descriptor *FieldDesc) BlockDtorFn
Invoked when a block is destroyed.
Definition: Descriptor.h:40
unsigned llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Definition: Descriptor.h:27
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:32
void(*)(Block *Storage, const std::byte *SrcFieldPtr, std::byte *DstFieldPtr, const Descriptor *FieldDesc) BlockMoveFn
Invoked when a block with pointers referencing it goes out of scope.
Definition: Descriptor.h:48
void(*)(Block *Storage, std::byte *FieldPtr, bool IsConst, bool IsMutable, bool IsActive, const Descriptor *FieldDesc) BlockCtorFn
Invoked whenever a block is created.
Definition: Descriptor.h:35
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
unsigned long uint64_t
#define false
Definition: stdbool.h:26
Token to denote structures of unknown size.
Definition: Descriptor.h:109
Describes a memory block created by an allocation site.
Definition: Descriptor.h:91
const bool IsConst
Flag indicating if the block is mutable.
Definition: Descriptor.h:123
unsigned getAllocSize() const
Returns the allocated size, including metadata.
Definition: Descriptor.h:204
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition: Descriptor.h:211
unsigned getSize() const
Returns the size of the object without metadata.
Definition: Descriptor.h:193
void makeDummy()
Make this descriptor a dummy descriptor.
Definition: Descriptor.h:166
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition: Descriptor.h:225
QualType getElemQualType() const
Definition: Descriptor.cpp:359
const BlockMoveFn MoveFn
Definition: Descriptor.h:136
const Expr * asExpr() const
Definition: Descriptor.h:173
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
Definition: Descriptor.h:218
const BlockDtorFn DtorFn
Definition: Descriptor.h:135
const ValueDecl * asValueDecl() const
Definition: Descriptor.h:176
const BlockCtorFn CtorFn
Storage management methods.
Definition: Descriptor.h:134
const Decl * asDecl() const
Definition: Descriptor.h:172
QualType getType() const
Definition: Descriptor.cpp:349
const FieldDecl * asFieldDecl() const
Definition: Descriptor.h:184
const Descriptor *const ElemDesc
Descriptor of the array element.
Definition: Descriptor.h:117
bool isDummy() const
Checks if this is a dummy descriptor.
Definition: Descriptor.h:232
unsigned getMetadataSize() const
Returns the size of the metadata.
Definition: Descriptor.h:208
SourceLocation getLocation() const
Definition: Descriptor.cpp:365
const bool IsMutable
Flag indicating if a field is mutable.
Definition: Descriptor.h:125
static constexpr MetadataSize InlineDescMD
Definition: Descriptor.h:112
const RecordDecl * asRecordDecl() const
Definition: Descriptor.h:188
std::optional< unsigned > MetadataSize
Definition: Descriptor.h:111
bool isUnknownSizeArray() const
Checks if the descriptor is of an array of unknown size.
Definition: Descriptor.h:222
bool IsDummy
Flag indicating if this is a dummy descriptor.
Definition: Descriptor.h:131
unsigned getElemSize() const
returns the size of an element when the structure is viewed as an array.
Definition: Descriptor.h:206
const bool IsArray
Flag indicating if the block is an array.
Definition: Descriptor.h:129
const DeclTy & getSource() const
Definition: Descriptor.h:174
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition: Descriptor.h:216
Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable)
Allocates a descriptor for a primitive.
Definition: Descriptor.cpp:270
bool isZeroSizeArray() const
Checks if the descriptor is of an array of zero size.
Definition: Descriptor.h:220
PrimType getPrimType() const
Definition: Descriptor.h:198
bool isRecord() const
Checks if the descriptor is of a record.
Definition: Descriptor.h:230
const bool IsTemporary
Flag indicating if the block is a temporary.
Definition: Descriptor.h:127
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition: Descriptor.h:115
const std::optional< PrimType > PrimT
The primitive type this descriptor was created for, or the primitive element type in case this is a p...
Definition: Descriptor.h:121
const VarDecl * asVarDecl() const
Definition: Descriptor.h:180
bool isArray() const
Checks if the descriptor is of an array.
Definition: Descriptor.h:228
Bitfield tracking the initialisation status of elements of primitive arrays.
Definition: Descriptor.h:239
InitMap(unsigned N)
Initializes the map with no fields set.
Definition: Descriptor.cpp:373
Inline descriptor embedded in structures and arrays.
Definition: Descriptor.h:56
unsigned IsActive
Flag indicating if the field is the active member of a union.
Definition: Descriptor.h:75
unsigned IsBase
Flag indicating if the field is an embedded base class.
Definition: Descriptor.h:72
const Descriptor * Desc
Definition: Descriptor.h:80
unsigned Offset
Offset inside the structure/array.
Definition: Descriptor.h:58
unsigned IsInitialized
For primitive fields, it indicates if the field was initialized.
Definition: Descriptor.h:69
unsigned IsConst
Flag indicating if the storage is constant or not.
Definition: Descriptor.h:63
unsigned IsFieldMutable
Flag indicating if the field is mutable (if in a record).
Definition: Descriptor.h:78