Skip to content

[flang][OpenMP] Handle directive arguments in OmpDirectiveSpecifier #124278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion flang/examples/FeatureList/FeatureList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,6 @@ struct NodeVisitor {
READ_FEATURE(OmpReductionClause)
READ_FEATURE(OmpInReductionClause)
READ_FEATURE(OmpReductionCombiner)
READ_FEATURE(OmpReductionCombiner::FunctionCombiner)
READ_FEATURE(OmpReductionInitializerClause)
READ_FEATURE(OmpReductionIdentifier)
READ_FEATURE(OmpAllocateClause)
Expand Down
9 changes: 7 additions & 2 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,12 @@ class ParseTreeDumper {
NODE(parser, NullInit)
NODE(parser, ObjectDecl)
NODE(parser, OldParameterStmt)
NODE(parser, OmpTypeSpecifier)
NODE(parser, OmpTypeNameList)
NODE(parser, OmpLocator)
NODE(parser, OmpLocatorList)
NODE(parser, OmpReductionSpecifier)
NODE(parser, OmpArgument)
NODE(parser, OmpMetadirectiveDirective)
NODE(parser, OmpMatchClause)
NODE(parser, OmpOtherwiseClause)
Expand Down Expand Up @@ -542,7 +548,7 @@ class ParseTreeDumper {
NODE(parser, OmpDeclareTargetSpecifier)
NODE(parser, OmpDeclareTargetWithClause)
NODE(parser, OmpDeclareTargetWithList)
NODE(parser, OmpDeclareMapperSpecifier)
NODE(parser, OmpMapperSpecifier)
NODE(parser, OmpDefaultClause)
NODE_ENUM(OmpDefaultClause, DataSharingAttribute)
NODE(parser, OmpVariableCategory)
Expand Down Expand Up @@ -625,7 +631,6 @@ class ParseTreeDumper {
NODE(parser, OmpReductionCombiner)
NODE(parser, OmpTaskReductionClause)
NODE(OmpTaskReductionClause, Modifier)
NODE(OmpReductionCombiner, FunctionCombiner)
NODE(parser, OmpReductionInitializerClause)
NODE(parser, OmpReductionIdentifier)
NODE(parser, OmpAllocateClause)
Expand Down
142 changes: 97 additions & 45 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3457,15 +3457,7 @@ WRAPPER_CLASS(PauseStmt, std::optional<StopCode>);
// --- Common definitions

struct OmpClause;
struct OmpClauseList;

struct OmpDirectiveSpecification {
TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification);
std::tuple<llvm::omp::Directive,
std::optional<common::Indirection<OmpClauseList>>>
t;
CharBlock source;
};
struct OmpDirectiveSpecification;

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

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

#define MODIFIER_BOILERPLATE(...) \
struct Modifier { \
using Variant = std::variant<__VA_ARGS__>; \
UNION_CLASS_BOILERPLATE(Modifier); \
CharBlock source; \
Variant u; \
}
// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
//
// reduction-identifier ->
// base-language-identifier | // since 4.5
// - | // since 4.5, until 5.2
// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
// MIN | MAX | IAND | IOR | IEOR // since 4.5
struct OmpReductionIdentifier {
UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
std::variant<DefinedOperator, ProcedureDesignator> u;
};

#define MODIFIERS() std::optional<std::list<Modifier>>
// Ref: [4.5:222:6], [5.0:305:27], [5.1:337:19], [5.2:126:3-4], [6.0:240:27-28]
//
// combiner-expression -> // since 4.5
// assignment-statement |
// function-reference
struct OmpReductionCombiner {
UNION_CLASS_BOILERPLATE(OmpReductionCombiner);
std::variant<AssignmentStmt, FunctionReference> u;
};

inline namespace arguments {
struct OmpTypeSpecifier {
UNION_CLASS_BOILERPLATE(OmpTypeSpecifier);
std::variant<TypeSpec, DeclarationTypeSpec> u;
};

WRAPPER_CLASS(OmpTypeNameList, std::list<OmpTypeSpecifier>);

struct OmpLocator {
UNION_CLASS_BOILERPLATE(OmpLocator);
std::variant<OmpObject, FunctionReference> u;
};

WRAPPER_CLASS(OmpLocatorList, std::list<OmpLocator>);

// Ref: [5.0:326:10-16], [5.1:359:5-11], [5.2:163:2-7], [6.0:293:16-21]
//
// mapper-specifier ->
// [mapper-identifier :] type :: var | // since 5.0
// DEFAULT type :: var
struct OmpMapperSpecifier {
// Absent mapper-identifier is equivalent to DEFAULT.
TUPLE_CLASS_BOILERPLATE(OmpMapperSpecifier);
std::tuple<std::optional<Name>, TypeSpec, Name> t;
};

// Ref: [4.5:222:1-5], [5.0:305:20-27], [5.1:337:11-19], [5.2:139:18-23],
// [6.0:260:16-20]
//
// reduction-specifier ->
// reduction-identifier : typename-list
// : combiner-expression // since 4.5, until 5.2
// reduction-identifier : typename-list // since 6.0
struct OmpReductionSpecifier {
TUPLE_CLASS_BOILERPLATE(OmpReductionSpecifier);
std::tuple<OmpReductionIdentifier, OmpTypeNameList,
std::optional<OmpReductionCombiner>>
t;
};

struct OmpArgument {
CharBlock source;
UNION_CLASS_BOILERPLATE(OmpArgument);
std::variant<OmpLocator, // {variable, extended, locator}-list-item
OmpMapperSpecifier, OmpReductionSpecifier>
u;
};
} // namespace arguments

inline namespace traits {
// trait-property-name ->
Expand Down Expand Up @@ -3620,6 +3673,16 @@ struct OmpContextSelectorSpecification { // Modifier
};
} // namespace traits

#define MODIFIER_BOILERPLATE(...) \
struct Modifier { \
using Variant = std::variant<__VA_ARGS__>; \
UNION_CLASS_BOILERPLATE(Modifier); \
CharBlock source; \
Variant u; \
}

#define MODIFIERS() std::optional<std::list<Modifier>>

inline namespace modifier {
// For uniformity, in all keyword modifiers the name of the type defined
// by ENUM_CLASS is "Value", e.g.
Expand Down Expand Up @@ -3832,18 +3895,6 @@ struct OmpPrescriptiveness {
WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value);
};

// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124]
//
// reduction-identifier ->
// base-language-identifier | // since 4.5
// - | // since 4.5, until 5.2
// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5
// MIN | MAX | IAND | IOR | IEOR // since 4.5
struct OmpReductionIdentifier {
UNION_CLASS_BOILERPLATE(OmpReductionIdentifier);
std::variant<DefinedOperator, ProcedureDesignator> u;
};

// Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137]
//
// reduction-modifier ->
Expand Down Expand Up @@ -3986,7 +4037,9 @@ struct OmpBindClause {
struct OmpDefaultClause {
ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None)
UNION_CLASS_BOILERPLATE(OmpDefaultClause);
std::variant<DataSharingAttribute, OmpDirectiveSpecification> u;
std::variant<DataSharingAttribute,
common::Indirection<OmpDirectiveSpecification>>
u;
};

// Ref: [4.5:103-107], [5.0:324-325], [5.1:357-358], [5.2:161-162]
Expand Down Expand Up @@ -4251,8 +4304,8 @@ struct OmpOrderClause {
// otherwise-clause ->
// OTHERWISE ([directive-specification])] // since 5.2
struct OmpOtherwiseClause {
WRAPPER_CLASS_BOILERPLATE(
OmpOtherwiseClause, std::optional<OmpDirectiveSpecification>);
WRAPPER_CLASS_BOILERPLATE(OmpOtherwiseClause,
std::optional<common::Indirection<OmpDirectiveSpecification>>);
};

// Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:229-230]
Expand Down Expand Up @@ -4348,7 +4401,9 @@ struct OmpUpdateClause {
struct OmpWhenClause {
TUPLE_CLASS_BOILERPLATE(OmpWhenClause);
MODIFIER_BOILERPLATE(OmpContextSelector);
std::tuple<MODIFIERS(), std::optional<OmpDirectiveSpecification>> t;
std::tuple<MODIFIERS(),
std::optional<common::Indirection<OmpDirectiveSpecification>>>
t;
};

// OpenMP Clauses
Expand All @@ -4375,6 +4430,14 @@ struct OmpClauseList {

// --- Directives and constructs

struct OmpDirectiveSpecification {
CharBlock source;
TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification);
std::tuple<llvm::omp::Directive, std::optional<std::list<OmpArgument>>,
std::optional<OmpClauseList>>
t;
};

struct OmpMetadirectiveDirective {
TUPLE_CLASS_BOILERPLATE(OmpMetadirectiveDirective);
std::tuple<OmpClauseList> t;
Expand Down Expand Up @@ -4475,27 +4538,16 @@ struct OpenMPDeclareTargetConstruct {
std::tuple<Verbatim, OmpDeclareTargetSpecifier> t;
};

struct OmpDeclareMapperSpecifier {
TUPLE_CLASS_BOILERPLATE(OmpDeclareMapperSpecifier);
std::tuple<std::optional<Name>, TypeSpec, Name> t;
};

// OMP v5.2: 5.8.8
// declare-mapper -> DECLARE MAPPER ([mapper-name :] type :: var) map-clauses
struct OpenMPDeclareMapperConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareMapperConstruct);
CharBlock source;
std::tuple<Verbatim, OmpDeclareMapperSpecifier, OmpClauseList> t;
std::tuple<Verbatim, OmpMapperSpecifier, OmpClauseList> t;
};

// 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list
// : combiner) [initializer-clause]
struct OmpReductionCombiner {
UNION_CLASS_BOILERPLATE(OmpReductionCombiner);
WRAPPER_CLASS(FunctionCombiner, Call);
std::variant<AssignmentStmt, FunctionCombiner> u;
};

WRAPPER_CLASS(OmpReductionInitializerClause, Expr);

struct OpenMPDeclareReductionConstruct {
Expand Down
68 changes: 45 additions & 23 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ void OmpDirectiveNameParser::initTokens(NameWithId *table) const {
[](auto &a, auto &b) { return a.first.size() > b.first.size(); });
}

// --- Modifier helpers -----------------------------------------------

template <typename Clause, typename Separator> struct ModifierList {
constexpr ModifierList(Separator sep) : sep_(sep) {}
constexpr ModifierList(const ModifierList &) = default;
Expand Down Expand Up @@ -118,10 +120,8 @@ struct SpecificModifierParser {
}
};

// OpenMP Clauses
// --- Iterator helpers -----------------------------------------------

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

TYPE_PARSER(sourced(construct<OmpDirectiveSpecification>(
OmpDirectiveNameParser{}, maybe(indirect(Parser<OmpClauseList>{})))))
// --- Parsers for arguments ------------------------------------------

// At the moment these are only directive arguments. This is needed for
// parsing directive-specification.

TYPE_PARSER( //
construct<OmpLocator>(Parser<OmpObject>{}) ||
construct<OmpLocator>(Parser<FunctionReference>{}))

TYPE_PARSER(sourced( //
construct<OmpArgument>(Parser<OmpMapperSpecifier>{}) ||
construct<OmpArgument>(Parser<OmpReductionSpecifier>{}) ||
construct<OmpArgument>(Parser<OmpLocator>{})))

TYPE_PARSER(construct<OmpLocatorList>(nonemptyList(Parser<OmpLocator>{})))

TYPE_PARSER( //
construct<OmpTypeSpecifier>(Parser<TypeSpec>{}) ||
construct<OmpTypeSpecifier>(Parser<DeclarationTypeSpec>{}))

TYPE_PARSER(construct<OmpReductionSpecifier>( //
Parser<OmpReductionIdentifier>{},
":"_tok >> nonemptyList(Parser<OmpTypeSpecifier>{}),
maybe(":"_tok >> Parser<OmpReductionCombiner>{})))

// --- Parsers for context traits -------------------------------------

Expand Down Expand Up @@ -213,15 +235,11 @@ static constexpr auto propertyListParser(PropParser... pp) {
// the entire list in each of the alternative property parsers. Otherwise,
// the name parser could stop after "foo" in "(foo, bar(1))", without
// allowing the next parser to give the list a try.
auto listOf{[](auto parser) { //
return nonemptySeparated(parser, ",");
}};

using P = OmpTraitProperty;
return maybe("(" >> //
construct<OmpTraitSelector::Properties>(
maybe(Parser<OmpTraitScore>{} / ":"),
(attempt(listOf(sourced(construct<P>(pp))) / ")") || ...)));
(attempt(nonemptyList(sourced(construct<P>(pp))) / ")") || ...)));
}

// Parser for OmpTraitSelector
Expand Down Expand Up @@ -309,7 +327,7 @@ TYPE_PARSER(sourced(construct<OmpTraitSetSelector>( //
TYPE_PARSER(sourced(construct<OmpContextSelectorSpecification>(
nonemptySeparated(Parser<OmpTraitSetSelector>{}, ","))))

// Parser<OmpContextSelector> == Parser<traits::OmpContextSelectorSpecification>
// Note: OmpContextSelector is a type alias.

// --- Parsers for clause modifiers -----------------------------------

Expand Down Expand Up @@ -543,7 +561,7 @@ TYPE_PARSER(construct<OmpDefaultClause::DataSharingAttribute>(
TYPE_PARSER(construct<OmpDefaultClause>(
construct<OmpDefaultClause>(
Parser<OmpDefaultClause::DataSharingAttribute>{}) ||
construct<OmpDefaultClause>(Parser<OmpDirectiveSpecification>{})))
construct<OmpDefaultClause>(indirect(Parser<OmpDirectiveSpecification>{}))))

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

TYPE_PARSER(construct<OmpOtherwiseClause>(
maybe(sourced(Parser<OmpDirectiveSpecification>{}))))
maybe(indirect(sourced(Parser<OmpDirectiveSpecification>{})))))

TYPE_PARSER(construct<OmpWhenClause>(
maybe(nonemptyList(Parser<OmpWhenClause::Modifier>{}) / ":"),
maybe(sourced(Parser<OmpDirectiveSpecification>{}))))
maybe(indirect(sourced(Parser<OmpDirectiveSpecification>{})))))

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

// --- Parsers for directives and constructs --------------------------

TYPE_PARSER(sourced(construct<OmpDirectiveSpecification>( //
OmpDirectiveNameParser{},
maybe(parenthesized(nonemptyList(Parser<OmpArgument>{}))),
maybe(Parser<OmpClauseList>{}))))

TYPE_PARSER(sourced(construct<OmpNothingDirective>("NOTHING" >> ok)))

TYPE_PARSER(sourced(construct<OpenMPUtilityConstruct>(
Expand Down Expand Up @@ -1145,20 +1170,17 @@ TYPE_PARSER(
TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
verbatim("DECLARE TARGET"_tok), Parser<OmpDeclareTargetSpecifier>{})))

// declare-mapper-specifier
TYPE_PARSER(construct<OmpDeclareMapperSpecifier>(
// mapper-specifier
TYPE_PARSER(construct<OmpMapperSpecifier>(
maybe(name / ":" / !":"_tok), typeSpec / "::", name))

// OpenMP 5.2: 5.8.8 Declare Mapper Construct
TYPE_PARSER(sourced(construct<OpenMPDeclareMapperConstruct>(
verbatim("DECLARE MAPPER"_tok),
"(" >> Parser<OmpDeclareMapperSpecifier>{} / ")", Parser<OmpClauseList>{})))
TYPE_PARSER(sourced(
construct<OpenMPDeclareMapperConstruct>(verbatim("DECLARE MAPPER"_tok),
parenthesized(Parser<OmpMapperSpecifier>{}), Parser<OmpClauseList>{})))

TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) ||
construct<OmpReductionCombiner>(
construct<OmpReductionCombiner::FunctionCombiner>(
construct<Call>(Parser<ProcedureDesignator>{},
parenthesized(optionalList(actualArgSpec))))))
construct<OmpReductionCombiner>(Parser<FunctionReference>{}))

// 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] |
// ATOMIC [clause]
Expand Down
Loading