Skip to content

Commit 424475c

Browse files
committed
[flang][OpenMP] Parsing support for map type modifiers
This commit adds parsing of type modifiers for the MAP clause: CLOSE, OMPX_HOLD, and PRESENT. The support for ALWAYS has already existed. The new modifiers are not yet handled in lowering: when present, a TODO message is emitted and compilation stops.
1 parent f59b0c7 commit 424475c

File tree

14 files changed

+355
-112
lines changed

14 files changed

+355
-112
lines changed

flang/examples/FeatureList/FeatureList.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,8 @@ struct NodeVisitor {
492492
READ_FEATURE(OmpLinearModifier::Type)
493493
READ_FEATURE(OmpLoopDirective)
494494
READ_FEATURE(OmpMapClause)
495-
READ_FEATURE(OmpMapType)
496-
READ_FEATURE(OmpMapType::Always)
497-
READ_FEATURE(OmpMapType::Type)
495+
READ_FEATURE(OmpMapClause::TypeModifier)
496+
READ_FEATURE(OmpMapClause::Type)
498497
READ_FEATURE(OmpObject)
499498
READ_FEATURE(OmpObjectList)
500499
READ_FEATURE(OmpOrderClause)

flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ void OpenMPCounterVisitor::Post(const OmpDependenceType::Type &c) {
226226
clauseDetails +=
227227
"type=" + std::string{OmpDependenceType::EnumToString(c)} + ";";
228228
}
229-
void OpenMPCounterVisitor::Post(const OmpMapType::Type &c) {
230-
clauseDetails += "type=" + std::string{OmpMapType::EnumToString(c)} + ";";
229+
void OpenMPCounterVisitor::Post(const OmpMapClause::Type &c) {
230+
clauseDetails += "type=" + std::string{OmpMapClause::EnumToString(c)} + ";";
231231
}
232232
void OpenMPCounterVisitor::Post(const OmpScheduleClause::ScheduleType &c) {
233233
clauseDetails +=

flang/examples/FlangOmpReport/FlangOmpReportVisitor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ struct OpenMPCounterVisitor {
7474
void Post(const OmpScheduleModifierType::ModType &c);
7575
void Post(const OmpLinearModifier::Type &c);
7676
void Post(const OmpDependenceType::Type &c);
77-
void Post(const OmpMapType::Type &c);
77+
void Post(const OmpMapClause::Type &c);
7878
void Post(const OmpScheduleClause::ScheduleType &c);
7979
void Post(const OmpIfClause::DirectiveNameModifier &c);
8080
void Post(const OmpCancelType::Type &c);

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -531,9 +531,8 @@ class ParseTreeDumper {
531531
NODE_ENUM(OmpLinearModifier, Type)
532532
NODE(parser, OmpLoopDirective)
533533
NODE(parser, OmpMapClause)
534-
NODE(parser, OmpMapType)
535-
NODE(OmpMapType, Always)
536-
NODE_ENUM(OmpMapType, Type)
534+
NODE_ENUM(OmpMapClause, TypeModifier)
535+
NODE_ENUM(OmpMapClause, Type)
537536
static std::string GetNodeName(const llvm::omp::Clause &x) {
538537
return llvm::Twine(
539538
"llvm::omp::Clause = ", llvm::omp::getOpenMPClauseName(x))

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3448,18 +3448,18 @@ struct OmpObject {
34483448

34493449
WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>);
34503450

3451-
// 2.15.5.1 map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE
3452-
struct OmpMapType {
3453-
TUPLE_CLASS_BOILERPLATE(OmpMapType);
3454-
EMPTY_CLASS(Always);
3455-
ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete)
3456-
std::tuple<std::optional<Always>, Type> t;
3457-
};
3458-
3459-
// 2.15.5.1 map -> MAP ([ [ALWAYS[,]] map-type : ] variable-name-list)
3451+
// 2.15.5.1 map ->
3452+
// MAP ([ [map-type-modifiers [,] ] map-type : ] variable-name-list)
3453+
// map-type-modifiers -> map-type-modifier [,] [...]
3454+
// map-type-modifier -> ALWAYS | CLOSE | PRESENT | OMPX_HOLD
3455+
// map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE
34603456
struct OmpMapClause {
3457+
ENUM_CLASS(TypeModifier, Always, Close, Present, OmpxHold);
3458+
ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete)
34613459
TUPLE_CLASS_BOILERPLATE(OmpMapClause);
3462-
std::tuple<std::optional<OmpMapType>, OmpObjectList> t;
3460+
std::tuple<std::optional<std::list<TypeModifier>>, std::optional<Type>,
3461+
OmpObjectList>
3462+
t;
34633463
};
34643464

34653465
// 2.15.5.2 defaultmap -> DEFAULTMAP (implicit-behavior[:variable-category])

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -945,40 +945,42 @@ bool ClauseProcessor::processMap(
945945
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
946946
// If the map type is specified, then process it else Tofrom is the
947947
// default.
948-
if (mapType) {
949-
switch (*mapType) {
950-
case Map::MapType::To:
951-
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
952-
break;
953-
case Map::MapType::From:
954-
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
955-
break;
956-
case Map::MapType::Tofrom:
957-
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
958-
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
959-
break;
960-
case Map::MapType::Alloc:
961-
case Map::MapType::Release:
962-
// alloc and release is the default map_type for the Target Data
963-
// Ops, i.e. if no bits for map_type is supplied then alloc/release
964-
// is implicitly assumed based on the target directive. Default
965-
// value for Target Data and Enter Data is alloc and for Exit Data
966-
// it is release.
967-
break;
968-
case Map::MapType::Delete:
969-
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
970-
}
971-
972-
auto &modTypeMods =
973-
std::get<std::optional<Map::MapTypeModifiers>>(clause.t);
974-
if (modTypeMods) {
975-
if (llvm::is_contained(*modTypeMods, Map::MapTypeModifier::Always))
976-
mapTypeBits |=
977-
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
978-
}
979-
} else {
948+
Map::MapType type = mapType.value_or(Map::MapType::Tofrom);
949+
switch (type) {
950+
case Map::MapType::To:
951+
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
952+
break;
953+
case Map::MapType::From:
954+
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
955+
break;
956+
case Map::MapType::Tofrom:
980957
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
981958
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
959+
break;
960+
case Map::MapType::Alloc:
961+
case Map::MapType::Release:
962+
// alloc and release is the default map_type for the Target Data
963+
// Ops, i.e. if no bits for map_type is supplied then alloc/release
964+
// is implicitly assumed based on the target directive. Default
965+
// value for Target Data and Enter Data is alloc and for Exit Data
966+
// it is release.
967+
break;
968+
case Map::MapType::Delete:
969+
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
970+
}
971+
972+
auto &modTypeMods =
973+
std::get<std::optional<Map::MapTypeModifiers>>(clause.t);
974+
if (modTypeMods) {
975+
if (llvm::is_contained(*modTypeMods, Map::MapTypeModifier::Always))
976+
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
977+
// Diagnose unimplemented map-type-modifiers.
978+
if (llvm::any_of(*modTypeMods, [](Map::MapTypeModifier m) {
979+
return m != Map::MapTypeModifier::Always;
980+
})) {
981+
TODO(currentLocation, "Map type modifiers (other than 'ALWAYS')"
982+
" are not implemented yet");
983+
}
982984
}
983985
processMapObjects(stmtCtx, clauseLocation,
984986
std::get<omp::ObjectList>(clause.t), mapTypeBits,

flang/lib/Lower/OpenMP/Clauses.cpp

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -846,41 +846,49 @@ Link make(const parser::OmpClause::Link &inp,
846846
Map make(const parser::OmpClause::Map &inp,
847847
semantics::SemanticsContext &semaCtx) {
848848
// inp.v -> parser::OmpMapClause
849+
using wrapped = parser::OmpMapClause;
849850

850851
CLAUSET_ENUM_CONVERT( //
851-
convert1, parser::OmpMapType::Type, Map::MapType,
852+
convert1, parser::OmpMapClause::Type, Map::MapType,
852853
// clang-format off
853-
MS(To, To)
854-
MS(From, From)
855-
MS(Tofrom, Tofrom)
856854
MS(Alloc, Alloc)
857-
MS(Release, Release)
858855
MS(Delete, Delete)
856+
MS(From, From)
857+
MS(Release, Release)
858+
MS(To, To)
859+
MS(Tofrom, Tofrom)
859860
// clang-format on
860861
);
861862

862-
// No convert2: MapTypeModifier is not an enum in parser.
863-
864-
auto &t0 = std::get<std::optional<parser::OmpMapType>>(inp.v.t);
865-
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
863+
CLAUSET_ENUM_CONVERT( //
864+
convert2, parser::OmpMapClause::TypeModifier, Map::MapTypeModifier,
865+
// clang-format off
866+
MS(Always, Always)
867+
MS(Close, Close)
868+
MS(OmpxHold, OmpxHold)
869+
MS(Present, Present)
870+
// clang-format on
871+
);
866872

867-
if (!t0) {
868-
return Map{{/*MapType=*/std::nullopt, /*MapTypeModifiers=*/std::nullopt,
869-
/*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt,
870-
/*LocatorList=*/makeObjects(t1, semaCtx)}};
871-
}
873+
auto &t0 = std::get<std::optional<std::list<wrapped::TypeModifier>>>(inp.v.t);
874+
auto &t1 = std::get<std::optional<wrapped::Type>>(inp.v.t);
875+
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
872876

873-
auto &s0 = std::get<std::optional<parser::OmpMapType::Always>>(t0->t);
874-
auto &s1 = std::get<parser::OmpMapType::Type>(t0->t);
877+
std::optional<Map::MapType> maybeType = maybeApply(convert1, t1);
875878

876-
std::optional<Map::MapTypeModifiers> maybeList;
877-
if (s0)
878-
maybeList = Map::MapTypeModifiers{Map::MapTypeModifier::Always};
879+
std::optional<Map::MapTypeModifiers> maybeTypeMods = maybeApply(
880+
[&](const std::list<wrapped::TypeModifier> &typeMods) {
881+
Map::MapTypeModifiers mods;
882+
for (wrapped::TypeModifier mod : typeMods)
883+
mods.push_back(convert2(mod));
884+
return mods;
885+
},
886+
t0);
879887

880-
return Map{{/*MapType=*/convert1(s1),
881-
/*MapTypeModifiers=*/maybeList,
888+
return Map{{/*MapType=*/maybeType,
889+
/*MapTypeModifiers=*/maybeTypeMods,
882890
/*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt,
883-
/*LocatorList=*/makeObjects(t1, semaCtx)}};
891+
/*LocatorList=*/makeObjects(t2, semaCtx)}};
884892
}
885893

886894
// Match: incomplete

flang/lib/Parser/openmp-parsers.cpp

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,55 @@ namespace Fortran::parser {
2323
constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
2424
constexpr auto endOmpLine = space >> endOfLine;
2525

26+
template <typename Separator>
27+
struct MapModifiers {
28+
constexpr MapModifiers(Separator sep,
29+
std::optional<MessageFixedText> msg = std::nullopt)
30+
: sep_(sep), msg_(msg) {}
31+
constexpr MapModifiers(const MapModifiers &) = default;
32+
constexpr MapModifiers(MapModifiers &&) = default;
33+
34+
using resultType =
35+
std::tuple<std::optional<std::list<OmpMapClause::TypeModifier>>,
36+
std::optional<OmpMapClause::Type>>;
37+
38+
std::optional<resultType> Parse(ParseState &state) const {
39+
auto pmod{Parser<OmpMapClause::TypeModifier>{}};
40+
auto ptype{Parser<OmpMapClause::Type>{}};
41+
auto startLoc{state.GetLocation()};
42+
43+
auto &&[mods, type] = [&]() -> resultType {
44+
// The 'maybe' will return optional<optional<list>>, and the outer
45+
// optional will never be nullopt.
46+
if (auto mods{
47+
*maybe(attempt(nonemptySeparated(pmod, sep_))).Parse(state)}) {
48+
// mods = optional<list>, and the list is nonempty.
49+
return attempt(sep_).Parse(state)
50+
? resultType(mods, *maybe(attempt(ptype)).Parse(state))
51+
: resultType(mods, std::nullopt);
52+
}
53+
return {std::nullopt, *maybe(attempt(ptype)).Parse(state)};
54+
}();
55+
auto endLoc{state.GetLocation()};
56+
57+
// The above always "succeeds", i.e. even if the input is junk, it will
58+
// return a tuple with two nullopts. If any of the components is not a
59+
// nullopt, expect a ":".
60+
if ((mods.has_value() || type.has_value()) &&
61+
!attempt(":"_tok).Parse(state)) {
62+
return std::nullopt;
63+
}
64+
if (msg_) {
65+
state.Say(CharBlock{startLoc, endLoc}, *msg_);
66+
}
67+
return resultType(mods, type);
68+
}
69+
70+
private:
71+
const Separator sep_;
72+
std::optional<MessageFixedText> msg_;
73+
};
74+
2675
// OpenMP Clauses
2776
// 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
2877
TYPE_PARSER(construct<OmpDefaultClause>(
@@ -38,20 +87,41 @@ TYPE_PARSER(construct<OmpProcBindClause>(
3887
"PRIMARY" >> pure(OmpProcBindClause::Type::Primary) ||
3988
"SPREAD" >> pure(OmpProcBindClause::Type::Spread)))
4089

41-
// 2.15.5.1 MAP ([ [ALWAYS[,]] map-type : ] variable-name-list)
42-
// map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE
43-
TYPE_PARSER(construct<OmpMapType>(
44-
maybe("ALWAYS" >> construct<OmpMapType::Always>() / maybe(","_tok)),
45-
("TO"_id >> pure(OmpMapType::Type::To) ||
46-
"FROM" >> pure(OmpMapType::Type::From) ||
47-
"TOFROM" >> pure(OmpMapType::Type::Tofrom) ||
48-
"ALLOC" >> pure(OmpMapType::Type::Alloc) ||
49-
"RELEASE" >> pure(OmpMapType::Type::Release) ||
50-
"DELETE" >> pure(OmpMapType::Type::Delete)) /
51-
":"))
52-
53-
TYPE_PARSER(construct<OmpMapClause>(
54-
maybe(Parser<OmpMapType>{}), Parser<OmpObjectList>{}))
90+
// 2.15.5.1 map ->
91+
// MAP ([ [map-type-modifiers [,] ] map-type : ] variable-name-list)
92+
// map-type-modifiers -> map-type-modifier [,] [...]
93+
// map-type-modifier -> ALWAYS | CLOSE | OMPX_HOLD | PRESENT
94+
// map-type -> ALLOC | DELETE | FROM | RELEASE | TO | TOFROM
95+
TYPE_PARSER(construct<OmpMapClause::TypeModifier>(
96+
"ALWAYS" >> pure(OmpMapClause::TypeModifier::Always) ||
97+
"CLOSE" >> pure(OmpMapClause::TypeModifier::Close) ||
98+
"OMPX_HOLD" >> pure(OmpMapClause::TypeModifier::OmpxHold) ||
99+
"PRESENT" >> pure(OmpMapClause::TypeModifier::Present)))
100+
101+
TYPE_PARSER(construct<OmpMapClause::Type>(
102+
"ALLOC" >> pure(OmpMapClause::Type::Alloc) ||
103+
"DELETE" >> pure(OmpMapClause::Type::Delete) ||
104+
"FROM" >> pure(OmpMapClause::Type::From) ||
105+
"RELEASE" >> pure(OmpMapClause::Type::Release) ||
106+
"TO"_id >> pure(OmpMapClause::Type::To) ||
107+
"TOFROM" >> pure(OmpMapClause::Type::Tofrom)))
108+
109+
static inline OmpMapClause
110+
makeMapClause(std::tuple<std::optional<std::list<OmpMapClause::TypeModifier>>,
111+
std::optional<OmpMapClause::Type>> &&mod,
112+
OmpObjectList &&obj) {
113+
return OmpMapClause{std::move(std::get<0>(mod)), std::move(std::get<1>(mod)),
114+
std::move(obj)};
115+
}
116+
117+
TYPE_PARSER(construct<OmpMapClause>(applyFunction(
118+
makeMapClause,
119+
(MapModifiers(","_tok) ||
120+
MapModifiers(
121+
maybe(","_tok),
122+
"the specification of modifiers without comma separators for the "
123+
"'MAP' clause has been deprecated"_port_en_US)),
124+
Parser<OmpObjectList>{})))
55125

56126
// [OpenMP 5.0]
57127
// 2.19.7.2 defaultmap(implicit-behavior[:variable-category])

flang/lib/Parser/unparse.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,11 +2073,24 @@ class UnparseVisitor {
20732073
":");
20742074
Walk(std::get<OmpObjectList>(x.t));
20752075
}
2076-
void Unparse(const OmpMapType::Always &) { Word("ALWAYS,"); }
20772076
void Unparse(const OmpMapClause &x) {
2078-
Walk(std::get<std::optional<OmpMapType>>(x.t), ":");
2077+
auto &typeMod =
2078+
std::get<std::optional<std::list<OmpMapClause::TypeModifier>>>(x.t);
2079+
auto &type = std::get<std::optional<OmpMapClause::Type>>(x.t);
2080+
Walk(typeMod);
2081+
if (typeMod.has_value() && type.has_value())
2082+
Put(", ");
2083+
Walk(type);
2084+
if (typeMod.has_value() || type.has_value())
2085+
Put(": ");
20792086
Walk(std::get<OmpObjectList>(x.t));
20802087
}
2088+
void Unparse(const OmpMapClause::TypeModifier &x) {
2089+
if (x == OmpMapClause::TypeModifier::OmpxHold)
2090+
Word("OMPX_HOLD");
2091+
else
2092+
Word(OmpMapClause::EnumToString(x));
2093+
}
20812094
void Unparse(const OmpScheduleModifier &x) {
20822095
Walk(std::get<OmpScheduleModifier::Modifier1>(x.t));
20832096
Walk(",", std::get<std::optional<OmpScheduleModifier::Modifier2>>(x.t));
@@ -2775,7 +2788,6 @@ class UnparseVisitor {
27752788
WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
27762789
WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier
27772790
WALK_NESTED_ENUM(OmpDependenceType, Type) // OMP dependence-type
2778-
WALK_NESTED_ENUM(OmpMapType, Type) // OMP map-type
27792791
WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
27802792
WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
27812793
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
@@ -2785,6 +2797,7 @@ class UnparseVisitor {
27852797
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
27862798
WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type
27872799
WALK_NESTED_ENUM(OmpOrderModifier, Kind) // OMP order-modifier
2800+
WALK_NESTED_ENUM(OmpMapClause, Type) // OMP map-type
27882801
#undef WALK_NESTED_ENUM
27892802
void Unparse(const ReductionOperator::Operator x) {
27902803
switch (x) {

0 commit comments

Comments
 (0)