Skip to content

Commit

Permalink
[flang][OpenMP] Normalize clause modifiers that exist on their own (l…
Browse files Browse the repository at this point in the history
…lvm#116655)

This is the first part of the effort to make parsing of clause modifiers
more uniform and robust. Currently, when multiple modifiers are allowed,
the parser will expect them to appear in a hard-coded order.
Additionally, modifier properties (such as "ultimate") are checked
separately for each case.

The overall plan is
1. Extract all modifiers into their own top-level classes, and then
equip them with sets of common properties that will allow performing the
property checks generically, without refering to the specific kind of
the modifier.
2. Define a parser (as a separate class) for each modifier.
3. For each clause define a union (std::variant) of all allowable
modifiers, and parse the modifiers as a list of these unions.

The intent is also to isolate parts of the code that could eventually be
auto-generated.

OpenMP modifier overhaul: #1/3
  • Loading branch information
kparzysz authored Nov 20, 2024
1 parent b49c4af commit cfd67c2
Show file tree
Hide file tree
Showing 19 changed files with 196 additions and 167 deletions.
8 changes: 4 additions & 4 deletions flang/examples/FeatureList/FeatureList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,9 +475,9 @@ struct NodeVisitor {
READ_FEATURE(OmpDoacross::Source)
READ_FEATURE(OmpDoacrossClause)
READ_FEATURE(OmpDependenceType)
READ_FEATURE(OmpDependenceType::Type)
READ_FEATURE(OmpDependenceType::Value)
READ_FEATURE(OmpTaskDependenceType)
READ_FEATURE(OmpTaskDependenceType::Type)
READ_FEATURE(OmpTaskDependenceType::Value)
READ_FEATURE(OmpIteration)
READ_FEATURE(OmpIterationOffset)
READ_FEATURE(OmpIterationVector)
Expand All @@ -495,7 +495,7 @@ struct NodeVisitor {
READ_FEATURE(OmpLinearClause::WithModifier)
READ_FEATURE(OmpLinearClause::WithoutModifier)
READ_FEATURE(OmpLinearModifier)
READ_FEATURE(OmpLinearModifier::Type)
READ_FEATURE(OmpLinearModifier::Value)
READ_FEATURE(OmpLoopDirective)
READ_FEATURE(OmpMapClause)
READ_FEATURE(OmpMapClause::TypeModifier)
Expand All @@ -515,7 +515,7 @@ struct NodeVisitor {
READ_FEATURE(OmpReductionCombiner)
READ_FEATURE(OmpReductionCombiner::FunctionCombiner)
READ_FEATURE(OmpReductionInitializerClause)
READ_FEATURE(OmpReductionOperator)
READ_FEATURE(OmpReductionIdentifier)
READ_FEATURE(OmpAllocateClause)
READ_FEATURE(OmpAllocateClause::AllocateModifier)
READ_FEATURE(OmpAllocateClause::AllocateModifier::Allocator)
Expand Down
4 changes: 2 additions & 2 deletions flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,11 @@ void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) {
clauseDetails +=
"modifier=" + std::string{OmpScheduleModifierType::EnumToString(c)} + ";";
}
void OpenMPCounterVisitor::Post(const OmpLinearModifier::Type &c) {
void OpenMPCounterVisitor::Post(const OmpLinearModifier::Value &c) {
clauseDetails +=
"modifier=" + std::string{OmpLinearModifier::EnumToString(c)} + ";";
}
void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Type &c) {
void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Value &c) {
clauseDetails +=
"type=" + std::string{OmpTaskDependenceType::EnumToString(c)} + ";";
}
Expand Down
4 changes: 2 additions & 2 deletions flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ struct OpenMPCounterVisitor {
void Post(const OmpDefaultmapClause::VariableCategory &c);
void Post(const OmpDeviceTypeClause::Type &c);
void Post(const OmpScheduleModifierType::ModType &c);
void Post(const OmpLinearModifier::Type &c);
void Post(const OmpTaskDependenceType::Type &c);
void Post(const OmpLinearModifier::Value &c);
void Post(const OmpTaskDependenceType::Value &c);
void Post(const OmpMapClause::Type &c);
void Post(const OmpScheduleClause::ScheduleType &c);
void Post(const OmpIfClause::DirectiveNameModifier &c);
Expand Down
10 changes: 5 additions & 5 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ class ParseTreeDumper {
NODE(parser, ObjectDecl)
NODE(parser, OldParameterStmt)
NODE(parser, OmpIteratorSpecifier)
NODE(parser, OmpIteratorModifier)
NODE(parser, OmpIterator)
NODE(parser, OmpAffinityClause)
NODE(parser, OmpAlignedClause)
NODE(parser, OmpAtomic)
Expand Down Expand Up @@ -513,9 +513,9 @@ class ParseTreeDumper {
NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior)
NODE_ENUM(OmpDefaultmapClause, VariableCategory)
NODE(parser, OmpDependenceType)
NODE_ENUM(OmpDependenceType, Type)
NODE_ENUM(OmpDependenceType, Value)
NODE(parser, OmpTaskDependenceType)
NODE_ENUM(OmpTaskDependenceType, Type)
NODE_ENUM(OmpTaskDependenceType, Value)
NODE(parser, OmpIterationOffset)
NODE(parser, OmpIteration)
NODE(parser, OmpIterationVector)
Expand Down Expand Up @@ -543,7 +543,7 @@ class ParseTreeDumper {
NODE(OmpLinearClause, WithModifier)
NODE(OmpLinearClause, WithoutModifier)
NODE(parser, OmpLinearModifier)
NODE_ENUM(OmpLinearModifier, Type)
NODE_ENUM(OmpLinearModifier, Value)
NODE(parser, OmpLoopDirective)
NODE(parser, OmpMapClause)
NODE(parser, OmpMapperIdentifier)
Expand Down Expand Up @@ -574,7 +574,7 @@ class ParseTreeDumper {
NODE(parser, OmpReductionCombiner)
NODE(OmpReductionCombiner, FunctionCombiner)
NODE(parser, OmpReductionInitializerClause)
NODE(parser, OmpReductionOperator)
NODE(parser, OmpReductionIdentifier)
NODE(parser, OmpAllocateClause)
NODE(OmpAllocateClause, AllocateModifier)
NODE(OmpAllocateClause::AllocateModifier, Allocator)
Expand Down
113 changes: 70 additions & 43 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3440,13 +3440,33 @@ struct OmpObject {

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

inline namespace modifier {
// For uniformity, in all keyword modifiers the name of the type defined
// by ENUM_CLASS is "Value", e.g.
// struct Foo {
// ENUM_CLASS(Value, Keyword1, Keyword2);
// };

// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
//
// iterator-specifier ->
// [iterator-type] iterator-identifier
// = range-specification | // since 5.0
// [iterator-type ::] iterator-identifier
// = range-specification // since 5.2
struct OmpIteratorSpecifier {
TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
CharBlock source;
std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
};

// Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289]
//
// dependence-type ->
// SINK | SOURCE | // since 4.5
// IN | OUT | INOUT | // since 4.5, until 5.1
// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1
// INOUTSET // since 5.1, until 5.1
// SINK | SOURCE | // since 4.5
// IN | OUT | INOUT | // since 4.5, until 5.1
// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1
// INOUTSET // since 5.1, until 5.1
//
// All of these, except SINK and SOURCE became task-dependence-type in 5.2.
//
Expand All @@ -3457,45 +3477,59 @@ WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
// vector). This would accept the vector "i, j, k" (although interpreted
// incorrectly), while flagging a syntax error for "i+1, j, k".
struct OmpDependenceType {
ENUM_CLASS(Type, Sink, Source);
WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type);
ENUM_CLASS(Value, Sink, Source);
WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Value);
};

// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
//
// task-dependence-type -> // "dependence-type" in 5.1 and before
// IN | OUT | INOUT | // since 4.5
// MUTEXINOUTSET | DEPOBJ | // since 5.0
// INOUTSET // since 5.2
struct OmpTaskDependenceType {
ENUM_CLASS(Type, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Type);
// iterator-modifier ->
// ITERATOR(iterator-specifier [, ...]) // since 5.0
struct OmpIterator {
WRAPPER_CLASS_BOILERPLATE(OmpIterator, std::list<OmpIteratorSpecifier>);
};

// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple
// iterator-modifier -> iterator-specifier-list
struct OmpIteratorSpecifier {
TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier);
CharBlock source;
std::tuple<TypeDeclarationStmt, SubscriptTriplet> t;
// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120]
//
// linear-modifier ->
// REF | UVAL | VAL // since 4.5
struct OmpLinearModifier {
ENUM_CLASS(Value, Ref, Uval, Val);
WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Value);
};

WRAPPER_CLASS(OmpIteratorModifier, std::list<OmpIteratorSpecifier>);

// 2.15.3.6 reduction-identifier -> + | - | * | .AND. | .OR. | .EQV. | .NEQV. |
// MAX | MIN | IAND | IOR | IEOR
struct OmpReductionOperator {
UNION_CLASS_BOILERPLATE(OmpReductionOperator);
// 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: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321]
//
// task-dependence-type -> // "dependence-type" in 5.1 and before
// IN | OUT | INOUT | // since 4.5
// MUTEXINOUTSET | DEPOBJ | // since 5.0
// INOUTSET // since 5.2
struct OmpTaskDependenceType {
ENUM_CLASS(Value, In, Out, Inout, Inoutset, Mutexinoutset, Depobj)
WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Value);
};
} // namespace modifier

// --- Clauses

// OMP 5.0 2.10.1 affinity([aff-modifier:] locator-list)
// aff-modifier: interator-modifier
struct OmpAffinityClause {
TUPLE_CLASS_BOILERPLATE(OmpAffinityClause);
std::tuple<std::optional<OmpIteratorModifier>, OmpObjectList> t;
std::tuple<std::optional<OmpIterator>, OmpObjectList> t;
};

// 2.8.1 aligned-clause -> ALIGNED (variable-name-list[ : scalar-constant])
Expand Down Expand Up @@ -3566,7 +3600,7 @@ WRAPPER_CLASS(OmpIterationVector, std::list<OmpIteration>);
// OmpDoacrossClause), so that the context in TYPE_CONTEXT_PARSER can be set
// separately for OmpDependClause and OmpDoacrossClause.
struct OmpDoacross {
OmpDependenceType::Type GetDepType() const;
OmpDependenceType::Value GetDepType() const;

WRAPPER_CLASS(Sink, OmpIterationVector);
EMPTY_CLASS(Source);
Expand All @@ -3586,10 +3620,9 @@ struct OmpDoacross {
struct OmpDependClause {
UNION_CLASS_BOILERPLATE(OmpDependClause);
struct TaskDep {
OmpTaskDependenceType::Type GetTaskDepType() const;
OmpTaskDependenceType::Value GetTaskDepType() const;
TUPLE_CLASS_BOILERPLATE(TaskDep);
std::tuple<std::optional<OmpIteratorModifier>, OmpTaskDependenceType,
OmpObjectList>
std::tuple<std::optional<OmpIterator>, OmpTaskDependenceType, OmpObjectList>
t;
};
std::variant<TaskDep, OmpDoacross> u;
Expand Down Expand Up @@ -3632,7 +3665,7 @@ struct OmpFromClause {
// As in the case of MAP, modifiers are parsed as lists, even if they
// are unique. These restrictions will be checked in semantic checks.
std::tuple<std::optional<std::list<Expectation>>,
std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
std::optional<std::list<OmpIterator>>, OmpObjectList,
bool> // were the modifiers comma-separated?
t;
};
Expand Down Expand Up @@ -3661,7 +3694,7 @@ struct OmpDetachClause {
// variable-name-list)
struct OmpInReductionClause {
TUPLE_CLASS_BOILERPLATE(OmpInReductionClause);
std::tuple<OmpReductionOperator, OmpObjectList> t;
std::tuple<OmpReductionIdentifier, OmpObjectList> t;
};

// OMP 5.0 2.19.4.5 lastprivate-clause ->
Expand All @@ -3673,12 +3706,6 @@ struct OmpLastprivateClause {
std::tuple<std::optional<LastprivateModifier>, OmpObjectList> t;
};

// 2.15.3.7 linear-modifier -> REF | VAL | UVAL
struct OmpLinearModifier {
ENUM_CLASS(Type, Ref, Val, Uval)
WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type);
};

// 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step])
// linear-list -> list | linear-modifier(list)
struct OmpLinearClause {
Expand Down Expand Up @@ -3723,7 +3750,7 @@ struct OmpMapClause {
// information about separator presence to emit a diagnostic if needed.
std::tuple<OmpMapperIdentifier, // Mapper name
std::optional<std::list<TypeModifier>>,
std::optional<std::list<OmpIteratorModifier>>, // unique
std::optional<std::list<OmpIterator>>, // unique
std::optional<std::list<Type>>, // unique
OmpObjectList,
bool> // were the modifiers comma-separated?
Expand Down Expand Up @@ -3753,7 +3780,7 @@ struct OmpProcBindClause {
struct OmpReductionClause {
TUPLE_CLASS_BOILERPLATE(OmpReductionClause);
ENUM_CLASS(ReductionModifier, Inscan, Task, Default)
std::tuple<std::optional<ReductionModifier>, OmpReductionOperator,
std::tuple<std::optional<ReductionModifier>, OmpReductionIdentifier,
OmpObjectList>
t;
};
Expand Down Expand Up @@ -3798,7 +3825,7 @@ struct OmpToClause {
// As in the case of MAP, modifiers are parsed as lists, even if they
// are unique. These restrictions will be checked in semantic checks.
std::tuple<std::optional<std::list<Expectation>>,
std::optional<std::list<OmpIteratorModifier>>, OmpObjectList,
std::optional<std::list<OmpIterator>>, OmpObjectList,
bool> // were the modifiers comma-separated?
t;
};
Expand Down Expand Up @@ -3946,7 +3973,7 @@ WRAPPER_CLASS(OmpReductionInitializerClause, Expr);
struct OpenMPDeclareReductionConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
CharBlock source;
std::tuple<Verbatim, OmpReductionOperator, std::list<DeclarationTypeSpec>,
std::tuple<Verbatim, OmpReductionIdentifier, std::list<DeclarationTypeSpec>,
OmpReductionCombiner, std::optional<OmpReductionInitializerClause>>
t;
};
Expand Down
Loading

0 comments on commit cfd67c2

Please sign in to comment.