[flang] [OpenMP] parse tree changes for Sections/Parallel Sections constructs (flang-compiler/f18#652)

```
!$omp sections [clause[ [,] clause] ... ]
[!$omp section]
structured-block
[!$omp section
structured-block]
...
!$omp end sections [nowait]
```

1. Following parse tree node changes for Block constructs, changing the
   Sections/Parallel Sections to `{Begin, Section-Blocks, End}`

2. Handles `!$omp section` in the parser, do not create parse tree node
   for this directive because basically it is a delimiter to split the
   code into different `Block`s within the Sections/Parallel Sections
   constructs. So, the `Section-Blocks` here is a `std::list` of `Block`s.
   (thanks to Tim's suggestion)

3. Modify check-omp-structure.* to avoid breaking existing tests

More tests will be added during Semantics. Also, similar to Block constructs,
the `Begin` and `End` directive matching will be done in future PR.

This commit also contains Peter's important fix for allowing "!$OMP END SECTION"
as a legal statement following `Block` (daf5630: Modify execution part error
recovery to not consume !$OMP SECTION).


Original-commit: flang-compiler/f18@75d016f6d2
Reviewed-on: https://github.com/flang-compiler/f18/pull/652
This commit is contained in:
Jinxin (Brian) Yang 2019-08-14 08:42:28 -07:00 committed by GitHub
parent e688b27210
commit e59305d7ae
8 changed files with 109 additions and 77 deletions

View file

@ -413,6 +413,7 @@ public:
NODE(parser, OmpAtomicUpdate)
NODE(parser, OmpAtomicWrite)
NODE(parser, OmpBeginBlockDirective)
NODE(parser, OmpBeginSectionsDirective)
NODE(parser, OmpBlockDirective)
NODE_ENUM(parser::OmpBlockDirective, Directive)
NODE(parser, OmpCancelType)
@ -471,8 +472,7 @@ public:
NODE(parser, OmpEndCriticalDirective)
NODE(parser, OmpEndDo)
NODE(parser, OmpEndDoSimd)
NODE(parser, OmpEndParallelSections)
NODE(parser, OmpEndSections)
NODE(parser, OmpEndSectionsDirective)
NODE(parser, OmpIfClause)
NODE_ENUM(parser::OmpIfClause, DirectiveNameModifier)
NODE(parser, OmpLinearClause)
@ -508,7 +508,9 @@ public:
NODE(parser::OmpScheduleModifier, Modifier2)
NODE(parser, OmpScheduleModifierType)
NODE_ENUM(parser::OmpScheduleModifierType, ModType)
NODE(parser, OmpSection)
NODE(parser, OmpSectionBlocks)
NODE(parser, OmpSectionsDirective)
NODE_ENUM(parser::OmpSectionsDirective, Directive)
NODE(parser, OmpSimpleStandaloneDirective)
NODE_ENUM(parser::OmpSimpleStandaloneDirective, Directive)
NODE(parser, Only)
@ -534,7 +536,6 @@ public:
NODE(parser, OpenMPStandaloneConstruct)
NODE(parser, OpenMPSectionsConstruct)
NODE(parser, OpenMPThreadprivate)
NODE(parser, OpenMPParallelSectionsConstruct)
NODE(parser, OpenStmt)
NODE(parser, Optional)
NODE(parser, OptionalStmt)

View file

@ -488,39 +488,40 @@ TYPE_PARSER(construct<OmpEndDoSimd>(maybe(construct<OmpNowait>("NOWAIT"_tok))))
// OMP END DO [NOWAIT]
TYPE_PARSER(construct<OmpEndDo>(maybe(construct<OmpNowait>("NOWAIT"_tok))))
// OMP END SECTIONS [NOWAIT]
TYPE_PARSER(startOmpLine >> "END SECTIONS"_tok >>
construct<OmpEndSections>(
maybe("NOWAIT" >> construct<OmpNowait>()) / endOmpLine))
// OMP SECTIONS Directive
TYPE_PARSER(construct<OmpSectionsDirective>(
first("SECTIONS" >> pure(OmpSectionsDirective::Directive::Sections),
"PARALLEL SECTIONS" >>
pure(OmpSectionsDirective::Directive::ParallelSections))))
// OMP SECTIONS
TYPE_PARSER(construct<OpenMPSectionsConstruct>(verbatim("SECTIONS"_tok),
Parser<OmpClauseList>{} / endOmpLine, block, Parser<OmpEndSections>{}))
// OMP BEGIN and END SECTIONS Directive
TYPE_PARSER(construct<OmpBeginSectionsDirective>(
sourced(Parser<OmpSectionsDirective>{}), Parser<OmpClauseList>{}))
TYPE_PARSER(
startOmpLine >> construct<OmpEndSectionsDirective>(
sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
Parser<OmpClauseList>{}))
// OMP END PARALLEL SECTIONS
TYPE_PARSER(construct<OmpEndParallelSections>(
startOmpLine >> "END PARALLEL SECTIONS"_tok / endOmpLine))
// OMP SECTION-BLOCK
TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >>
construct<OmpSectionBlocks>(
nonemptySeparated(block, startOmpLine >> "SECTION"_tok / endOmpLine)))
// OMP PARALLEL SECTIONS
TYPE_PARSER(construct<OpenMPParallelSectionsConstruct>(
verbatim("PARALLEL SECTIONS"_tok), Parser<OmpClauseList>{} / endOmpLine,
block, Parser<OmpEndParallelSections>{}))
TYPE_PARSER(construct<OmpSection>(verbatim("SECTION"_tok) / endOmpLine))
// OMP SECTIONS, PARALLEL SECTIONS
TYPE_PARSER(construct<OpenMPSectionsConstruct>(
Parser<OmpBeginSectionsDirective>{} / endOmpLine,
Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine))
TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
startOmpLine >>
first(construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}),
construct<OpenMPConstruct>(
Parser<OpenMPParallelSectionsConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPBlockConstruct>{}),
// OpenMPBlockConstruct is attempted before
// OpenMPStandaloneConstruct to resolve !$OMP ORDERED
construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{}),
construct<OpenMPConstruct>(Parser<OmpSection>{})))
construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{})))
// END OMP Block directives
TYPE_PARSER(

View file

@ -3468,17 +3468,28 @@ struct OmpClauseList {
};
// SECTIONS, PARALLEL SECTIONS
WRAPPER_CLASS(OmpEndSections, std::optional<OmpNowait>);
WRAPPER_CLASS(OmpSection, Verbatim);
struct OpenMPSectionsConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
std::tuple<Verbatim, OmpClauseList, Block, OmpEndSections> t;
struct OmpSectionsDirective {
ENUM_CLASS(Directive, Sections, ParallelSections);
WRAPPER_CLASS_BOILERPLATE(OmpSectionsDirective, Directive);
CharBlock source;
};
EMPTY_CLASS(OmpEndParallelSections);
struct OpenMPParallelSectionsConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPParallelSectionsConstruct);
std::tuple<Verbatim, OmpClauseList, Block, OmpEndParallelSections> t;
struct OmpBeginSectionsDirective {
TUPLE_CLASS_BOILERPLATE(OmpBeginSectionsDirective);
std::tuple<OmpSectionsDirective, OmpClauseList> t;
};
struct OmpEndSectionsDirective {
TUPLE_CLASS_BOILERPLATE(OmpEndSectionsDirective);
std::tuple<OmpSectionsDirective, OmpClauseList> t;
};
WRAPPER_CLASS(OmpSectionBlocks, std::list<Block>);
struct OpenMPSectionsConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
std::tuple<OmpBeginSectionsDirective, OmpSectionBlocks,
OmpEndSectionsDirective>
t;
};
// OpenMP directive beginning or ending a block
@ -3729,9 +3740,8 @@ struct OpenMPLoopConstruct {
struct OpenMPConstruct {
UNION_CLASS_BOILERPLATE(OpenMPConstruct);
std::variant<OpenMPStandaloneConstruct, OpenMPSectionsConstruct,
OpenMPParallelSectionsConstruct, OpenMPLoopConstruct,
OpenMPBlockConstruct, OpenMPAtomicConstruct, OpenMPCriticalConstruct,
OmpSection>
OpenMPLoopConstruct, OpenMPBlockConstruct, OpenMPAtomicConstruct,
OpenMPCriticalConstruct>
u;
};
}

View file

@ -85,7 +85,7 @@ constexpr auto skipBadLine{SkipPast<'\n'>{} >> construct<ErrorRecovery>()};
constexpr auto executionPartErrorRecovery{stmtErrorRecoveryStart >>
!"END"_tok >> !"CONTAINS"_tok >> !"ELSE"_tok >> !"CASE"_tok >>
!"TYPE IS"_tok >> !"CLASS"_tok >> !"RANK"_tok >>
!("!$OMP "_sptok >> "END"_tok) >> skipBadLine};
!("!$OMP "_sptok >> ("END"_tok || "SECTION"_id)) >> skipBadLine};
// END statement error recovery
constexpr auto missingOptionalName{defaulted(cut >> maybe(name))};

View file

@ -2266,33 +2266,33 @@ public:
Walk(x.v);
EndOpenMP();
}
void Unparse(const OmpSection &x) {
BeginOpenMP();
Word("!$OMP SECTION");
Put("\n");
EndOpenMP();
void Unparse(const OmpSectionsDirective &x) {
switch (x.v) {
case OmpSectionsDirective::Directive::Sections: Word("SECTIONS "); break;
case OmpSectionsDirective::Directive::ParallelSections:
Word("PARALLEL SECTIONS ");
break;
}
}
void Unparse(const OmpSectionBlocks &x) {
for (const auto &y : x.v) {
BeginOpenMP();
Word("!$OMP SECTION");
Put("\n");
EndOpenMP();
Walk(y, ""); // y is Block
}
}
void Unparse(const OpenMPSectionsConstruct &x) {
BeginOpenMP();
Word("!$OMP SECTIONS");
Walk(std::get<OmpClauseList>(x.t));
Word("!$OMP ");
Walk(std::get<OmpBeginSectionsDirective>(x.t));
Put("\n");
EndOpenMP();
Walk(std::get<Block>(x.t), "");
Walk(std::get<OmpSectionBlocks>(x.t));
BeginOpenMP();
Word("!$OMP END SECTIONS");
Put("\n");
EndOpenMP();
}
void Unparse(const OpenMPParallelSectionsConstruct &x) {
BeginOpenMP();
Word("!$OMP PARALLEL SECTIONS");
Walk(std::get<OmpClauseList>(x.t));
Put("\n");
EndOpenMP();
Walk(std::get<Block>(x.t), "");
BeginOpenMP();
Word("!$OMP END PARALLEL SECTIONS");
Word("!$OMP END ");
Walk(std::get<OmpEndSectionsDirective>(x.t));
Put("\n");
EndOpenMP();
}

View file

@ -212,25 +212,43 @@ void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) {
}
void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContext(dir.source, OmpDirective::SECTIONS);
OmpClauseSet allowed{OmpClause::PRIVATE, OmpClause::FIRSTPRIVATE,
OmpClause::LASTPRIVATE, OmpClause::REDUCTION};
SetContextAllowed(allowed);
const auto &beginSectionsDir{
std::get<parser::OmpBeginSectionsDirective>(x.t)};
const auto &beginDir{
std::get<parser::OmpSectionsDirective>(beginSectionsDir.t)};
switch (beginDir.v) {
// 2.7.2 sections-clause -> private-clause |
// firstprivate-clause |
// lastprivate-clause |
// reduction-clause
case parser::OmpSectionsDirective::Directive::Sections: {
PushContext(beginDir.source, OmpDirective::SECTIONS);
OmpClauseSet allowed{OmpClause::PRIVATE, OmpClause::FIRSTPRIVATE,
OmpClause::LASTPRIVATE, OmpClause::REDUCTION};
SetContextAllowed(allowed);
} break;
case parser::OmpSectionsDirective::Directive::ParallelSections: {
// TODO
} break;
}
}
void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) {
ompContext_.pop_back();
}
void OmpStructureChecker::Enter(const parser::OmpSection &x) {
const auto &dir{x.v}; // Verbatim
if (!CurrentDirectiveIsNested() ||
GetContext().directive != OmpDirective::SECTIONS) {
// if not currently nested, SECTION is orphaned
context_.Say(dir.source,
"SECTION directive must appear within "
"the SECTIONS construct"_err_en_US);
void OmpStructureChecker::Enter(const parser::OmpEndSectionsDirective &x) {
const auto &dir{std::get<parser::OmpSectionsDirective>(x.t)};
ResetPartialContext(dir.source);
switch (dir.v) {
// 2.7.2 end-sections -> END SECTIONS [nowait-clause]
case parser::OmpSectionsDirective::Directive::Sections:
SetContextDirectiveEnum(OmpDirective::END_SECTIONS);
SetContextAllowed(OmpClauseSet{OmpClause::NOWAIT});
break;
default:
// no clauses are allowed
break;
}
}

View file

@ -66,7 +66,7 @@ public:
void Enter(const parser::OpenMPSectionsConstruct &);
void Leave(const parser::OpenMPSectionsConstruct &);
void Enter(const parser::OmpSection &);
void Enter(const parser::OmpEndSectionsDirective &);
void Enter(const parser::OpenMPDeclareSimdConstruct &);
void Leave(const parser::OpenMPDeclareSimdConstruct &);

View file

@ -173,13 +173,15 @@
!$omp end sections nowait
!$omp end parallel
!ERROR: SECTION directive must appear within the SECTIONS construct
!$omp section
a = 0.0
!$omp parallel
!ERROR: SECTION directive must appear within the SECTIONS construct
!$omp sections
a = 0.0
b = 1
!$omp section
a = 3.14
c = 1
d = 2
!ERROR: NUM_THREADS clause is not allowed on the END SECTIONS directive
!$omp end sections num_threads(4)
!$omp end parallel
! 2.7.3 single-clause -> private-clause |