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