Skip to content

Commit ee8a759

Browse files
[flang][openmp] Adds Parser and Semantic Support for Interop Construct, and Init and Use Clauses. (#120584)
Adds Parser and Semantic Support for the below construct and clauses: - Interop Construct - Init Clause - Use Clause Note: The other clauses supported by Interop Construct such as Destroy, Use, Depend and Device are added already.
1 parent 541ab52 commit ee8a759

File tree

14 files changed

+511
-2
lines changed

14 files changed

+511
-2
lines changed

flang/examples/FeatureList/FeatureList.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,13 @@ struct NodeVisitor {
522522
READ_FEATURE(OmpScheduleClause)
523523
READ_FEATURE(OmpScheduleClause::Kind)
524524
READ_FEATURE(OmpScheduleClause::Modifier)
525+
READ_FEATURE(OmpInteropRuntimeIdentifier)
526+
READ_FEATURE(OmpInteropPreference)
527+
READ_FEATURE(OmpInteropType)
528+
READ_FEATURE(OmpInteropType::Value)
529+
READ_FEATURE(OmpInitClause)
530+
READ_FEATURE(OmpInitClause::Modifier)
531+
READ_FEATURE(OmpUseClause)
525532
READ_FEATURE(OmpDeviceModifier)
526533
READ_FEATURE(OmpDeviceClause)
527534
READ_FEATURE(OmpDeviceClause::Modifier)
@@ -542,6 +549,7 @@ struct NodeVisitor {
542549
READ_FEATURE(OpenACCConstruct)
543550
READ_FEATURE(OpenACCDeclarativeConstruct)
544551
READ_FEATURE(OpenACCLoopConstruct)
552+
READ_FEATURE(OpenMPInteropConstruct)
545553
READ_FEATURE(OpenACCRoutineConstruct)
546554
READ_FEATURE(OpenACCStandaloneDeclarativeConstruct)
547555
READ_FEATURE(OpenACCStandaloneConstruct)

flang/include/flang/Parser/dump-parse-tree.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,13 @@ class ParseTreeDumper {
656656
NODE_ENUM(OmpDeviceModifier, Value)
657657
NODE(parser, OmpDeviceTypeClause)
658658
NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription)
659+
NODE(parser, OmpInteropRuntimeIdentifier)
660+
NODE(parser, OmpInteropPreference)
661+
NODE(parser, OmpInteropType)
662+
NODE_ENUM(OmpInteropType, Value)
663+
NODE(parser, OmpInitClause)
664+
NODE(OmpInitClause, Modifier)
665+
NODE(parser, OmpUseClause)
659666
NODE(parser, OmpUpdateClause)
660667
NODE(parser, OmpChunkModifier)
661668
NODE_ENUM(OmpChunkModifier, Value)
@@ -675,6 +682,7 @@ class ParseTreeDumper {
675682
NODE(parser, OpenACCDeclarativeConstruct)
676683
NODE(parser, OpenACCEndConstruct)
677684
NODE(parser, OpenACCLoopConstruct)
685+
NODE(parser, OpenMPInteropConstruct)
678686
NODE(parser, OpenACCRoutineConstruct)
679687
NODE(parser, OpenACCStandaloneDeclarativeConstruct)
680688
NODE(parser, OpenACCStandaloneConstruct)

flang/include/flang/Parser/parse-tree.h

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3824,6 +3824,33 @@ struct OmpExpectation {
38243824
WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value);
38253825
};
38263826

3827+
// REF: [5.1:217-220], [5.2:293-294]
3828+
//
3829+
// OmpInteropRuntimeIdentifier -> // since 5.2
3830+
// CharLiteralConstant || ScalarIntConstantExpr
3831+
struct OmpInteropRuntimeIdentifier {
3832+
UNION_CLASS_BOILERPLATE(OmpInteropRuntimeIdentifier);
3833+
std::variant<CharLiteralConstant, ScalarIntConstantExpr> u;
3834+
};
3835+
3836+
// REF: [5.1:217-220], [5.2:293-294]
3837+
//
3838+
// OmpInteropPreference -> // since 5.2
3839+
// ([OmpRuntimeIdentifier, ...])
3840+
struct OmpInteropPreference {
3841+
WRAPPER_CLASS_BOILERPLATE(
3842+
OmpInteropPreference, std::list<OmpInteropRuntimeIdentifier>);
3843+
};
3844+
3845+
// REF: [5.1:217-220], [5.2:293-294]
3846+
//
3847+
// InteropType -> target || targetsync // since 5.2
3848+
// There can be at most only two interop-type.
3849+
struct OmpInteropType {
3850+
ENUM_CLASS(Value, Target, TargetSync)
3851+
WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value);
3852+
};
3853+
38273854
// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
38283855
//
38293856
// iterator-modifier ->
@@ -4481,6 +4508,25 @@ struct OmpWhenClause {
44814508
t;
44824509
};
44834510

4511+
// REF: [5.1:217-220], [5.2:293-294]
4512+
//
4513+
// init-clause -> INIT ([interop-modifier,] [interop-type,]
4514+
// interop-type: interop-var)
4515+
// interop-modifier: prefer_type(preference-list)
4516+
// interop-type: target, targetsync
4517+
// interop-var: Ompobject
4518+
// There can be at most only two interop-type.
4519+
struct OmpInitClause {
4520+
TUPLE_CLASS_BOILERPLATE(OmpInitClause);
4521+
MODIFIER_BOILERPLATE(OmpInteropPreference, OmpInteropType);
4522+
std::tuple<MODIFIERS(), OmpObject> t;
4523+
};
4524+
4525+
// REF: [5.1:217-220], [5.2:294]
4526+
//
4527+
// 14.1.3 use-clause -> USE (interop-var)
4528+
WRAPPER_CLASS(OmpUseClause, OmpObject);
4529+
44844530
// OpenMP Clauses
44854531
struct OmpClause {
44864532
UNION_CLASS_BOILERPLATE(OmpClause);
@@ -4939,6 +4985,15 @@ struct OmpSimpleStandaloneDirective {
49394985
CharBlock source;
49404986
};
49414987

4988+
// Ref: [5.1:217-220], [5.2:291-292]
4989+
//
4990+
// interop -> INTEROP clause[ [ [,] clause]...]
4991+
struct OpenMPInteropConstruct {
4992+
TUPLE_CLASS_BOILERPLATE(OpenMPInteropConstruct);
4993+
CharBlock source;
4994+
std::tuple<Verbatim, OmpClauseList> t;
4995+
};
4996+
49424997
struct OpenMPSimpleStandaloneConstruct {
49434998
TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct);
49444999
CharBlock source;
@@ -4950,7 +5005,7 @@ struct OpenMPStandaloneConstruct {
49505005
CharBlock source;
49515006
std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
49525007
OpenMPCancelConstruct, OpenMPCancellationPointConstruct,
4953-
OpenMPDepobjConstruct, OmpMetadirectiveDirective>
5008+
OpenMPDepobjConstruct, OmpMetadirectiveDirective, OpenMPInteropConstruct>
49545009
u;
49555010
};
49565011

flang/include/flang/Semantics/openmp-modifiers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ DECLARE_DESCRIPTOR(parser::OmpDependenceType);
7777
DECLARE_DESCRIPTOR(parser::OmpDeviceModifier);
7878
DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier);
7979
DECLARE_DESCRIPTOR(parser::OmpExpectation);
80+
DECLARE_DESCRIPTOR(parser::OmpInteropPreference);
81+
DECLARE_DESCRIPTOR(parser::OmpInteropType);
8082
DECLARE_DESCRIPTOR(parser::OmpIterator);
8183
DECLARE_DESCRIPTOR(parser::OmpLastprivateModifier);
8284
DECLARE_DESCRIPTOR(parser::OmpLinearModifier);

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,9 @@ extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) {
425425
},
426426
[](const parser::OpenMPDepobjConstruct &c) {
427427
return llvm::omp::OMPD_depobj;
428+
},
429+
[](const parser::OpenMPInteropConstruct &c) {
430+
return llvm::omp::OMPD_interop;
428431
}},
429432
c.u);
430433
},
@@ -3375,6 +3378,13 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
33753378
TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct");
33763379
}
33773380

3381+
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
3382+
semantics::SemanticsContext &semaCtx,
3383+
lower::pft::Evaluation &eval,
3384+
const parser::OpenMPInteropConstruct &interopConstruct) {
3385+
TODO(converter.getCurrentLocation(), "OpenMPInteropConstruct");
3386+
}
3387+
33783388
static void
33793389
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
33803390
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,17 @@ TYPE_PARSER(construct<OmpDeviceModifier>(
394394
TYPE_PARSER(construct<OmpExpectation>( //
395395
"PRESENT" >> pure(OmpExpectation::Value::Present)))
396396

397+
TYPE_PARSER(construct<OmpInteropRuntimeIdentifier>(
398+
construct<OmpInteropRuntimeIdentifier>(charLiteralConstant) ||
399+
construct<OmpInteropRuntimeIdentifier>(scalarIntConstantExpr)))
400+
401+
TYPE_PARSER(construct<OmpInteropPreference>(verbatim("PREFER_TYPE"_tok) >>
402+
parenthesized(nonemptyList(Parser<OmpInteropRuntimeIdentifier>{}))))
403+
404+
TYPE_PARSER(construct<OmpInteropType>(
405+
"TARGETSYNC" >> pure(OmpInteropType::Value::TargetSync) ||
406+
"TARGET" >> pure(OmpInteropType::Value::Target)))
407+
397408
TYPE_PARSER(construct<OmpIteratorSpecifier>(
398409
// Using Parser<TypeDeclarationStmt> or Parser<EntityDecl> has the problem
399410
// that they will attempt to treat what follows the '=' as initialization.
@@ -521,6 +532,11 @@ TYPE_PARSER(sourced(
521532

522533
TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
523534

535+
TYPE_PARSER(sourced(
536+
construct<OmpInitClause::Modifier>(
537+
construct<OmpInitClause::Modifier>(Parser<OmpInteropPreference>{})) ||
538+
construct<OmpInitClause::Modifier>(Parser<OmpInteropType>{})))
539+
524540
TYPE_PARSER(sourced(construct<OmpInReductionClause::Modifier>(
525541
Parser<OmpReductionIdentifier>{})))
526542

@@ -757,6 +773,11 @@ TYPE_PARSER(
757773
// OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle)
758774
TYPE_PARSER(construct<OmpDetachClause>(Parser<OmpObject>{}))
759775

776+
// init clause
777+
TYPE_PARSER(construct<OmpInitClause>(
778+
maybe(nonemptyList(Parser<OmpInitClause::Modifier>{}) / ":"),
779+
Parser<OmpObject>{}))
780+
760781
// 2.8.1 ALIGNED (list: alignment)
761782
TYPE_PARSER(construct<OmpAlignedClause>(Parser<OmpObjectList>{},
762783
maybe(":" >> nonemptyList(Parser<OmpAlignedClause::Modifier>{}))))
@@ -896,6 +917,8 @@ TYPE_PARSER( //
896917
"IF" >> construct<OmpClause>(construct<OmpClause::If>(
897918
parenthesized(Parser<OmpIfClause>{}))) ||
898919
"INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) ||
920+
"INIT" >> construct<OmpClause>(construct<OmpClause::Init>(
921+
parenthesized(Parser<OmpInitClause>{}))) ||
899922
"INCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Inclusive>(
900923
parenthesized(Parser<OmpObjectList>{}))) ||
901924
"INITIALIZER" >> construct<OmpClause>(construct<OmpClause::Initializer>(
@@ -985,6 +1008,8 @@ TYPE_PARSER( //
9851008
parenthesized(scalarIntExpr))) ||
9861009
"TO" >> construct<OmpClause>(construct<OmpClause::To>(
9871010
parenthesized(Parser<OmpToClause>{}))) ||
1011+
"USE" >> construct<OmpClause>(construct<OmpClause::Use>(
1012+
parenthesized(Parser<OmpObject>{}))) ||
9881013
"USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
9891014
parenthesized(Parser<OmpObjectList>{}))) ||
9901015
"USE_DEVICE_ADDR" >>
@@ -1212,6 +1237,10 @@ TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
12121237
TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>(
12131238
Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{})))
12141239

1240+
// OMP 5.2 14.1 Interop construct
1241+
TYPE_PARSER(sourced(construct<OpenMPInteropConstruct>(
1242+
verbatim("INTEROP"_tok), sourced(Parser<OmpClauseList>{}))))
1243+
12151244
// Standalone Constructs
12161245
TYPE_PARSER(
12171246
sourced(construct<OpenMPStandaloneConstruct>(
@@ -1223,7 +1252,9 @@ TYPE_PARSER(
12231252
construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
12241253
construct<OpenMPStandaloneConstruct>(
12251254
Parser<OmpMetadirectiveDirective>{}) ||
1226-
construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{})) /
1255+
construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{}) ||
1256+
construct<OpenMPStandaloneConstruct>(
1257+
Parser<OpenMPInteropConstruct>{})) /
12271258
endOfLine)
12281259

12291260
// Directives enclosing structured-block

flang/lib/Parser/unparse.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,6 +2179,30 @@ class UnparseVisitor {
21792179
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
21802180
Walk(std::get<OmpObjectList>(x.t));
21812181
}
2182+
void Unparse(const OmpInteropPreference &x) { Walk(x.v, ","); }
2183+
void Unparse(const OmpInitClause &x) {
2184+
using Modifier = OmpInitClause::Modifier;
2185+
auto &modifiers{std::get<std::optional<std::list<Modifier>>>(x.t)};
2186+
bool isTypeStart{true};
2187+
for (const Modifier &m : *modifiers) {
2188+
if (auto *interopPreferenceMod{
2189+
std::get_if<parser::OmpInteropPreference>(&m.u)}) {
2190+
Put("PREFER_TYPE(");
2191+
Walk(*interopPreferenceMod);
2192+
Put("),");
2193+
} else if (auto *interopTypeMod{
2194+
std::get_if<parser::OmpInteropType>(&m.u)}) {
2195+
if (isTypeStart) {
2196+
isTypeStart = false;
2197+
} else {
2198+
Put(",");
2199+
}
2200+
Walk(*interopTypeMod);
2201+
}
2202+
}
2203+
Put(": ");
2204+
Walk(std::get<OmpObject>(x.t));
2205+
}
21822206
void Unparse(const OmpMapClause &x) {
21832207
using Modifier = OmpMapClause::Modifier;
21842208
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
@@ -2740,6 +2764,15 @@ class UnparseVisitor {
27402764
Put("\n");
27412765
EndOpenMP();
27422766
}
2767+
2768+
void Unparse(const OpenMPInteropConstruct &x) {
2769+
BeginOpenMP();
2770+
Word("!$OMP INTEROP");
2771+
Walk(std::get<OmpClauseList>(x.t));
2772+
Put("\n");
2773+
EndOpenMP();
2774+
}
2775+
27432776
void Unparse(const OpenMPDeclarativeAssumes &x) {
27442777
BeginOpenMP();
27452778
Word("!$OMP ASSUMES ");
@@ -3037,6 +3070,7 @@ class UnparseVisitor {
30373070
OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type
30383071
WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier
30393072
WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation
3073+
WALK_NESTED_ENUM(OmpInteropType, Value) // OMP InteropType
30403074
WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering
30413075
WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier
30423076
WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5665,6 +5665,88 @@ void OmpStructureChecker::Leave(const parser::DoConstruct &x) {
56655665
Base::Leave(x);
56665666
}
56675667

5668+
void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) {
5669+
bool isDependClauseOccured{false};
5670+
int targetCount{0}, targetSyncCount{0};
5671+
const auto &dir{std::get<parser::Verbatim>(x.t)};
5672+
std::set<const Symbol *> objectSymbolList;
5673+
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_interop);
5674+
const auto &clauseList{std::get<parser::OmpClauseList>(x.t)};
5675+
for (const auto &clause : clauseList.v) {
5676+
common::visit(
5677+
common::visitors{
5678+
[&](const parser::OmpClause::Init &initClause) {
5679+
if (OmpVerifyModifiers(initClause.v, llvm::omp::OMPC_init,
5680+
GetContext().directiveSource, context_)) {
5681+
5682+
auto &modifiers{OmpGetModifiers(initClause.v)};
5683+
auto &&interopTypeModifier{
5684+
OmpGetRepeatableModifier<parser::OmpInteropType>(
5685+
modifiers)};
5686+
for (const auto &it : interopTypeModifier) {
5687+
if (it->v == parser::OmpInteropType::Value::TargetSync) {
5688+
++targetSyncCount;
5689+
} else {
5690+
++targetCount;
5691+
}
5692+
}
5693+
}
5694+
const auto &interopVar{parser::Unwrap<parser::OmpObject>(
5695+
std::get<parser::OmpObject>(initClause.v.t))};
5696+
const auto *name{parser::Unwrap<parser::Name>(interopVar)};
5697+
const auto *objectSymbol{name->symbol};
5698+
if (llvm::is_contained(objectSymbolList, objectSymbol)) {
5699+
context_.Say(GetContext().directiveSource,
5700+
"Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
5701+
} else {
5702+
objectSymbolList.insert(objectSymbol);
5703+
}
5704+
},
5705+
[&](const parser::OmpClause::Depend &dependClause) {
5706+
isDependClauseOccured = true;
5707+
},
5708+
[&](const parser::OmpClause::Destroy &destroyClause) {
5709+
const auto &interopVar{
5710+
parser::Unwrap<parser::OmpObject>(destroyClause.v)};
5711+
const auto *name{parser::Unwrap<parser::Name>(interopVar)};
5712+
const auto *objectSymbol{name->symbol};
5713+
if (llvm::is_contained(objectSymbolList, objectSymbol)) {
5714+
context_.Say(GetContext().directiveSource,
5715+
"Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
5716+
} else {
5717+
objectSymbolList.insert(objectSymbol);
5718+
}
5719+
},
5720+
[&](const parser::OmpClause::Use &useClause) {
5721+
const auto &interopVar{
5722+
parser::Unwrap<parser::OmpObject>(useClause.v)};
5723+
const auto *name{parser::Unwrap<parser::Name>(interopVar)};
5724+
const auto *objectSymbol{name->symbol};
5725+
if (llvm::is_contained(objectSymbolList, objectSymbol)) {
5726+
context_.Say(GetContext().directiveSource,
5727+
"Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
5728+
} else {
5729+
objectSymbolList.insert(objectSymbol);
5730+
}
5731+
},
5732+
[&](const auto &) {},
5733+
},
5734+
clause.u);
5735+
}
5736+
if (targetCount > 1 || targetSyncCount > 1) {
5737+
context_.Say(GetContext().directiveSource,
5738+
"Each interop-type may be specified at most once."_err_en_US);
5739+
}
5740+
if (isDependClauseOccured && !targetSyncCount) {
5741+
context_.Say(GetContext().directiveSource,
5742+
"A DEPEND clause can only appear on the directive if the interop-type includes TARGETSYNC"_err_en_US);
5743+
}
5744+
}
5745+
5746+
void OmpStructureChecker::Leave(const parser::OpenMPInteropConstruct &) {
5747+
dirContext_.pop_back();
5748+
}
5749+
56685750
void OmpStructureChecker::CheckAllowedRequiresClause(llvmOmpClause clause) {
56695751
CheckAllowedClause(clause);
56705752

flang/lib/Semantics/check-omp-structure.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class OmpStructureChecker
7373

7474
void Enter(const parser::OpenMPConstruct &);
7575
void Leave(const parser::OpenMPConstruct &);
76+
void Enter(const parser::OpenMPInteropConstruct &);
77+
void Leave(const parser::OpenMPInteropConstruct &);
7678
void Enter(const parser::OpenMPDeclarativeConstruct &);
7779
void Leave(const parser::OpenMPDeclarativeConstruct &);
7880

0 commit comments

Comments
 (0)