1e5dd7070Spatrick====================
2e5dd7070SpatrickConstant Interpreter
3e5dd7070Spatrick====================
4e5dd7070Spatrick
5e5dd7070Spatrick.. contents::
6e5dd7070Spatrick   :local:
7e5dd7070Spatrick
8e5dd7070SpatrickIntroduction
9e5dd7070Spatrick============
10e5dd7070Spatrick
11*ec727ea7SpatrickThe constexpr interpreter aims to replace the existing tree evaluator in
12*ec727ea7Spatrickclang, improving performance on constructs which are executed inefficiently
13*ec727ea7Spatrickby the evaluator. The interpreter is activated using the following flags:
14e5dd7070Spatrick
15*ec727ea7Spatrick* ``-fexperimental-new-constant-interpreter`` enables the interpreter,
16*ec727ea7Spatrick  emitting an error if an unsupported feature is encountered
17e5dd7070Spatrick
18e5dd7070SpatrickBytecode Compilation
19e5dd7070Spatrick====================
20e5dd7070Spatrick
21*ec727ea7SpatrickBytecode compilation is handled in ``ByteCodeStmtGen.h`` for statements
22*ec727ea7Spatrickand ``ByteCodeExprGen.h`` for expressions. The compiler has two different
23*ec727ea7Spatrickbackends: one to generate bytecode for functions (``ByteCodeEmitter``) and
24*ec727ea7Spatrickone to directly evaluate expressions as they are compiled, without
25*ec727ea7Spatrickgenerating bytecode (``EvalEmitter``). All functions are compiled to
26*ec727ea7Spatrickbytecode, while toplevel expressions used in constant contexts are directly
27*ec727ea7Spatrickevaluated since the bytecode would never be reused. This mechanism aims to
28*ec727ea7Spatrickpave the way towards replacing the evaluator, improving its performance on
29*ec727ea7Spatrickfunctions and loops, while being just as fast on single-use toplevel
30*ec727ea7Spatrickexpressions.
31e5dd7070Spatrick
32*ec727ea7SpatrickThe interpreter relies on stack-based, strongly-typed opcodes. The glue
33*ec727ea7Spatricklogic between the code generator, along with the enumeration and
34*ec727ea7Spatrickdescription of opcodes, can be found in ``Opcodes.td``. The opcodes are
35*ec727ea7Spatrickimplemented as generic template methods in ``Interp.h`` and instantiated
36*ec727ea7Spatrickwith the relevant primitive types by the interpreter loop or by the
37*ec727ea7Spatrickevaluating emitter.
38e5dd7070Spatrick
39e5dd7070SpatrickPrimitive Types
40e5dd7070Spatrick---------------
41e5dd7070Spatrick
42e5dd7070Spatrick* ``PT_{U|S}int{8|16|32|64}``
43e5dd7070Spatrick
44*ec727ea7Spatrick  Signed or unsigned integers of a specific bit width, implemented using
45*ec727ea7Spatrick  the ```Integral``` type.
46e5dd7070Spatrick
47e5dd7070Spatrick* ``PT_{U|S}intFP``
48e5dd7070Spatrick
49*ec727ea7Spatrick  Signed or unsigned integers of an arbitrary, but fixed width used to
50*ec727ea7Spatrick  implement integral types which are required by the target, but are not
51*ec727ea7Spatrick  supported by the host. Under the hood, they rely on APValue. The
52*ec727ea7Spatrick  ``Integral`` specialisation for these types is required by opcodes to
53*ec727ea7Spatrick  share an implementation with fixed integrals.
54e5dd7070Spatrick
55e5dd7070Spatrick* ``PT_Bool``
56e5dd7070Spatrick
57*ec727ea7Spatrick  Representation for boolean types, essentially a 1-bit unsigned
58*ec727ea7Spatrick  ``Integral``.
59e5dd7070Spatrick
60e5dd7070Spatrick* ``PT_RealFP``
61e5dd7070Spatrick
62*ec727ea7Spatrick  Arbitrary, but fixed precision floating point numbers. Could be
63*ec727ea7Spatrick  specialised in the future similarly to integers in order to improve
64*ec727ea7Spatrick  floating point performance.
65e5dd7070Spatrick
66e5dd7070Spatrick* ``PT_Ptr``
67e5dd7070Spatrick
68*ec727ea7Spatrick  Pointer type, defined in ``"Pointer.h"``. A pointer can be either null,
69*ec727ea7Spatrick  reference interpreter-allocated memory (``BlockPointer``) or point to an
70*ec727ea7Spatrick  address which can be derived, but not accessed (``ExternPointer``).
71e5dd7070Spatrick
72e5dd7070Spatrick* ``PT_FnPtr``
73e5dd7070Spatrick
74*ec727ea7Spatrick  Function pointer type, can also be a null function pointer. Defined
75*ec727ea7Spatrick  in ``"FnPointer.h"``.
76e5dd7070Spatrick
77e5dd7070Spatrick* ``PT_MemPtr``
78e5dd7070Spatrick
79*ec727ea7Spatrick  Member pointer type, can also be a null member pointer. Defined
80*ec727ea7Spatrick  in ``"MemberPointer.h"``
81*ec727ea7Spatrick
82*ec727ea7Spatrick* ``PT_VoidPtr``
83*ec727ea7Spatrick
84*ec727ea7Spatrick  Void pointer type, can be used for rount-trip casts. Represented as
85*ec727ea7Spatrick  the union of all pointers which can be cast to void.
86*ec727ea7Spatrick  Defined in ``"VoidPointer.h"``.
87*ec727ea7Spatrick
88*ec727ea7Spatrick* ``PT_ObjCBlockPtr``
89*ec727ea7Spatrick
90*ec727ea7Spatrick  Pointer type for ObjC blocks. Defined in ``"ObjCBlockPointer.h"``.
91e5dd7070Spatrick
92e5dd7070SpatrickComposite types
93e5dd7070Spatrick---------------
94e5dd7070Spatrick
95*ec727ea7SpatrickThe interpreter distinguishes two kinds of composite types: arrays and
96*ec727ea7Spatrickrecords (structs and classes). Unions are represented as records, except
97*ec727ea7Spatrickat most a single field can be marked as active. The contents of inactive
98*ec727ea7Spatrickfields are kept until they are reactivated and overwritten.
99*ec727ea7SpatrickComplex numbers (``_Complex``) and vectors
100*ec727ea7Spatrick(``__attribute((vector_size(16)))``) are treated as arrays.
101e5dd7070Spatrick
102e5dd7070Spatrick
103e5dd7070SpatrickBytecode Execution
104e5dd7070Spatrick==================
105e5dd7070Spatrick
106*ec727ea7SpatrickBytecode is executed using a stack-based interpreter. The execution
107*ec727ea7Spatrickcontext consists of an ``InterpStack``, along with a chain of
108*ec727ea7Spatrick``InterpFrame`` objects storing the call frames. Frames are built by
109*ec727ea7Spatrickcall instructions and destroyed by return instructions. They perform
110*ec727ea7Spatrickone allocation to reserve space for all locals in a single block.
111*ec727ea7SpatrickThese objects store all the required information to emit stack traces
112*ec727ea7Spatrickwhenever evaluation fails.
113e5dd7070Spatrick
114e5dd7070SpatrickMemory Organisation
115e5dd7070Spatrick===================
116e5dd7070Spatrick
117e5dd7070SpatrickMemory management in the interpreter relies on 3 data structures: ``Block``
118*ec727ea7Spatrickobjects which store the data and associated inline metadata, ``Pointer``
119*ec727ea7Spatrickobjects which refer to or into blocks, and ``Descriptor`` structures which
120*ec727ea7Spatrickdescribe blocks and subobjects nested inside blocks.
121e5dd7070Spatrick
122e5dd7070SpatrickBlocks
123e5dd7070Spatrick------
124e5dd7070Spatrick
125*ec727ea7SpatrickBlocks contain data interleaved with metadata. They are allocated either
126*ec727ea7Spatrickstatically in the code generator (globals, static members, dummy parameter
127*ec727ea7Spatrickvalues etc.) or dynamically in the interpreter, when creating the frame
128*ec727ea7Spatrickcontaining the local variables of a function. Blocks are associated with a
129*ec727ea7Spatrickdescriptor that characterises the entire allocation, along with a few
130*ec727ea7Spatrickadditional attributes:
131e5dd7070Spatrick
132*ec727ea7Spatrick* ``IsStatic`` indicates whether the block has static duration in the
133*ec727ea7Spatrick  interpreter, i.e. it is not a local in a frame.
134e5dd7070Spatrick
135*ec727ea7Spatrick* ``DeclID`` identifies each global declaration (it is set to an invalid
136*ec727ea7Spatrick  and irrelevant value for locals) in order to prevent illegal writes and
137*ec727ea7Spatrick  reads involving globals and temporaries with static storage duration.
138e5dd7070Spatrick
139*ec727ea7SpatrickStatic blocks are never deallocated, but local ones might be deallocated
140*ec727ea7Spatrickeven when there are live pointers to them. Pointers are only valid as
141*ec727ea7Spatricklong as the blocks they point to are valid, so a block with pointers to
142*ec727ea7Spatrickit whose lifetime ends is kept alive until all pointers to it go out of
143*ec727ea7Spatrickscope. Since the frame is destroyed on function exit, such blocks are
144*ec727ea7Spatrickturned into a ``DeadBlock`` and copied to storage managed by the
145*ec727ea7Spatrickinterpreter itself, not the frame. Reads and writes to these blocks are
146*ec727ea7Spatrickillegal and cause an appropriate diagnostic to be emitted. When the last
147*ec727ea7Spatrickpointer goes out of scope, dead blocks are also deallocated.
148e5dd7070Spatrick
149*ec727ea7SpatrickThe lifetime of blocks is managed through 3 methods stored in the
150*ec727ea7Spatrickdescriptor of the block:
151e5dd7070Spatrick
152*ec727ea7Spatrick* **CtorFn**: initializes the metadata which is store in the block,
153*ec727ea7Spatrick  alongside actual data. Invokes the default constructors of objects
154*ec727ea7Spatrick  which are not trivial (``Pointer``, ``RealFP``, etc.)
155e5dd7070Spatrick
156e5dd7070Spatrick* **DtorFn**: invokes the destructors of non-trivial objects.
157*ec727ea7Spatrick
158e5dd7070Spatrick* **MoveFn**: moves a block to dead storage.
159e5dd7070Spatrick
160*ec727ea7SpatrickNon-static blocks track all the pointers into them through an intrusive
161*ec727ea7Spatrickdoubly-linked list, required to adjust and invalidate all pointers when
162*ec727ea7Spatricktransforming a block into a dead block. If the lifetime of an object ends,
163*ec727ea7Spatrickall pointers to it are invalidated, emitting the appropriate diagnostics when
164*ec727ea7Spatrickdereferenced.
165*ec727ea7Spatrick
166*ec727ea7SpatrickThe interpreter distinguishes 3 different kinds of blocks:
167*ec727ea7Spatrick
168*ec727ea7Spatrick* **Primitives**
169*ec727ea7Spatrick
170*ec727ea7Spatrick  A block containing a single primitive with no additional metadata.
171*ec727ea7Spatrick
172*ec727ea7Spatrick* **Arrays of primitives**
173*ec727ea7Spatrick
174*ec727ea7Spatrick  An array of primitives contains a pointer to an ``InitMap`` storage as its
175*ec727ea7Spatrick  first field: the initialisation map is a bit map indicating all elements of
176*ec727ea7Spatrick  the array which were initialised. If the pointer is null, no elements were
177*ec727ea7Spatrick  initialised, while a value of ``(InitMap*)-1`` indicates that the object was
178*ec727ea7Spatrick  fully initialised. When all fields are initialised, the map is deallocated
179*ec727ea7Spatrick  and replaced with that token.
180*ec727ea7Spatrick
181*ec727ea7Spatrick  Array elements are stored sequentially, without padding, after the pointer
182*ec727ea7Spatrick  to the map.
183*ec727ea7Spatrick
184*ec727ea7Spatrick* **Arrays of composites and records**
185*ec727ea7Spatrick
186*ec727ea7Spatrick  Each element in an array of composites is preceded by an ``InlineDescriptor``
187*ec727ea7Spatrick  which stores the attributes specific to the field and not the whole
188*ec727ea7Spatrick  allocation site. Descriptors and elements are stored sequentially in the
189*ec727ea7Spatrick  block.
190*ec727ea7Spatrick  Records are laid out identically to arrays of composites: each field and base
191*ec727ea7Spatrick  class is preceded by an inline descriptor. The ``InlineDescriptor``
192*ec727ea7Spatrick  has the following fields:
193*ec727ea7Spatrick
194*ec727ea7Spatrick   * **Offset**: byte offset into the array or record, used to step back to the
195*ec727ea7Spatrick     parent array or record.
196*ec727ea7Spatrick   * **IsConst**: flag indicating if the field is const-qualified.
197*ec727ea7Spatrick   * **IsInitialized**: flag indicating whether the field or element was
198*ec727ea7Spatrick     initialized. For non-primitive fields, this is only relevant to determine
199*ec727ea7Spatrick     the dynamic type of objects during construction.
200*ec727ea7Spatrick   * **IsBase**: flag indicating whether the record is a base class. In that
201*ec727ea7Spatrick     case, the offset can be used to identify the derived class.
202*ec727ea7Spatrick   * **IsActive**: indicates if the field is the active field of a union.
203*ec727ea7Spatrick   * **IsMutable**: indicates if the field is marked as mutable.
204*ec727ea7Spatrick
205*ec727ea7SpatrickInline descriptors are filled in by the `CtorFn` of blocks, which leaves storage
206*ec727ea7Spatrickin an uninitialised, but valid state.
207e5dd7070Spatrick
208e5dd7070SpatrickDescriptors
209e5dd7070Spatrick-----------
210e5dd7070Spatrick
211*ec727ea7SpatrickDescriptors are generated at bytecode compilation time and contain information
212*ec727ea7Spatrickrequired to determine if a particular memory access is allowed in constexpr.
213*ec727ea7SpatrickThey also carry all the information required to emit a diagnostic involving
214*ec727ea7Spatricka memory access, such as the declaration which originates the block.
215*ec727ea7SpatrickCurrently there is a single kind of descriptor encoding information for all
216*ec727ea7Spatrickblock types.
217e5dd7070Spatrick
218e5dd7070SpatrickPointers
219e5dd7070Spatrick--------
220e5dd7070Spatrick
221*ec727ea7SpatrickPointers, implemented in ``Pointer.h`` are represented as a tagged union.
222*ec727ea7SpatrickSome of these may not yet be available in upstream ``clang``.
223*ec727ea7Spatrick
224*ec727ea7Spatrick * **BlockPointer**: used to reference memory allocated and managed by the
225*ec727ea7Spatrick   interpreter, being the only pointer kind which allows dereferencing in the
226*ec727ea7Spatrick   interpreter
227*ec727ea7Spatrick * **ExternPointer**: points to memory which can be addressed, but not read by
228*ec727ea7Spatrick   the interpreter. It is equivalent to APValue, tracking a declaration and a path
229*ec727ea7Spatrick   of fields and indices into that allocation.
230*ec727ea7Spatrick * **TargetPointer**: represents a target address derived from a base address
231*ec727ea7Spatrick   through pointer arithmetic, such as ``((int *)0x100)[20]``. Null pointers are
232*ec727ea7Spatrick   target pointers with a zero offset.
233*ec727ea7Spatrick * **TypeInfoPointer**: tracks information for the opaque type returned by
234*ec727ea7Spatrick   ``typeid``
235*ec727ea7Spatrick * **InvalidPointer**: is dummy pointer created by an invalid operation which
236*ec727ea7Spatrick   allows the interpreter to continue execution. Does not allow pointer
237*ec727ea7Spatrick   arithmetic or dereferencing.
238*ec727ea7Spatrick
239*ec727ea7SpatrickBesides the previously mentioned union, a number of other pointer-like types
240*ec727ea7Spatrickhave their own type:
241*ec727ea7Spatrick
242*ec727ea7Spatrick * **ObjCBlockPointer** tracks Objective-C blocks
243*ec727ea7Spatrick * **FnPointer** tracks functions and lazily caches their compiled version
244*ec727ea7Spatrick * **MemberPointer** tracks C++ object members
245*ec727ea7Spatrick
246*ec727ea7SpatrickVoid pointers, which can be built by casting any of the aforementioned
247*ec727ea7Spatrickpointers, are implemented as a union of all pointer types. The ``BitCast``
248*ec727ea7Spatrickopcode is responsible for performing all legal conversions between these
249*ec727ea7Spatricktypes and primitive integers.
250*ec727ea7Spatrick
251*ec727ea7SpatrickBlockPointer
252*ec727ea7Spatrick~~~~~~~~~~~~
253*ec727ea7Spatrick
254*ec727ea7SpatrickBlock pointers track a ``Pointee``, the block to which they point, along
255*ec727ea7Spatrickwith a ``Base`` and an ``Offset``. The base identifies the innermost field,
256*ec727ea7Spatrickwhile the offset points to an array element relative to the base (including
257*ec727ea7Spatrickone-past-end pointers). The offset identifies the array element or field
258*ec727ea7Spatrickwhich is referenced, while the base points to the outer object or array which
259*ec727ea7Spatrickcontains the field. These two fields allow all pointers to be uniquely
260*ec727ea7Spatrickidentified, disambiguated and characterised.
261e5dd7070Spatrick
262e5dd7070SpatrickAs an example, consider the following structure:
263e5dd7070Spatrick
264e5dd7070Spatrick.. code-block:: c
265e5dd7070Spatrick
266e5dd7070Spatrick    struct A {
267e5dd7070Spatrick        struct B {
268e5dd7070Spatrick            int x;
269e5dd7070Spatrick            int y;
270e5dd7070Spatrick        } b;
271e5dd7070Spatrick        struct C {
272e5dd7070Spatrick            int a;
273e5dd7070Spatrick            int b;
274e5dd7070Spatrick        } c[2];
275e5dd7070Spatrick        int z;
276e5dd7070Spatrick    };
277e5dd7070Spatrick    constexpr A a;
278e5dd7070Spatrick
279*ec727ea7SpatrickOn the target, ``&a`` and ``&a.b.x`` are equal. So are ``&a.c[0]`` and
280*ec727ea7Spatrick``&a.c[0].a``. In the interpreter, all these pointers must be
281*ec727ea7Spatrickdistinguished since the are all allowed to address distinct range of
282*ec727ea7Spatrickmemory.
283e5dd7070Spatrick
284*ec727ea7SpatrickIn the interpreter, the object would require 240 bytes of storage and
285*ec727ea7Spatrickwould have its field interleaved with metadata. The pointers which can
286*ec727ea7Spatrickbe derived to the object are illustrated in the following diagram:
287e5dd7070Spatrick
288e5dd7070Spatrick::
289e5dd7070Spatrick
290e5dd7070Spatrick      0   16  32  40  56  64  80  96  112 120 136 144 160 176 184 200 208 224 240
291e5dd7070Spatrick  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
292e5dd7070Spatrick  + B | D | D | x | D | y | D | D | D | a | D | b | D | D | a | D | b | D | z |
293e5dd7070Spatrick  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
294e5dd7070Spatrick      ^   ^   ^       ^       ^   ^   ^       ^       ^   ^       ^       ^
295e5dd7070Spatrick      |   |   |       |       |   |   |   &a.c[0].b   |   |   &a.c[1].b   |
296e5dd7070Spatrick      a   |&a.b.x   &a.y    &a.c  |&a.c[0].a          |&a.c[1].a          |
297e5dd7070Spatrick        &a.b                   &a.c[0]            &a.c[1]               &a.z
298e5dd7070Spatrick
299*ec727ea7SpatrickThe ``Base`` offset of all pointers points to the start of a field or
300*ec727ea7Spatrickan array and is preceded by an inline descriptor (unless ``Base`` is
301*ec727ea7Spatrickzero, pointing to the root). All the relevant attributes can be read
302*ec727ea7Spatrickfrom either the inline descriptor or the descriptor of the block.
303e5dd7070Spatrick
304*ec727ea7Spatrick
305*ec727ea7SpatrickArray elements are identified by the ``Offset`` field of pointers,
306*ec727ea7Spatrickpointing to past the inline descriptors for composites and before
307*ec727ea7Spatrickthe actual data in the case of primitive arrays. The ``Offset``
308*ec727ea7Spatrickpoints to the offset where primitives can be read from. As an example,
309*ec727ea7Spatrick``a.c + 1`` would have the same base as ``a.c`` since it is an element
310*ec727ea7Spatrickof ``a.c``, but its offset would point to ``&a.c[1]``. The
311*ec727ea7Spatrickarray-to-pointer decay operation adjusts a pointer to an array (where
312*ec727ea7Spatrickthe offset is equal to the base) to a pointer to the first element.
313*ec727ea7Spatrick
314*ec727ea7SpatrickExternPointer
315*ec727ea7Spatrick~~~~~~~~~~~~~
316*ec727ea7Spatrick
317*ec727ea7SpatrickExtern pointers can be derived, pointing into symbols which are not
318*ec727ea7Spatrickreadable from constexpr. An external pointer consists of a base
319*ec727ea7Spatrickdeclaration, along with a path designating a subobject, similar to
320*ec727ea7Spatrickthe ``LValuePath`` of an APValue. Extern pointers can be converted
321*ec727ea7Spatrickto block pointers if the underlying variable is defined after the
322*ec727ea7Spatrickpointer is created, as is the case in the following example:
323*ec727ea7Spatrick
324*ec727ea7Spatrick.. code-block:: c
325*ec727ea7Spatrick
326*ec727ea7Spatrick  extern const int a;
327*ec727ea7Spatrick  constexpr const int *p = &a;
328*ec727ea7Spatrick  const int a = 5;
329*ec727ea7Spatrick  static_assert(*p == 5, "x");
330*ec727ea7Spatrick
331*ec727ea7SpatrickTargetPointer
332*ec727ea7Spatrick~~~~~~~~~~~~~
333*ec727ea7Spatrick
334*ec727ea7SpatrickWhile null pointer arithmetic or integer-to-pointer conversion is
335*ec727ea7Spatrickbanned in constexpr, some expressions on target offsets must be folded,
336*ec727ea7Spatrickreplicating the behaviour of the ``offsetof`` builtin. Target pointers
337*ec727ea7Spatrickare characterised by 3 offsets: a field offset, an array offset and a
338*ec727ea7Spatrickbase offset, along with a descriptor specifying the type the pointer is
339*ec727ea7Spatricksupposed to refer to. Array indexing adjusts the array offset, while the
340*ec727ea7Spatrickfield offset is adjusted when a pointer to a member is created. Casting
341*ec727ea7Spatrickan integer to a pointer sets the value of the base offset. As a special
342*ec727ea7Spatrickcase, null pointers are target pointers with all offsets set to 0.
343*ec727ea7Spatrick
344*ec727ea7SpatrickTypeInfoPointer
345*ec727ea7Spatrick~~~~~~~~~~~~~~~
346*ec727ea7Spatrick
347*ec727ea7Spatrick``TypeInfoPointer`` tracks two types: the type assigned to
348*ec727ea7Spatrick``std::type_info`` and the type which was passed to ``typeinfo``.
349*ec727ea7Spatrick
350*ec727ea7SpatrickInvalidPointer
351*ec727ea7Spatrick~~~~~~~~~~~~~~
352*ec727ea7Spatrick
353*ec727ea7SpatrickSuch pointers are built by operations which cannot generate valid
354*ec727ea7Spatrickpointers, allowing the interpreter to continue execution after emitting
355*ec727ea7Spatricka warning. Inspecting such a pointer stops execution.
356e5dd7070Spatrick
357e5dd7070SpatrickTODO
358e5dd7070Spatrick====
359e5dd7070Spatrick
360e5dd7070SpatrickMissing Language Features
361e5dd7070Spatrick-------------------------
362e5dd7070Spatrick
363e5dd7070Spatrick* Changing the active field of unions
364e5dd7070Spatrick* ``volatile``
365e5dd7070Spatrick* ``__builtin_constant_p``
366e5dd7070Spatrick* ``dynamic_cast``
367*ec727ea7Spatrick* ``new`` and ``delete``
368*ec727ea7Spatrick* Fixed Point numbers and arithmetic on Complex numbers
369*ec727ea7Spatrick* Several builtin methods, including string operations and
370*ec727ea7Spatrick  ``__builtin_bit_cast``
371*ec727ea7Spatrick* Continue-after-failure: a form of exception handling at the bytecode
372*ec727ea7Spatrick  level should be implemented to allow execution to resume. As an example,
373*ec727ea7Spatrick  argument evaluation should resume after the computation of an argument fails.
374*ec727ea7Spatrick* Pointer-to-Integer conversions
375*ec727ea7Spatrick* Lazy descriptors: the interpreter creates a ``Record`` and ``Descriptor``
376*ec727ea7Spatrick  when it encounters a type: ones which are not yet defined should be lazily
377*ec727ea7Spatrick  created when required
378e5dd7070Spatrick
379e5dd7070SpatrickKnown Bugs
380e5dd7070Spatrick----------
381e5dd7070Spatrick
382*ec727ea7Spatrick* If execution fails, memory storing APInts and APFloats is leaked when the
383*ec727ea7Spatrick  stack is cleared
384