aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Parser
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Parser')
-rw-r--r--flang/lib/Parser/openmp-parsers.cpp149
-rw-r--r--flang/lib/Parser/unparse.cpp32
2 files changed, 149 insertions, 32 deletions
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index d349d8c..9b73dc8 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -34,6 +34,39 @@ namespace Fortran::parser {
constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
constexpr auto endOmpLine = space >> endOfLine;
+// Given a parser for a single element, and a parser for a list of elements
+// of the same type, create a parser that constructs the entire list by having
+// the single element be the head of the list, and the rest be the tail.
+template <typename ParserH, typename ParserT> struct ConsParser {
+ static_assert(std::is_same_v<std::list<typename ParserH::resultType>,
+ typename ParserT::resultType>);
+
+ using resultType = typename ParserT::resultType;
+ constexpr ConsParser(ParserH h, ParserT t) : head_(h), tail_(t) {}
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ if (auto &&first{head_.Parse(state)}) {
+ if (auto rest{tail_.Parse(state)}) {
+ rest->push_front(std::move(*first));
+ return std::move(*rest);
+ }
+ }
+ return std::nullopt;
+ }
+
+private:
+ const ParserH head_;
+ const ParserT tail_;
+};
+
+template <typename ParserH, typename ParserT,
+ typename ValueH = typename ParserH::resultType,
+ typename ValueT = typename ParserT::resultType,
+ typename = std::enable_if_t<std::is_same_v<std::list<ValueH>, ValueT>>>
+constexpr auto cons(ParserH head, ParserT tail) {
+ return ConsParser<ParserH, ParserT>(head, tail);
+}
+
// Given a parser P for a wrapper class, invoke P, and if it succeeds return
// the wrapped object.
template <typename Parser> struct UnwrapParser {
@@ -449,6 +482,9 @@ TYPE_PARSER(construct<OmpAllocatorSimpleModifier>(scalarIntExpr))
TYPE_PARSER(construct<OmpAlwaysModifier>( //
"ALWAYS" >> pure(OmpAlwaysModifier::Value::Always)))
+TYPE_PARSER(construct<OmpAutomapModifier>(
+ "AUTOMAP" >> pure(OmpAutomapModifier::Value::Automap)))
+
TYPE_PARSER(construct<OmpChunkModifier>( //
"SIMD" >> pure(OmpChunkModifier::Value::Simd)))
@@ -466,6 +502,8 @@ TYPE_PARSER(construct<OmpDeviceModifier>(
"ANCESTOR" >> pure(OmpDeviceModifier::Value::Ancestor) ||
"DEVICE_NUM" >> pure(OmpDeviceModifier::Value::Device_Num)))
+TYPE_PARSER(construct<OmpDirectiveNameModifier>(OmpDirectiveNameParser{}))
+
TYPE_PARSER(construct<OmpExpectation>( //
"PRESENT" >> pure(OmpExpectation::Value::Present)))
@@ -601,6 +639,9 @@ TYPE_PARSER(sourced(construct<OmpDependClause::TaskDep::Modifier>(sourced(
TYPE_PARSER(
sourced(construct<OmpDeviceClause::Modifier>(Parser<OmpDeviceModifier>{})))
+TYPE_PARSER(
+ sourced(construct<OmpEnterClause::Modifier>(Parser<OmpAutomapModifier>{})))
+
TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>(
sourced(construct<OmpFromClause::Modifier>(Parser<OmpExpectation>{}) ||
construct<OmpFromClause::Modifier>(Parser<OmpMapper>{}) ||
@@ -609,7 +650,8 @@ TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>(
TYPE_PARSER(sourced(
construct<OmpGrainsizeClause::Modifier>(Parser<OmpPrescriptiveness>{})))
-TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
+TYPE_PARSER(sourced(
+ construct<OmpIfClause::Modifier>(Parser<OmpDirectiveNameModifier>{})))
TYPE_PARSER(sourced(
construct<OmpInitClause::Modifier>(
@@ -735,6 +777,10 @@ TYPE_PARSER(construct<OmpDefaultClause>(
Parser<OmpDefaultClause::DataSharingAttribute>{}) ||
construct<OmpDefaultClause>(indirect(Parser<OmpDirectiveSpecification>{}))))
+TYPE_PARSER(construct<OmpEnterClause>(
+ maybe(nonemptyList(Parser<OmpEnterClause::Modifier>{}) / ":"),
+ Parser<OmpObjectList>{}))
+
TYPE_PARSER(construct<OmpFailClause>(
"ACQ_REL" >> pure(common::OmpMemoryOrderType::Acq_Rel) ||
"ACQUIRE" >> pure(common::OmpMemoryOrderType::Acquire) ||
@@ -1023,7 +1069,7 @@ TYPE_PARSER( //
"DYNAMIC_ALLOCATORS" >>
construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) ||
"ENTER" >> construct<OmpClause>(construct<OmpClause::Enter>(
- parenthesized(Parser<OmpObjectList>{}))) ||
+ parenthesized(Parser<OmpEnterClause>{}))) ||
"EXCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Exclusive>(
parenthesized(Parser<OmpObjectList>{}))) ||
"FAIL" >> construct<OmpClause>(construct<OmpClause::Fail>(
@@ -1208,6 +1254,61 @@ TYPE_PARSER(sourced(
maybe(Parser<OmpClauseList>{}),
pure(OmpDirectiveSpecification::Flags::None))))
+static bool IsFortranBlockConstruct(const ExecutionPartConstruct &epc) {
+ // ExecutionPartConstruct -> ExecutableConstruct
+ // -> Indirection<BlockConstruct>
+ if (auto *ec{std::get_if<ExecutableConstruct>(&epc.u)}) {
+ return std::holds_alternative<common::Indirection<BlockConstruct>>(ec->u);
+ } else {
+ return false;
+ }
+}
+
+struct StrictlyStructuredBlockParser {
+ using resultType = Block;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ // Detect BLOCK construct without parsing the entire thing.
+ if (lookAhead(skipStuffBeforeStatement >> "BLOCK"_tok).Parse(state)) {
+ if (auto epc{Parser<ExecutionPartConstruct>{}.Parse(state)}) {
+ if (IsFortranBlockConstruct(*epc)) {
+ Block block;
+ block.emplace_back(std::move(*epc));
+ return std::move(block);
+ }
+ }
+ }
+ return std::nullopt;
+ }
+};
+
+struct LooselyStructuredBlockParser {
+ using resultType = Block;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ // Detect BLOCK construct without parsing the entire thing.
+ if (lookAhead(skipStuffBeforeStatement >> "BLOCK"_tok).Parse(state)) {
+ return std::nullopt;
+ }
+ Block body;
+ if (auto epc{attempt(Parser<ExecutionPartConstruct>{}).Parse(state)}) {
+ if (!IsFortranBlockConstruct(*epc)) {
+ body.emplace_back(std::move(*epc));
+ if (auto &&blk{attempt(block).Parse(state)}) {
+ for (auto &&s : *blk) {
+ body.emplace_back(std::move(s));
+ }
+ }
+ } else {
+ // Fail if the first construct is BLOCK.
+ return std::nullopt;
+ }
+ }
+ // Empty body is ok.
+ return std::move(body);
+ }
+};
+
TYPE_PARSER(sourced(construct<OmpNothingDirective>("NOTHING" >> ok)))
TYPE_PARSER(sourced(construct<OpenMPUtilityConstruct>(
@@ -1570,12 +1671,16 @@ TYPE_PARSER(
Parser<OpenMPInteropConstruct>{})) /
endOfLine)
+// Directive names (of non-block constructs) whose prefix is a name of
+// a block-associated construct. We need to exclude them from the block
+// directive parser below to avoid parsing parts of them.
+static constexpr auto StandaloneDirectiveLookahead{//
+ "TARGET ENTER DATA"_sptok || "TARGET_ENTER_DATA"_sptok || //
+ "TARGET EXIT DATA"_sptok || "TARGET_EXIT"_sptok || //
+ "TARGET UPDATE"_sptok || "TARGET_UPDATE"_sptok};
+
// Directives enclosing structured-block
-TYPE_PARSER(
- // In this context "TARGET UPDATE" can be parsed as a TARGET directive
- // followed by an UPDATE clause. This is the only combination at the
- // moment, exclude it explicitly.
- (!("TARGET UPDATE"_sptok || "TARGET_UPDATE"_sptok)) >=
+TYPE_PARSER((!StandaloneDirectiveLookahead) >=
construct<OmpBlockDirective>(first(
"MASKED" >> pure(llvm::omp::Directive::OMPD_masked),
"MASTER" >> pure(llvm::omp::Directive::OMPD_master),
@@ -1749,9 +1854,12 @@ TYPE_PARSER(sourced(
block, maybe(Parser<OmpEndAssumeDirective>{} / endOmpLine))))
// Block Construct
-TYPE_PARSER(construct<OpenMPBlockConstruct>(
- Parser<OmpBeginBlockDirective>{} / endOmpLine, block,
- Parser<OmpEndBlockDirective>{} / endOmpLine))
+TYPE_PARSER( //
+ construct<OpenMPBlockConstruct>(Parser<OmpBeginBlockDirective>{},
+ StrictlyStructuredBlockParser{},
+ maybe(Parser<OmpEndBlockDirective>{})) ||
+ construct<OpenMPBlockConstruct>(Parser<OmpBeginBlockDirective>{},
+ LooselyStructuredBlockParser{}, Parser<OmpEndBlockDirective>{}))
// OMP SECTIONS Directive
TYPE_PARSER(construct<OmpSectionsDirective>(first(
@@ -1766,19 +1874,20 @@ TYPE_PARSER(
sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
Parser<OmpClauseList>{})))
-// OMP SECTION-BLOCK
-
-TYPE_PARSER(construct<OpenMPSectionConstruct>(block))
-
-TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >>
- construct<OmpSectionBlocks>(nonemptySeparated(
- construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})),
- startOmpLine >> "SECTION"_tok / endOmpLine)))
+static constexpr auto sectionDir{
+ startOmpLine >> (predicated(OmpDirectiveNameParser{},
+ IsDirective(llvm::omp::Directive::OMPD_section)) >=
+ Parser<OmpDirectiveSpecification>{})};
// OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3)
-TYPE_PARSER(construct<OpenMPSectionsConstruct>(
+TYPE_PARSER(sourced(construct<OpenMPSectionsConstruct>(
Parser<OmpBeginSectionsDirective>{} / endOmpLine,
- Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine))
+ cons( //
+ construct<OpenMPConstruct>(sourced(
+ construct<OpenMPSectionConstruct>(maybe(sectionDir), block))),
+ many(construct<OpenMPConstruct>(
+ sourced(construct<OpenMPSectionConstruct>(sectionDir, block))))),
+ Parser<OmpEndSectionsDirective>{} / endOmpLine)))
static bool IsExecutionPart(const OmpDirectiveName &name) {
return name.IsExecutionPart();
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 8ed1690..ef209ff 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2250,6 +2250,11 @@ public:
Walk(std::get<OmpObjectList>(x.t));
Walk(": ", std::get<std::optional<std::list<Modifier>>>(x.t));
}
+ void Unparse(const OmpEnterClause &x) {
+ using Modifier = OmpEnterClause::Modifier;
+ Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
+ Walk(std::get<OmpObjectList>(x.t));
+ }
void Unparse(const OmpFromClause &x) {
using Modifier = OmpFromClause::Modifier;
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
@@ -2801,16 +2806,16 @@ public:
break;
}
}
- void Unparse(const OmpSectionBlocks &x) {
- for (const auto &y : x.v) {
+ void Unparse(const OpenMPSectionConstruct &x) {
+ if (auto &&dirSpec{
+ std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
BeginOpenMP();
- Word("!$OMP SECTION");
+ Word("!$OMP ");
+ Walk(*dirSpec);
Put("\n");
EndOpenMP();
- // y.u is an OpenMPSectionConstruct
- // (y.u).v is Block
- Walk(std::get<OpenMPSectionConstruct>(y.u).v, "");
}
+ Walk(std::get<Block>(x.t), "");
}
void Unparse(const OpenMPSectionsConstruct &x) {
BeginOpenMP();
@@ -2818,7 +2823,7 @@ public:
Walk(std::get<OmpBeginSectionsDirective>(x.t));
Put("\n");
EndOpenMP();
- Walk(std::get<OmpSectionBlocks>(x.t));
+ Walk(std::get<std::list<OpenMPConstruct>>(x.t), "");
BeginOpenMP();
Word("!$OMP END ");
Walk(std::get<OmpEndSectionsDirective>(x.t));
@@ -2898,11 +2903,13 @@ public:
Put("\n");
EndOpenMP();
Walk(std::get<Block>(x.t), "");
- BeginOpenMP();
- Word("!$OMP END ");
- Walk(std::get<OmpEndBlockDirective>(x.t));
- Put("\n");
- EndOpenMP();
+ if (auto &&end{std::get<std::optional<OmpEndBlockDirective>>(x.t)}) {
+ BeginOpenMP();
+ Word("!$OMP END ");
+ Walk(*end);
+ Put("\n");
+ EndOpenMP();
+ }
}
void Unparse(const OpenMPLoopConstruct &x) {
BeginOpenMP();
@@ -2984,6 +2991,7 @@ public:
WALK_NESTED_ENUM(UseStmt, ModuleNature) // R1410
WALK_NESTED_ENUM(OmpAdjustArgsClause::OmpAdjustOp, Value) // OMP adjustop
WALK_NESTED_ENUM(OmpAtClause, ActionTime) // OMP at
+ WALK_NESTED_ENUM(OmpAutomapModifier, Value) // OMP automap-modifier
WALK_NESTED_ENUM(OmpBindClause, Binding) // OMP bind
WALK_NESTED_ENUM(OmpProcBindClause, AffinityPolicy) // OMP proc_bind
WALK_NESTED_ENUM(OmpDefaultClause, DataSharingAttribute) // OMP default