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