Skip to content

Commit e8100c3

Browse files
authored
[flang][OpenMP] Handle directive arguments in OmpDirectiveSpecifier (#124278)
Implement parsing and symbol resolution for directives that take arguments. There are a few, and most of them take objects. Special handling is needed for two that take more specialized arguments: DECLARE MAPPER and DECLARE REDUCTION. This only affects directives in METADIRECTIVE's WHEN and OTHERWISE clauses. Parsing and semantic checks of other cases is unaffected.
1 parent 39879e4 commit e8100c3

File tree

9 files changed

+517
-121
lines changed

9 files changed

+517
-121
lines changed

flang/examples/FeatureList/FeatureList.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,6 @@ struct NodeVisitor {
514514
READ_FEATURE(OmpReductionClause)
515515
READ_FEATURE(OmpInReductionClause)
516516
READ_FEATURE(OmpReductionCombiner)
517-
READ_FEATURE(OmpReductionCombiner::FunctionCombiner)
518517
READ_FEATURE(OmpReductionInitializerClause)
519518
READ_FEATURE(OmpReductionIdentifier)
520519
READ_FEATURE(OmpAllocateClause)

flang/include/flang/Parser/dump-parse-tree.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,12 @@ class ParseTreeDumper {
477477
NODE(parser, NullInit)
478478
NODE(parser, ObjectDecl)
479479
NODE(parser, OldParameterStmt)
480+
NODE(parser, OmpTypeSpecifier)
481+
NODE(parser, OmpTypeNameList)
482+
NODE(parser, OmpLocator)
483+
NODE(parser, OmpLocatorList)
484+
NODE(parser, OmpReductionSpecifier)
485+
NODE(parser, OmpArgument)
480486
NODE(parser, OmpMetadirectiveDirective)
481487
NODE(parser, OmpMatchClause)
482488
NODE(parser, OmpOtherwiseClause)
@@ -542,7 +548,7 @@ class ParseTreeDumper {
542548
NODE(parser, OmpDeclareTargetSpecifier)
543549
NODE(parser, OmpDeclareTargetWithClause)
544550
NODE(parser, OmpDeclareTargetWithList)
545-
NODE(parser, OmpDeclareMapperSpecifier)
551+
NODE(parser, OmpMapperSpecifier)
546552
NODE(parser, OmpDefaultClause)
547553
NODE_ENUM(OmpDefaultClause, DataSharingAttribute)
548554
NODE(parser, OmpVariableCategory)
@@ -625,7 +631,6 @@ class ParseTreeDumper {
625631
NODE(parser, OmpReductionCombiner)
626632
NODE(parser, OmpTaskReductionClause)
627633
NODE(OmpTaskReductionClause, Modifier)
628-
NODE(OmpReductionCombiner, FunctionCombiner)
629634
NODE(parser, OmpReductionInitializerClause)
630635
NODE(parser, OmpReductionIdentifier)
631636
NODE(parser, OmpAllocateClause)

flang/include/flang/Parser/parse-tree.h

Lines changed: 97 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3457,15 +3457,7 @@ WRAPPER_CLASS(PauseStmt, std::optional<StopCode>);
34573457
// --- Common definitions
34583458

34593459
struct OmpClause;
3460-
struct OmpClauseList;
3461-
3462-
struct OmpDirectiveSpecification {
3463-
TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification);
3464-
std::tuple<llvm::omp::Directive,
3465-
std::optional<common::Indirection<OmpClauseList>>>
3466-
t;
3467-
CharBlock source;
3468-
};
3460+
struct OmpDirectiveSpecification;
34693461

34703462
// 2.1 Directives or clauses may accept a list or extended-list.
34713463
// A list item is a variable, array section or common block name (enclosed
@@ -3478,15 +3470,76 @@ struct OmpObject {
34783470

34793471
WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
34803472

3481-
#define MODIFIER_BOILERPLATE(...) \
3482-
struct Modifier { \
3483-
using Variant = std::variant<__VA_ARGS__>; \
3484-
UNION_CLASS_BOILERPLATE(Modifier); \
3485-
CharBlock source; \
3486-
Variant u; \
3487-
}
3473+
// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
3474+
//
3475+
// reduction-identifier ->
3476+
// base-language-identifier | // since 4.5
3477+
// - | // since 4.5, until 5.2
3478+
// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
3479+
// MIN | MAX | IAND | IOR | IEOR // since 4.5
3480+
struct OmpReductionIdentifier {
3481+
UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
3482+
std::variant<DefinedOperator, ProcedureDesignator> u;
3483+
};
34883484

3489-
#define MODIFIERS() std::optional<std::list<Modifier>>
3485+
// Ref: [4.5:222:6], [5.0:305:27], [5.1:337:19], [5.2:126:3-4], [6.0:240:27-28]
3486+
//
3487+
// combiner-expression -> // since 4.5
3488+
// assignment-statement |
3489+
// function-reference
3490+
struct OmpReductionCombiner {
3491+
UNION_CLASS_BOILERPLATE(OmpReductionCombiner);
3492+
std::variant<AssignmentStmt, FunctionReference> u;
3493+
};
3494+
3495+
inline namespace arguments {
3496+
struct OmpTypeSpecifier {
3497+
UNION_CLASS_BOILERPLATE(OmpTypeSpecifier);
3498+
std::variant<TypeSpec, DeclarationTypeSpec> u;
3499+
};
3500+
3501+
WRAPPER_CLASS(OmpTypeNameList, std::list<OmpTypeSpecifier>);
3502+
3503+
struct OmpLocator {
3504+
UNION_CLASS_BOILERPLATE(OmpLocator);
3505+
std::variant<OmpObject, FunctionReference> u;
3506+
};
3507+
3508+
WRAPPER_CLASS(OmpLocatorList, std::list<OmpLocator>);
3509+
3510+
// Ref: [5.0:326:10-16], [5.1:359:5-11], [5.2:163:2-7], [6.0:293:16-21]
3511+
//
3512+
// mapper-specifier ->
3513+
// [mapper-identifier :] type :: var | // since 5.0
3514+
// DEFAULT type :: var
3515+
struct OmpMapperSpecifier {
3516+
// Absent mapper-identifier is equivalent to DEFAULT.
3517+
TUPLE_CLASS_BOILERPLATE(OmpMapperSpecifier);
3518+
std::tuple<std::optional<Name>, TypeSpec, Name> t;
3519+
};
3520+
3521+
// Ref: [4.5:222:1-5], [5.0:305:20-27], [5.1:337:11-19], [5.2:139:18-23],
3522+
// [6.0:260:16-20]
3523+
//
3524+
// reduction-specifier ->
3525+
// reduction-identifier : typename-list
3526+
// : combiner-expression // since 4.5, until 5.2
3527+
// reduction-identifier : typename-list // since 6.0
3528+
struct OmpReductionSpecifier {
3529+
TUPLE_CLASS_BOILERPLATE(OmpReductionSpecifier);
3530+
std::tuple<OmpReductionIdentifier, OmpTypeNameList,
3531+
std::optional<OmpReductionCombiner>>
3532+
t;
3533+
};
3534+
3535+
struct OmpArgument {
3536+
CharBlock source;
3537+
UNION_CLASS_BOILERPLATE(OmpArgument);
3538+
std::variant<OmpLocator, // {variable, extended, locator}-list-item
3539+
OmpMapperSpecifier, OmpReductionSpecifier>
3540+
u;
3541+
};
3542+
} // namespace arguments
34903543

34913544
inline namespace traits {
34923545
// trait-property-name ->
@@ -3620,6 +3673,16 @@ struct OmpContextSelectorSpecification { // Modifier
36203673
};
36213674
} // namespace traits
36223675

3676+
#define MODIFIER_BOILERPLATE(...) \
3677+
struct Modifier { \
3678+
using Variant = std::variant<__VA_ARGS__>; \
3679+
UNION_CLASS_BOILERPLATE(Modifier); \
3680+
CharBlock source; \
3681+
Variant u; \
3682+
}
3683+
3684+
#define MODIFIERS() std::optional<std::list<Modifier>>
3685+
36233686
inline namespace modifier {
36243687
// For uniformity, in all keyword modifiers the name of the type defined
36253688
// by ENUM_CLASS is "Value", e.g.
@@ -3832,18 +3895,6 @@ struct OmpPrescriptiveness {
38323895
WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value);
38333896
};
38343897

3835-
// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
3836-
//
3837-
// reduction-identifier ->
3838-
// base-language-identifier | // since 4.5
3839-
// - | // since 4.5, until 5.2
3840-
// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
3841-
// MIN | MAX | IAND | IOR | IEOR // since 4.5
3842-
struct OmpReductionIdentifier {
3843-
UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
3844-
std::variant<DefinedOperator, ProcedureDesignator> u;
3845-
};
3846-
38473898
// Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137]
38483899
//
38493900
// reduction-modifier ->
@@ -3986,7 +4037,9 @@ struct OmpBindClause {
39864037
struct OmpDefaultClause {
39874038
ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None)
39884039
UNION_CLASS_BOILERPLATE(OmpDefaultClause);
3989-
std::variant<DataSharingAttribute, OmpDirectiveSpecification> u;
4040+
std::variant<DataSharingAttribute,
4041+
common::Indirection<OmpDirectiveSpecification>>
4042+
u;
39904043
};
39914044

39924045
// Ref: [4.5:103-107], [5.0:324-325], [5.1:357-358], [5.2:161-162]
@@ -4251,8 +4304,8 @@ struct OmpOrderClause {
42514304
// otherwise-clause ->
42524305
// OTHERWISE ([directive-specification])] // since 5.2
42534306
struct OmpOtherwiseClause {
4254-
WRAPPER_CLASS_BOILERPLATE(
4255-
OmpOtherwiseClause, std::optional<OmpDirectiveSpecification>);
4307+
WRAPPER_CLASS_BOILERPLATE(OmpOtherwiseClause,
4308+
std::optional<common::Indirection<OmpDirectiveSpecification>>);
42564309
};
42574310

42584311
// Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:229-230]
@@ -4348,7 +4401,9 @@ struct OmpUpdateClause {
43484401
struct OmpWhenClause {
43494402
TUPLE_CLASS_BOILERPLATE(OmpWhenClause);
43504403
MODIFIER_BOILERPLATE(OmpContextSelector);
4351-
std::tuple<MODIFIERS(), std::optional<OmpDirectiveSpecification>> t;
4404+
std::tuple<MODIFIERS(),
4405+
std::optional<common::Indirection<OmpDirectiveSpecification>>>
4406+
t;
43524407
};
43534408

43544409
// OpenMP Clauses
@@ -4375,6 +4430,14 @@ struct OmpClauseList {
43754430

43764431
// --- Directives and constructs
43774432

4433+
struct OmpDirectiveSpecification {
4434+
CharBlock source;
4435+
TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification);
4436+
std::tuple<llvm::omp::Directive, std::optional<std::list<OmpArgument>>,
4437+
std::optional<OmpClauseList>>
4438+
t;
4439+
};
4440+
43784441
struct OmpMetadirectiveDirective {
43794442
TUPLE_CLASS_BOILERPLATE(OmpMetadirectiveDirective);
43804443
std::tuple<OmpClauseList> t;
@@ -4475,27 +4538,16 @@ struct OpenMPDeclareTargetConstruct {
44754538
std::tuple<Verbatim, OmpDeclareTargetSpecifier> t;
44764539
};
44774540

4478-
struct OmpDeclareMapperSpecifier {
4479-
TUPLE_CLASS_BOILERPLATE(OmpDeclareMapperSpecifier);
4480-
std::tuple<std::optional<Name>, TypeSpec, Name> t;
4481-
};
4482-
44834541
// OMP v5.2: 5.8.8
44844542
// declare-mapper -> DECLARE MAPPER ([mapper-name :] type :: var) map-clauses
44854543
struct OpenMPDeclareMapperConstruct {
44864544
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareMapperConstruct);
44874545
CharBlock source;
4488-
std::tuple<Verbatim, OmpDeclareMapperSpecifier, OmpClauseList> t;
4546+
std::tuple<Verbatim, OmpMapperSpecifier, OmpClauseList> t;
44894547
};
44904548

44914549
// 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list
44924550
// : combiner) [initializer-clause]
4493-
struct OmpReductionCombiner {
4494-
UNION_CLASS_BOILERPLATE(OmpReductionCombiner);
4495-
WRAPPER_CLASS(FunctionCombiner, Call);
4496-
std::variant<AssignmentStmt, FunctionCombiner> u;
4497-
};
4498-
44994551
WRAPPER_CLASS(OmpReductionInitializerClause, Expr);
45004552

45014553
struct OpenMPDeclareReductionConstruct {

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ void OmpDirectiveNameParser::initTokens(NameWithId *table) const {
6868
[](auto &a, auto &b) { return a.first.size() > b.first.size(); });
6969
}
7070

71+
// --- Modifier helpers -----------------------------------------------
72+
7173
template <typename Clause, typename Separator> struct ModifierList {
7274
constexpr ModifierList(Separator sep) : sep_(sep) {}
7375
constexpr ModifierList(const ModifierList &) = default;
@@ -118,10 +120,8 @@ struct SpecificModifierParser {
118120
}
119121
};
120122

121-
// OpenMP Clauses
123+
// --- Iterator helpers -----------------------------------------------
122124

123-
// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple |
124-
// identifier = subscript-triple
125125
// [5.0:47:17-18] In an iterator-specifier, if the iterator-type is not
126126
// specified then the type of that iterator is default integer.
127127
// [5.0:49:14] The iterator-type must be an integer type.
@@ -153,8 +153,30 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) {
153153
makeEntityList(std::move(names)));
154154
}
155155

156-
TYPE_PARSER(sourced(construct<OmpDirectiveSpecification>(
157-
OmpDirectiveNameParser{}, maybe(indirect(Parser<OmpClauseList>{})))))
156+
// --- Parsers for arguments ------------------------------------------
157+
158+
// At the moment these are only directive arguments. This is needed for
159+
// parsing directive-specification.
160+
161+
TYPE_PARSER( //
162+
construct<OmpLocator>(Parser<OmpObject>{}) ||
163+
construct<OmpLocator>(Parser<FunctionReference>{}))
164+
165+
TYPE_PARSER(sourced( //
166+
construct<OmpArgument>(Parser<OmpMapperSpecifier>{}) ||
167+
construct<OmpArgument>(Parser<OmpReductionSpecifier>{}) ||
168+
construct<OmpArgument>(Parser<OmpLocator>{})))
169+
170+
TYPE_PARSER(construct<OmpLocatorList>(nonemptyList(Parser<OmpLocator>{})))
171+
172+
TYPE_PARSER( //
173+
construct<OmpTypeSpecifier>(Parser<TypeSpec>{}) ||
174+
construct<OmpTypeSpecifier>(Parser<DeclarationTypeSpec>{}))
175+
176+
TYPE_PARSER(construct<OmpReductionSpecifier>( //
177+
Parser<OmpReductionIdentifier>{},
178+
":"_tok >> nonemptyList(Parser<OmpTypeSpecifier>{}),
179+
maybe(":"_tok >> Parser<OmpReductionCombiner>{})))
158180

159181
// --- Parsers for context traits -------------------------------------
160182

@@ -213,15 +235,11 @@ static constexpr auto propertyListParser(PropParser... pp) {
213235
// the entire list in each of the alternative property parsers. Otherwise,
214236
// the name parser could stop after "foo" in "(foo, bar(1))", without
215237
// allowing the next parser to give the list a try.
216-
auto listOf{[](auto parser) { //
217-
return nonemptySeparated(parser, ",");
218-
}};
219-
220238
using P = OmpTraitProperty;
221239
return maybe("(" >> //
222240
construct<OmpTraitSelector::Properties>(
223241
maybe(Parser<OmpTraitScore>{} / ":"),
224-
(attempt(listOf(sourced(construct<P>(pp))) / ")") || ...)));
242+
(attempt(nonemptyList(sourced(construct<P>(pp))) / ")") || ...)));
225243
}
226244

227245
// Parser for OmpTraitSelector
@@ -309,7 +327,7 @@ TYPE_PARSER(sourced(construct<OmpTraitSetSelector>( //
309327
TYPE_PARSER(sourced(construct<OmpContextSelectorSpecification>(
310328
nonemptySeparated(Parser<OmpTraitSetSelector>{}, ","))))
311329

312-
// Parser<OmpContextSelector> == Parser<traits::OmpContextSelectorSpecification>
330+
// Note: OmpContextSelector is a type alias.
313331

314332
// --- Parsers for clause modifiers -----------------------------------
315333

@@ -543,7 +561,7 @@ TYPE_PARSER(construct<OmpDefaultClause::DataSharingAttribute>(
543561
TYPE_PARSER(construct<OmpDefaultClause>(
544562
construct<OmpDefaultClause>(
545563
Parser<OmpDefaultClause::DataSharingAttribute>{}) ||
546-
construct<OmpDefaultClause>(Parser<OmpDirectiveSpecification>{})))
564+
construct<OmpDefaultClause>(indirect(Parser<OmpDirectiveSpecification>{}))))
547565

548566
// 2.5 PROC_BIND (MASTER | CLOSE | PRIMARY | SPREAD)
549567
TYPE_PARSER(construct<OmpProcBindClause>(
@@ -713,11 +731,11 @@ TYPE_PARSER(construct<OmpMatchClause>(
713731
Parser<traits::OmpContextSelectorSpecification>{}))
714732

715733
TYPE_PARSER(construct<OmpOtherwiseClause>(
716-
maybe(sourced(Parser<OmpDirectiveSpecification>{}))))
734+
maybe(indirect(sourced(Parser<OmpDirectiveSpecification>{})))))
717735

718736
TYPE_PARSER(construct<OmpWhenClause>(
719737
maybe(nonemptyList(Parser<OmpWhenClause::Modifier>{}) / ":"),
720-
maybe(sourced(Parser<OmpDirectiveSpecification>{}))))
738+
maybe(indirect(sourced(Parser<OmpDirectiveSpecification>{})))))
721739

722740
// OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression)
723741
TYPE_PARSER(construct<OmpGrainsizeClause>(
@@ -933,6 +951,13 @@ TYPE_PARSER(construct<OmpObjectList>(nonemptyList(Parser<OmpObject>{})))
933951
TYPE_PARSER(sourced(construct<OmpErrorDirective>(
934952
verbatim("ERROR"_tok), Parser<OmpClauseList>{})))
935953

954+
// --- Parsers for directives and constructs --------------------------
955+
956+
TYPE_PARSER(sourced(construct<OmpDirectiveSpecification>( //
957+
OmpDirectiveNameParser{},
958+
maybe(parenthesized(nonemptyList(Parser<OmpArgument>{}))),
959+
maybe(Parser<OmpClauseList>{}))))
960+
936961
TYPE_PARSER(sourced(construct<OmpNothingDirective>("NOTHING" >> ok)))
937962

938963
TYPE_PARSER(sourced(construct<OpenMPUtilityConstruct>(
@@ -1145,20 +1170,17 @@ TYPE_PARSER(
11451170
TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
11461171
verbatim("DECLARE TARGET"_tok), Parser<OmpDeclareTargetSpecifier>{})))
11471172

1148-
// declare-mapper-specifier
1149-
TYPE_PARSER(construct<OmpDeclareMapperSpecifier>(
1173+
// mapper-specifier
1174+
TYPE_PARSER(construct<OmpMapperSpecifier>(
11501175
maybe(name / ":" / !":"_tok), typeSpec / "::", name))
11511176

11521177
// OpenMP 5.2: 5.8.8 Declare Mapper Construct
1153-
TYPE_PARSER(sourced(construct<OpenMPDeclareMapperConstruct>(
1154-
verbatim("DECLARE MAPPER"_tok),
1155-
"(" >> Parser<OmpDeclareMapperSpecifier>{} / ")", Parser<OmpClauseList>{})))
1178+
TYPE_PARSER(sourced(
1179+
construct<OpenMPDeclareMapperConstruct>(verbatim("DECLARE MAPPER"_tok),
1180+
parenthesized(Parser<OmpMapperSpecifier>{}), Parser<OmpClauseList>{})))
11561181

11571182
TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) ||
1158-
construct<OmpReductionCombiner>(
1159-
construct<OmpReductionCombiner::FunctionCombiner>(
1160-
construct<Call>(Parser<ProcedureDesignator>{},
1161-
parenthesized(optionalList(actualArgSpec))))))
1183+
construct<OmpReductionCombiner>(Parser<FunctionReference>{}))
11621184

11631185
// 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] |
11641186
// ATOMIC [clause]

0 commit comments

Comments
 (0)