diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index a1a908820e39c..e34f103a1df04 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -522,6 +522,13 @@ struct NodeVisitor { READ_FEATURE(OmpScheduleClause) READ_FEATURE(OmpScheduleClause::Kind) READ_FEATURE(OmpScheduleClause::Modifier) + READ_FEATURE(OmpInteropRuntimeIdentifier) + READ_FEATURE(OmpInteropPreference) + READ_FEATURE(OmpInteropType) + READ_FEATURE(OmpInteropType::Value) + READ_FEATURE(OmpInitClause) + READ_FEATURE(OmpInitClause::Modifier) + READ_FEATURE(OmpUseClause) READ_FEATURE(OmpDeviceModifier) READ_FEATURE(OmpDeviceClause) READ_FEATURE(OmpDeviceClause::Modifier) @@ -542,6 +549,7 @@ struct NodeVisitor { READ_FEATURE(OpenACCConstruct) READ_FEATURE(OpenACCDeclarativeConstruct) READ_FEATURE(OpenACCLoopConstruct) + READ_FEATURE(OpenMPInteropConstruct) READ_FEATURE(OpenACCRoutineConstruct) READ_FEATURE(OpenACCStandaloneDeclarativeConstruct) READ_FEATURE(OpenACCStandaloneConstruct) diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 25fcc843f3732..8f6fd868feaf0 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -656,6 +656,13 @@ class ParseTreeDumper { NODE_ENUM(OmpDeviceModifier, Value) NODE(parser, OmpDeviceTypeClause) NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription) + NODE(parser, OmpInteropRuntimeIdentifier) + NODE(parser, OmpInteropPreference) + NODE(parser, OmpInteropType) + NODE_ENUM(OmpInteropType, Value) + NODE(parser, OmpInitClause) + NODE(OmpInitClause, Modifier) + NODE(parser, OmpUseClause) NODE(parser, OmpUpdateClause) NODE(parser, OmpChunkModifier) NODE_ENUM(OmpChunkModifier, Value) @@ -675,6 +682,7 @@ class ParseTreeDumper { NODE(parser, OpenACCDeclarativeConstruct) NODE(parser, OpenACCEndConstruct) NODE(parser, OpenACCLoopConstruct) + NODE(parser, OpenMPInteropConstruct) NODE(parser, OpenACCRoutineConstruct) NODE(parser, OpenACCStandaloneDeclarativeConstruct) NODE(parser, OpenACCStandaloneConstruct) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 1b1d4125464e3..371d7653b3b34 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3824,6 +3824,33 @@ struct OmpExpectation { WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value); }; +// REF: [5.1:217-220], [5.2:293-294] +// +// OmpInteropRuntimeIdentifier -> // since 5.2 +// CharLiteralConstant || ScalarIntConstantExpr +struct OmpInteropRuntimeIdentifier { + UNION_CLASS_BOILERPLATE(OmpInteropRuntimeIdentifier); + std::variant u; +}; + +// REF: [5.1:217-220], [5.2:293-294] +// +// OmpInteropPreference -> // since 5.2 +// ([OmpRuntimeIdentifier, ...]) +struct OmpInteropPreference { + WRAPPER_CLASS_BOILERPLATE( + OmpInteropPreference, std::list); +}; + +// REF: [5.1:217-220], [5.2:293-294] +// +// InteropType -> target || targetsync // since 5.2 +// There can be at most only two interop-type. +struct OmpInteropType { + ENUM_CLASS(Value, Target, TargetSync) + WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value); +}; + // Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69] // // iterator-modifier -> @@ -4481,6 +4508,25 @@ struct OmpWhenClause { t; }; +// REF: [5.1:217-220], [5.2:293-294] +// +// init-clause -> INIT ([interop-modifier,] [interop-type,] +// interop-type: interop-var) +// interop-modifier: prefer_type(preference-list) +// interop-type: target, targetsync +// interop-var: Ompobject +// There can be at most only two interop-type. +struct OmpInitClause { + TUPLE_CLASS_BOILERPLATE(OmpInitClause); + MODIFIER_BOILERPLATE(OmpInteropPreference, OmpInteropType); + std::tuple t; +}; + +// REF: [5.1:217-220], [5.2:294] +// +// 14.1.3 use-clause -> USE (interop-var) +WRAPPER_CLASS(OmpUseClause, OmpObject); + // OpenMP Clauses struct OmpClause { UNION_CLASS_BOILERPLATE(OmpClause); @@ -4939,6 +4985,15 @@ struct OmpSimpleStandaloneDirective { CharBlock source; }; +// Ref: [5.1:217-220], [5.2:291-292] +// +// interop -> INTEROP clause[ [ [,] clause]...] +struct OpenMPInteropConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPInteropConstruct); + CharBlock source; + std::tuple t; +}; + struct OpenMPSimpleStandaloneConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct); CharBlock source; @@ -4950,7 +5005,7 @@ struct OpenMPStandaloneConstruct { CharBlock source; std::variant + OpenMPDepobjConstruct, OmpMetadirectiveDirective, OpenMPInteropConstruct> u; }; diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h index 7cdbf65adebe1..4fbd80f989e72 100644 --- a/flang/include/flang/Semantics/openmp-modifiers.h +++ b/flang/include/flang/Semantics/openmp-modifiers.h @@ -77,6 +77,8 @@ DECLARE_DESCRIPTOR(parser::OmpDependenceType); DECLARE_DESCRIPTOR(parser::OmpDeviceModifier); DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier); DECLARE_DESCRIPTOR(parser::OmpExpectation); +DECLARE_DESCRIPTOR(parser::OmpInteropPreference); +DECLARE_DESCRIPTOR(parser::OmpInteropType); DECLARE_DESCRIPTOR(parser::OmpIterator); DECLARE_DESCRIPTOR(parser::OmpLastprivateModifier); DECLARE_DESCRIPTOR(parser::OmpLinearModifier); diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 2cfc1bd88dcef..9dbb5e7a5f7bf 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -425,6 +425,9 @@ extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) { }, [](const parser::OpenMPDepobjConstruct &c) { return llvm::omp::OMPD_depobj; + }, + [](const parser::OpenMPInteropConstruct &c) { + return llvm::omp::OMPD_interop; }}, c.u); }, @@ -3364,6 +3367,13 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct"); } +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPInteropConstruct &interopConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPInteropConstruct"); +} + static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 8c5c7063553ed..1aa3527c754fc 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -394,6 +394,17 @@ TYPE_PARSER(construct( TYPE_PARSER(construct( // "PRESENT" >> pure(OmpExpectation::Value::Present))) +TYPE_PARSER(construct( + construct(charLiteralConstant) || + construct(scalarIntConstantExpr))) + +TYPE_PARSER(construct(verbatim("PREFER_TYPE"_tok) >> + parenthesized(nonemptyList(Parser{})))) + +TYPE_PARSER(construct( + "TARGETSYNC" >> pure(OmpInteropType::Value::TargetSync) || + "TARGET" >> pure(OmpInteropType::Value::Target))) + TYPE_PARSER(construct( // Using Parser or Parser has the problem // that they will attempt to treat what follows the '=' as initialization. @@ -521,6 +532,11 @@ TYPE_PARSER(sourced( TYPE_PARSER(sourced(construct(OmpDirectiveNameParser{}))) +TYPE_PARSER(sourced( + construct( + construct(Parser{})) || + construct(Parser{}))) + TYPE_PARSER(sourced(construct( Parser{}))) @@ -757,6 +773,11 @@ TYPE_PARSER( // OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle) TYPE_PARSER(construct(Parser{})) +// init clause +TYPE_PARSER(construct( + maybe(nonemptyList(Parser{}) / ":"), + Parser{})) + // 2.8.1 ALIGNED (list: alignment) TYPE_PARSER(construct(Parser{}, maybe(":" >> nonemptyList(Parser{})))) @@ -896,6 +917,8 @@ TYPE_PARSER( // "IF" >> construct(construct( parenthesized(Parser{}))) || "INBRANCH" >> construct(construct()) || + "INIT" >> construct(construct( + parenthesized(Parser{}))) || "INCLUSIVE" >> construct(construct( parenthesized(Parser{}))) || "INITIALIZER" >> construct(construct( @@ -985,6 +1008,8 @@ TYPE_PARSER( // parenthesized(scalarIntExpr))) || "TO" >> construct(construct( parenthesized(Parser{}))) || + "USE" >> construct(construct( + parenthesized(Parser{}))) || "USE_DEVICE_PTR" >> construct(construct( parenthesized(Parser{}))) || "USE_DEVICE_ADDR" >> @@ -1212,6 +1237,10 @@ TYPE_PARSER(sourced(construct(first( TYPE_PARSER(sourced(construct( Parser{}, Parser{}))) +// OMP 5.2 14.1 Interop construct +TYPE_PARSER(sourced(construct( + verbatim("INTEROP"_tok), sourced(Parser{})))) + // Standalone Constructs TYPE_PARSER( sourced(construct( @@ -1223,7 +1252,9 @@ TYPE_PARSER( construct(Parser{}) || construct( Parser{}) || - construct(Parser{})) / + construct(Parser{}) || + construct( + Parser{})) / endOfLine) // Directives enclosing structured-block diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index c5de5d1d08dd5..37a17d3b88085 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2179,6 +2179,30 @@ class UnparseVisitor { Walk(std::get>>(x.t), ": "); Walk(std::get(x.t)); } + void Unparse(const OmpInteropPreference &x) { Walk(x.v, ","); } + void Unparse(const OmpInitClause &x) { + using Modifier = OmpInitClause::Modifier; + auto &modifiers{std::get>>(x.t)}; + bool isTypeStart{true}; + for (const Modifier &m : *modifiers) { + if (auto *interopPreferenceMod{ + std::get_if(&m.u)}) { + Put("PREFER_TYPE("); + Walk(*interopPreferenceMod); + Put("),"); + } else if (auto *interopTypeMod{ + std::get_if(&m.u)}) { + if (isTypeStart) { + isTypeStart = false; + } else { + Put(","); + } + Walk(*interopTypeMod); + } + } + Put(": "); + Walk(std::get(x.t)); + } void Unparse(const OmpMapClause &x) { using Modifier = OmpMapClause::Modifier; Walk(std::get>>(x.t), ": "); @@ -2740,6 +2764,15 @@ class UnparseVisitor { Put("\n"); EndOpenMP(); } + + void Unparse(const OpenMPInteropConstruct &x) { + BeginOpenMP(); + Word("!$OMP INTEROP"); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OpenMPDeclarativeAssumes &x) { BeginOpenMP(); Word("!$OMP ASSUMES "); @@ -3037,6 +3070,7 @@ class UnparseVisitor { OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation + WALK_NESTED_ENUM(OmpInteropType, Value) // OMP InteropType WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 5fcebdca0bc5f..afd2814bba30c 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -5638,6 +5638,88 @@ void OmpStructureChecker::Leave(const parser::DoConstruct &x) { Base::Leave(x); } +void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) { + bool isDependClauseOccured{false}; + int targetCount{0}, targetSyncCount{0}; + const auto &dir{std::get(x.t)}; + std::set objectSymbolList; + PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_interop); + const auto &clauseList{std::get(x.t)}; + for (const auto &clause : clauseList.v) { + common::visit( + common::visitors{ + [&](const parser::OmpClause::Init &initClause) { + if (OmpVerifyModifiers(initClause.v, llvm::omp::OMPC_init, + GetContext().directiveSource, context_)) { + + auto &modifiers{OmpGetModifiers(initClause.v)}; + auto &&interopTypeModifier{ + OmpGetRepeatableModifier( + modifiers)}; + for (const auto &it : interopTypeModifier) { + if (it->v == parser::OmpInteropType::Value::TargetSync) { + ++targetSyncCount; + } else { + ++targetCount; + } + } + } + const auto &interopVar{parser::Unwrap( + std::get(initClause.v.t))}; + const auto *name{parser::Unwrap(interopVar)}; + const auto *objectSymbol{name->symbol}; + if (llvm::is_contained(objectSymbolList, objectSymbol)) { + context_.Say(GetContext().directiveSource, + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); + } else { + objectSymbolList.insert(objectSymbol); + } + }, + [&](const parser::OmpClause::Depend &dependClause) { + isDependClauseOccured = true; + }, + [&](const parser::OmpClause::Destroy &destroyClause) { + const auto &interopVar{ + parser::Unwrap(destroyClause.v)}; + const auto *name{parser::Unwrap(interopVar)}; + const auto *objectSymbol{name->symbol}; + if (llvm::is_contained(objectSymbolList, objectSymbol)) { + context_.Say(GetContext().directiveSource, + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); + } else { + objectSymbolList.insert(objectSymbol); + } + }, + [&](const parser::OmpClause::Use &useClause) { + const auto &interopVar{ + parser::Unwrap(useClause.v)}; + const auto *name{parser::Unwrap(interopVar)}; + const auto *objectSymbol{name->symbol}; + if (llvm::is_contained(objectSymbolList, objectSymbol)) { + context_.Say(GetContext().directiveSource, + "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US); + } else { + objectSymbolList.insert(objectSymbol); + } + }, + [&](const auto &) {}, + }, + clause.u); + } + if (targetCount > 1 || targetSyncCount > 1) { + context_.Say(GetContext().directiveSource, + "Each interop-type may be specified at most once."_err_en_US); + } + if (isDependClauseOccured && !targetSyncCount) { + context_.Say(GetContext().directiveSource, + "A DEPEND clause can only appear on the directive if the interop-type includes TARGETSYNC"_err_en_US); + } +} + +void OmpStructureChecker::Leave(const parser::OpenMPInteropConstruct &) { + dirContext_.pop_back(); +} + void OmpStructureChecker::CheckAllowedRequiresClause(llvmOmpClause clause) { CheckAllowedClause(clause); diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 4c4e65cd7a2db..4f7308a0dbf8d 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -73,6 +73,8 @@ class OmpStructureChecker void Enter(const parser::OpenMPConstruct &); void Leave(const parser::OpenMPConstruct &); + void Enter(const parser::OpenMPInteropConstruct &); + void Leave(const parser::OpenMPInteropConstruct &); void Enter(const parser::OpenMPDeclarativeConstruct &); void Leave(const parser::OpenMPDeclarativeConstruct &); diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp index 73ad7751ee517..c84e832ee52a1 100644 --- a/flang/lib/Semantics/openmp-modifiers.cpp +++ b/flang/lib/Semantics/openmp-modifiers.cpp @@ -240,6 +240,38 @@ const OmpModifierDescriptor &OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"interop-preference", + /*props=*/ + { + {52, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {52, {Clause::OMPC_init}}, + }, + }; + return desc; +} + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"interop-type", + /*props=*/ + { + {52, {OmpProperty::Required}}, + }, + /*clauses=*/ + { + {52, {Clause::OMPC_init}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ diff --git a/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 b/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 new file mode 100644 index 0000000000000..f7920c09464ed --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 @@ -0,0 +1,9 @@ +! REQUIRES: openmp_runtime +! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s + +! CHECK: not yet implemented: OpenMPInteropConstruct +program interop_test + use omp_lib + integer(omp_interop_kind) :: obj + !$omp interop init(targetsync,target: obj) +end program interop_test diff --git a/flang/test/Parser/OpenMP/interop-construct.f90 b/flang/test/Parser/OpenMP/interop-construct.f90 new file mode 100644 index 0000000000000..a1781d559b46d --- /dev/null +++ b/flang/test/Parser/OpenMP/interop-construct.f90 @@ -0,0 +1,204 @@ +! REQUIRES: openmp_runtime +! RUN: %flang_fc1 -fdebug-unparse -fopenmp-version=52 -fopenmp %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp-version=52 -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s + +SUBROUTINE test_interop_01() + !$OMP INTEROP DEVICE(1) + PRINT *,'pass' +END SUBROUTINE test_interop_01 + +!UNPARSE: SUBROUTINE test_interop_01 +!UNPARSE: !$OMP INTEROP DEVICE(1_4) +!UNPARSE: PRINT *, "pass" +!UNPARSE: END SUBROUTINE test_interop_01 + +!PARSE-TREE: | SubroutineStmt +!PARSE-TREE: | | Name = 'test_interop_01' +!PARSE-TREE: | SpecificationPart +!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | ExecutionPart -> Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct +!PARSE-TREE: | | | Verbatim +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Device -> OmpDeviceClause +!PARSE-TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: | | | Format -> Star +!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant +!PARSE-TREE: | | | | string = 'pass' +!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_01' + +SUBROUTINE test_interop_02() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj1, obj2, obj3 + !$OMP INTEROP INIT(TARGETSYNC: obj) USE(obj1) DESTROY(obj3) + PRINT *,'pass' +END SUBROUTINE test_interop_02 + +!UNPARSE: SUBROUTINE test_interop_02 +!UNPARSE: USE :: omp_lib +!UNPARSE: INTEGER(KIND=8_4) obj1, obj2, obj3 +!UNPARSE: !$OMP INTEROP INIT(TARGETSYNC: obj) USE(obj1) DESTROY(obj3) +!UNPARSE: PRINT *, "pass" +!UNPARSE: END SUBROUTINE test_interop_02 + +!PARSE-TREE: | SubroutineStmt +!PARSE-TREE: | | Name = 'test_interop_02' +!PARSE-TREE: | SpecificationPart +!PARSE-TREE: | | UseStmt +!PARSE-TREE: | | | Name = 'omp_lib' +!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj1' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj2' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj3' +!PARSE-TREE: | ExecutionPart -> Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct +!PARSE-TREE: | | | Verbatim +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!PARSE-TREE: | | | | Modifier -> OmpInteropType -> Value = TargetSync +!PARSE-TREE: | | | | OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | OmpClause -> Use -> OmpUseClause -> OmpObject -> Designator -> DataRef -> Name = 'obj1' +!PARSE-TREE: | | | OmpClause -> Destroy -> OmpDestroyClause -> OmpObject -> Designator -> DataRef -> Name = 'obj3' +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: | | | Format -> Star +!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant +!PARSE-TREE: | | | | string = 'pass' +!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_02' + +SUBROUTINE test_interop_03() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj + !$OMP INTEROP INIT(TARGETSYNC: obj) DEPEND(INOUT: obj) + PRINT *,'pass' +END SUBROUTINE test_interop_03 + +!UNPARSE: SUBROUTINE test_interop_03 +!UNPARSE: USE :: omp_lib +!UNPARSE: INTEGER(KIND=8_4) obj +!UNPARSE: !$OMP INTEROP INIT(TARGETSYNC: obj) DEPEND(INOUT: obj) +!UNPARSE: PRINT *, "pass" +!UNPARSE: END SUBROUTINE test_interop_03 + +!PARSE-TREE: | SubroutineStmt +!PARSE-TREE: | | Name = 'test_interop_03' +!PARSE-TREE: | SpecificationPart +!PARSE-TREE: | | UseStmt +!PARSE-TREE: | | | Name = 'omp_lib' +!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj' +!PARSE-TREE: | ExecutionPart -> Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct +!PARSE-TREE: | | | Verbatim +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!PARSE-TREE: | | | | Modifier -> OmpInteropType -> Value = TargetSync +!PARSE-TREE: | | | | OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | OmpClause -> Depend -> OmpDependClause -> TaskDep +!PARSE-TREE: | | | | Modifier -> OmpTaskDependenceType -> Value = Inout +!PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: | | | Format -> Star +!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant +!PARSE-TREE: | | | | string = 'pass' +!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_03' + +SUBROUTINE test_interop_04() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj + INTEGER, DIMENSION(1,10) :: arr + !$OMP INTEROP INIT(PREFER_TYPE("cuda"),TARGETSYNC,TARGET: obj) DEPEND(INOUT: arr) NOWAIT + PRINT *,'pass' +END SUBROUTINE test_interop_04 + +!UNPARSE: SUBROUTINE test_interop_04 +!UNPARSE: USE :: omp_lib +!UNPARSE: INTEGER(KIND=8_4) obj +!UNPARSE: INTEGER, DIMENSION(1_4,10_4) :: arr +!UNPARSE: !$OMP INTEROP INIT(PREFER_TYPE("cuda"),TARGETSYNC,TARGET: obj) DEPEND(INOUT: a& +!UNPARSE: !$OMP&rr) NOWAIT +!UNPARSE: PRINT *, "pass" +!UNPARSE: END SUBROUTINE test_interop_04 + +!PARSE-TREE: | SubroutineStmt +!PARSE-TREE: | | Name = 'test_interop_04' +!PARSE-TREE: | SpecificationPart +!PARSE-TREE: | | UseStmt +!PARSE-TREE: | | | Name = 'omp_lib' +!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj' +!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!PARSE-TREE: | | | AttrSpec -> ArraySpec -> ExplicitShapeSpec +!PARSE-TREE: | | | | SpecificationExpr -> Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '1' +!PARSE-TREE: | | | ExplicitShapeSpec +!PARSE-TREE: | | | | SpecificationExpr -> Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '10' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'arr' +!PARSE-TREE: | ExecutionPart -> Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct +!PARSE-TREE: | | | Verbatim +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!PARSE-TREE: | | | | Modifier -> OmpInteropPreference -> OmpInteropRuntimeIdentifier -> CharLiteralConstant +!PARSE-TREE: | | | | | string = 'cuda' +!PARSE-TREE: | | | | Modifier -> OmpInteropType -> Value = TargetSync +!PARSE-TREE: | | | | Modifier -> OmpInteropType -> Value = Target +!PARSE-TREE: | | | | OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | OmpClause -> Depend -> OmpDependClause -> TaskDep +!PARSE-TREE: | | | | Modifier -> OmpTaskDependenceType -> Value = Inout +!PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'arr' +!PARSE-TREE: | | | OmpClause -> Nowait +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: | | | Format -> Star +!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant +!PARSE-TREE: | | | | string = 'pass' +!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_04' + +SUBROUTINE test_interop_05() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj + !$OMP INTEROP INIT(PREFER_TYPE(omp_ifr_sycl), TARGETSYNC: obj) DEVICE(DEVICE_NUM:0) + PRINT *,'pass' +END SUBROUTINE test_interop_05 + +!UNPARSE: SUBROUTINE test_interop_05 +!UNPARSE: USE :: omp_lib +!UNPARSE: INTEGER(KIND=8_4) obj +!UNPARSE: !$OMP INTEROP INIT(PREFER_TYPE(4_4),TARGETSYNC: obj) DEVICE(DEVICE_NUM: 0_4) +!UNPARSE: PRINT *, "pass" +!UNPARSE: END SUBROUTINE test_interop_05 + +!PARSE-TREE: | SubroutineStmt +!PARSE-TREE: | | Name = 'test_interop_05' +!PARSE-TREE: | SpecificationPart +!PARSE-TREE: | | UseStmt +!PARSE-TREE: | | | Name = 'omp_lib' +!PARSE-TREE: | | ImplicitPart -> +!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind' +!PARSE-TREE: | | | EntityDecl +!PARSE-TREE: | | | | Name = 'obj' +!PARSE-TREE: | ExecutionPart -> Block +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct +!PARSE-TREE: | | | Verbatim +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause +!PARSE-TREE: | | | | Modifier -> OmpInteropPreference -> OmpInteropRuntimeIdentifier -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_ifr_sycl' +!PARSE-TREE: | | | | Modifier -> OmpInteropType -> Value = TargetSync +!PARSE-TREE: | | | | OmpObject -> Designator -> DataRef -> Name = 'obj' +!PARSE-TREE: | | | OmpClause -> Device -> OmpDeviceClause +!PARSE-TREE: | | | | Modifier -> OmpDeviceModifier -> Value = Device_Num +!PARSE-TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '0' +!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt +!PARSE-TREE: | | | Format -> Star +!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant +!PARSE-TREE: | | | | string = 'pass' +!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_05' + diff --git a/flang/test/Semantics/OpenMP/interop-construct.f90 b/flang/test/Semantics/OpenMP/interop-construct.f90 new file mode 100644 index 0000000000000..5df7fe8b655e7 --- /dev/null +++ b/flang/test/Semantics/OpenMP/interop-construct.f90 @@ -0,0 +1,30 @@ +! REQUIRES: openmp_runtime + +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 +! OpenMP Version 5.2 +! 14.1 Interop construct +! To check various semantic errors for inteorp construct. + +SUBROUTINE test_interop_01() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj + !ERROR: Each interop-var may be specified for at most one action-clause of each INTEROP construct. + !$OMP INTEROP INIT(TARGETSYNC,TARGET: obj) USE(obj) + PRINT *, 'pass' +END SUBROUTINE test_interop_01 + +SUBROUTINE test_interop_02() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj + !ERROR: Each interop-type may be specified at most once. + !$OMP INTEROP INIT(TARGETSYNC,TARGET,TARGETSYNC: obj) + PRINT *, 'pass' +END SUBROUTINE test_interop_02 + +SUBROUTINE test_interop_03() + USE omp_lib + INTEGER(OMP_INTEROP_KIND) :: obj + !ERROR: A DEPEND clause can only appear on the directive if the interop-type includes TARGETSYNC + !$OMP INTEROP INIT(TARGET: obj) DEPEND(INOUT: obj) + PRINT *, 'pass' +END SUBROUTINE test_interop_03 diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index 75347061d9a92..e2a1449d8cc76 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -244,6 +244,7 @@ def OMPC_Indirect : Clause<"indirect"> { } def OMPC_Init : Clause<"init"> { let clangClass = "OMPInitClause"; + let flangClass = "OmpInitClause"; } def OMPC_Initializer : Clause<"initializer"> { let flangClass = "OmpInitializerClause"; @@ -526,6 +527,7 @@ def OMPC_Update : Clause<"update"> { } def OMPC_Use : Clause<"use"> { let clangClass = "OMPUseClause"; + let flangClass = "OmpUseClause"; } def OMPC_UsesAllocators : Clause<"uses_allocators"> { let clangClass = "OMPUsesAllocatorsClause";