.. contents:: :local:
OpenMP divides directives into three categories as follows. The directives that are in the same categories share some characteristics.
An OpenMP directive may only be placed in a declarative context. A declarative directive results in one or more declarations only; it is not associated with the immediate execution of any user code.
List of existing ones:
There is a parser node for each of these directives and the parser node saves information associated with the directive, for example, the name of the procedure-name in the declare simd
directive.
Each parse tree node keeps source provenance, one for the directive name itself and one for the entire directive starting from the directive name.
A top-level class, OpenMPDeclarativeConstruct
, holds all four of the node types as discriminated unions along with the source provenance for the entire directive starting from !$OMP
.
In parser-tree.h
, OpenMPDeclarativeConstruct
is part of the SpecificationConstruct
and SpecificationPart
in F18 because a declarative directive can only be placed in the specification part of a Fortran program.
All the Names
or Designators
associated with the declarative directive will be resolved in later phases.
An OpenMP directive that is not declarative. That is, it may only be placed in an executable context. It contains stand-alone directives and constructs that are associated with code blocks. The stand-alone directive is described in the next section.
The constructs associated with code blocks listed below share a similar structure: Begin Directive, Clause List, Code Block, End Directive. The End Directive is optional for constructs like Loop-associated constructs.
OpenMPBlockConstruct
)OpenMPLoopConstruct
)OpenMPAtomicConstruct
)OpenMPSectionsConstruct
, contains Sections/Parallel Sections constructs)OpenMPCriticalConstruct
)A top-level class, OpenMPConstruct
, includes stand-alone directive and constructs listed above as discriminated unions.
In the parse-tree.h
, OpenMPConstruct
is an element of the ExecutableConstruct
.
All the Names
or Designators
associated with the executable directive will be resolved in Semantic Analysis.
When the backtracking parser can not identify the associated code blocks, the parse tree will be rewritten later in the Semantics Analysis.
An OpenMP executable directive that has no associated user code except for that which appears in clauses in the directive.
List of existing ones:
A higher-level class is created for each category which contains directives listed above that share a similar structure:
A top-level class, OpenMPStandaloneConstruct
, holds all four of the node types as discriminated unions along with the source provenance for the entire directive. Also, each parser node for the stand-alone directive saves the source provenance for the directive name itself.
Each clause represented as a distinct class in parse-tree.h
. A top-level class, OmpClause
, includes all the clauses as discriminated unions. The parser node for OmpClause
saves the source provenance for the entire clause.
All the Names
or Designators
associated with the clauses will be resolved in Semantic Analysis.
Note that the backtracking parser will not validate that the list of clauses associated with a directive is valid other than to make sure they are well-formed. In particular, the parser does not check that the association between directive and clauses is correct nor check that the values in the directives or clauses are correct. These checks are deferred to later phases of semantics to simplify the parser.
Name resolution can be impacted by the OpenMP code. In addition to the regular steps to do the name resolution, new scopes and symbols may need to be created when encountering certain OpenMP constructs. This section describes the extensions for OpenMP during Symbol Table construction.
OpenMP uses the fork-join model of parallel execution and all OpenMP threads have access to a shared memory place to store and retrieve variables but each thread can also have access to its threadprivate memory that must not be accessed by other threads.
For the directives and clauses that can control the data environments, compiler needs to determine two kinds of access to variables used in the directive’s associated structured block: shared and private. Each variable referenced in the structured block has an original variable immediately outside of the OpenMP constructs. Reference to a shared variable in the structured block becomes a reference to the original variable. However, each private variable referenced in the structured block, a new version of the original variable (of the same type and size) will be created in the threadprivate memory.
There are exceptions that directives/clauses need to create a new Symbol
without creating a new Scope
, but in general, when encountering each of the data environment controlling directives (discussed in the following sections), a new Scope
will be created. For each private variable referenced in the structured block, a new Symbol
is created out of the original variable and the new Symbol
is associated with original variable’s Symbol
via HostAssocDetails
. A new set of OpenMP specific flags are added into Flag
class in symbol.h
to indicate the types of associations, data-sharing attributes, and data-mapping attributes in the OpenMP data environments.
OpenMP directives that require new Symbol
to be created but not new Scope
are listed in the following table in terms of the Symbol Table extensions for OpenMP:
- No Action * Discussed in “Module File Extensions for OpenMP” section
For the following OpenMP regions:
target
regionsteams
regionsparallel
regionssimd
regionstask
or taskloop
constructs)do
, sections
, single
, or workshare
constructs)A new Scope
will be created when encountering the above OpenMP constructs to ensure the correct data environment during the Code Generation. To determine whether a variable referenced in these regions needs the creation of a new Symbol
, all the data-sharing attribute rules described in OpenMP Spec [2.15.1] apply during the Name Resolution. The available data-sharing attributes are: shared, private, linear, firstprivate, and lastprivate. The attribute is represented as Flag
in the Symbol
object.
More details are listed in the following table:
To determine the right data-sharing attribute, OpenMP defines that the data-sharing attributes of variables that are referenced in a construct can be predetermined, explicitly determined, or implicitly determined.
Variables with explicitly determined data-sharing attributes are:
The data-sharing attribute clauses are:
Symbol
created with the flag OmpReduction
set)Note that variables with predetermined data-sharing attributes may not be listed (with exceptions) in data-sharing attribute clauses.
Variables with implicitly determined data-sharing attributes are:
Rules for variables with implicitly determined data-sharing attributes:
When encountering the target data and target directives, the data-mapping attributes of any variable referenced in a target region will be determined and represented as Flag
in the Symbol
object of the variable. No Symbol
or Scope
will be created.
The basic steps to determine the data-mapping attribute are:
Flag
are listed below:After the completion of the Name Resolution phase, all the data-sharing or data-mapping attributes marked for the Symbols
may be used later in the Semantics Analysis and in the Code Generation.
After the successful compilation of modules and submodules that may contain the following Declarative Directives, the entire directive starting from !$OMP
needs to be written out into .mod
files in their corresponding Specification Part:
declare simd or declare target
In the “New Symbol without new Scope” section, we described that when encountering these two declarative directives, new Flag
will be applied to the Symbol of the name of the enclosing function, subroutine, or interface body to which it applies, or proc-name. This Flag
should be part of the API information for the given subroutine or function
declare reduction
The reduction-identifier in this directive can be use-associated or host-associated. However, it will not act like other Symbols because user may have a reduction name that is the same as a Fortran entity name in the same scope. Therefore a specific data structure needs to be created to save the reduction-identifier information in the Scope and this directive needs to be written into .mod
files
OpenMPLoopConstruct
with DoConstruct
and OpenMPEndLoopDirective
.mod
files.mod
files