[lldb][test] Skip runlocker test on AArch64 Linux
[llvm-project.git] / flang / docs / RuntimeDescriptor.md
blobe6ce825b044022c95077a5aae8d81b99cb537de8
1 <!--===- docs/RuntimeDescriptor.md 
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 -->
9 # Runtime Descriptors
11 ```{contents}
12 ---
13 local:
14 ---
15 ```
17 ## Concept
18 The properties that characterize data values and objects in Fortran
19 programs must sometimes be materialized when the program runs.
21 Some properties are known during compilation and constant during
22 execution, yet must be reified anyway for execution in order to
23 drive the interfaces of a language support library or the mandated
24 interfaces of interoperable (i.e., C) procedure calls.
26 Note that many Fortran intrinsic subprograms have interfaces
27 that are more flexible and generic than actual Fortran subprograms
28 can be, so properties that must be known during compilation and
29 are constant during execution may still need to be materialized
30 for calls to the library, even if only by modifying names to
31 distinguish types or their kind specializations.
33 Other properties are deferred to execution, and need to be represented
34 to serve the needs of compiled code and the run time support library.
36 Previous implementations of Fortran have typically defined a small
37 sheaf of _descriptor_ data structures for this purpose, and attached
38 these descriptors as additional hidden arguments, type components,
39 and local variables so as to convey dynamic characteristics between
40 subprograms and between user code and the run-time support library.
42 ### References
43 References are to the 12-2017 draft of the Fortran 2018 standard
44 (N2146).
46 Section 15.4.2.2 can be interpreted as a decent list of things that
47 might need descriptors or other hidden state passed across a
48 subprogram call, since such features (apart from assumed-length
49 `CHARACTER` function results) trigger a requirement for the
50 subprogram to have an explicit interface visible to their callers.
52 Section 15.5.2 has good laundry lists of situations that can arise
53 across subprogram call boundaries.
55 ## A survey of dynamic characteristics
57 ### Length of assumed-length `CHARACTER` function results (B.3.6)
58 ```
59 CHARACTER*8 :: FOO
60 PRINT *, FOO('abcdefghijklmnopqrstuvwxyz')
61 ...
62 CHARACTER*(*) FUNCTION FOO(STR)
63   CHARACTER*26 STR
64   FOO=STR
65 END
66 ```
68 prints `abcdefgh` because the length parameter of the character type
69 of the result of `FOO` is passed across the call -- even in the absence
70 of an explicit interface!
72 ### Assumed length type parameters (7.2)
73 Dummy arguments and associate names for `SELECT TYPE` can have assumed length
74 type parameters, which are denoted by asterisks (not colons).
75 Their values come from actual arguments or the associated expression (resp.).
77 ### Explicit-shape arrays (8.5.8.2)
78 The expressions used for lower and upper bounds must be captured and remain
79 invariant over the scope of an array, even if they contain references to
80 variables that are later modified.
82 Explicit-shape arrays can be dummy arguments, "adjustable" local variables,
83 and components of derived type (using specification expressions in terms
84 of constants and KIND type parameters).
86 ### Leading dimensions of assumed-size arrays (8.5.8.5)
87 ```
88 SUBROUTINE BAR(A)
89   REAL A(2,3,*)
90 END
91 ```
92 The total size and final dimension's extent do not constitute dynamic
93 properties.
94 The called subprogram has no means to extract the extent of the
95 last (major) dimension, and may not depend upon it implicitly by using
96 the array in any context that demands a known shape.
98 The values of the expressions used as the bounds of the dimensions
99 that appear prior to
100 the last dimension are, however, effectively captured on entry to the
101 subprogram, and remain invariant even if the variables that appear in
102 those expressions have their values modified later.
103 This is similar to the requirements for an explicit-shape array.
105 ### Some function results
106 1. Deferred-shape
107 2. Deferred length type parameter values
108 3. Stride information for `POINTER` results
110 Note that while function result variables can have the `ALLOCATABLE`
111 attribute, the function itself and the value returned to the caller
112 do not possess the attribute.
114 ### Assumed-shape arrays
115 The extents of the dimensions of assumed-shape dummy argument arrays
116 are conveyed from those of the actual effective arguments.
117 The bounds, however, are not.  The called subprogram can define the
118 lower bound to be a value other than 1, but that is a local effect
119 only.
121 ### Deferred-shape arrays
122 The extents and bounds of `POINTER` and `ALLOCATABLE` arrays are
123 established by pointer assignments and `ALLOCATE` statements.
124 Note that dummy arguments and function results that are `POINTER`
125 or `ALLOCATABLE` can be deferred-shape, not assumed-shape -- one cannot
126 supply a lower bound expression as a local effect.
128 ### Strides
129 Some arrays can have discontiguous (or negative) strides.
130 These include assumed-shape dummy arguments and deferred-shape
131 `POINTER` variables, components, and function results.
133 Fortran disallows some conceivable cases that might otherwise
134 require implied strides, such as passing an array of an extended
135 derived type as an actual argument that corresponds to a
136 nonpolymorphic dummy array of a base type, or the similar
137 case of pointer assignment to a base of an extended derived type.
139 Other arrays, including `ALLOCATABLE`, can be assured to
140 be contiguous, and do not necessarily need to manage or
141 convey dynamic stride information.
142 `CONTIGUOUS` dummy arguments and `POINTER` arrays need not
143 record stride information either.
144 (The standard notes that a `CONTIGUOUS POINTER` occupies a
145 number of storage units that is distinct from that required
146 to hold a non-`CONTIGUOUS` pointer.)
148 Note that Fortran distinguishes the `CONTIGUOUS` attribute from
149 the concept of being known or required to be _simply contiguous_ (9.5.4),
150 which includes `CONTIGUOUS` entities as well as many others, and
151 the concept of actually _being_ contiguous (8.5.7) during execution.
152 I believe that the property of being simply contiguous implies
153 that an entity is known at compilation time to not require the
154 use or maintenance of hidden stride values.
156 ### Derived type component initializers
157 Fortran allows components of derived types to be declared with
158 initial values that are to be assigned to the components when an
159 instance of the derived type is created.
160 These include `ALLOCATABLE` components, which are always initialized
161 to a deallocated state.
163 These can be implemented with constructor subroutines, inline
164 stores or block copies from static initializer blocks, or a sequence
165 of sparse offset/size/value component initializers to be emplaced
166 by the run-time library.
168 N.B. Fortran allows kind type parameters to appear in component
169 initialization constant expressions, but not length type parameters,
170 so the initialization values are constants.
172 N.B. Initialization is not assignment, and cannot be implemented
173 with assignments to uninitialized derived type instances from
174 static constant initializers.
176 ### Polymorphic `CLASS()`, `CLASS(*)`, and `TYPE(*)`
177 Type identification for `SELECT TYPE`.
178 Default initializers (see above).
179 Offset locations of `ALLOCATABLE` and polymorphic components.
180 Presence of `FINAL` procedures.
181 Mappings to overridable type-bound specific procedures.
183 ### Deferred length type parameters
184 Derived types with length type parameters, and `CHARACTER`, may be used
185 with the values of those parameters deferred to execution.
186 Their actual values must be maintained as characteristics of the dynamic
187 type that is associated with a value or object
189 A single copy of the deferred length type parameters suffices for
190 all of the elements of an array of that parameterized derived type.
192 ### Components whose types and/or shape depends on length type parameters
193 Non-pointer, non-allocatable components whose types or shapes are expressed
194 in terms of length type parameters will probably have to be implemented as
195 if they had deferred type and/or shape and were `ALLOCATABLE`.
196 The derived type instance constructor must allocate them and possibly
197 initialize them; the instance destructor must deallocate them.
199 ### Assumed rank arrays
200 Rank is almost always known at compilation time and would be redundant
201 in most circumstances if also managed dynamically.
202 `DIMENSION(..)` dummy arguments (8.5.8.7), however, are a recent feature
203 with which the rank of a whole array is dynamic outside the cases of
204 a `SELECT RANK` construct.
206 The lower bounds of the dimensions of assumed rank arrays
207 are always 1.
209 ### Cached invariant subexpressions for addressing
210 Implementations of Fortran have often maintained precalculated integer
211 values to accelerate subscript computations.
212 For example, given `REAL*8 :: A(2:4,3:5)`, the data reference `A(I,J)`
213 resolves to something like `&A + 8*((I-2)+3*(J-3))`, and this can be
214 effectively reassociated to `&A - 88 + 8*I + 24*J`
215 or `&A - 88 + 8*(I + 3*J)`.
216 When the offset term and coefficients are not compile-time constants,
217 they are at least invariant and can be precomputed.
219 In the cases of dummy argument arrays, `POINTER`, and `ALLOCATABLE`,
220 these addressing invariants could be managed alongside other dynamic
221 information like deferred extents and lower bounds to avoid their
222 recalculation.
223 It's not clear that it's worth the trouble to do so, since the
224 expressions are invariant and cheap.
226 ### Coarray state (8.5.6)
227 A _coarray_ is an `ALLOCATABLE` variable or component, or statically
228 allocated variable (`SAVE` attribute explicit or implied), or dummy
229 argument whose ultimate effective argument is one of such things.
231 Each image in a team maintains its portion of each coarray and can
232 access those portions of the coarray that are maintained by other images
233 in the team.
234 Allocations and deallocations are synchronization events at which
235 the several images can exchange whatever information is needed by
236 the underlying intercommunication interface to access the data
237 of their peers.
238 (Strictly speaking, an implementation could synchronize
239 images at allocations and deallocations with simple barriers, and defer
240 the communication of remote access information until it is needed for a
241 given coarray on a given image, so long as it could be acquired in a
242 "one-sided" fashion.)
244 ### Presence of `OPTIONAL` dummy arguments
245 Typically indicated with null argument addresses.
246 Note that `POINTER` and `ALLOCATABLE` objects can be passed to
247 non-`POINTER` non-`ALLOCATABLE` dummy arguments, and their
248 association or allocation status (resp.) determines the presence
249 of the dummy argument.
251 ### Stronger contiguity enforcement or indication
252 Some implementations of Fortran guarantee that dummy argument arrays
253 are, or have been made to be, contiguous on one or more dimensions
254 when the language does not require them to be so (8.5.7 p2).
255 Others pass a flag to identify contiguous arrays (or could pass the
256 number of contiguous leading dimensions, although I know of no such
257 implementation) so that optimizing transformations that depend on
258 contiguity can be made conditional with multiple-version code generation
259 and selected during execution.
261 In the absence of a contiguity guarantee or flag, the called side
262 would have to determine contiguity dynamically, if it cares,
263 by calculating addresses of elements in the array whose subscripts
264 differ by exactly 1 on exactly 1 dimension of interest, and checking
265 whether that difference exactly matches the byte size of the type times
266 the product of the extents of any prior dimensions.
268 ### Host instances for dummy procedures and procedure pointers
269 A static link or other means of accessing the imported state of the
270 host procedure must be available when an internal procedure is
271 used as an actual argument or as a pointer assignment target.
273 ### Alternate returns
274 Subroutines (only) with alternate return arguments need a
275 means, such as the otherwise unused function return value, by which
276 to distinguish and identify the use of an alternate `RETURN` statement.
277 The protocol can be a simple nonzero integer that drives a switch
278 in the caller, or the caller can pass multiple return addresses as
279 arguments for the callee to substitute on the stack for the original
280 return address in the event of an alternate `RETURN`.
282 ## Implementation options
284 ### A note on array descriptions
285 Some arrays require dynamic management of distinct combinations of
286 values per dimension.
288 One can extract the extent on a dimension from its bounds, or extract
289 the upper bound from the extent and the lower bound.  Having distinct
290 extent and upper bound would be redundant.
292 Contiguous arrays can assume a stride of 1 on each dimension.
294 Assumed-shape and assumed-size dummy argument arrays need not convey
295 lower bounds.
297 So there are examples of dimensions with
298  * extent only (== upper bound): `CONTIGUOUS` assumed-shape, explict shape and multidimensional assumed-size with constant lower bound
299  * lower bound and either extent or upper bound: `ALLOCATABLE`, `CONTIGUOUS` `POINTER`, general explicit-shape and multidimensional assumed-size
300  * extent (== upper bound) and stride: general (non-`CONTIGUOUS`) assumed-shape
301  * lower bound, stride, and either extent or upper bound: general (non-`CONTIGUOUS`) `POINTER`, assumed-rank
303 and these cases could be accompanied by precomputed invariant
304 addressing subexpressions to accelerate indexing calculations.
306 ### Interoperability requirements
308 Fortran 2018 requires that a Fortran implementation supply a header file
309 `ISO_Fortran_binding.h` for use in C and C++ programs that defines and
310 implements an interface to Fortran objects from the _interoperable_
311 subset of Fortran objects and their types suitable for use when those
312 objects are passed to C functions.
313 This interface mandates a fat descriptor that is passed by address,
314 containing (at least)
315  * a data base address
316  * explicit rank and type
317  * flags to distinguish `POINTER` and `ALLOCATABLE`
318  * elemental byte size, and
319  * (per-dimension) lower bound, extent, and byte stride
321 The requirements on the interoperability API do not mandate any
322 support for features like derived type component initialization,
323 automatic deallocation of `ALLOCATABLE` components, finalization,
324 derived type parameters, data contiguity flags, &c.
325 But neither does the Standard preclude inclusion of additional
326 interfaces to describe and support such things.
328 Given a desire to fully support the Fortran 2018 language, we need
329 to either support the interoperability requirements as a distinct
330 specialization of the procedure call protocol, or use the
331 `ISO_Fortran_binding.h` header file requirements as a subset basis for a
332 complete implementation that adds representations for all the
333 missing capabilities, which would be isolated and named so as
334 to prevent user C code from relying upon them.
336 ### Design space
337 There is a range of possible options for representing the
338 properties of values and objects during the execution of Fortran
339 programs.
341 At one extreme, the amount of dynamic information is minimized,
342 and is packaged in custom data structures or additional arguments
343 for each situation to convey only the values that are unknown at
344 compilation time and actually needed at execution time.
346 At the other extreme, data values and objects are described completely,
347 including even the values of properties are known at compilation time.
348 This is not as silly as it sounds -- e.g., Fortran array descriptors
349 have historically materialized the number of dimensions they cover, even
350 though rank will be (nearly) always be a known constant during compilation.
352 When data are packaged, their containers can be self-describing to
353 some degree.
354 Description records can have tag values or strings.
355 Their fields can have presence flags or identifying tags, and fields
356 need not have fixed offsets or ordering.
357 This flexibility can increase binary compatibility across revisions
358 of the run-time support library, and is convenient for debugging
359 that library.
360 However, it is not free.
362 Further, the requirements of the representation of dynamic
363 properties of values and objects depend on the execution model:
364 specifically, are the complicated semantics of intrinsic assignment,
365 deallocation, and finalization of allocatables implemented entirely
366 in the support library, in generated code for non-recursive cases,
367 or by means of a combination of the two approaches?
369 Consider how to implement the following:
371 TYPE :: LIST
372   REAL :: HEAD
373   TYPE(LIST), ALLOCATABLE :: REST
374 END TYPE LIST
375 TYPE(LIST), ALLOCATABLE :: A, B
377 A = B
380 Fortran requires that `A`'s arbitrary-length linked list be deleted and
381 replaced with a "deep copy" of `B`'s.
382 So either a complicated pair of loops must be generated by the compiler,
383 or a sophisticated run time support library needs to be driven with
384 an expressive representation of type information.
386 ## Proposal
387 We need to write `ISO_Fortran_binding.h` in any event.
388 It is a header that is published for use in user C code for interoperation
389 with compiled Fortran and the Fortran run time support library.
391 There is a sole descriptor structure defined in `ISO_Fortran_binding.h`.
392 It is suitable for characterizing scalars and array sections of intrinsic
393 types.
394 It is essentially a "fat" data pointer that encapsulates a raw data pointer,
395 a type code, rank, elemental byte size, and per-dimension bounds and stride.
397 Please note that the mandated interoperable descriptor includes the data
398 pointer.
399 This design in the Standard precludes the use of static descriptors that
400 could be associated with dynamic base addresses.
402 The F18 runtime cannot use just the mandated interoperable
403 `struct CFI_cdesc_t` argument descriptor structure as its
404 all-purpose data descriptor.
405 It has no information about derived type components, overridable
406 type-bound procedure bindings, type parameters, &c.
408 However, we could extend the standard interoperable argument descriptor.
409 The `struct CFI_cdesc_t` structure is not of fixed size, but we
410 can efficiently locate the first address after an instance of the
411 standard descriptor and attach our own data record there to
412 hold what we need.
413 There's at least one unused padding byte in the standard argument
414 descriptor that can be used to hold a flag indicating the presence
415 of the addenda.
417 The definitions of our additional run time data structures must
418 appear in a header file that is distinct from `ISO_Fortran_binding.h`,
419 and they should never be used by user applications.
421 This expanded descriptor structure can serve, at least initially for
422 simplicity, as the sole representation of `POINTER` variables and
423 components, `ALLOCATABLE` variables and components, and derived type
424 instances, including length parameter values.
426 An immediate concern with this concept is the amount of space and
427 initialization time that would be wasted when derived type components
428 needing a descriptor would have to be accompanied by an instance
429 of the general descriptor.
430 (In the linked list example close above, what could be done with a
431 single pointer for the `REST` component would become at least
432 a four-word dynamic structure.)
433 This concern is amplified when derived type instances
434 are allocated as arrays, since the overhead is per-element.
436 We can reduce this wastage in two ways.
437 First, when the content of the component's descriptor is constant
438 at compilation apart from its base address, a static descriptor
439 can be placed in read-only storage and attached to the description
440 of the derived type's components.
441 Second, we could eventually optimize the storage requirements by
442 omitting all static fields from the dynamic descriptor, and
443 expand the compressed dynamic descriptor during execution when
444 needed.