2018-05-01 21:50:34 +02:00
|
|
|
|
<!--
|
|
|
|
|
Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
|
|
|
|
-->
|
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
The semantic pass will determine whether the input program is a legal Fortran
|
|
|
|
|
program.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
If the program is not legal, the results of the semantic pass will be a list of
|
|
|
|
|
errors associated with the program.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
If the program is legal, the semantic pass will produce an unambiguous parse
|
|
|
|
|
tree with additional information that is useful for the tools API and creation
|
|
|
|
|
of the DST.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
|
|
|
|
What is required of semantics?
|
|
|
|
|
* Error checking
|
|
|
|
|
* A non-ambiguous parse tree
|
|
|
|
|
* Symbol tables with scope information
|
|
|
|
|
* Name & operator resolution
|
|
|
|
|
|
|
|
|
|
What do we want from semantics?
|
|
|
|
|
* Cache information about labels and references to labels
|
|
|
|
|
* Cache information derived from static expression evaluation
|
|
|
|
|
|
|
|
|
|
What don’t we want from semantics?
|
2018-03-22 19:53:59 +01:00
|
|
|
|
* Semantics will not display error messages directly. Instead, error messages
|
|
|
|
|
and their associated source locations will be saved and returned to the caller.
|
|
|
|
|
* The parse tree will not be modified except to resolve ambiguity and resolve
|
|
|
|
|
names, operators, and labels.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
Semantic checking does not need to preserve information that is easily
|
|
|
|
|
recomputed, such as pointers to enclosing structures.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
The parse tree shall be immutable after resolution of names, operators, labels
|
|
|
|
|
and ambiguous sub-trees. This means that the parse tree does not have direct
|
|
|
|
|
references to error messages, etc.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
Much of the work that is to be performed by semantic analysis has been specified
|
|
|
|
|
in the Fortran standard with numbered constraints. The structure of the code in
|
|
|
|
|
the semantic analyzer should correspond to the structure of the Fortran standard
|
|
|
|
|
as closely as possible so that one can refer to the Standard easily from the
|
|
|
|
|
code, and so that we can audit the code for missing checks.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
The code that generates LLVM will be able to be implemented with assertions
|
|
|
|
|
rather than with user error message generation; in other words, semantic
|
|
|
|
|
analysis will detect and report all errors. Note that informational and warning
|
|
|
|
|
messages may be generated after semantic analysis.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
Analyses and data structures that can be deferred to the deep structure should
|
|
|
|
|
be so, with exceptions for cases where completing an analysis is just a little
|
|
|
|
|
more complex than completing a correctness check (e.g. EQUIVALENCE overlays).
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Symbol resolution and scope assignment
|
2018-03-22 19:53:59 +01:00
|
|
|
|
The section describes the when scopes are created and how symbols are resolved.
|
|
|
|
|
It is a step-by-step process. Each step is envisioned as a separate pass over
|
|
|
|
|
the tree. The sub-bullets under each step will happen roughly in the order
|
|
|
|
|
specified.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
There is a special predefined scope for intrinsics. This scope is an ancestor
|
|
|
|
|
of all other scopes.
|
|
|
|
|
|
|
|
|
|
More detail is needed about this predefined scope. Who populates this special
|
|
|
|
|
intrinsic scope? Does it need to be constructed and populated for each
|
|
|
|
|
compilation unit? Maybe it could be a single distinct immutable scope from which
|
|
|
|
|
names can be associated, rather than an ancestor.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
|
|
|
|
The following steps will be followed each program unit:
|
|
|
|
|
|
|
|
|
|
_N.B. Modules are not yet covered_
|
|
|
|
|
|
|
|
|
|
_N.B. We need to define the semantics of the LOC intrinsic_
|
|
|
|
|
|
|
|
|
|
#### Step 1. Process the top-level declaration, e.g. a subroutine
|
|
|
|
|
1. Create a new scope
|
2018-03-22 19:53:59 +01:00
|
|
|
|
1. Add the name of the program unit to the scope except for functions without
|
|
|
|
|
result clause
|
2018-03-20 23:47:52 +01:00
|
|
|
|
1. Add the result variable to the scope
|
|
|
|
|
1. Add the names of the dummy arguments to the scope
|
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
Implementation note: When a program make an illegal forward reference, we
|
|
|
|
|
should emit at least a warning so that programs that are illegally assuming host
|
|
|
|
|
association for a name won’t be silently invalidated; preferably with a message
|
|
|
|
|
that references both instances.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
|
|
|
|
#### Step 2. Process the specification part
|
2018-03-22 19:53:59 +01:00
|
|
|
|
1. Set up implicit rules
|
2018-03-20 23:47:52 +01:00
|
|
|
|
1. Process imports, uses, and host association
|
|
|
|
|
1. Add the names of the internal and module procedures
|
|
|
|
|
1. Process declaration constructs in a single pass
|
2018-03-22 19:53:59 +01:00
|
|
|
|
1. Apply implicit rules to undefined locals, dummy arguments and the function
|
|
|
|
|
result
|
2018-03-20 23:47:52 +01:00
|
|
|
|
1. Create new scopes for derived type, structure, union
|
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
Host association logically happens at step 2; perhaps host association can
|
|
|
|
|
be deferred until the symbol is referenced?
|
2018-03-22 06:45:43 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
At this point, all names in the specification part of the parse tree reference
|
|
|
|
|
a symbol.
|
2018-03-22 06:42:05 +01:00
|
|
|
|
|
|
|
|
|
We can process declaration constructs in a single pass because:
|
2018-03-22 19:53:59 +01:00
|
|
|
|
- It is not legal to reference an internal procedure.
|
|
|
|
|
- It is not legal to reference not-yet-defined parameters, constants, etc.
|
|
|
|
|
- It is not possible to inquire about a type parameter or array bound for an
|
|
|
|
|
object that is not yet defined
|
2018-03-22 06:42:05 +01:00
|
|
|
|
- So, no other forward definitions, so yes, we can do in a single pass
|
|
|
|
|
|
|
|
|
|
Do we ever need to apply implicit rules in the specification section?
|
|
|
|
|
1. `integer(kind = kind(x)) :: y ! does implicit rule apply to ‘x’`?
|
|
|
|
|
1. `integer, parameter :: z = rank(x) ! use implicit rule to get ‘0’`?
|
|
|
|
|
|
|
|
|
|
What if (1) and (2) are legal & x’s type is subsequently declared?
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
|
|
|
|
#### Step 3. Resolve statement functions vs array assignments
|
|
|
|
|
1. Rewrite and move array assignments to execution part
|
|
|
|
|
1. Why rewrite? Because array assignment needs processing in Step 4
|
|
|
|
|
1. Statement functions need scopes for the dummy arguments
|
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
N.B. As soon as a statement function definition is determined to actually be a
|
|
|
|
|
misrecognized assignment to an array element, all of the statement definitions
|
|
|
|
|
that follow it in the same specification-part must also be converted into array
|
|
|
|
|
element assignments, even if that would lead to an error.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
|
|
|
|
#### Step 4. Resolve symbols in the execution part
|
2018-03-22 19:53:59 +01:00
|
|
|
|
1. Look up the name
|
2018-03-20 23:47:52 +01:00
|
|
|
|
- If it exists in a scope, update the name to reference the symbol
|
|
|
|
|
- If it does not exist,
|
|
|
|
|
* Apply the implicit rules
|
|
|
|
|
* Add the name to the scope
|
|
|
|
|
* Update the name to reference the new symbol
|
|
|
|
|
- Introduce new scopes for
|
|
|
|
|
* Select Type type guard statements
|
|
|
|
|
* Select Rank case statements
|
|
|
|
|
* Associate construct
|
|
|
|
|
* Block construct
|
|
|
|
|
- Block has a specification part
|
|
|
|
|
- Blocks start Step 1..4 again
|
|
|
|
|
- N.B. Implicits are applied to the host scope
|
|
|
|
|
* Implied Do
|
|
|
|
|
* Index names in Forall and Do Concurrent
|
|
|
|
|
* Change Team
|
|
|
|
|
* OpenMP and OpenACC constructs
|
|
|
|
|
* ENTRY
|
|
|
|
|
|
|
|
|
|
References to derived types members are not resolved until semantics
|
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
No semantic checking or resolving of types (except for implicit declarations)
|
|
|
|
|
has happened yet.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
|
|
|
|
#### Step 5. Perform Step 1..4 on each internal procedure
|
2018-03-22 19:53:59 +01:00
|
|
|
|
- Side effect is that each internal procedure gets a proper interface in the
|
|
|
|
|
parent scope
|
|
|
|
|
- We do this now because we need to know the return and argument types for
|
|
|
|
|
functions, e.g. `a = f(a, b, c) % x + 1`
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
|
|
|
|
#### Step 6. Tree Disambiguation
|
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
At this point, or during Step 3 (TBD), the tree can be rewritten to be
|
|
|
|
|
unambiguous.
|
2018-03-22 06:42:05 +01:00
|
|
|
|
- Structure vs operator a.b.c.d
|
|
|
|
|
- Array references vs function calls
|
|
|
|
|
- Statement functions vs array assignment (In Step 3)
|
|
|
|
|
- READ/WRITE stmts where the arguments do not have keywords
|
2018-03-20 23:47:52 +01:00
|
|
|
|
- WRITE (6, X) ….
|
|
|
|
|
- That X might be a namelist group or an internal variable
|
|
|
|
|
- Need to know the names of the namelist groups to disambiguate it
|
2018-03-22 06:42:05 +01:00
|
|
|
|
- Others….? TBD
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
Resolution of parse tree ambiguity (statement function definition, function vs.
|
|
|
|
|
array)
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
|
|
|
|
#### Step 7. Do enough semantic processing to generate .mod files
|
2018-03-22 06:42:05 +01:00
|
|
|
|
- Fully resolve derived types
|
2018-03-22 19:53:59 +01:00
|
|
|
|
- Combine and check declarations of all entities within a given scope; resolve
|
|
|
|
|
their type, rank, shape, and other attributes.
|
2018-03-22 06:42:05 +01:00
|
|
|
|
- Constant evaluation is required at this point.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
2018-03-22 19:53:59 +01:00
|
|
|
|
Why do Step 7 before the rest of semantic checking? The sooner we can generate
|
|
|
|
|
mod file the sooner we can read ‘em; you can test a lot of Fortran programs as
|
|
|
|
|
soon as you can read mod files.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
|
|
|
|
|
#### Step 8. Semantic Rule Checking
|
|
|
|
|
|
|
|
|
|
An incomplete and unordered list of requirements for semantic analysis:
|
|
|
|
|
|
|
|
|
|
* EQUIVALENCE overlaying (checking at least)
|
|
|
|
|
* Intrinsic function generic->specific resolution, constraint checking, T/R/S.
|
2018-03-22 19:53:59 +01:00
|
|
|
|
* Compile-time evaluation of constant expressions, including intrinsic
|
|
|
|
|
functions.
|
2018-03-20 23:47:52 +01:00
|
|
|
|
* Resolution of generics and type-bound procedures.
|
|
|
|
|
* Identifying and recording uplevel references.
|
|
|
|
|
* Control flow constraint checking
|
2018-03-22 19:53:59 +01:00
|
|
|
|
* Labeled DO loop terminal statement expansion? (maybe not, can defer to CFG in
|
|
|
|
|
DST).
|
2018-03-20 23:47:52 +01:00
|
|
|
|
* Construct association: distinguish pointer-like from allocatable-like
|
|
|
|
|
* OMP and OACC checking
|
|
|
|
|
* CUF constraint checking
|
|
|
|
|
|
|
|
|
|
## Utility Routines
|
|
|
|
|
|
|
|
|
|
### Diagnostic Output
|
|
|
|
|
TBD
|
|
|
|
|
|
|
|
|
|
### Constant Expression Evaluation
|
2018-03-22 06:42:05 +01:00
|
|
|
|
- Scalars
|
|
|
|
|
- Array intrinsics
|