-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[flang][OpenMP] Parse WHEN, OTHERWISE, MATCH clauses plus METADIRECTIVE #121817
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
Conversation
@llvm/pr-subscribers-flang-fir-hlfir @llvm/pr-subscribers-flang-parser Author: Krzysztof Parzyszek (kparzysz) ChangesParse METADIRECTIVE as a standalone executable directive at the moment. This will allow testing the parser code. There is no lowering, not even clause conversion yet. There is also no verification of the allowed values for trait sets, trait properties. Patch is 23.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/121817.diff 12 Files Affected:
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index a61d7973dd5c36..94ca7c67cbd52e 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -476,6 +476,11 @@ class ParseTreeDumper {
NODE(parser, NullInit)
NODE(parser, ObjectDecl)
NODE(parser, OldParameterStmt)
+ NODE(parser, OmpMetadirectiveDirective)
+ NODE(parser, OmpMatchClause)
+ NODE(parser, OmpOtherwiseClause)
+ NODE(parser, OmpWhenClause)
+ NODE(OmpWhenClause, Modifier)
NODE(parser, OmpDirectiveSpecification)
NODE(parser, OmpTraitPropertyName)
NODE(parser, OmpTraitScore)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 697bddfaf16150..113ff3380ba22c 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3964,6 +3964,7 @@ struct OmpBindClause {
// data-sharing-attribute ->
// SHARED | NONE | // since 4.5
// PRIVATE | FIRSTPRIVATE // since 5.0
+// See also otherwise-clause.
struct OmpDefaultClause {
ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None)
WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, DataSharingAttribute);
@@ -4184,6 +4185,16 @@ struct OmpMapClause {
std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
};
+// Ref: [5.0:58-60], [5.1:63-68], [5.2:194-195]
+//
+// match-clause ->
+// MATCH (context-selector-specification) // since 5.0
+struct OmpMatchClause {
+ // The context-selector is an argument.
+ WRAPPER_CLASS_BOILERPLATE(
+ OmpMatchClause, traits::OmpContextSelectorSpecification);
+};
+
// Ref: [5.2:217-218]
// message-clause ->
// MESSAGE("message-text")
@@ -4214,6 +4225,17 @@ struct OmpOrderClause {
std::tuple<MODIFIERS(), Ordering> t;
};
+// Ref: [5.0:56-57], [5.1:60-62], [5.2:191]
+//
+// otherwise-clause ->
+// DEFAULT ([directive-specification]) // since 5.0, until 5.1
+// otherwise-clause ->
+// OTHERWISE ([directive-specification])] // since 5.2
+struct OmpOtherwiseClause {
+ WRAPPER_CLASS_BOILERPLATE(
+ OmpOtherwiseClause, std::optional<OmpDirectiveSpecification>);
+};
+
// Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:229-230]
//
// proc-bind-clause ->
@@ -4299,6 +4321,17 @@ struct OmpUpdateClause {
std::variant<OmpDependenceType, OmpTaskDependenceType> u;
};
+// Ref: [5.0:56-57], [5.1:60-62], [5.2:190-191]
+//
+// when-clause ->
+// WHEN (context-selector :
+// [directive-specification]) // since 5.0
+struct OmpWhenClause {
+ TUPLE_CLASS_BOILERPLATE(OmpWhenClause);
+ MODIFIER_BOILERPLATE(OmpContextSelector);
+ std::tuple<MODIFIERS(), std::optional<OmpDirectiveSpecification>> t;
+};
+
// OpenMP Clauses
struct OmpClause {
UNION_CLASS_BOILERPLATE(OmpClause);
@@ -4323,6 +4356,12 @@ struct OmpClauseList {
// --- Directives and constructs
+struct OmpMetadirectiveDirective {
+ TUPLE_CLASS_BOILERPLATE(OmpMetadirectiveDirective);
+ std::tuple<OmpClauseList> t;
+ CharBlock source;
+};
+
// Ref: [5.1:89-90], [5.2:216]
//
// nothing-directive ->
@@ -4696,7 +4735,7 @@ struct OpenMPStandaloneConstruct {
CharBlock source;
std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
OpenMPCancelConstruct, OpenMPCancellationPointConstruct,
- OpenMPDepobjConstruct>
+ OpenMPDepobjConstruct, OmpMetadirectiveDirective>
u;
};
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index b424e209d56da9..d60171552087fa 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -230,9 +230,9 @@ MAKE_EMPTY_CLASS(Threadprivate, Threadprivate);
MAKE_INCOMPLETE_CLASS(AdjustArgs, AdjustArgs);
MAKE_INCOMPLETE_CLASS(AppendArgs, AppendArgs);
-MAKE_INCOMPLETE_CLASS(Match, Match);
+// MAKE_INCOMPLETE_CLASS(Match, Match);
// MAKE_INCOMPLETE_CLASS(Otherwise, ); // missing-in-parser
-MAKE_INCOMPLETE_CLASS(When, When);
+// MAKE_INCOMPLETE_CLASS(When, When);
List<IteratorSpecifier>
makeIteratorSpecifiers(const parser::OmpIteratorSpecifier &inp,
@@ -997,7 +997,11 @@ Map make(const parser::OmpClause::Map &inp,
/*LocatorList=*/makeObjects(t4, semaCtx)}};
}
-// Match: incomplete
+Match make(const parser::OmpClause::Match &inp,
+ semantics::SemanticsContext &semaCtx) {
+ return Match{};
+}
+
// MemoryOrder: empty
// Mergeable: empty
@@ -1102,6 +1106,10 @@ Ordered make(const parser::OmpClause::Ordered &inp,
}
// Otherwise: incomplete, missing-in-parser
+Otherwise make(const parser::OmpClause::Otherwise &inp,
+ semantics::SemanticsContext &semaCtx) {
+ return Otherwise{};
+}
Partial make(const parser::OmpClause::Partial &inp,
semantics::SemanticsContext &semaCtx) {
@@ -1356,7 +1364,12 @@ UsesAllocators make(const parser::OmpClause::UsesAllocators &inp,
}
// Weak: empty
-// When: incomplete
+
+When make(const parser::OmpClause::When &inp,
+ semantics::SemanticsContext &semaCtx) {
+ return When{};
+}
+
// Write: empty
} // namespace clause
diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h
index 65282d243d87af..aea317b5907fff 100644
--- a/flang/lib/Lower/OpenMP/Clauses.h
+++ b/flang/lib/Lower/OpenMP/Clauses.h
@@ -257,6 +257,7 @@ using OmpxBare = tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy>;
using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT<TypeTy, IdTy, ExprTy>;
using Ordered = tomp::clause::OrderedT<TypeTy, IdTy, ExprTy>;
using Order = tomp::clause::OrderT<TypeTy, IdTy, ExprTy>;
+using Otherwise = tomp::clause::OtherwiseT<TypeTy, IdTy, ExprTy>;
using Partial = tomp::clause::PartialT<TypeTy, IdTy, ExprTy>;
using Priority = tomp::clause::PriorityT<TypeTy, IdTy, ExprTy>;
using Private = tomp::clause::PrivateT<TypeTy, IdTy, ExprTy>;
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index cd4b25a17722c1..ee164e45a0f828 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2794,6 +2794,12 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct");
}
+static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
+ semantics::SemanticsContext &semaCtx,
+ lower::pft::Evaluation &eval,
+ const parser::OmpMetadirectiveDirective &construct) {
+}
+
static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 35ed32602ecc94..c42a74c5023618 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -424,6 +424,9 @@ TYPE_PARSER(sourced(construct<OmpToClause::Modifier>(
construct<OmpToClause::Modifier>(Parser<OmpMapper>{}) ||
construct<OmpToClause::Modifier>(Parser<OmpIterator>{})))))
+TYPE_PARSER(sourced(construct<OmpWhenClause::Modifier>( //
+ Parser<OmpContextSelector>{})))
+
// --- Parsers for clauses --------------------------------------------
/// `MOBClause` is a clause that has a
@@ -621,6 +624,16 @@ TYPE_PARSER(construct<OmpOrderClause>(
maybe(nonemptyList(Parser<OmpOrderClause::Modifier>{}) / ":"),
"CONCURRENT" >> pure(OmpOrderClause::Ordering::Concurrent)))
+TYPE_PARSER(construct<OmpMatchClause>(
+ Parser<traits::OmpContextSelectorSpecification>{}))
+
+TYPE_PARSER(construct<OmpOtherwiseClause>(
+ maybe(sourced(Parser<OmpDirectiveSpecification>{}))))
+
+TYPE_PARSER(construct<OmpWhenClause>(
+ maybe(nonemptyList(Parser<OmpWhenClause::Modifier>{}) / ":"),
+ maybe(sourced(Parser<OmpDirectiveSpecification>{}))))
+
// OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression)
TYPE_PARSER(construct<OmpGrainsizeClause>(
maybe(nonemptyList(Parser<OmpGrainsizeClause::Modifier>{}) / ":"),
@@ -738,6 +751,8 @@ TYPE_PARSER(
parenthesized(Parser<OmpObjectList>{}))) ||
"MAP" >> construct<OmpClause>(construct<OmpClause::Map>(
parenthesized(Parser<OmpMapClause>{}))) ||
+ "MATCH" >> construct<OmpClause>(construct<OmpClause::Match>(
+ parenthesized(Parser<OmpMatchClause>{}))) ||
"MERGEABLE" >> construct<OmpClause>(construct<OmpClause::Mergeable>()) ||
"MESSAGE" >> construct<OmpClause>(construct<OmpClause::Message>(
parenthesized(Parser<OmpMessageClause>{}))) ||
@@ -758,6 +773,8 @@ TYPE_PARSER(
parenthesized(Parser<OmpOrderClause>{}))) ||
"ORDERED" >> construct<OmpClause>(construct<OmpClause::Ordered>(
maybe(parenthesized(scalarIntConstantExpr)))) ||
+ "OTHERWISE" >> construct<OmpClause>(construct<OmpClause::Otherwise>(
+ maybe(parenthesized(Parser<OmpOtherwiseClause>{})))) ||
"PARTIAL" >> construct<OmpClause>(construct<OmpClause::Partial>(
maybe(parenthesized(scalarIntConstantExpr)))) ||
"PRIORITY" >> construct<OmpClause>(construct<OmpClause::Priority>(
@@ -813,7 +830,9 @@ TYPE_PARSER(
parenthesized(nonemptyList(name)))) ||
"UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()) ||
"UPDATE" >> construct<OmpClause>(construct<OmpClause::Update>(
- parenthesized(Parser<OmpUpdateClause>{}))))
+ parenthesized(Parser<OmpUpdateClause>{}))) ||
+ "WHEN" >> construct<OmpClause>(construct<OmpClause::When>(
+ parenthesized(Parser<OmpWhenClause>{}))))
// [Clause, [Clause], ...]
TYPE_PARSER(sourced(construct<OmpClauseList>(
@@ -833,6 +852,9 @@ TYPE_PARSER(sourced(construct<OpenMPUtilityConstruct>(
sourced(construct<OpenMPUtilityConstruct>(
sourced(Parser<OmpNothingDirective>{}))))))
+TYPE_PARSER(sourced(construct<OmpMetadirectiveDirective>(
+ "METADIRECTIVE" >> Parser<OmpClauseList>{})))
+
// Omp directives enclosing do loop
TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
"DISTRIBUTE PARALLEL DO SIMD" >>
@@ -978,6 +1000,8 @@ TYPE_PARSER(
construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
construct<OpenMPStandaloneConstruct>(
Parser<OpenMPCancellationPointConstruct>{}) ||
+ construct<OpenMPStandaloneConstruct>(
+ Parser<OmpMetadirectiveDirective>{}) ||
construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{})) /
endOfLine)
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 31a2c3bbc408d5..4a485c09a97cc2 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2293,6 +2293,11 @@ class UnparseVisitor {
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
Walk(std::get<OmpObjectList>(x.t));
}
+ void Unparse(const OmpWhenClause &x) {
+ using Modifier = OmpWhenClause::Modifier;
+ Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
+ Walk(std::get<std::optional<OmpDirectiveSpecification>>(x.t));
+ }
#define GEN_FLANG_CLAUSE_UNPARSE
#include "llvm/Frontend/OpenMP/OMP.inc"
void Unparse(const OmpLoopDirective &x) {
@@ -2802,6 +2807,13 @@ class UnparseVisitor {
},
x.u);
}
+ void Unparse(const OmpMetadirectiveDirective &x) {
+ BeginOpenMP();
+ Word("!$OMP METADIRECTIVE ");
+ Walk(std::get<OmpClauseList>(x.t));
+ Put("\n");
+ EndOpenMP();
+ }
void Unparse(const OpenMPDepobjConstruct &x) {
BeginOpenMP();
Word("!$OMP DEPOBJ");
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 67f7f65b7e422b..56f6aedc9d8c45 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -598,6 +598,14 @@ void OmpStructureChecker::Leave(const parser::OmpDirectiveSpecification &) {
dirContext_.pop_back();
}
+void OmpStructureChecker::Enter(const parser::OmpMetadirectiveDirective &x) {
+ PushContextAndClauseSets(x.source, llvm::omp::Directive::OMPD_metadirective);
+}
+
+void OmpStructureChecker::Leave(const parser::OmpMetadirectiveDirective &) {
+ dirContext_.pop_back();
+}
+
void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
// Simd Construct with Ordered Construct Nesting check
// We cannot use CurrentDirectiveIsNested() here because
@@ -2902,6 +2910,7 @@ CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext)
CHECK_SIMPLE_CLAUSE(Severity, OMPC_severity)
CHECK_SIMPLE_CLAUSE(Message, OMPC_message)
CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter)
+CHECK_SIMPLE_CLAUSE(Otherwise, OMPC_otherwise)
CHECK_SIMPLE_CLAUSE(When, OMPC_when)
CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args)
CHECK_SIMPLE_CLAUSE(AppendArgs, OMPC_append_args)
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 1fc7e6c1e9baaa..c323bf4fca16e6 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -147,6 +147,9 @@ class OmpStructureChecker
void Enter(const parser::OmpDirectiveSpecification &);
void Leave(const parser::OmpDirectiveSpecification &);
+ void Enter(const parser::OmpMetadirectiveDirective &);
+ void Leave(const parser::OmpMetadirectiveDirective &);
+
#define GEN_FLANG_CLAUSE_CHECK_ENTER
#include "llvm/Frontend/OpenMP/OMP.inc"
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 4e423ea1b43251..52be8d13ef4710 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -356,6 +356,11 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
return true;
}
void Post(const parser::OmpDirectiveSpecification &) { PopContext(); }
+ bool Pre(const parser::OmpMetadirectiveDirective &x) {
+ PushContext(x.source, llvm::omp::Directive::OMPD_metadirective);
+ return true;
+ }
+ void Post(const parser::OmpMetadirectiveDirective &) { PopContext(); }
bool Pre(const parser::OpenMPBlockConstruct &);
void Post(const parser::OpenMPBlockConstruct &);
diff --git a/flang/test/Parser/OpenMP/metadirective.f90 b/flang/test/Parser/OpenMP/metadirective.f90
new file mode 100644
index 00000000000000..c0f120fd7910af
--- /dev/null
+++ b/flang/test/Parser/OpenMP/metadirective.f90
@@ -0,0 +1,165 @@
+!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=52 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
+!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+subroutine f00
+ !$omp metadirective when(construct={target, parallel}: nothing)
+end
+
+!UNPARSE: SUBROUTINE f00
+!UNPARSE: !$OMP METADIRECTIVE WHEN(CONSTRUCT={TARGET, PARALLEL}: NOTHING)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OmpMetadirectiveDirective
+!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause
+!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector
+!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = Construct
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> llvm::omp::Directive = target
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> llvm::omp::Directive = parallel
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | llvm::omp::Directive = nothing
+!PARSE-TREE: | | | OmpClauseList ->
+
+subroutine f10
+ !$omp metadirective when(device={kind(host), device_num(1)}: nothing)
+end
+
+!UNPARSE: SUBROUTINE f10
+!UNPARSE: !$OMP METADIRECTIVE WHEN(DEVICE={KIND(host), DEVICE_NUM(1_4)}: NOTHING)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OmpMetadirectiveDirective
+!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause
+!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector
+!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = Device
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Kind
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> OmpTraitPropertyName -> string = 'host'
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Device_Num
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '1_4'
+!PARSE-TREE: | | | | | | LiteralConstant -> IntLiteralConstant = '1'
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | llvm::omp::Directive = nothing
+!PARSE-TREE: | | | OmpClauseList ->
+
+subroutine f20
+ !$omp metadirective when(target_device={kind(any), device_num(7)}: nothing)
+end
+
+!UNPARSE: SUBROUTINE f20
+!UNPARSE: !$OMP METADIRECTIVE WHEN(TARGET_DEVICE={KIND(any), DEVICE_NUM(7_4)}: NOTHING)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OmpMetadirectiveDirective
+!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause
+!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector
+!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = Target_Device
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Kind
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> OmpTraitPropertyName -> string = 'any'
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Device_Num
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '7_4'
+!PARSE-TREE: | | | | | | LiteralConstant -> IntLiteralConstant = '7'
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | llvm::omp::Directive = nothing
+!PARSE-TREE: | | | OmpClauseList ->
+
+subroutine f30
+ !$omp metadirective &
+ !$omp when(implementation={atomic_default_mem_order(acq_rel)}: nothing)
+end
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OmpMetadirectiveDirective
+!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause
+!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector
+!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = Implementation
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Atomic_Default_Mem_Order
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> OmpTraitPropertyName -> string = 'acq_rel'
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | llvm::omp::Directive = nothing
+!PARSE-TREE: | | | OmpClauseList ->
+
+!UNPARSE: SUBROUTINE f30
+!UNPARSE: !$OMP METADIRECTIVE WHEN(IMPLEMENTATION={ATOMIC_DEFAULT_MEM_ORDER(acq_rel)}: &
+!UNPARSE: !$OMP&NOTHING)
+!UNPARSE: END SUBROUTINE
+
+subroutine f31
+ !$omp metadirective &
+ !$omp when(implementation={extension(haha(1), foo(lol, "bar"(1)))}: nothing)
+end
+
+!UNPARSE: SUBROUTINE f31
+!UNPARSE: !$OMP METADIRECTIVE WHEN(IMPLEMENTATION={EXTENSION(haha(1_4), foo(lol,bar(1_4)))}: &
+!UNPARSE: !$OMP&NOTHING)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OmpMetadirectiveDirective
+!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause
+!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector
+!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = Implementation
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Extension
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> OmpTraitPropertyExtension
+!PARSE-TREE: | | | | | | OmpTraitPropertyName -> string = 'haha'
+!PARSE-TREE: | | | | | | ExtensionValue -> Scalar -> Expr = '1_4'
+!PARSE-TREE: | | | | | | | LiteralConstant -> IntLiteralConstant = '1'
+!PARSE-TREE: | | | | | OmpTraitProperty -> OmpTraitPropertyExtension
+!PARSE-TREE: | | | | | | OmpTraitProp...
[truncated]
|
@llvm/pr-subscribers-flang-openmp Author: Krzysztof Parzyszek (kparzysz) ChangesParse METADIRECTIVE as a standalone executable directive at the moment. This will allow testing the parser code. There is no lowering, not even clause conversion yet. There is also no verification of the allowed values for trait sets, trait properties. Patch is 23.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/121817.diff 12 Files Affected:
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index a61d7973dd5c36..94ca7c67cbd52e 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -476,6 +476,11 @@ class ParseTreeDumper {
NODE(parser, NullInit)
NODE(parser, ObjectDecl)
NODE(parser, OldParameterStmt)
+ NODE(parser, OmpMetadirectiveDirective)
+ NODE(parser, OmpMatchClause)
+ NODE(parser, OmpOtherwiseClause)
+ NODE(parser, OmpWhenClause)
+ NODE(OmpWhenClause, Modifier)
NODE(parser, OmpDirectiveSpecification)
NODE(parser, OmpTraitPropertyName)
NODE(parser, OmpTraitScore)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 697bddfaf16150..113ff3380ba22c 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3964,6 +3964,7 @@ struct OmpBindClause {
// data-sharing-attribute ->
// SHARED | NONE | // since 4.5
// PRIVATE | FIRSTPRIVATE // since 5.0
+// See also otherwise-clause.
struct OmpDefaultClause {
ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None)
WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, DataSharingAttribute);
@@ -4184,6 +4185,16 @@ struct OmpMapClause {
std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
};
+// Ref: [5.0:58-60], [5.1:63-68], [5.2:194-195]
+//
+// match-clause ->
+// MATCH (context-selector-specification) // since 5.0
+struct OmpMatchClause {
+ // The context-selector is an argument.
+ WRAPPER_CLASS_BOILERPLATE(
+ OmpMatchClause, traits::OmpContextSelectorSpecification);
+};
+
// Ref: [5.2:217-218]
// message-clause ->
// MESSAGE("message-text")
@@ -4214,6 +4225,17 @@ struct OmpOrderClause {
std::tuple<MODIFIERS(), Ordering> t;
};
+// Ref: [5.0:56-57], [5.1:60-62], [5.2:191]
+//
+// otherwise-clause ->
+// DEFAULT ([directive-specification]) // since 5.0, until 5.1
+// otherwise-clause ->
+// OTHERWISE ([directive-specification])] // since 5.2
+struct OmpOtherwiseClause {
+ WRAPPER_CLASS_BOILERPLATE(
+ OmpOtherwiseClause, std::optional<OmpDirectiveSpecification>);
+};
+
// Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:229-230]
//
// proc-bind-clause ->
@@ -4299,6 +4321,17 @@ struct OmpUpdateClause {
std::variant<OmpDependenceType, OmpTaskDependenceType> u;
};
+// Ref: [5.0:56-57], [5.1:60-62], [5.2:190-191]
+//
+// when-clause ->
+// WHEN (context-selector :
+// [directive-specification]) // since 5.0
+struct OmpWhenClause {
+ TUPLE_CLASS_BOILERPLATE(OmpWhenClause);
+ MODIFIER_BOILERPLATE(OmpContextSelector);
+ std::tuple<MODIFIERS(), std::optional<OmpDirectiveSpecification>> t;
+};
+
// OpenMP Clauses
struct OmpClause {
UNION_CLASS_BOILERPLATE(OmpClause);
@@ -4323,6 +4356,12 @@ struct OmpClauseList {
// --- Directives and constructs
+struct OmpMetadirectiveDirective {
+ TUPLE_CLASS_BOILERPLATE(OmpMetadirectiveDirective);
+ std::tuple<OmpClauseList> t;
+ CharBlock source;
+};
+
// Ref: [5.1:89-90], [5.2:216]
//
// nothing-directive ->
@@ -4696,7 +4735,7 @@ struct OpenMPStandaloneConstruct {
CharBlock source;
std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
OpenMPCancelConstruct, OpenMPCancellationPointConstruct,
- OpenMPDepobjConstruct>
+ OpenMPDepobjConstruct, OmpMetadirectiveDirective>
u;
};
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index b424e209d56da9..d60171552087fa 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -230,9 +230,9 @@ MAKE_EMPTY_CLASS(Threadprivate, Threadprivate);
MAKE_INCOMPLETE_CLASS(AdjustArgs, AdjustArgs);
MAKE_INCOMPLETE_CLASS(AppendArgs, AppendArgs);
-MAKE_INCOMPLETE_CLASS(Match, Match);
+// MAKE_INCOMPLETE_CLASS(Match, Match);
// MAKE_INCOMPLETE_CLASS(Otherwise, ); // missing-in-parser
-MAKE_INCOMPLETE_CLASS(When, When);
+// MAKE_INCOMPLETE_CLASS(When, When);
List<IteratorSpecifier>
makeIteratorSpecifiers(const parser::OmpIteratorSpecifier &inp,
@@ -997,7 +997,11 @@ Map make(const parser::OmpClause::Map &inp,
/*LocatorList=*/makeObjects(t4, semaCtx)}};
}
-// Match: incomplete
+Match make(const parser::OmpClause::Match &inp,
+ semantics::SemanticsContext &semaCtx) {
+ return Match{};
+}
+
// MemoryOrder: empty
// Mergeable: empty
@@ -1102,6 +1106,10 @@ Ordered make(const parser::OmpClause::Ordered &inp,
}
// Otherwise: incomplete, missing-in-parser
+Otherwise make(const parser::OmpClause::Otherwise &inp,
+ semantics::SemanticsContext &semaCtx) {
+ return Otherwise{};
+}
Partial make(const parser::OmpClause::Partial &inp,
semantics::SemanticsContext &semaCtx) {
@@ -1356,7 +1364,12 @@ UsesAllocators make(const parser::OmpClause::UsesAllocators &inp,
}
// Weak: empty
-// When: incomplete
+
+When make(const parser::OmpClause::When &inp,
+ semantics::SemanticsContext &semaCtx) {
+ return When{};
+}
+
// Write: empty
} // namespace clause
diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h
index 65282d243d87af..aea317b5907fff 100644
--- a/flang/lib/Lower/OpenMP/Clauses.h
+++ b/flang/lib/Lower/OpenMP/Clauses.h
@@ -257,6 +257,7 @@ using OmpxBare = tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy>;
using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT<TypeTy, IdTy, ExprTy>;
using Ordered = tomp::clause::OrderedT<TypeTy, IdTy, ExprTy>;
using Order = tomp::clause::OrderT<TypeTy, IdTy, ExprTy>;
+using Otherwise = tomp::clause::OtherwiseT<TypeTy, IdTy, ExprTy>;
using Partial = tomp::clause::PartialT<TypeTy, IdTy, ExprTy>;
using Priority = tomp::clause::PriorityT<TypeTy, IdTy, ExprTy>;
using Private = tomp::clause::PrivateT<TypeTy, IdTy, ExprTy>;
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index cd4b25a17722c1..ee164e45a0f828 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2794,6 +2794,12 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct");
}
+static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
+ semantics::SemanticsContext &semaCtx,
+ lower::pft::Evaluation &eval,
+ const parser::OmpMetadirectiveDirective &construct) {
+}
+
static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 35ed32602ecc94..c42a74c5023618 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -424,6 +424,9 @@ TYPE_PARSER(sourced(construct<OmpToClause::Modifier>(
construct<OmpToClause::Modifier>(Parser<OmpMapper>{}) ||
construct<OmpToClause::Modifier>(Parser<OmpIterator>{})))))
+TYPE_PARSER(sourced(construct<OmpWhenClause::Modifier>( //
+ Parser<OmpContextSelector>{})))
+
// --- Parsers for clauses --------------------------------------------
/// `MOBClause` is a clause that has a
@@ -621,6 +624,16 @@ TYPE_PARSER(construct<OmpOrderClause>(
maybe(nonemptyList(Parser<OmpOrderClause::Modifier>{}) / ":"),
"CONCURRENT" >> pure(OmpOrderClause::Ordering::Concurrent)))
+TYPE_PARSER(construct<OmpMatchClause>(
+ Parser<traits::OmpContextSelectorSpecification>{}))
+
+TYPE_PARSER(construct<OmpOtherwiseClause>(
+ maybe(sourced(Parser<OmpDirectiveSpecification>{}))))
+
+TYPE_PARSER(construct<OmpWhenClause>(
+ maybe(nonemptyList(Parser<OmpWhenClause::Modifier>{}) / ":"),
+ maybe(sourced(Parser<OmpDirectiveSpecification>{}))))
+
// OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression)
TYPE_PARSER(construct<OmpGrainsizeClause>(
maybe(nonemptyList(Parser<OmpGrainsizeClause::Modifier>{}) / ":"),
@@ -738,6 +751,8 @@ TYPE_PARSER(
parenthesized(Parser<OmpObjectList>{}))) ||
"MAP" >> construct<OmpClause>(construct<OmpClause::Map>(
parenthesized(Parser<OmpMapClause>{}))) ||
+ "MATCH" >> construct<OmpClause>(construct<OmpClause::Match>(
+ parenthesized(Parser<OmpMatchClause>{}))) ||
"MERGEABLE" >> construct<OmpClause>(construct<OmpClause::Mergeable>()) ||
"MESSAGE" >> construct<OmpClause>(construct<OmpClause::Message>(
parenthesized(Parser<OmpMessageClause>{}))) ||
@@ -758,6 +773,8 @@ TYPE_PARSER(
parenthesized(Parser<OmpOrderClause>{}))) ||
"ORDERED" >> construct<OmpClause>(construct<OmpClause::Ordered>(
maybe(parenthesized(scalarIntConstantExpr)))) ||
+ "OTHERWISE" >> construct<OmpClause>(construct<OmpClause::Otherwise>(
+ maybe(parenthesized(Parser<OmpOtherwiseClause>{})))) ||
"PARTIAL" >> construct<OmpClause>(construct<OmpClause::Partial>(
maybe(parenthesized(scalarIntConstantExpr)))) ||
"PRIORITY" >> construct<OmpClause>(construct<OmpClause::Priority>(
@@ -813,7 +830,9 @@ TYPE_PARSER(
parenthesized(nonemptyList(name)))) ||
"UNTIED" >> construct<OmpClause>(construct<OmpClause::Untied>()) ||
"UPDATE" >> construct<OmpClause>(construct<OmpClause::Update>(
- parenthesized(Parser<OmpUpdateClause>{}))))
+ parenthesized(Parser<OmpUpdateClause>{}))) ||
+ "WHEN" >> construct<OmpClause>(construct<OmpClause::When>(
+ parenthesized(Parser<OmpWhenClause>{}))))
// [Clause, [Clause], ...]
TYPE_PARSER(sourced(construct<OmpClauseList>(
@@ -833,6 +852,9 @@ TYPE_PARSER(sourced(construct<OpenMPUtilityConstruct>(
sourced(construct<OpenMPUtilityConstruct>(
sourced(Parser<OmpNothingDirective>{}))))))
+TYPE_PARSER(sourced(construct<OmpMetadirectiveDirective>(
+ "METADIRECTIVE" >> Parser<OmpClauseList>{})))
+
// Omp directives enclosing do loop
TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
"DISTRIBUTE PARALLEL DO SIMD" >>
@@ -978,6 +1000,8 @@ TYPE_PARSER(
construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
construct<OpenMPStandaloneConstruct>(
Parser<OpenMPCancellationPointConstruct>{}) ||
+ construct<OpenMPStandaloneConstruct>(
+ Parser<OmpMetadirectiveDirective>{}) ||
construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{})) /
endOfLine)
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 31a2c3bbc408d5..4a485c09a97cc2 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2293,6 +2293,11 @@ class UnparseVisitor {
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
Walk(std::get<OmpObjectList>(x.t));
}
+ void Unparse(const OmpWhenClause &x) {
+ using Modifier = OmpWhenClause::Modifier;
+ Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
+ Walk(std::get<std::optional<OmpDirectiveSpecification>>(x.t));
+ }
#define GEN_FLANG_CLAUSE_UNPARSE
#include "llvm/Frontend/OpenMP/OMP.inc"
void Unparse(const OmpLoopDirective &x) {
@@ -2802,6 +2807,13 @@ class UnparseVisitor {
},
x.u);
}
+ void Unparse(const OmpMetadirectiveDirective &x) {
+ BeginOpenMP();
+ Word("!$OMP METADIRECTIVE ");
+ Walk(std::get<OmpClauseList>(x.t));
+ Put("\n");
+ EndOpenMP();
+ }
void Unparse(const OpenMPDepobjConstruct &x) {
BeginOpenMP();
Word("!$OMP DEPOBJ");
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 67f7f65b7e422b..56f6aedc9d8c45 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -598,6 +598,14 @@ void OmpStructureChecker::Leave(const parser::OmpDirectiveSpecification &) {
dirContext_.pop_back();
}
+void OmpStructureChecker::Enter(const parser::OmpMetadirectiveDirective &x) {
+ PushContextAndClauseSets(x.source, llvm::omp::Directive::OMPD_metadirective);
+}
+
+void OmpStructureChecker::Leave(const parser::OmpMetadirectiveDirective &) {
+ dirContext_.pop_back();
+}
+
void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
// Simd Construct with Ordered Construct Nesting check
// We cannot use CurrentDirectiveIsNested() here because
@@ -2902,6 +2910,7 @@ CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext)
CHECK_SIMPLE_CLAUSE(Severity, OMPC_severity)
CHECK_SIMPLE_CLAUSE(Message, OMPC_message)
CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter)
+CHECK_SIMPLE_CLAUSE(Otherwise, OMPC_otherwise)
CHECK_SIMPLE_CLAUSE(When, OMPC_when)
CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args)
CHECK_SIMPLE_CLAUSE(AppendArgs, OMPC_append_args)
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 1fc7e6c1e9baaa..c323bf4fca16e6 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -147,6 +147,9 @@ class OmpStructureChecker
void Enter(const parser::OmpDirectiveSpecification &);
void Leave(const parser::OmpDirectiveSpecification &);
+ void Enter(const parser::OmpMetadirectiveDirective &);
+ void Leave(const parser::OmpMetadirectiveDirective &);
+
#define GEN_FLANG_CLAUSE_CHECK_ENTER
#include "llvm/Frontend/OpenMP/OMP.inc"
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 4e423ea1b43251..52be8d13ef4710 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -356,6 +356,11 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
return true;
}
void Post(const parser::OmpDirectiveSpecification &) { PopContext(); }
+ bool Pre(const parser::OmpMetadirectiveDirective &x) {
+ PushContext(x.source, llvm::omp::Directive::OMPD_metadirective);
+ return true;
+ }
+ void Post(const parser::OmpMetadirectiveDirective &) { PopContext(); }
bool Pre(const parser::OpenMPBlockConstruct &);
void Post(const parser::OpenMPBlockConstruct &);
diff --git a/flang/test/Parser/OpenMP/metadirective.f90 b/flang/test/Parser/OpenMP/metadirective.f90
new file mode 100644
index 00000000000000..c0f120fd7910af
--- /dev/null
+++ b/flang/test/Parser/OpenMP/metadirective.f90
@@ -0,0 +1,165 @@
+!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=52 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
+!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+subroutine f00
+ !$omp metadirective when(construct={target, parallel}: nothing)
+end
+
+!UNPARSE: SUBROUTINE f00
+!UNPARSE: !$OMP METADIRECTIVE WHEN(CONSTRUCT={TARGET, PARALLEL}: NOTHING)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OmpMetadirectiveDirective
+!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause
+!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector
+!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = Construct
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> llvm::omp::Directive = target
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> llvm::omp::Directive = parallel
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | llvm::omp::Directive = nothing
+!PARSE-TREE: | | | OmpClauseList ->
+
+subroutine f10
+ !$omp metadirective when(device={kind(host), device_num(1)}: nothing)
+end
+
+!UNPARSE: SUBROUTINE f10
+!UNPARSE: !$OMP METADIRECTIVE WHEN(DEVICE={KIND(host), DEVICE_NUM(1_4)}: NOTHING)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OmpMetadirectiveDirective
+!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause
+!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector
+!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = Device
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Kind
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> OmpTraitPropertyName -> string = 'host'
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Device_Num
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '1_4'
+!PARSE-TREE: | | | | | | LiteralConstant -> IntLiteralConstant = '1'
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | llvm::omp::Directive = nothing
+!PARSE-TREE: | | | OmpClauseList ->
+
+subroutine f20
+ !$omp metadirective when(target_device={kind(any), device_num(7)}: nothing)
+end
+
+!UNPARSE: SUBROUTINE f20
+!UNPARSE: !$OMP METADIRECTIVE WHEN(TARGET_DEVICE={KIND(any), DEVICE_NUM(7_4)}: NOTHING)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OmpMetadirectiveDirective
+!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause
+!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector
+!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = Target_Device
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Kind
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> OmpTraitPropertyName -> string = 'any'
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Device_Num
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '7_4'
+!PARSE-TREE: | | | | | | LiteralConstant -> IntLiteralConstant = '7'
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | llvm::omp::Directive = nothing
+!PARSE-TREE: | | | OmpClauseList ->
+
+subroutine f30
+ !$omp metadirective &
+ !$omp when(implementation={atomic_default_mem_order(acq_rel)}: nothing)
+end
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OmpMetadirectiveDirective
+!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause
+!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector
+!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = Implementation
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Atomic_Default_Mem_Order
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> OmpTraitPropertyName -> string = 'acq_rel'
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | llvm::omp::Directive = nothing
+!PARSE-TREE: | | | OmpClauseList ->
+
+!UNPARSE: SUBROUTINE f30
+!UNPARSE: !$OMP METADIRECTIVE WHEN(IMPLEMENTATION={ATOMIC_DEFAULT_MEM_ORDER(acq_rel)}: &
+!UNPARSE: !$OMP&NOTHING)
+!UNPARSE: END SUBROUTINE
+
+subroutine f31
+ !$omp metadirective &
+ !$omp when(implementation={extension(haha(1), foo(lol, "bar"(1)))}: nothing)
+end
+
+!UNPARSE: SUBROUTINE f31
+!UNPARSE: !$OMP METADIRECTIVE WHEN(IMPLEMENTATION={EXTENSION(haha(1_4), foo(lol,bar(1_4)))}: &
+!UNPARSE: !$OMP&NOTHING)
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OmpMetadirectiveDirective
+!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause
+!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector
+!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = Implementation
+!PARSE-TREE: | | | OmpTraitSelector
+!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Extension
+!PARSE-TREE: | | | | Properties
+!PARSE-TREE: | | | | | OmpTraitProperty -> OmpTraitPropertyExtension
+!PARSE-TREE: | | | | | | OmpTraitPropertyName -> string = 'haha'
+!PARSE-TREE: | | | | | | ExtensionValue -> Scalar -> Expr = '1_4'
+!PARSE-TREE: | | | | | | | LiteralConstant -> IntLiteralConstant = '1'
+!PARSE-TREE: | | | | | OmpTraitProperty -> OmpTraitPropertyExtension
+!PARSE-TREE: | | | | | | OmpTraitProp...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
The build failures are unrelated to the code. There is some flaky testcase that causes the breakage. |
A trait poperty can be one of serveral alternatives, and each property in a list was parsed as if it could be any of these alternatives independently from other properties. This made the parsing vulnerable to certain ambiguities in the trait grammar (provided in the OpenMP spec). At the same time the OpenMP spec gives the expected types of properties for almost every trait: all properties listed for a given trait are usually of the same type, e.g. names, clauses, etc. Incorporate these restrictions into the parser, and additionally use property extensions as the fallback if the parsing of the expected property type failed. This is intended to allow the parser to succeed, and instead let the semantic-checking code emit a more user-friendly message.
Parse METADIRECTIVE as a standalone executable directive at the moment. This will allow testing the parser code. There is no lowering, not even clause conversion yet. There is also no verification of the allowed values for trait sets, trait properties.
cf9a727
to
fe3ec47
Compare
…sz/spr/m03-meta-simple
Force-pushed to change the base. There were no review comments yes, so it shouldn't mess up anything. |
…sz/spr/m03-meta-simple
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor comments.
@@ -845,7 +851,8 @@ def OMP_Metadirective : Directive<"metadirective"> { | |||
VersionedClause<OMPC_When>, | |||
]; | |||
let allowedOnceClauses = [ | |||
VersionedClause<OMPC_Default>, | |||
VersionedClause<OMPC_Otherwise, 52>, | |||
VersionedClause<OMPC_Default, 50, 51>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this tested in Flang?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a parser test for DEFAULT.
@@ -265,6 +265,7 @@ def OMPC_Map : Clause<"map"> { | |||
let flangClass = "OmpMapClause"; | |||
} | |||
def OMPC_Match : Clause<"match"> { | |||
let flangClass = "OmpMatchClause"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a test for Match?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we don't have DECLARE VARIANT yet.
@@ -214,6 +214,11 @@ class AssociatedLoopChecker { | |||
}; | |||
|
|||
bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) { | |||
// Do not do clause checks while processing METADIRECTIVE. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add the reason also?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'll add a comment. The reason was that when you specify a clause inside of a context selector, the visitor will think it was applied to METADIRECTIVE itself...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/29/builds/9678 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/17/builds/5442 Here is the relevant piece of the build log for the reference
|
Parse METADIRECTIVE as a standalone executable directive at the moment. This will allow testing the parser code.
There is no lowering, not even clause conversion yet. There is also no verification of the allowed values for trait sets, trait properties.