[llvm-branch-commits] [flang] [flang][OpenMP] Parsing context selectors for METADIRECTIVE (PR #121815)
Krzysztof Parzyszek via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Jan 10 07:39:35 PST 2025
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/121815
>From 215c7e6133bf07d005ac7483b8faf797e319a1fa Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 12 Dec 2024 15:26:26 -0600
Subject: [PATCH 1/7] [flang][OpenMP] Parsing context selectors for
METADIRECTIVE
This is just adding parsers for context selectors. There are no tests
because there is no way to execute these parsers yet.
---
flang/include/flang/Parser/characters.h | 2 +
flang/include/flang/Parser/dump-parse-tree.h | 14 ++
flang/include/flang/Parser/parse-tree.h | 136 +++++++++++++++++++
flang/lib/Parser/openmp-parsers.cpp | 78 +++++++++++
flang/lib/Parser/token-parsers.h | 4 +
flang/lib/Parser/unparse.cpp | 38 ++++++
flang/lib/Semantics/check-omp-structure.cpp | 8 ++
flang/lib/Semantics/check-omp-structure.h | 3 +
flang/lib/Semantics/resolve-directives.cpp | 6 +
9 files changed, 289 insertions(+)
diff --git a/flang/include/flang/Parser/characters.h b/flang/include/flang/Parser/characters.h
index df188d674b9eeb..dbdc058c44995a 100644
--- a/flang/include/flang/Parser/characters.h
+++ b/flang/include/flang/Parser/characters.h
@@ -180,6 +180,8 @@ inline constexpr bool IsValidFortranTokenCharacter(char ch) {
case '>':
case '[':
case ']':
+ case '{': // Used in OpenMP context selector specification
+ case '}': //
return true;
default:
return IsLegalIdentifierStart(ch) || IsDecimalDigit(ch);
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 3331520922bc63..a61d7973dd5c36 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -476,6 +476,20 @@ class ParseTreeDumper {
NODE(parser, NullInit)
NODE(parser, ObjectDecl)
NODE(parser, OldParameterStmt)
+ NODE(parser, OmpDirectiveSpecification)
+ NODE(parser, OmpTraitPropertyName)
+ NODE(parser, OmpTraitScore)
+ NODE(parser, OmpTraitPropertyExtension)
+ NODE(OmpTraitPropertyExtension, ExtensionValue)
+ NODE(parser, OmpTraitProperty)
+ NODE(parser, OmpTraitSelectorName)
+ NODE_ENUM(OmpTraitSelectorName, Value)
+ NODE(parser, OmpTraitSelector)
+ NODE(OmpTraitSelector, Properties)
+ NODE(parser, OmpTraitSetSelectorName)
+ NODE_ENUM(OmpTraitSetSelectorName, Value)
+ NODE(parser, OmpTraitSetSelector)
+ NODE(parser, OmpContextSelectorSpecification)
NODE(parser, OmpMapper)
NODE(parser, OmpMapType)
NODE_ENUM(OmpMapType, Value)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 941d70d3876291..697bddfaf16150 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3453,6 +3453,17 @@ 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;
+};
+
// 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
// in slashes). An extended list item is a list item or a procedure Name.
@@ -3474,6 +3485,128 @@ WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
#define MODIFIERS() std::optional<std::list<Modifier>>
+inline namespace traits {
+// trait-property-name ->
+// identifier | string-literal
+struct OmpTraitPropertyName {
+ WRAPPER_CLASS_BOILERPLATE(OmpTraitPropertyName, std::string);
+};
+
+// trait-score ->
+// SCORE(non-negative-const-integer-expression)
+struct OmpTraitScore {
+ WRAPPER_CLASS_BOILERPLATE(OmpTraitScore, ScalarIntExpr);
+};
+
+// trait-property-extension ->
+// trait-property-name (trait-property-value, ...)
+// trait-property-value ->
+// trait-property-name |
+// scalar-integer-expression |
+// trait-property-extension
+//
+// The grammar in OpenMP 5.2+ spec is ambiguous, the above is a different
+// version (but equivalent) that doesn't have ambiguities.
+// The ambiguity is in
+// trait-property:
+// trait-property-name <- (a)
+// trait-property-clause
+// trait-property-expression <- (b)
+// trait-property-extension <- this conflicts with (a) and (b)
+// trait-property-extension:
+// trait-property-name <- conflict with (a)
+// identifier(trait-property-extension[, trait-property-extension[, ...]])
+// constant integer expression <- conflict with (b)
+//
+struct OmpTraitPropertyExtension {
+ TUPLE_CLASS_BOILERPLATE(OmpTraitPropertyExtension);
+ struct ExtensionValue {
+ UNION_CLASS_BOILERPLATE(ExtensionValue);
+ std::variant<OmpTraitPropertyName, ScalarExpr,
+ common::Indirection<OmpTraitPropertyExtension>>
+ u;
+ };
+ using ExtensionList = std::list<ExtensionValue>;
+ std::tuple<OmpTraitPropertyName, ExtensionList> t;
+};
+
+// trait-property ->
+// trait-property-name | OmpClause |
+// trait-property-expression | trait-property-extension
+// trait-property-expression ->
+// scalar-logical-expression | scalar-integer-expression
+//
+// The parser for a logical expression will accept an integer expression,
+// and if it's not logical, it will flag an error later. The same thing
+// will happen if the scalar integer expression sees a logical expresion.
+// To avoid this, parse all expressions as scalar expressions.
+struct OmpTraitProperty {
+ UNION_CLASS_BOILERPLATE(OmpTraitProperty);
+ std::variant<OmpTraitPropertyName, common::Indirection<OmpClause>,
+ ScalarExpr, // trait-property-expresion
+ OmpTraitPropertyExtension>
+ u;
+};
+
+// trait-selector-name ->
+// KIND | DT // name-list (host, nohost, +/add-def-doc)
+// ISA | DT // name-list (isa_name, ... /impl-defined)
+// ARCH | DT // name-list (arch_name, ... /impl-defined)
+// directive-name | C // no properties
+// SIMD | C // clause-list (from declare_simd)
+// // (at least simdlen, inbranch/notinbranch)
+// DEVICE_NUM | T // device-number
+// UID | T // unique-string-id /impl-defined
+// VENDOR | I // name-list (vendor-id /add-def-doc)
+// EXTENSION | I // name-list (ext_name /impl-defined)
+// ATOMIC_DEFAULT_MEM_ORDER I | // value of admo
+// REQUIRES | I // clause-list (from requires)
+// CONDITION U // logical-expr
+//
+// Trait-set-selectors:
+// [D]evice, [T]arget_device, [C]onstruct, [I]mplementation, [U]ser.
+struct OmpTraitSelectorName {
+ UNION_CLASS_BOILERPLATE(OmpTraitSelectorName);
+ ENUM_CLASS(Value, Arch, Atomic_Default_Mem_Order, Condition, Device_Num,
+ Extension, Isa, Kind, Requires, Simd, Uid, Vendor)
+ std::variant<Value, llvm::omp::Directive> u;
+};
+
+// trait-selector ->
+// trait-selector-name |
+// trait-selector-name ([trait-score:] trait-property, ...)
+struct OmpTraitSelector {
+ TUPLE_CLASS_BOILERPLATE(OmpTraitSelector);
+ struct Properties {
+ TUPLE_CLASS_BOILERPLATE(Properties);
+ std::tuple<std::optional<OmpTraitScore>, std::list<OmpTraitProperty>> t;
+ };
+ std::tuple<OmpTraitSelectorName, std::optional<Properties>> t;
+};
+
+// trait-set-selector-name ->
+// CONSTRUCT | DEVICE | IMPLEMENTATION | USER | // since 5.0
+// TARGET_DEVICE // since 5.1
+struct OmpTraitSetSelectorName {
+ ENUM_CLASS(Value, Construct, Device, Implementation, Target_Device, User)
+ WRAPPER_CLASS_BOILERPLATE(OmpTraitSetSelectorName, Value);
+};
+
+// trait-set-selector ->
+// trait-set-selector-name = {trait-selector, ...}
+struct OmpTraitSetSelector {
+ TUPLE_CLASS_BOILERPLATE(OmpTraitSetSelector);
+ std::tuple<OmpTraitSetSelectorName, std::list<OmpTraitSelector>> t;
+};
+
+// context-selector-specification ->
+// trait-set-selector, ...
+struct OmpContextSelectorSpecification { // Modifier
+ WRAPPER_CLASS_BOILERPLATE(
+ OmpContextSelectorSpecification, std::list<OmpTraitSetSelector>);
+};
+} // namespace traits
+
inline namespace modifier {
// For uniformity, in all keyword modifiers the name of the type defined
// by ENUM_CLASS is "Value", e.g.
@@ -3744,6 +3877,9 @@ struct OmpVariableCategory {
ENUM_CLASS(Value, Aggregate, All, Allocatable, Pointer, Scalar)
WRAPPER_CLASS_BOILERPLATE(OmpVariableCategory, Value);
};
+
+// context-selector
+using OmpContextSelector = traits::OmpContextSelectorSpecification;
} // namespace modifier
// --- Clauses
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 894c458a335b27..35ed32602ecc94 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -153,6 +153,84 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) {
makeEntityList(std::move(names)));
}
+TYPE_PARSER(sourced(construct<OmpDirectiveSpecification>(
+ OmpDirectiveNameParser{}, maybe(indirect(Parser<OmpClauseList>{})))))
+
+// --- Parsers for context traits -------------------------------------
+
+TYPE_PARSER(construct<OmpTraitPropertyName>( //
+ (space >> charLiteralConstantWithoutKind) ||
+ applyMem(&Name::ToString, Parser<Name>{})))
+
+TYPE_PARSER(construct<OmpTraitScore>( //
+ "SCORE" >> parenthesized(scalarIntExpr)))
+
+TYPE_PARSER(construct<OmpTraitPropertyExtension::ExtensionValue>(
+ // Parse nested extension first.
+ construct<OmpTraitPropertyExtension::ExtensionValue>(
+ indirect(Parser<OmpTraitPropertyExtension>{})) ||
+ construct<OmpTraitPropertyExtension::ExtensionValue>(
+ Parser<OmpTraitPropertyName>{}) ||
+ construct<OmpTraitPropertyExtension::ExtensionValue>(scalarExpr)))
+
+TYPE_PARSER(construct<OmpTraitPropertyExtension>( //
+ Parser<OmpTraitPropertyName>{},
+ parenthesized(nonemptySeparated(
+ Parser<OmpTraitPropertyExtension::ExtensionValue>{}, ","_tok))))
+
+TYPE_PARSER(construct<OmpTraitProperty>(
+ // Try extension first, before OmpTraitPropertyName.
+ construct<OmpTraitProperty>(Parser<OmpTraitPropertyExtension>{}) ||
+ construct<OmpTraitProperty>(Parser<OmpTraitPropertyName>{}) ||
+ construct<OmpTraitProperty>(indirect(Parser<OmpClause>{})) ||
+ construct<OmpTraitProperty>(scalarExpr)))
+
+TYPE_PARSER(construct<OmpTraitSelectorName::Value>(
+ "ARCH" >> pure(OmpTraitSelectorName::Value::Arch) ||
+ "ATOMIC_DEFAULT_MEM_ORDER" >>
+ pure(OmpTraitSelectorName::Value::Atomic_Default_Mem_Order) ||
+ "CONDITION" >> pure(OmpTraitSelectorName::Value::Condition) ||
+ "DEVICE_NUM" >> pure(OmpTraitSelectorName::Value::Device_Num) ||
+ "EXTENSION" >> pure(OmpTraitSelectorName::Value::Extension) ||
+ "ISA" >> pure(OmpTraitSelectorName::Value::Isa) ||
+ "KIND" >> pure(OmpTraitSelectorName::Value::Kind) ||
+ "REQUIRES" >> pure(OmpTraitSelectorName::Value::Requires) ||
+ "SIMD" >> pure(OmpTraitSelectorName::Value::Simd) ||
+ "UID" >> pure(OmpTraitSelectorName::Value::Uid) ||
+ "VENDOR" >> pure(OmpTraitSelectorName::Value::Vendor)))
+
+TYPE_PARSER(construct<OmpTraitSelectorName>(
+ // Parse predefined names first (because of SIMD).
+ construct<OmpTraitSelectorName>(Parser<OmpTraitSelectorName::Value>{}) ||
+ construct<OmpTraitSelectorName>(OmpDirectiveNameParser{})))
+
+TYPE_PARSER(construct<OmpTraitSelector::Properties>(
+ maybe(Parser<OmpTraitScore>{} / ":"_tok),
+ nonemptySeparated(Parser<OmpTraitProperty>{}, ","_tok)))
+
+TYPE_PARSER(construct<OmpTraitSelector>( //
+ Parser<OmpTraitSelectorName>{}, //
+ maybe(parenthesized(Parser<OmpTraitSelector::Properties>{}))))
+
+TYPE_PARSER(construct<OmpTraitSetSelectorName::Value>(
+ "CONSTRUCT" >> pure(OmpTraitSetSelectorName::Value::Construct) ||
+ "DEVICE" >> pure(OmpTraitSetSelectorName::Value::Device) ||
+ "IMPLEMENTATION" >> pure(OmpTraitSetSelectorName::Value::Implementation) ||
+ "TARGET_DEVICE" >> pure(OmpTraitSetSelectorName::Value::Target_Device) ||
+ "USER" >> pure(OmpTraitSetSelectorName::Value::User)))
+
+TYPE_PARSER(construct<OmpTraitSetSelectorName>(
+ Parser<OmpTraitSetSelectorName::Value>{}))
+
+TYPE_PARSER(construct<OmpTraitSetSelector>( //
+ Parser<OmpTraitSetSelectorName>{},
+ "=" >> braced(nonemptySeparated(Parser<OmpTraitSelector>{}, ","_tok))))
+
+TYPE_PARSER(construct<OmpContextSelectorSpecification>(
+ nonemptySeparated(Parser<OmpTraitSetSelector>{}, ","_tok)))
+
+// Parser<OmpContextSelector> == Parser<traits::OmpContextSelectorSpecification>
+
// --- Parsers for clause modifiers -----------------------------------
TYPE_PARSER(construct<OmpAlignment>(scalarIntExpr))
diff --git a/flang/lib/Parser/token-parsers.h b/flang/lib/Parser/token-parsers.h
index fe6bc1f69f576b..3e0c59b89d9649 100644
--- a/flang/lib/Parser/token-parsers.h
+++ b/flang/lib/Parser/token-parsers.h
@@ -215,6 +215,10 @@ template <class PA> inline constexpr auto bracketed(const PA &p) {
return "[" >> p / "]";
}
+template <class PA> inline constexpr auto braced(const PA &p) {
+ return "{" >> p / "}";
+}
+
// Quoted character literal constants.
struct CharLiteralChar {
using resultType = std::pair<char, bool /* was escaped */>;
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 58820476c51bc1..31a2c3bbc408d5 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2067,6 +2067,41 @@ class UnparseVisitor {
}
// OpenMP Clauses & Directives
+ void Unparse(const llvm::omp::Directive &x) {
+ Word(llvm::omp::getOpenMPDirectiveName(x).str());
+ }
+ void Unparse(const OmpDirectiveSpecification &x) {
+ Walk(std::get<llvm::omp::Directive>(x.t));
+ Walk(std::get<std::optional<common::Indirection<OmpClauseList>>>(x.t));
+ }
+ void Unparse(const OmpTraitScore &x) {
+ Word("SCORE(");
+ Walk(x.v);
+ Put(")");
+ }
+ void Unparse(const OmpTraitPropertyExtension &x) {
+ Walk(std::get<OmpTraitPropertyName>(x.t));
+ Put("(");
+ Walk(std::get<OmpTraitPropertyExtension::ExtensionList>(x.t), ",");
+ Put(")");
+ }
+ void Unparse(const OmpTraitSelector &x) {
+ Walk(std::get<OmpTraitSelectorName>(x.t));
+ Walk(std::get<std::optional<OmpTraitSelector::Properties>>(x.t));
+ }
+ void Unparse(const OmpTraitSelector::Properties &x) {
+ Put("(");
+ Walk(std::get<std::optional<OmpTraitScore>>(x.t), ": ");
+ Walk(std::get<std::list<OmpTraitProperty>>(x.t));
+ Put(")");
+ }
+ void Unparse(const OmpTraitSetSelector &x) {
+ Walk(std::get<OmpTraitSetSelectorName>(x.t));
+ Put("={");
+ Walk(std::get<std::list<OmpTraitSelector>>(x.t));
+ Put("}");
+ }
+
void Unparse(const OmpObject &x) {
common::visit(common::visitors{
[&](const Designator &y) { Walk(y); },
@@ -2916,6 +2951,9 @@ class UnparseVisitor {
WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness
WALK_NESTED_ENUM(OmpMapType, Value) // OMP map-type
WALK_NESTED_ENUM(OmpMapTypeModifier, Value) // OMP map-type-modifier
+ WALK_NESTED_ENUM(OmpTraitSelectorName, Value)
+ WALK_NESTED_ENUM(OmpTraitSetSelectorName, Value)
+
#undef WALK_NESTED_ENUM
void Unparse(const ReductionOperator::Operator x) {
switch (x) {
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 6db43cf6f04bd3..67f7f65b7e422b 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -590,6 +590,14 @@ void OmpStructureChecker::CheckHintClause(
}
}
+void OmpStructureChecker::Enter(const parser::OmpDirectiveSpecification &x) {
+ PushContextAndClauseSets(x.source, std::get<llvm::omp::Directive>(x.t));
+}
+
+void OmpStructureChecker::Leave(const parser::OmpDirectiveSpecification &) {
+ dirContext_.pop_back();
+}
+
void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
// Simd Construct with Ordered Construct Nesting check
// We cannot use CurrentDirectiveIsNested() here because
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index dc360957c873b7..1fc7e6c1e9baaa 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -144,6 +144,9 @@ class OmpStructureChecker
void Enter(const parser::DoConstruct &);
void Leave(const parser::DoConstruct &);
+ void Enter(const parser::OmpDirectiveSpecification &);
+ void Leave(const parser::OmpDirectiveSpecification &);
+
#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 39478b58a9070d..4e423ea1b43251 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -351,6 +351,12 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
return true;
}
+ bool Pre(const parser::OmpDirectiveSpecification &x) {
+ PushContext(x.source, std::get<llvm::omp::Directive>(x.t));
+ return true;
+ }
+ void Post(const parser::OmpDirectiveSpecification &) { PopContext(); }
+
bool Pre(const parser::OpenMPBlockConstruct &);
void Post(const parser::OpenMPBlockConstruct &);
>From 0e317db2f2bbc24f0c3b427031cb26ba4daf9e6e Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 9 Jan 2025 09:22:59 -0600
Subject: [PATCH 2/7] Remove DirectiveSpecification
---
flang/include/flang/Parser/dump-parse-tree.h | 1 -
flang/include/flang/Parser/parse-tree.h | 8 --------
flang/lib/Parser/openmp-parsers.cpp | 3 ---
flang/lib/Parser/unparse.cpp | 4 ----
flang/lib/Semantics/check-omp-structure.cpp | 8 --------
flang/lib/Semantics/check-omp-structure.h | 3 ---
flang/lib/Semantics/resolve-directives.cpp | 6 ------
7 files changed, 33 deletions(-)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index a61d7973dd5c36..11725991e9c9a9 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -476,7 +476,6 @@ class ParseTreeDumper {
NODE(parser, NullInit)
NODE(parser, ObjectDecl)
NODE(parser, OldParameterStmt)
- NODE(parser, OmpDirectiveSpecification)
NODE(parser, OmpTraitPropertyName)
NODE(parser, OmpTraitScore)
NODE(parser, OmpTraitPropertyExtension)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 697bddfaf16150..fbe0ff39f40799 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3456,14 +3456,6 @@ WRAPPER_CLASS(PauseStmt, std::optional<StopCode>);
struct OmpClause;
struct OmpClauseList;
-struct OmpDirectiveSpecification {
- TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification);
- std::tuple<llvm::omp::Directive,
- std::optional<common::Indirection<OmpClauseList>>>
- t;
- CharBlock source;
-};
-
// 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
// in slashes). An extended list item is a list item or a procedure Name.
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 35ed32602ecc94..ca9a2caf56fd76 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -153,9 +153,6 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) {
makeEntityList(std::move(names)));
}
-TYPE_PARSER(sourced(construct<OmpDirectiveSpecification>(
- OmpDirectiveNameParser{}, maybe(indirect(Parser<OmpClauseList>{})))))
-
// --- Parsers for context traits -------------------------------------
TYPE_PARSER(construct<OmpTraitPropertyName>( //
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 31a2c3bbc408d5..ddd20ddeb4302a 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2070,10 +2070,6 @@ class UnparseVisitor {
void Unparse(const llvm::omp::Directive &x) {
Word(llvm::omp::getOpenMPDirectiveName(x).str());
}
- void Unparse(const OmpDirectiveSpecification &x) {
- Walk(std::get<llvm::omp::Directive>(x.t));
- Walk(std::get<std::optional<common::Indirection<OmpClauseList>>>(x.t));
- }
void Unparse(const OmpTraitScore &x) {
Word("SCORE(");
Walk(x.v);
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 67f7f65b7e422b..6db43cf6f04bd3 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -590,14 +590,6 @@ void OmpStructureChecker::CheckHintClause(
}
}
-void OmpStructureChecker::Enter(const parser::OmpDirectiveSpecification &x) {
- PushContextAndClauseSets(x.source, std::get<llvm::omp::Directive>(x.t));
-}
-
-void OmpStructureChecker::Leave(const parser::OmpDirectiveSpecification &) {
- dirContext_.pop_back();
-}
-
void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
// Simd Construct with Ordered Construct Nesting check
// We cannot use CurrentDirectiveIsNested() here because
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 1fc7e6c1e9baaa..dc360957c873b7 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -144,9 +144,6 @@ class OmpStructureChecker
void Enter(const parser::DoConstruct &);
void Leave(const parser::DoConstruct &);
- void Enter(const parser::OmpDirectiveSpecification &);
- void Leave(const parser::OmpDirectiveSpecification &);
-
#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..39478b58a9070d 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -351,12 +351,6 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
return true;
}
- bool Pre(const parser::OmpDirectiveSpecification &x) {
- PushContext(x.source, std::get<llvm::omp::Directive>(x.t));
- return true;
- }
- void Post(const parser::OmpDirectiveSpecification &) { PopContext(); }
-
bool Pre(const parser::OpenMPBlockConstruct &);
void Post(const parser::OpenMPBlockConstruct &);
>From 419bdfa27ef1ed3ca3a46cf8601c2536e091ba85 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Tue, 7 Jan 2025 14:47:15 -0600
Subject: [PATCH 3/7] Fix unparsing multiple set selectors
---
flang/lib/Parser/unparse.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index ddd20ddeb4302a..7bf404bba2c3e4 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2097,6 +2097,7 @@ class UnparseVisitor {
Walk(std::get<std::list<OmpTraitSelector>>(x.t));
Put("}");
}
+ void Unparse(const OmpContextSelectorSpecification &x) { Walk(x.v, ", "); }
void Unparse(const OmpObject &x) {
common::visit(common::visitors{
>From c4b900779d1f132ba2f50f592fbffe15e2ff0c3b Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 9 Jan 2025 10:15:41 -0600
Subject: [PATCH 4/7] Add "source" to context objects
---
flang/include/flang/Parser/parse-tree.h | 10 +++++++
flang/lib/Parser/openmp-parsers.cpp | 40 ++++++++++++-------------
2 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index fbe0ff39f40799..1d4d5a820249c5 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3481,12 +3481,14 @@ inline namespace traits {
// trait-property-name ->
// identifier | string-literal
struct OmpTraitPropertyName {
+ CharBlock source;
WRAPPER_CLASS_BOILERPLATE(OmpTraitPropertyName, std::string);
};
// trait-score ->
// SCORE(non-negative-const-integer-expression)
struct OmpTraitScore {
+ CharBlock source;
WRAPPER_CLASS_BOILERPLATE(OmpTraitScore, ScalarIntExpr);
};
@@ -3511,8 +3513,10 @@ struct OmpTraitScore {
// constant integer expression <- conflict with (b)
//
struct OmpTraitPropertyExtension {
+ CharBlock source;
TUPLE_CLASS_BOILERPLATE(OmpTraitPropertyExtension);
struct ExtensionValue {
+ CharBlock source;
UNION_CLASS_BOILERPLATE(ExtensionValue);
std::variant<OmpTraitPropertyName, ScalarExpr,
common::Indirection<OmpTraitPropertyExtension>>
@@ -3533,6 +3537,7 @@ struct OmpTraitPropertyExtension {
// will happen if the scalar integer expression sees a logical expresion.
// To avoid this, parse all expressions as scalar expressions.
struct OmpTraitProperty {
+ CharBlock source;
UNION_CLASS_BOILERPLATE(OmpTraitProperty);
std::variant<OmpTraitPropertyName, common::Indirection<OmpClause>,
ScalarExpr, // trait-property-expresion
@@ -3558,6 +3563,7 @@ struct OmpTraitProperty {
// Trait-set-selectors:
// [D]evice, [T]arget_device, [C]onstruct, [I]mplementation, [U]ser.
struct OmpTraitSelectorName {
+ CharBlock source;
UNION_CLASS_BOILERPLATE(OmpTraitSelectorName);
ENUM_CLASS(Value, Arch, Atomic_Default_Mem_Order, Condition, Device_Num,
Extension, Isa, Kind, Requires, Simd, Uid, Vendor)
@@ -3568,6 +3574,7 @@ struct OmpTraitSelectorName {
// trait-selector-name |
// trait-selector-name ([trait-score:] trait-property, ...)
struct OmpTraitSelector {
+ CharBlock source;
TUPLE_CLASS_BOILERPLATE(OmpTraitSelector);
struct Properties {
TUPLE_CLASS_BOILERPLATE(Properties);
@@ -3580,6 +3587,7 @@ struct OmpTraitSelector {
// CONSTRUCT | DEVICE | IMPLEMENTATION | USER | // since 5.0
// TARGET_DEVICE // since 5.1
struct OmpTraitSetSelectorName {
+ CharBlock source;
ENUM_CLASS(Value, Construct, Device, Implementation, Target_Device, User)
WRAPPER_CLASS_BOILERPLATE(OmpTraitSetSelectorName, Value);
};
@@ -3587,6 +3595,7 @@ struct OmpTraitSetSelectorName {
// trait-set-selector ->
// trait-set-selector-name = {trait-selector, ...}
struct OmpTraitSetSelector {
+ CharBlock source;
TUPLE_CLASS_BOILERPLATE(OmpTraitSetSelector);
std::tuple<OmpTraitSetSelectorName, std::list<OmpTraitSelector>> t;
};
@@ -3594,6 +3603,7 @@ struct OmpTraitSetSelector {
// context-selector-specification ->
// trait-set-selector, ...
struct OmpContextSelectorSpecification { // Modifier
+ CharBlock source;
WRAPPER_CLASS_BOILERPLATE(
OmpContextSelectorSpecification, std::list<OmpTraitSetSelector>);
};
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index ca9a2caf56fd76..7f7eaaeaef6351 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -155,32 +155,32 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) {
// --- Parsers for context traits -------------------------------------
-TYPE_PARSER(construct<OmpTraitPropertyName>( //
+TYPE_PARSER(sourced(construct<OmpTraitPropertyName>( //
(space >> charLiteralConstantWithoutKind) ||
- applyMem(&Name::ToString, Parser<Name>{})))
+ applyMem(&Name::ToString, Parser<Name>{}))))
-TYPE_PARSER(construct<OmpTraitScore>( //
- "SCORE" >> parenthesized(scalarIntExpr)))
+TYPE_PARSER(sourced(construct<OmpTraitScore>( //
+ "SCORE" >> parenthesized(scalarIntExpr))))
-TYPE_PARSER(construct<OmpTraitPropertyExtension::ExtensionValue>(
+TYPE_PARSER(sourced(construct<OmpTraitPropertyExtension::ExtensionValue>(
// Parse nested extension first.
construct<OmpTraitPropertyExtension::ExtensionValue>(
indirect(Parser<OmpTraitPropertyExtension>{})) ||
construct<OmpTraitPropertyExtension::ExtensionValue>(
Parser<OmpTraitPropertyName>{}) ||
- construct<OmpTraitPropertyExtension::ExtensionValue>(scalarExpr)))
+ construct<OmpTraitPropertyExtension::ExtensionValue>(scalarExpr))))
-TYPE_PARSER(construct<OmpTraitPropertyExtension>( //
+TYPE_PARSER(sourced(construct<OmpTraitPropertyExtension>( //
Parser<OmpTraitPropertyName>{},
parenthesized(nonemptySeparated(
- Parser<OmpTraitPropertyExtension::ExtensionValue>{}, ","_tok))))
+ Parser<OmpTraitPropertyExtension::ExtensionValue>{}, ","_tok)))))
-TYPE_PARSER(construct<OmpTraitProperty>(
+TYPE_PARSER(sourced(construct<OmpTraitProperty>(
// Try extension first, before OmpTraitPropertyName.
construct<OmpTraitProperty>(Parser<OmpTraitPropertyExtension>{}) ||
construct<OmpTraitProperty>(Parser<OmpTraitPropertyName>{}) ||
construct<OmpTraitProperty>(indirect(Parser<OmpClause>{})) ||
- construct<OmpTraitProperty>(scalarExpr)))
+ construct<OmpTraitProperty>(scalarExpr))))
TYPE_PARSER(construct<OmpTraitSelectorName::Value>(
"ARCH" >> pure(OmpTraitSelectorName::Value::Arch) ||
@@ -196,18 +196,18 @@ TYPE_PARSER(construct<OmpTraitSelectorName::Value>(
"UID" >> pure(OmpTraitSelectorName::Value::Uid) ||
"VENDOR" >> pure(OmpTraitSelectorName::Value::Vendor)))
-TYPE_PARSER(construct<OmpTraitSelectorName>(
+TYPE_PARSER(sourced(construct<OmpTraitSelectorName>(
// Parse predefined names first (because of SIMD).
construct<OmpTraitSelectorName>(Parser<OmpTraitSelectorName::Value>{}) ||
- construct<OmpTraitSelectorName>(OmpDirectiveNameParser{})))
+ construct<OmpTraitSelectorName>(OmpDirectiveNameParser{}))))
TYPE_PARSER(construct<OmpTraitSelector::Properties>(
maybe(Parser<OmpTraitScore>{} / ":"_tok),
nonemptySeparated(Parser<OmpTraitProperty>{}, ","_tok)))
-TYPE_PARSER(construct<OmpTraitSelector>( //
+TYPE_PARSER(sourced(construct<OmpTraitSelector>( //
Parser<OmpTraitSelectorName>{}, //
- maybe(parenthesized(Parser<OmpTraitSelector::Properties>{}))))
+ maybe(parenthesized(Parser<OmpTraitSelector::Properties>{})))))
TYPE_PARSER(construct<OmpTraitSetSelectorName::Value>(
"CONSTRUCT" >> pure(OmpTraitSetSelectorName::Value::Construct) ||
@@ -216,15 +216,15 @@ TYPE_PARSER(construct<OmpTraitSetSelectorName::Value>(
"TARGET_DEVICE" >> pure(OmpTraitSetSelectorName::Value::Target_Device) ||
"USER" >> pure(OmpTraitSetSelectorName::Value::User)))
-TYPE_PARSER(construct<OmpTraitSetSelectorName>(
- Parser<OmpTraitSetSelectorName::Value>{}))
+TYPE_PARSER(sourced(construct<OmpTraitSetSelectorName>(
+ Parser<OmpTraitSetSelectorName::Value>{})))
-TYPE_PARSER(construct<OmpTraitSetSelector>( //
+TYPE_PARSER(sourced(construct<OmpTraitSetSelector>( //
Parser<OmpTraitSetSelectorName>{},
- "=" >> braced(nonemptySeparated(Parser<OmpTraitSelector>{}, ","_tok))))
+ "=" >> braced(nonemptySeparated(Parser<OmpTraitSelector>{}, ","_tok)))))
-TYPE_PARSER(construct<OmpContextSelectorSpecification>(
- nonemptySeparated(Parser<OmpTraitSetSelector>{}, ","_tok)))
+TYPE_PARSER(sourced(construct<OmpContextSelectorSpecification>(
+ nonemptySeparated(Parser<OmpTraitSetSelector>{}, ","_tok))))
// Parser<OmpContextSelector> == Parser<traits::OmpContextSelectorSpecification>
>From d6ca30be75a54d0fe2b9f56e9494ad6bab25a479 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 9 Jan 2025 10:23:26 -0600
Subject: [PATCH 5/7] Try clause first when parsing trait
---
flang/lib/Parser/openmp-parsers.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 7f7eaaeaef6351..44db56165452c4 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -176,10 +176,10 @@ TYPE_PARSER(sourced(construct<OmpTraitPropertyExtension>( //
Parser<OmpTraitPropertyExtension::ExtensionValue>{}, ","_tok)))))
TYPE_PARSER(sourced(construct<OmpTraitProperty>(
- // Try extension first, before OmpTraitPropertyName.
+ // Try clause first, then extension before OmpTraitPropertyName.
+ construct<OmpTraitProperty>(indirect(Parser<OmpClause>{})) ||
construct<OmpTraitProperty>(Parser<OmpTraitPropertyExtension>{}) ||
construct<OmpTraitProperty>(Parser<OmpTraitPropertyName>{}) ||
- construct<OmpTraitProperty>(indirect(Parser<OmpClause>{})) ||
construct<OmpTraitProperty>(scalarExpr))))
TYPE_PARSER(construct<OmpTraitSelectorName::Value>(
>From e0ca3474881b4a64247c87605a4d2bbeacc94c2d Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Fri, 10 Jan 2025 09:24:14 -0600
Subject: [PATCH 6/7] add comment with explanation
---
flang/include/flang/Parser/parse-tree.h | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 1d4d5a820249c5..00d85aa05fb3a5 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3480,6 +3480,18 @@ WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
inline namespace traits {
// trait-property-name ->
// identifier | string-literal
+//
+// This is a bit of a problematic case. The spec says that a word in quotes,
+// and the same word without quotes are equivalent. We currently parse both
+// as a string, but it's likely just a temporary solution.
+//
+// The problem is that trait-property can be (among other things) a
+// trait-property-name or a trait-property-expression. A simple identifier
+// can be either, there is no reasonably simple way of telling them apart
+// in the parser. There is a similar issue with extensions. Some of that
+// disambiguation may need to be done in the "canonicalization" pass and
+// then some of those AST nodes would be rewritten into different ones.
+//
struct OmpTraitPropertyName {
CharBlock source;
WRAPPER_CLASS_BOILERPLATE(OmpTraitPropertyName, std::string);
>From ca7584b5432b2e8351d1f2ab50c830377b2f1478 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Fri, 10 Jan 2025 09:38:31 -0600
Subject: [PATCH 7/7] remove use of applyMem
---
flang/lib/Parser/openmp-parsers.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 44db56165452c4..5ff91da082c852 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -155,9 +155,11 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) {
// --- Parsers for context traits -------------------------------------
+static std::string nameToString(Name &&name) { return name.ToString(); }
+
TYPE_PARSER(sourced(construct<OmpTraitPropertyName>( //
(space >> charLiteralConstantWithoutKind) ||
- applyMem(&Name::ToString, Parser<Name>{}))))
+ applyFunction(nameToString, Parser<Name>{}))))
TYPE_PARSER(sourced(construct<OmpTraitScore>( //
"SCORE" >> parenthesized(scalarIntExpr))))
More information about the llvm-branch-commits
mailing list