[flang] Simplify by using the term F77ish

Original-commit: flang-compiler/f18@063d9dc6c8
Reviewed-on: https://github.com/flang-compiler/f18/pull/683
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2019-08-28 13:59:48 -07:00
parent f4f44b90f0
commit 76337eb4cb
1 changed files with 76 additions and 77 deletions

View File

@ -26,7 +26,7 @@ functions, or calls to internal runtime support library routines.
and their contents are contiguous.
* An *assumed-size* array is an explicit-shape array with `*` as its
final dimension, which the most-significant one in Fortran.
* A *deferred-shape* array is a `POINTER` or `ALLOCATABLE`.
* A *deferred-shape* array (`DIMENSION(:)`) is a `POINTER` or `ALLOCATABLE`.
`POINTER` target data might not be contiguous.
* An *assumed-shape* (not size!) array is a dummy argument whose
upper bounds take their values from the *shape* of the effective
@ -34,102 +34,111 @@ functions, or calls to internal runtime support library routines.
them and default to 1.
* An *assumed-length* `CHARACTER(*)` dummy argument
takes its length from the effective argument.
* An *assumed-length* `CHARACTER(*)` function result
takes its length from its eventual declaration in a calling scope.
* An *assumed-rank* dummy argument array has an unknown number
* An *assumed-length* `CHARACTER(*)` result of an external function (C721)
has its length determined by its eventual declaration in a calling scope.
* An *assumed-rank* `DIMENSION(..)` dummy argument array has an unknown number
of dimensions.
* A *polymorphic* dummy argument has a specific derived type or any
* A *polymorphic* `CLASS(t)` dummy argument has a specific derived type or any
possible extension of that type. An *unlimited polymorphic*
dummy argument can have any type.
`CLASS(*)` dummy argument can have intrinsic or derived type.
* *Interoperable* `BIND(C)` procedures are written in C or callable from C.
## Interfaces
Referenced procedures may or may not have declared interfaces
available to their call sites.
Calls to procedures with some post-Fortran '77 features require an
explicit interface (15.4.2.2):
Procedures with some post-Fortran '77 features *require* an
explicit interface to be called (15.4.2.2) or even passed (4.3.4(2)):
* use of argument keywords
* use of argument keywords in a call
* procedures that are `ELEMENTAL` or `BIND(C)`
* procedures that are required to be `PURE` due to the context of the call
(specification expression, `DO CONCURRENT`, `FORALL`)
* dummy arguments with these attributes: `ALLOCATABLE`, `POINTER`,
`VALUE`, `TARGET`, `OPTIONAL`, `ASYNCHRONOUS`, `VOLATILE`
(but *not* `CONTIGUOUS`, `INTENT()`)
* dummy arguments that are coarrays, have assumed-shape/-rank,
have parameterized derived types, &/or are polymorphic
* function results that are arrays, `ALLOCATABLE`, `POINTER`,
or have derived types with any length parameters that are
neither constant nor assumed
(but *not* `CONTIGUOUS` or `INTENT()`)
* dummy arguments that are coarrays
* dummy arguments that are assumed-shape or assumed-rank arrays
* dummy arguments with parameterized derived types
* dummy arguments that are polymorphic
* function result that is an array
* function result that is `ALLOCATABLE` or `POINTER`
* `CHARACTER` function result whose length is neither constant
nor assumed
* derived type function result with `LEN` type parameter value that is
not constant
(note that result derived type parameters cannot be assumed (C795))
Module procedures, internal procedures, procedure pointers,
type-bound procedures, and recursive references by a procedure to itself
always have explicit interfaces.
(Consequentially, they cannot be assumed-length `CHARACTER(*)` functions;
in fact, recursive function calls cannot have results with assumed
parameters of any type (15.6.2.1(3))).
conveniently, assumed-length `CHARACTER(*)` functions are prohibited from
recursion (15.6.2.1(3))).
Other uses of procedures besides calls may also require explicit interfaces,
such as procedure pointer assignment, type-bound procedure bindings, &c.
Note that non-parameterized monomorphic derived type arguments do
not by themselves require the use of an explicit interface.
*not* by themselves require the use of an explicit interface.
However, dummy arguments with any derived type parameters *do*
require an explicit interface, even if they are all `KIND` type
parameters.
A procedure that requires an explicit interface must, in a strict
reading of the standard (4.3.4(2) & 15.4.2.2),
have that interface available when the procedure is passed as an
argument.
As a special case, see also 15.5.2.9(2), which explicitly
allows an assumed-length `CHARACTER(*)` function to be passed as an actual
argument to an explicit-length dummy); this has implications for
calls to character-valued dummy functions and function pointers.
15.5.2.9(2) explicitly allows an assumed-length `CHARACTER(*)` function
to be passed as an actual argument to an explicit-length dummy);
this has implications for calls to character-valued dummy functions
and function pointers.
(In the scopes that reference `CHARACTER` functions, they must have
visible definitions with explicit result lengths.)
### Implicit interfaces
In the absence of any characteristic or context that requires an
In the absence of any characteristic or context that *requires* an
explicit interface (see above), an external function or subroutine (R503)
or `ENTRY` (R1541) can be called directly or indirectly via its implicit interface.
Each of the arguments can be passed as a simple address, including
dummy procedures.
Procedures that *can* be called via an implicit interface can
enjoy more thorough checking
by semantics when they do have a visible external interface, but must be
undergo more thorough checking
by semantics when an explicit interface for them exists, but they must be
compiled as if all calls to them were through the implicit interface.
This note will mention special handling for procedures that are exposed
to the possibility of being called with an implicit interface as *F77ish* procedures
below; this is of course not standard terminology.
Internal and module subprograms that are ever passed as arguments &/or
assigned as targets of procedure pointers are also potentially at risk of
being called indirectly through implicit interfaces.
assigned as targets of procedure pointers may be F77ish.
Every procedure callable via an implicit interface
can and must be distiguished at compilation time.
Every F77ish procedure can and must be distiguished at compilation time.
Such procedures should respect the external naming conventions (when external)
and any legacy ABI used for Fortran '77 programs on the target architecture,
so that portable libraries can be compiled
and used by distinct implementations (and their versions)
of Fortran.
Note that functions callable via implicit interfaces still have known result
types, possibly by means of implicit typing of their names.
Note that F77ish functions still have known result types, possibly by means
of implicit typing of their names.
They can also be `CHARACTER(*)` assumed-length character functions.
In other words: procedures that can be referenced with implicit interfaces
have argument lists that comprise only addresses of effective arguments
and the length of a `CHARACTER` function result (if any),
and they can return only scalar values of intrinsic types.
In other words: these F77sh procedures that do not require the use of an explicit
interface and that can possibly be referenced, directly or indirectly,
with implicit interfaces are limited to argument lists that comprise
only the addresses of effective arguments and the length of a `CHARACTER` function result
(when there is one), and they can return only scalar values with constant
type parameter values.
None of their arguments or results need be (or can be) implemented
with descriptors,
and any internal procedures passed to them as arguments must be
addresses of trampolines.
simple addresses of non-internal subprograms or trampolines for
internal procedures.
Note that `INTENT` and `CONTIGUOUS` attributes do not, by themselves,
require the use of explicit interface; neither does the use of dummy
procedures (implicit or explicit in their interfaces).
require the use of explicit interface; neither does the use of a dummy
procedure (implicit or explicit in their interfaces).
Analyses of calls to procedures with implicit interfaces must make
Analyses of calls to F77ish procedures must make
allowances or impose restrictions capable of dealing with any of the
invisible `INTENT` and `CONTIGUOUS` attributes of dummy arguments
in the called procedure.
@ -154,7 +163,7 @@ some design alternatives that are explored further below.
neither `POINTER` nor `ALLOCATABLE` must have explicit shapes (C816).
1. Create and populate a descriptor for the function result, if it
needs one (deferred-shape/-length `POINTER`, any `ALLOCATABLE`,
parameterized derived type with non-constant length parameters, &c.).
derived type with non-constant length parameters, &c.).
1. Capture the values of host-escaping local objects in memory;
package them into single address (for calls to internal procedures &
for calls that pass internal procedures as arguments).
@ -162,10 +171,8 @@ some design alternatives that are explored further below.
1. Marshal effective argument addresses (or values for `VALUE`/`%VAL()`) into registers.
1. Marshal `CHARACTER` argument lengths in additional value arguments for
`CHARACTER` effective arguments not passed via descriptors.
1. Marshal an extra argument for the `CHARACTER` result
length when calling a `CHARACTER`-valued function, if there is a chance
that it might be assumed-length or could be called over an implicit
interface.
1. Marshal an extra argument for the length of a `CHARACTER` function
result if the function is F77ish.
1. Marshal an extra argument for the function result's descriptor,
if it needs one.
1. Set the "host instance" (static link) register when calling an internal
@ -260,7 +267,8 @@ be copied into temporaries in the following situations.
(15.4.2.4(21)); `INTENT()` can't always be checked.
1. Non-simply-contiguous (9.5.4) arrays being passed to non-`POINTER`
dummy arguments that must be contiguous due to a `CONTIGUOUS`
attribute, implicit interface, or not being assumed-shape/-rank.
attribute or not being assumed-shape or assumed-rank (which
is always the case for F77ish procedures).
This should be a runtime decision, so that effective arguments
that turn out to be contiguous can be passed cheaply.
This rule does not apply to coarray dummies, whose effective arguments
@ -354,15 +362,13 @@ when they have any of the following characteristics:
1. coarray dummy argument
1. `INTENT(IN) POINTER` argument (15.5.2.7, C.10.4)
In procedures that cannot be called with an implicit interface
due to their other characteristics, two other kinds of dummy
arguments are represented with descriptors:
Non-F77ish procedures use descriptors to represent two further
kinds of dummy arguments:
1. assumed-length `CHARACTER(*)`
1. dummy procedure
1. dummy procedures
When the procedure can be called with an implicit interface,
other means are used to convey character length and host instance
F77ish procedures use other means to convey character length and host instance
links (respectively) for these arguments.
Function results are described by the caller & callee in
@ -371,12 +377,9 @@ characteristics, some which necessitate an explicit interface:
1. deferred-shape array (so `ALLOCATABLE` or `POINTER`)
1. derived type with any non-constant `LEN` parameter
(C795 prohibit assumed lengths)
1. procedure pointer result (when the interface must be explicit)
A `CHARACTER` function that can be called with an implicit interface
is passed its result length as an additional value argument in case
it might be defined as assumed-length `CHARACTER(*)`.
Storage for a function call's result is allocated by the caller when
possible: the result is neither `ALLOCATABLE` nor `POINTER`,
the shape is scalar or explicit, and the type has `LEN` parameters
@ -474,13 +477,10 @@ represent a procedure pointer.
It also needs to be conveyed alongside the text address for a
dummy procedure.
For procedures that can be called with an implicit interface,
we cannot use a "procedure pointer descriptor" to pass them an
a procedure argument -- a Fortran '77 routine
with an `EXTERNAL` dummy argument expects to receive a single
address argument. Instead, when passing an effective procedure
to a procedure that can be called with an implicit interface,
we will need to package the host instance link in a trampoline
For F77ish procedures, we cannot use a "procedure pointer descriptor"
to pass a procedure argument -- they expect to receive a single
address argument.
We will need to package the host instance link in a trampoline
that loads its address into the designated register.
GNU Fortran and Intel Fortran construct trampolines by writing
@ -498,8 +498,8 @@ sometimes leading to crashes when they turn out to be needed.
F18 will manage a pool of trampolines in its runtime support library
that can be used to pass internal procedures as effective arguments
to targets that might be called with an implicit interface, so that
a bare code address is used to represent the effective argument.
to F77ish procedures, so that
a bare code address can serve to represent the effective argument.
But targets that can only be called with an explicit interface
have the option of using a "fat pointer" (or additional argument)
to represent a dummy procedure closure so as
@ -511,9 +511,9 @@ Procedure descriptors can also support multiple code addresses.
External subroutines and functions (R503) and `ENTRY` points (R1541)
with `BIND(C)` (R808) have linker-visible names that are either explicitly
specified in the program or determined by straightforward rules.
The names of other external procedures that might be called
via an implicit interface should respect the conventions of the target architecture
for legacy Fortran '77 programs; this is typically something like `foo_`.
The names of other F77ish external procedures should respect the conventions
of the target architecture for legacy Fortran '77 programs; this is typically
something like `foo_`.
In other cases, however, we have fewer constraints on external naming,
as well as some additional requirements and goals.
@ -529,7 +529,7 @@ entry points used for packed SIMD arguments of various widths if we support
calls to these functions in SIMD parallel contexts.
There are already conventions for these names in `libpgmath`.
The names of external procedures that cannot be called via an implicit interface
The names of non-F77ish external procedures
should be distinguished as such so that incorrect attempts to call or pass
them with an implicit interface will fail to resolve at link time.
Fortran 2018 explicitly enables us to do this with a correction to Fortran
@ -602,7 +602,7 @@ the dummy and effective arguments have the same attributes:
15.5.2.8 corray dummy arguments:
* (1) effective argument must be coarray
* (1) `VOLATILE` attributes must match
* (2) `CONTIGUOUS` dummy (or implicitly contiguous non-assumed-shape array) requires simply contiguous actual
* (2) `CONTIGUOUS` dummy (or implicitly contiguous non-assumed-shape/-rank array) requires simply contiguous actual
15.5.2.9 dummy procedures:
* (1) explicit dummy procedure interface must have same characteristics as actual
@ -610,9 +610,8 @@ the dummy and effective arguments have the same attributes:
15.6.2.1 procedure definitions:
* `NON_RECURSIVE` procedures cannot recurse.
* Functions with assumed type parameter values (including `CHARACTER(*)`) are not `RECURSIVE` by
default, cannot be `RECURSIVE`, array-valued, `POINTER`, `ELEMENTAL`, or `PURE' (C723),
and cannot be called recursively (15.6.2.1(3)).
* Assumed-length `CHARACTER(*)` functions cannot be declared as `RECURSIVE`, array-valued,
`POINTER`, `ELEMENTAL`, or `PURE' (C723), and cannot be called recursively (15.6.2.1(3)).
`PURE` requirements (15.7): C1583 - C1599.
These also apply to `ELEMENTAL` procedures that are not `IMPURE`.