Skip to content

Commit e230e8a

Browse files
committed
[flang][OpenMP] Handle directive arguments in OmpDirectiveSpecifier
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 7c2a3be commit e230e8a

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
@@ -476,6 +476,12 @@ class ParseTreeDumper {
476476
NODE(parser, NullInit)
477477
NODE(parser, ObjectDecl)
478478
NODE(parser, OldParameterStmt)
479+
NODE(parser, OmpTypeSpecifier)
480+
NODE(parser, OmpTypeNameList)
481+
NODE(parser, OmpLocator)
482+
NODE(parser, OmpLocatorList)
483+
NODE(parser, OmpReductionSpecifier)
484+
NODE(parser, OmpArgument)
479485
NODE(parser, OmpMetadirectiveDirective)
480486
NODE(parser, OmpMatchClause)
481487
NODE(parser, OmpOtherwiseClause)
@@ -541,7 +547,7 @@ class ParseTreeDumper {
541547
NODE(parser, OmpDeclareTargetSpecifier)
542548
NODE(parser, OmpDeclareTargetWithClause)
543549
NODE(parser, OmpDeclareTargetWithList)
544-
NODE(parser, OmpDeclareMapperSpecifier)
550+
NODE(parser, OmpMapperSpecifier)
545551
NODE(parser, OmpDefaultClause)
546552
NODE_ENUM(OmpDefaultClause, DataSharingAttribute)
547553
NODE(parser, OmpVariableCategory)
@@ -624,7 +630,6 @@ class ParseTreeDumper {
624630
NODE(parser, OmpReductionCombiner)
625631
NODE(parser, OmpTaskReductionClause)
626632
NODE(OmpTaskReductionClause, Modifier)
627-
NODE(OmpReductionCombiner, FunctionCombiner)
628633
NODE(parser, OmpReductionInitializerClause)
629634
NODE(parser, OmpReductionIdentifier)
630635
NODE(parser, OmpAllocateClause)

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

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

34563456
struct OmpClause;
3457-
struct OmpClauseList;
3458-
3459-
struct OmpDirectiveSpecification {
3460-
TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification);
3461-
std::tuple<llvm::omp::Directive,
3462-
std::optional<common::Indirection<OmpClauseList>>>
3463-
t;
3464-
CharBlock source;
3465-
};
3457+
struct OmpDirectiveSpecification;
34663458

34673459
// 2.1 Directives or clauses may accept a list or extended-list.
34683460
// A list item is a variable, array section or common block name (enclosed
@@ -3475,15 +3467,76 @@ struct OmpObject {
34753467

34763468
WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
34773469

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

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

34883541
inline namespace traits {
34893542
// trait-property-name ->
@@ -3617,6 +3670,16 @@ struct OmpContextSelectorSpecification { // Modifier
36173670
};
36183671
} // namespace traits
36193672

3673+
#define MODIFIER_BOILERPLATE(...) \
3674+
struct Modifier { \
3675+
using Variant = std::variant<__VA_ARGS__>; \
3676+
UNION_CLASS_BOILERPLATE(Modifier); \
3677+
CharBlock source; \
3678+
Variant u; \
3679+
}
3680+
3681+
#define MODIFIERS() std::optional<std::list<Modifier>>
3682+
36203683
inline namespace modifier {
36213684
// For uniformity, in all keyword modifiers the name of the type defined
36223685
// by ENUM_CLASS is "Value", e.g.
@@ -3829,18 +3892,6 @@ struct OmpPrescriptiveness {
38293892
WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value);
38303893
};
38313894

3832-
// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
3833-
//
3834-
// reduction-identifier ->
3835-
// base-language-identifier | // since 4.5
3836-
// - | // since 4.5, until 5.2
3837-
// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
3838-
// MIN | MAX | IAND | IOR | IEOR // since 4.5
3839-
struct OmpReductionIdentifier {
3840-
UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
3841-
std::variant<DefinedOperator, ProcedureDesignator> u;
3842-
};
3843-
38443895
// Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137]
38453896
//
38463897
// reduction-modifier ->
@@ -3983,7 +4034,9 @@ struct OmpBindClause {
39834034
struct OmpDefaultClause {
39844035
ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None)
39854036
UNION_CLASS_BOILERPLATE(OmpDefaultClause);
3986-
std::variant<DataSharingAttribute, OmpDirectiveSpecification> u;
4037+
std::variant<DataSharingAttribute,
4038+
common::Indirection<OmpDirectiveSpecification>>
4039+
u;
39874040
};
39884041

39894042
// Ref: [4.5:103-107], [5.0:324-325], [5.1:357-358], [5.2:161-162]
@@ -4248,8 +4301,8 @@ struct OmpOrderClause {
42484301
// otherwise-clause ->
42494302
// OTHERWISE ([directive-specification])] // since 5.2
42504303
struct OmpOtherwiseClause {
4251-
WRAPPER_CLASS_BOILERPLATE(
4252-
OmpOtherwiseClause, std::optional<OmpDirectiveSpecification>);
4304+
WRAPPER_CLASS_BOILERPLATE(OmpOtherwiseClause,
4305+
std::optional<common::Indirection<OmpDirectiveSpecification>>);
42534306
};
42544307

42554308
// Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:229-230]
@@ -4345,7 +4398,9 @@ struct OmpUpdateClause {
43454398
struct OmpWhenClause {
43464399
TUPLE_CLASS_BOILERPLATE(OmpWhenClause);
43474400
MODIFIER_BOILERPLATE(OmpContextSelector);
4348-
std::tuple<MODIFIERS(), std::optional<OmpDirectiveSpecification>> t;
4401+
std::tuple<MODIFIERS(),
4402+
std::optional<common::Indirection<OmpDirectiveSpecification>>>
4403+
t;
43494404
};
43504405

43514406
// OpenMP Clauses
@@ -4372,6 +4427,14 @@ struct OmpClauseList {
43724427

43734428
// --- Directives and constructs
43744429

4430+
struct OmpDirectiveSpecification {
4431+
CharBlock source;
4432+
TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification);
4433+
std::tuple<llvm::omp::Directive, std::optional<std::list<OmpArgument>>,
4434+
std::optional<OmpClauseList>>
4435+
t;
4436+
};
4437+
43754438
struct OmpMetadirectiveDirective {
43764439
TUPLE_CLASS_BOILERPLATE(OmpMetadirectiveDirective);
43774440
std::tuple<OmpClauseList> t;
@@ -4472,27 +4535,16 @@ struct OpenMPDeclareTargetConstruct {
44724535
std::tuple<Verbatim, OmpDeclareTargetSpecifier> t;
44734536
};
44744537

4475-
struct OmpDeclareMapperSpecifier {
4476-
TUPLE_CLASS_BOILERPLATE(OmpDeclareMapperSpecifier);
4477-
std::tuple<std::optional<Name>, TypeSpec, Name> t;
4478-
};
4479-
44804538
// OMP v5.2: 5.8.8
44814539
// declare-mapper -> DECLARE MAPPER ([mapper-name :] type :: var) map-clauses
44824540
struct OpenMPDeclareMapperConstruct {
44834541
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareMapperConstruct);
44844542
CharBlock source;
4485-
std::tuple<Verbatim, OmpDeclareMapperSpecifier, OmpClauseList> t;
4543+
std::tuple<Verbatim, OmpMapperSpecifier, OmpClauseList> t;
44864544
};
44874545

44884546
// 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list
44894547
// : combiner) [initializer-clause]
4490-
struct OmpReductionCombiner {
4491-
UNION_CLASS_BOILERPLATE(OmpReductionCombiner);
4492-
WRAPPER_CLASS(FunctionCombiner, Call);
4493-
std::variant<AssignmentStmt, FunctionCombiner> u;
4494-
};
4495-
44964548
WRAPPER_CLASS(OmpReductionInitializerClause, Expr);
44974549

44984550
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>(
@@ -929,6 +947,13 @@ TYPE_PARSER(construct<OmpObjectList>(nonemptyList(Parser<OmpObject>{})))
929947
TYPE_PARSER(sourced(construct<OmpErrorDirective>(
930948
verbatim("ERROR"_tok), Parser<OmpClauseList>{})))
931949

950+
// --- Parsers for directives and constructs --------------------------
951+
952+
TYPE_PARSER(sourced(construct<OmpDirectiveSpecification>( //
953+
OmpDirectiveNameParser{},
954+
maybe(parenthesized(nonemptyList(Parser<OmpArgument>{}))),
955+
maybe(Parser<OmpClauseList>{}))))
956+
932957
TYPE_PARSER(sourced(construct<OmpNothingDirective>("NOTHING" >> ok)))
933958

934959
TYPE_PARSER(sourced(construct<OpenMPUtilityConstruct>(
@@ -1141,20 +1166,17 @@ TYPE_PARSER(
11411166
TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
11421167
verbatim("DECLARE TARGET"_tok), Parser<OmpDeclareTargetSpecifier>{})))
11431168

1144-
// declare-mapper-specifier
1145-
TYPE_PARSER(construct<OmpDeclareMapperSpecifier>(
1169+
// mapper-specifier
1170+
TYPE_PARSER(construct<OmpMapperSpecifier>(
11461171
maybe(name / ":" / !":"_tok), typeSpec / "::", name))
11471172

11481173
// OpenMP 5.2: 5.8.8 Declare Mapper Construct
1149-
TYPE_PARSER(sourced(construct<OpenMPDeclareMapperConstruct>(
1150-
verbatim("DECLARE MAPPER"_tok),
1151-
"(" >> Parser<OmpDeclareMapperSpecifier>{} / ")", Parser<OmpClauseList>{})))
1174+
TYPE_PARSER(sourced(
1175+
construct<OpenMPDeclareMapperConstruct>(verbatim("DECLARE MAPPER"_tok),
1176+
parenthesized(Parser<OmpMapperSpecifier>{}), Parser<OmpClauseList>{})))
11521177

11531178
TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) ||
1154-
construct<OmpReductionCombiner>(
1155-
construct<OmpReductionCombiner::FunctionCombiner>(
1156-
construct<Call>(Parser<ProcedureDesignator>{},
1157-
parenthesized(optionalList(actualArgSpec))))))
1179+
construct<OmpReductionCombiner>(Parser<FunctionReference>{}))
11581180

11591181
// 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] |
11601182
// ATOMIC [clause]

0 commit comments

Comments
 (0)