xref: /llvm-project/flang/docs/RuntimeTypeInfo.md (revision b7ff03206d668cd5a620a9d4e1b22ea112ed56e3)
1<!--===- docs/RuntimeTypeInfo.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-->
8
9# The derived type runtime information table
10
11```{contents}
12---
13local:
14---
15```
16
17## Overview
18
19Many operations on derived types must be implemented, or can be
20implemented, with calls to the runtime support library rather than
21directly with generated code.
22Some operations might be initially implemented in the runtime library
23and then reimplemented later in generated code for compelling
24performance gains in optimized compilations.
25
26The runtime library uses *derived type description* tables to represent
27the relevant characteristics of derived types.
28This note summarizes the requirements for these descriptions.
29
30The semantics phase of the F18 frontend constructs derived type
31descriptions from its scoped symbol table after name resolution
32and semantic constraint checking have succeeded.
33The lowering phase then transfers the tables to the static
34read-only data section of the generated program by translating them into
35initialized objects.
36During execution, references to the tables occur by passing their addresses
37as arguments to relevant runtime library APIs and as pointers in
38the addenda of descriptors.
39
40## Requirements
41
42The following Fortran language features require, or may require, the use of
43derived type descriptions in the runtime library.
44
45### Components
46
47The components of a derived type need to be described in component
48order (7.4.7), but when there is a parent component, its components
49can be described by reference to the description of the type of the
50parent component.
51
52The ordered component descriptions are needed to implement
53* default initialization
54* `ALLOCATE`, with and without `SOURCE=`
55* intrinsic assignment of derived types with `ALLOCATABLE` and
56  automatic components
57* intrinsic I/O of derived type instances
58* `NAMELIST` I/O of derived type instances
59* "same type" tests
60
61The characteristics of data components include their names, types,
62offsets, bounds, cobounds, derived type descriptions when appropriate,
63default component initializers, and flags for `ALLOCATABLE`, `POINTER`,
64`PRIVATE`, and automatic components (implicit allocatables).
65Procedure pointer components require only their offsets and address(es).
66
67### Calls to type-bound procedures
68
69Only extensible derived types -- those without `SEQUENCE` or `BIND(C)`
70-- are allowed to have type-bound procedures.
71Calls to these bindings will be resolved at compilation time when
72the binding is `NON_OVERRIDABLE` or when an object is not polymorphic.
73Calls to overridable bindings of polymorphic objects requires the
74use of a runtime table of procedure addresses.
75
76Each derived type (or instantiation of a parameterized derived type)
77will have a complete type-bound procedure table in which all of the
78bindings of its ancestor types appear first.
79(Specifically, the table offsets of any inherited bindings must be
80the same as they are in the table of the ancestral type's table.)
81These ancestral bindings reflect their overrides, if any.
82
83The non-inherited bindings of a type then follow the inherited
84bindings, and they do so in alphabetical order of binding name.
85(This is an arbitrary choice -- we could also define them to
86appear in binding declaration order, I suppose -- but a consistent
87ordering should be used so that relocatables generated by distinct
88versions of the F18 compiler will have a better chance to interoperate.)
89
90### Type parameter values and "same type" testing
91
92The values of the `KIND` and `LEN` parameters of a particular derived type
93instance can be obtained to implement type parameter inquiries without
94requiring derived type information tables.
95In the case of a `KIND` type parameter, it's a constant value known at
96compilation time, and in the case of a `LEN` type parameter, it's a
97member of the addendum to the object's descriptor.
98
99The runtime library will have an API (TBD) to be called as
100part of the implementation of `TYPE IS` and `CLASS IS` guards
101of the `SELECT TYPE` construct.
102This language support predicate returns a true result when
103an object's type matches a particular type specification and
104`KIND` (but not `LEN`) type parameter values.
105
106Note that this "is same type as" predicate is *not* the same as
107the one to be called to implement the `SAME_TYPE_AS()` intrinsic function,
108which is specified so as to *ignore* the values of `KIND` type
109parameters.
110
111Subclause 7.5.2 defines what being the "same" derived type means
112in Fortran.
113In short, each definition of a derived type defines a distinct type,
114so type equality testing can usually compare addresses of derived
115type descriptions at runtime.
116The exceptions are `SEQUENCE` types and interoperable (`BIND(C)`)
117types.
118Independent definitions of each of these are considered to be the "same type"
119when these definitions match in terms of names, types, and attributes,
120both being either `SEQUENCE` or `BIND(C)`, and containing
121no `PRIVATE` components.
122These "sequence" derived types cannot have type parameters, type-bound
123procedures, an absence of components, or components that are not themselves
124of a sequence type, so we can use a static hash code to implement
125their "same type" tests.
126
127### FINAL subroutines
128
129When an instance of a derived type is deallocated or goes out of scope,
130one of its `FINAL` subroutines may be called.
131Subclause 7.5.6.3 defines when finalization occurs -- it doesn't happen
132in all situations.
133
134The subroutines named in a derived type's `FINAL` statements are not
135bindings, so their arguments are not passed object dummy arguments and
136do not have to satisfy the constraints of a passed object.
137Specifically, they can be arrays, and cannot be polymorphic.
138If a `FINAL` subroutine's dummy argument is an array, it may be
139assumed-shape or assumed-rank, but it could also be an explicit-shape
140or assumed-size argument.
141This means that it may or may not be passed by means of a descriptor.
142
143Note that a `FINAL` subroutine with a scalar argument does not define
144a finalizer for array objects unless the subroutine is elemental
145(and probably `IMPURE`).
146This seems to be a language pitfall and F18 will emit a
147warning when an array of a finalizable derived type is declared
148with a rank lacking a `FINAL` subroutine when other ranks do have one.
149
150So the necessary information in the derived type table for a `FINAL`
151subroutine comprises:
152* address(es) of the subroutine
153* rank of the argument, or whether it is assumed-rank
154* for rank 0, whether the subroutine is elemental
155* for rank > 0, whether the argument requires a descriptor
156
157This descriptor flag is needed to handle a difficult case with
158`FINAL` subroutines that most other implementations of Fortran
159fail to get right: a `FINAL` subroutine
160whose argument is a an explicit shape or assumed size array may
161have to be called upon the parent component of an array of
162an extended derived type.
163
164```
165  module m
166    type :: parent
167      integer :: n
168     contains
169      final :: subr
170    end type
171    type, extends(parent) :: extended
172      integer :: m
173    end type
174   contains
175    subroutine subr(a)
176      type(parent) :: a(1)
177    end subroutine
178  end module
179  subroutine demo
180    use m
181    type(extended) :: arr(1)
182  end subroutine
183```
184
185If the `FINAL` subroutine doesn't use a descriptor -- and it
186will not if there are no `LEN` type parameters -- the runtime
187will have to allocate and populate a temporary array of copies
188elements of the parent component of the array so that it can
189be passed by reference to the `FINAL` subroutine.
190
191### Defined assignment
192
193A defined assignment subroutine for a derived type can be declared
194by means of a generic `INTERFACE ASSIGNMENT(=)` and by means of
195a generic type-bound procedure.
196Defined assignments with non-type-bound generic interfaces are
197resolved to specific subroutines at compilation time.
198Most cases of type-bound defined assignment are resolved to their
199bindings at compilation time as well (with possible runtime
200resolution of overridable bindings).
201
202Intrinsic assignment of derived types with components that have
203derived types with type-bound generic assignments is specified
204by subclause 10.2.1.3 paragraph 13 as invoking defined assignment
205subroutines, however.
206
207This seems to be the only case of defined assignment that may be of
208interest to the runtime library.
209If this is correct, then the requirements are somewhat constrained;
210we know that the rank of the target of the assignment must match
211the rank of the source, and that one of the dummy arguments of the
212bound subroutine is a passed object dummy argument and satisfies
213all of the constraints of one -- in particular, it's scalar and
214polymorphic.
215
216So the derived type information for a defined assignment needs to
217comprise:
218* address(es) of the subroutine
219* whether the first, second, or both arguments are descriptors
220* whether the subroutine is elemental (necessarily also impure)
221
222### User defined derived type I/O
223
224Fortran programs can specify subroutines that implement formatted and
225unformatted `READ` and `WRITE` operations for derived types.
226These defined I/O subroutines may be specified with an explicit `INTERFACE`
227or with a type-bound generic.
228When specified with an `INTERFACE`, the first argument must not be
229polymorphic, but when specified with a type-bound generic, the first
230argument is a passed-object dummy argument and required to be so.
231In any case, the argument is scalar.
232
233Nearly all invocations of user defined derived type I/O subroutines
234are resolved at compilation time to specific procedures or to
235overridable bindings.
236(The I/O library APIs for acquiring their arguments remain to be
237designed, however.)
238The case that is of interest to the runtime library is that of
239NAMELIST I/O, which is specified to invoke user defined derived
240type I/O subroutines if they have been defined.
241
242The derived type information for a user defined derived type I/O
243subroutine comprises:
244* address(es) of the subroutine
245* whether it is for a read or a write
246* whether it is formatted or unformatted
247* whether the first argument is a descriptor (true if it is a
248  binding of the derived type, or has a `LEN` type parameter)
249
250## Exporting derived type descriptions from module relocatables
251
252Subclause 7.5.2 requires that two objects be considered as having the
253same derived type if they are declared "with reference to the same
254derived type definition".
255For derived types that are defined in modules and accessed by means
256of use association, we need to be able to describe the type in the
257read-only static data section of the module and access the description
258as a link-time external.
259
260This is not always possible to achieve in the case of instantiations
261of parameterized derived types, however.
262Two identical instantiations in distinct compilation units of the same
263use associated parameterized derived type seem impractical to implement
264using the same address.
265(Perhaps some linkers would support unification of global objects
266with "mangled" names and identical contents, but this seems unportable.)
267
268Derived type descriptions therefore will contain pointers to
269their "uninstantiated" original derived types.
270For derived types with no `KIND` type parameters, these pointers
271will be null; for uninstantiated derived types, these pointers
272will point at themselves.
273