Skip to content

Commit

Permalink
[flang] naming
Browse files Browse the repository at this point in the history
Original-commit: flang-compiler/f18@c367328
Reviewed-on: flang-compiler/f18#683
Tree-same-pre-rewrite: false
  • Loading branch information
klausler committed Aug 26, 2019
1 parent 0c3a942 commit 1e90c6b
Showing 1 changed file with 88 additions and 36 deletions.
124 changes: 88 additions & 36 deletions flang/documentation/Calls.md
Expand Up @@ -29,7 +29,7 @@ Calls to procedures with some post-'77 features require an explicit interface
(specification expression, `DO CONCURRENT`, `FORALL`)
* dummy arguments with these attributes: `ALLOCATABLE`, `POINTER`,
`VALUE`, `TARGET`, `OPTIONAL`, `ASYNCHRONOUS`, `VOLATILE`
(but *not* `CONTIGUOUS` or `INTENT()`!)
(but *not* `CONTIGUOUS`, `INTENT()`, or nonparameterized derived type)
* dummy arguments that are coarrays, have assumed-shape/-rank,
have parameterized derived types, &/or are polymorphic
* function results that are arrays, `ALLOCATABLE`, `POINTER`,
Expand All @@ -46,34 +46,35 @@ such as procedure pointer assignment, type-bound procedure bindings, &c.
### Implicit interfaces

In the absence of any characteristic or context that requires an
explicit interface (see above), a top-level function or subroutine
can be called via its implicit interface.
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
compiled as if all calls to them were through the implicit interface.

Internal and module procedures that are ever passed as arguments &/or
used as targets of procedure pointers are also potentially at risk of
being called through internal interfaces.
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 internal interfaces.

Procedures that can be called via an implicit interface should respect
the naming conventions (when not internal or module) and legacy ABI (if any)
used for Fortran '77 programs
on the target architecture, so that portable libraries can be compiled
Every procedure callable via an implicit interface
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 with implicit interfaces still have known result
Note that functions callable via implicit interfaces 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 actual arguments,
ad the length of an assumed-length `CHARACTER(*)` result, and they can
return only scalar values of intrinsic types.
and possibly the length of an assumed-length `CHARACTER(*)` result,
and they can return only scalar values of intrinsic types.
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
Expand Down Expand Up @@ -252,7 +253,6 @@ needed to recalculate them) of the actual argument designator, or its
elements, in additional temporary storage if they can't be safely or
quickly recomputed after the call.


### `INTENT(OUT)` preparation

Actual arguments that are associated with `INTENT(OUT)`
Expand Down Expand Up @@ -294,6 +294,24 @@ are required to be associated only with dummy arguments with the
requirement that the local image somehow reallocate remote storage
when copying the data back.

### Polymorphic bindings

Calls to the type-bound procedures of non-polymorphic types are
resolved at compilation time, as are calls to `NON_OVERRIDABLE`
type-bound procedures.
The resolution of calls to overridable type-bound procedures of
polymorphic types must be completed at execution (generic resolution
of type-bound procedure bindings from actual argument types, kinds,
and ranks is always a compilation-time task (C.10.6)).

Each derived type that declares or inherits any overridable
type-bound procedure bindings must correspond to a static constant
table of code addresses (or, more likely, a static constant type
description containing or pointing to such a table, along with
information used by the runtime support library for initialization,
copying, finalization, and I/O of type instances). Each overridable
type-bound procedure in the type corresponds to an index into this table.

### Host association linkage

Calls to dummy procedures and procedure pointers that resolve to
Expand Down Expand Up @@ -322,9 +340,9 @@ represent a procedure pointer.
It also needs to be conveyed alongside the text address for a
dummy procedure.

For subprograms that can be called with an implicit interface,
we cannot use a "procedure pointer descriptor" to represent a
a dummy procedure -- a Fortran '77 routine
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 actual procedure
to a procedure that can be called with an implicit interface,
Expand All @@ -339,21 +357,63 @@ to their construction and a reclamation obligation;
NAG Fortran manages a static fixed-sized stack of trampolines
per call site, imposing a hidden limit on recursion and foregoing
reentrancy;
PGI uses descriptors, but loses the host link when
passing the dummy procedure code address over an implicit interface,
leading to crashes when they turn out to be needed.
PGI passes host variable links in descriptors in additional arguments
that are not always successfully forwarded across implicit interfaces,
sometimes leading to crashes when they turn out to be needed.

F18 will use both descriptors and a pool of trampolines in its runtime support library,
and use the trampolines only for calls to routines that need to support an
F18 will use descriptors in most cases to pass procedures as arguments,
but also maintain a pool of trampolines in its runtime support library
to implement calls to routines that need to support an
implicit interface.

## Further topics to document

### Target resolution
* polymorphic bindings
* procedure pointers
* dummy procedures
* generic resolution
### Naming

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.

In other cases, however, we have no constraints on external naming
(other than extreme length and maybe good taste), and some additional
requirements.

Module procedures need to be distinguished by the name of their module
and (when they have one) the submodule where their interface was
defined.
Note that submodule names are distinct in their modules, not hierarchical,
so at most two levels of qualification are needed.

Pure `ELEMENTAL` functions (15.8) must use distinct names for any alternate
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`.

We may choose to distinguish the names of external procedures that cannot
be called via an implicit interface as a means for catching attempts
to do so and causing them to fail with link errors.

We may also choose to distinguish both of these classes of names with
extra characters that make it impossible to link with code compiled
by other Fortran compilers or other incompatible versions of F18.

Last, there must be reasonably permanent naming conventions used
by the F18 runtime library for those unrestricted specific intrinsic
functions (table 16.2 in 16.8) and extensions that can be passed as
arguments.

I suggest that in these cases where external naming is at the discretion
of the implementation, we use names that are not in the C language
user namespace, begin with something that identifies
the current incompatible version of F18, the module, the submodule, and
elemental SIMD width, and are followed by the external name.
The parts of the external name can be separated by some character that
is acceptable for use in LLVM IR and assembly language but not in user
Fortran or C code, or by switching case (e.g., `__f18a_moduleSUBMODULEentry`).

## Further topics to document

### Arguments
* Alternate return specifiers
Expand All @@ -363,14 +423,6 @@ implicit interface.
* Whether lower bounds in argument descriptors should be
initialized (they shouldn't be used)

### Naming
* Modules and submodules
* Procedures that can be called with implicit interfaces
* Procedures that must be called with explicit interfaces (possibly
with versioning)
* SIMD vs. scalar versions of `ELEMENTAL` procedures
* Unrestricted specific intrinsic functions (and perhaps SIMD variants)

### Other
* SIMD variants of `ELEMENTAL` procedures (& unrestricted specific intrinsics)
* Interoperable procedures
Expand Down

0 comments on commit 1e90c6b

Please sign in to comment.