NODE(parser, OmpScheduleModifierType)
NODE_ENUM(parser::OmpScheduleModifierType, ModType)
NODE(parser, OmpSection)
- NODE(parser, OmpStandaloneDirective)
- NODE_ENUM(parser::OmpStandaloneDirective, Directive)
+ NODE(parser, OmpSimpleStandaloneDirective)
+ NODE_ENUM(parser::OmpSimpleStandaloneDirective, Directive)
NODE(parser, Only)
NODE(parser, OpenMPAtomicConstruct)
NODE(parser, OpenMPBlockConstruct)
NODE(parser, OpenMPEndLoopDirective)
NODE(parser, OpenMPFlushConstruct)
NODE(parser, OpenMPLoopConstruct)
- NODE(parser, OpenMPSimpleConstruct)
- NODE_ENUM(parser::OpenMPSimpleConstruct, Directive)
+ NODE(parser, OpenMPSimpleStandaloneConstruct)
NODE(parser, OpenMPStandaloneConstruct)
NODE(parser, OpenMPSectionsConstruct)
NODE(parser, OpenMPSingleConstruct)
"TASKGROUP" >> pure(OmpCancelType::Type::Taskgroup)))))
// Cancellation Point construct
-TYPE_PARSER(construct<OpenMPCancellationPointConstruct>(
- sourced("CANCELLATION POINT" >> Parser<OmpCancelType>{})))
+TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>(
+ verbatim("CANCELLATION POINT"_tok), Parser<OmpCancelType>{})))
// Cancel construct
-TYPE_PARSER(construct<OpenMPCancelConstruct>(
- sourced("CANCEL" >> Parser<OmpCancelType>{}),
- maybe("IF" >> parenthesized(scalarLogicalExpr))))
+TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok),
+ Parser<OmpCancelType>{}, maybe("IF" >> parenthesized(scalarLogicalExpr)))))
// Flush construct
TYPE_PARSER(sourced(construct<OpenMPFlushConstruct>(
- "FLUSH" >> maybe(parenthesized(Parser<OmpObjectList>{})))))
+ verbatim("FLUSH"_tok), maybe(parenthesized(Parser<OmpObjectList>{})))))
-// Standalone directives
-TYPE_PARSER(sourced(construct<OmpStandaloneDirective>(first(
+// Simple Standalone Directives
+TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
+ "BARRIER" >> pure(OmpSimpleStandaloneDirective::Directive::Barrier),
+ "ORDERED" >> pure(OmpSimpleStandaloneDirective::Directive::Ordered),
"TARGET ENTER DATA" >>
- pure(OmpStandaloneDirective::Directive::TargetEnterData),
+ pure(OmpSimpleStandaloneDirective::Directive::TargetEnterData),
"TARGET EXIT DATA" >>
- pure(OmpStandaloneDirective::Directive::TargetExitData),
- "TARGET UPDATE" >> pure(OmpStandaloneDirective::Directive::TargetUpdate)))))
+ pure(OmpSimpleStandaloneDirective::Directive::TargetExitData),
+ "TARGET UPDATE" >>
+ pure(OmpSimpleStandaloneDirective::Directive::TargetUpdate),
+ "TASKWAIT" >> pure(OmpSimpleStandaloneDirective::Directive::Taskwait),
+ "TASKYIELD" >> pure(OmpSimpleStandaloneDirective::Directive::Taskyield)))))
+
+TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>(
+ Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{})))
+
+// Standalone Constructs
+TYPE_PARSER(
+ sourced(construct<OpenMPStandaloneConstruct>(
+ Parser<OpenMPSimpleStandaloneConstruct>{}) ||
+ construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) ||
+ construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
+ construct<OpenMPStandaloneConstruct>(
+ Parser<OpenMPCancellationPointConstruct>{})) /
+ endOfLine)
// Directives enclosing structured-block
TYPE_PARSER(sourced(construct<OmpBlockDirective>(
Parser<OmpClauseList>{} / endOmpLine, block,
Parser<OmpEndBlockDirective>{}))
-// Simple constructs without clauses
-TYPE_PARSER(
- sourced(construct<OpenMPSimpleConstruct>(first(
- "BARRIER" >> pure(OpenMPSimpleConstruct::Directive::Barrier),
- "TASKWAIT" >> pure(OpenMPSimpleConstruct::Directive::Taskwait),
- "TASKYIELD" >> pure(OpenMPSimpleConstruct::Directive::Taskyield)))) /
- endOmpLine)
-
-TYPE_PARSER(construct<OpenMPStandaloneConstruct>(
- Parser<OmpStandaloneDirective>{}, Parser<OmpClauseList>{} / endOmpLine))
-
// OMP SINGLE
TYPE_PARSER(startOmpLine >> construct<OmpEndSingle>(verbatim("END SINGLE"_tok),
Parser<OmpClauseList>{}) /
TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
startOmpLine >>
- first(construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
- construct<OpenMPConstruct>(Parser<OpenMPSimpleConstruct>{}),
- construct<OpenMPConstruct>(Parser<OpenMPSingleConstruct>{}),
+ first(construct<OpenMPConstruct>(Parser<OpenMPSingleConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}),
construct<OpenMPConstruct>(
Parser<OpenMPParallelSectionsConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPWorkshareConstruct>{}),
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<OpenMPCancelConstruct>{}),
- construct<OpenMPConstruct>(
- Parser<OpenMPCancellationPointConstruct>{}),
- construct<OpenMPConstruct>(Parser<OpenMPFlushConstruct>{}),
construct<OpenMPConstruct>(Parser<OmpSection>{})))
// END OMP Block directives
};
// CANCELLATION POINT
-WRAPPER_CLASS(OpenMPCancellationPointConstruct, OmpCancelType);
+struct OpenMPCancellationPointConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct);
+ CharBlock source;
+ std::tuple<Verbatim, OmpCancelType> t;
+};
// CANCEL
struct OpenMPCancelConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct);
WRAPPER_CLASS(If, ScalarLogicalExpr);
- std::tuple<OmpCancelType, std::optional<If>> t;
+ CharBlock source;
+ std::tuple<Verbatim, OmpCancelType, std::optional<If>> t;
};
// FLUSH
struct OpenMPFlushConstruct {
- WRAPPER_CLASS_BOILERPLATE(OpenMPFlushConstruct, std::optional<OmpObjectList>);
+ TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct);
CharBlock source;
+ std::tuple<Verbatim, std::optional<OmpObjectList>> t;
};
// These simple constructs do not have clauses.
-struct OpenMPSimpleConstruct {
- ENUM_CLASS(Directive, Barrier, Taskwait, Taskyield)
- WRAPPER_CLASS_BOILERPLATE(OpenMPSimpleConstruct, Directive);
+struct OmpSimpleStandaloneDirective {
+ ENUM_CLASS(Directive, Barrier, Taskwait, Taskyield, TargetEnterData,
+ TargetExitData, TargetUpdate, Ordered)
+ WRAPPER_CLASS_BOILERPLATE(OmpSimpleStandaloneDirective, Directive);
CharBlock source;
};
-// Standalone constructs; these can have clauses.
-struct OmpStandaloneDirective {
- ENUM_CLASS(Directive, TargetEnterData, TargetExitData, TargetUpdate)
- WRAPPER_CLASS_BOILERPLATE(OmpStandaloneDirective, Directive);
+struct OpenMPSimpleStandaloneConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct);
CharBlock source;
+ std::tuple<OmpSimpleStandaloneDirective, OmpClauseList> t;
};
struct OpenMPStandaloneConstruct {
- TUPLE_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
- std::tuple<OmpStandaloneDirective, OmpClauseList> t;
+ UNION_CLASS_BOILERPLATE(OpenMPStandaloneConstruct);
+ CharBlock source;
+ std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
+ OpenMPCancelConstruct, OpenMPCancellationPointConstruct>
+ u;
};
WRAPPER_CLASS(OmpEndBlockDirective, OmpBlockDirective);
struct OpenMPConstruct {
UNION_CLASS_BOILERPLATE(OpenMPConstruct);
- std::variant<OpenMPStandaloneConstruct, OpenMPSimpleConstruct,
- OpenMPSingleConstruct, OpenMPSectionsConstruct,
- OpenMPParallelSectionsConstruct, OpenMPWorkshareConstruct,
- OpenMPLoopConstruct, OpenMPBlockConstruct,
- OpenMPCancellationPointConstruct, OpenMPCancelConstruct,
- OpenMPFlushConstruct, OpenMPAtomicConstruct, OpenMPCriticalConstruct,
- OmpSection>
+ std::variant<OpenMPStandaloneConstruct, OpenMPSingleConstruct,
+ OpenMPSectionsConstruct, OpenMPParallelSectionsConstruct,
+ OpenMPWorkshareConstruct, OpenMPLoopConstruct, OpenMPBlockConstruct,
+ OpenMPAtomicConstruct, OpenMPCriticalConstruct, OmpSection>
u;
};
}
}
}
void Unparse(const OmpObjectList &x) { Walk(x.v, ","); }
- void Unparse(const OmpStandaloneDirective &x) {
+ void Unparse(const OmpSimpleStandaloneDirective &x) {
switch (x.v) {
- case OmpStandaloneDirective::Directive::TargetEnterData:
+ case OmpSimpleStandaloneDirective::Directive::Barrier:
+ Word("BARRIER ");
+ break;
+ case OmpSimpleStandaloneDirective::Directive::Taskwait:
+ Word("TASKWAIT ");
+ break;
+ case OmpSimpleStandaloneDirective::Directive::Taskyield:
+ Word("TASKYIELD ");
+ break;
+ case OmpSimpleStandaloneDirective::Directive::TargetEnterData:
Word("TARGET ENTER DATA ");
break;
- case OmpStandaloneDirective::Directive::TargetExitData:
+ case OmpSimpleStandaloneDirective::Directive::TargetExitData:
Word("TARGET EXIT DATA ");
break;
- case OmpStandaloneDirective::Directive::TargetUpdate:
+ case OmpSimpleStandaloneDirective::Directive::TargetUpdate:
Word("TARGET UPDATE ");
break;
+ case OmpSimpleStandaloneDirective::Directive::Ordered:
+ Word("ORDERED ");
+ break;
}
}
void Unparse(const OmpBlockDirective &x) {
void Unparse(const OpenMPCancellationPointConstruct &x) {
BeginOpenMP();
Word("!$OMP CANCELLATION POINT ");
- Walk(x.v);
+ Walk(std::get<OmpCancelType>(x.t));
Put("\n");
EndOpenMP();
}
void Unparse(const OpenMPFlushConstruct &x) {
BeginOpenMP();
Word("!$OMP FLUSH");
- if ((x.v).has_value()) {
- Put("(");
- Walk(x.v);
- Put(")");
- }
+ Walk("(", std::get<std::optional<OmpObjectList>>(x.t), ")");
Put("\n");
EndOpenMP();
}
EndOpenMP();
}
void Unparse(const OmpClauseList &x) { Walk(" ", x.v, " "); }
- void Unparse(const OpenMPSimpleConstruct &x) {
- BeginOpenMP();
- Word("!$OMP ");
- switch (x.v) {
- case OpenMPSimpleConstruct::Directive::Barrier: Word("BARRIER"); break;
- case OpenMPSimpleConstruct::Directive::Taskwait: Word("TASKWAIT"); break;
- case OpenMPSimpleConstruct::Directive::Taskyield: Word("TASKYIELD"); break;
- }
- Put("\n");
- EndOpenMP();
- }
- void Unparse(const OpenMPStandaloneConstruct &x) {
+ void Unparse(const OpenMPSimpleStandaloneConstruct &x) {
BeginOpenMP();
Word("!$OMP ");
- Walk(std::get<OmpStandaloneDirective>(x.t));
+ Walk(std::get<OmpSimpleStandaloneDirective>(x.t));
Walk(std::get<OmpClauseList>(x.t));
Put("\n");
EndOpenMP();
SetContextAllowed(allowed);
}
-void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &x) {
+void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) {
ompContext_.pop_back();
}
SetContextAllowed(allowed);
}
-void OmpStructureChecker::Leave(const parser::OpenMPSingleConstruct &x) {
+void OmpStructureChecker::Leave(const parser::OpenMPSingleConstruct &) {
ompContext_.pop_back();
}
SetContextAllowedOnce(allowedOnce);
}
-void OmpStructureChecker::Leave(const parser::OmpEndSingle &x) {
+void OmpStructureChecker::Leave(const parser::OmpEndSingle &) {
ompContext_.pop_back();
}
PushContext(dir.source, OmpDirective::WORKSHARE);
}
-void OmpStructureChecker::Leave(const parser::OpenMPWorkshareConstruct &x) {
+void OmpStructureChecker::Leave(const parser::OpenMPWorkshareConstruct &) {
ompContext_.pop_back();
}
PushContext(dir.source, OmpDirective::DECLARE_SIMD);
}
-void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &x) {
+void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &) {
ompContext_.pop_back();
}
+void OmpStructureChecker::Enter(
+ const parser::OpenMPSimpleStandaloneConstruct &x) {
+ const auto &dir{std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
+ PushContext(dir.source);
+}
+
+void OmpStructureChecker::Leave(
+ const parser::OpenMPSimpleStandaloneConstruct &) {
+ ompContext_.pop_back();
+}
+
+void OmpStructureChecker::Enter(const parser::OpenMPFlushConstruct &x) {
+ const auto &dir{std::get<parser::Verbatim>(x.t)};
+ PushContext(dir.source, OmpDirective::FLUSH);
+}
+
+void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &) {
+ ompContext_.pop_back();
+}
+
+void OmpStructureChecker::Enter(const parser::OpenMPCancelConstruct &x) {
+ const auto &dir{std::get<parser::Verbatim>(x.t)};
+ PushContext(dir.source, OmpDirective::CANCEL);
+}
+
+void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) {
+ ompContext_.pop_back();
+}
+
+void OmpStructureChecker::Enter(
+ const parser::OpenMPCancellationPointConstruct &x) {
+ const auto &dir{std::get<parser::Verbatim>(x.t)};
+ PushContext(dir.source, OmpDirective::CANCELLATION_POINT);
+}
+
+void OmpStructureChecker::Leave(
+ const parser::OpenMPCancellationPointConstruct &) {
+ ompContext_.pop_back();
+}
+
+void OmpStructureChecker::Enter(const parser::OmpSimpleStandaloneDirective &x) {
+ switch (x.v) {
+ case parser::OmpSimpleStandaloneDirective::Directive::Ordered: {
+ // 2.13.8 ordered-construct-clause -> depend-clause
+ SetContextDirectiveEnum(OmpDirective::ORDERED);
+ OmpClauseSet allowed{OmpClause::DEPEND};
+ SetContextAllowed(allowed);
+ }
+ default:
+ // TODO others
+ break;
+ }
+}
+
void OmpStructureChecker::Enter(const parser::OmpBlockDirective &x) {
switch (x.v) {
// 2.5 parallel-clause -> if-clause |
void Enter(const parser::OpenMPDeclareSimdConstruct &);
void Leave(const parser::OpenMPDeclareSimdConstruct &);
+ void Enter(const parser::OpenMPSimpleStandaloneConstruct &);
+ void Leave(const parser::OpenMPSimpleStandaloneConstruct &);
+ void Enter(const parser::OmpSimpleStandaloneDirective &);
+ void Enter(const parser::OpenMPFlushConstruct &);
+ void Leave(const parser::OpenMPFlushConstruct &);
+ void Enter(const parser::OpenMPCancelConstruct &);
+ void Leave(const parser::OpenMPCancelConstruct &);
+ void Enter(const parser::OpenMPCancellationPointConstruct &);
+ void Leave(const parser::OpenMPCancellationPointConstruct &);
+
void Leave(const parser::OmpClauseList &);
void Enter(const parser::OmpClause &);
void Enter(const parser::OmpNowait &);
integer :: b = 128
integer :: c = 32
integer, parameter :: num = 16
+ real(8) :: arrayA(256), arrayB(512)
+
+ arrayA = 1.414
+ arrayB = 3.14
N = 1024
! 2.5 parallel-clause -> if-clause |
a = 3.14
enddo
enddo
-end
+
+! Standalone Directives (basic)
+
+ !$omp taskyield
+ !$omp barrier
+ !$omp taskwait
+ ! !$omp target enter data map(to:arrayA) map(alloc:arrayB)
+ ! !$omp target update from(arrayA) to(arrayB)
+ ! !$omp target exit data map(from:arrayA) map(delete:arrayB)
+ !$omp ordered depend(source)
+ !ERROR: Internal: no symbol found for 'i'
+ !$omp ordered depend(sink:i-1)
+ !$omp flush (c)
+ !$omp cancel DO
+ !$omp cancellation point parallel
+end program