forked from OSchip/llvm-project
[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:
parent
e688b27210
commit
e59305d7ae
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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))};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 &);
|
||||
|
|
|
@ -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 |
|
||||
|
|
Loading…
Reference in New Issue