Skip to content

Commit 697d65d

Browse files
authored
[flang][OpenMP] Parsing support for map type modifiers (#111860)
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 64bcb27 commit 697d65d

17 files changed

+403
-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: 97 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,70 @@ namespace Fortran::parser {
2323
constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
2424
constexpr auto endOmpLine = space >> endOfLine;
2525

26+
// Map modifiers come from two categories: map-type-modifier and map-type.
27+
// There can be zero or more map-type-modifiers, and zero or one map-type.
28+
// Syntax-wise they look like a single list, where the last element could
29+
// be a map-type, and all elements in that list are comma-separated[1].
30+
// Only if there was at least one modifier (of any kind) specified, the
31+
// list must end with ":".
32+
// [1] Any of the commas are optional, but that syntax has been deprecated,
33+
// and the parsing code is intended to identify that. There are complications
34+
// coming from the fact that the comma separating the two kinds of modifiers
35+
// is only allowed if there is at least one modifier of each kind.
36+
// The MapModifiers parser parses the modifier list as a whole, and returns
37+
// a tuple with the (optional) map-type-modifier list, and the (optional)
38+
// type modifier as its members.
39+
// The list is then parsed, first with a mandatory separator, and if that
40+
// fails, with an optional one. If the latter succeeds, a deprecation
41+
// message is printed.
42+
template <typename Separator> struct MapModifiers {
43+
constexpr MapModifiers(
44+
Separator sep, std::optional<MessageFixedText> msg = std::nullopt)
45+
: sep_(sep), msg_(msg) {}
46+
constexpr MapModifiers(const MapModifiers &) = default;
47+
constexpr MapModifiers(MapModifiers &&) = default;
48+
49+
using resultType =
50+
std::tuple<std::optional<std::list<OmpMapClause::TypeModifier>>,
51+
std::optional<OmpMapClause::Type>>;
52+
53+
std::optional<resultType> Parse(ParseState &state) const {
54+
auto pmod{Parser<OmpMapClause::TypeModifier>{}};
55+
auto ptype{Parser<OmpMapClause::Type>{}};
56+
auto startLoc{state.GetLocation()};
57+
58+
auto &&[mods, type] = [&]() -> resultType {
59+
// The 'maybe' will return optional<optional<list>>, and the outer
60+
// optional will never be nullopt.
61+
if (auto mods{
62+
*maybe(attempt(nonemptySeparated(pmod, sep_))).Parse(state)}) {
63+
// mods = optional<list>, and the list is nonempty.
64+
return attempt(sep_).Parse(state)
65+
? resultType(mods, *maybe(attempt(ptype)).Parse(state))
66+
: resultType(mods, std::nullopt);
67+
}
68+
return {std::nullopt, *maybe(attempt(ptype)).Parse(state)};
69+
}();
70+
auto endLoc{state.GetLocation()};
71+
72+
// The above always "succeeds", i.e. even if the input is junk, it will
73+
// return a tuple with two nullopts. If any of the components is not a
74+
// nullopt, expect a ":".
75+
if ((mods.has_value() || type.has_value()) &&
76+
!attempt(":"_tok).Parse(state)) {
77+
return std::nullopt;
78+
}
79+
if (msg_) {
80+
state.Say(CharBlock{startLoc, endLoc}, *msg_);
81+
}
82+
return resultType(mods, type);
83+
}
84+
85+
private:
86+
const Separator sep_;
87+
std::optional<MessageFixedText> msg_;
88+
};
89+
2690
// OpenMP Clauses
2791
// 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE)
2892
TYPE_PARSER(construct<OmpDefaultClause>(
@@ -38,20 +102,39 @@ TYPE_PARSER(construct<OmpProcBindClause>(
38102
"PRIMARY" >> pure(OmpProcBindClause::Type::Primary) ||
39103
"SPREAD" >> pure(OmpProcBindClause::Type::Spread)))
40104

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>{}))
105+
// 2.15.5.1 map ->
106+
// MAP ([ [map-type-modifiers [,] ] map-type : ] variable-name-list)
107+
// map-type-modifiers -> map-type-modifier [,] [...]
108+
// map-type-modifier -> ALWAYS | CLOSE | OMPX_HOLD | PRESENT
109+
// map-type -> ALLOC | DELETE | FROM | RELEASE | TO | TOFROM
110+
TYPE_PARSER(construct<OmpMapClause::TypeModifier>(
111+
"ALWAYS" >> pure(OmpMapClause::TypeModifier::Always) ||
112+
"CLOSE" >> pure(OmpMapClause::TypeModifier::Close) ||
113+
"OMPX_HOLD" >> pure(OmpMapClause::TypeModifier::OmpxHold) ||
114+
"PRESENT" >> pure(OmpMapClause::TypeModifier::Present)))
115+
116+
TYPE_PARSER(
117+
construct<OmpMapClause::Type>("ALLOC" >> pure(OmpMapClause::Type::Alloc) ||
118+
"DELETE" >> pure(OmpMapClause::Type::Delete) ||
119+
"FROM" >> pure(OmpMapClause::Type::From) ||
120+
"RELEASE" >> pure(OmpMapClause::Type::Release) ||
121+
"TO"_id >> pure(OmpMapClause::Type::To) ||
122+
"TOFROM" >> pure(OmpMapClause::Type::Tofrom)))
123+
124+
static inline OmpMapClause makeMapClause(
125+
std::tuple<std::optional<std::list<OmpMapClause::TypeModifier>>,
126+
std::optional<OmpMapClause::Type>> &&mod,
127+
OmpObjectList &&obj) {
128+
return OmpMapClause{
129+
std::move(std::get<0>(mod)), std::move(std::get<1>(mod)), std::move(obj)};
130+
}
131+
132+
TYPE_PARSER(construct<OmpMapClause>(applyFunction<OmpMapClause>(makeMapClause,
133+
(MapModifiers(","_tok) ||
134+
MapModifiers(maybe(","_tok),
135+
"the specification of modifiers without comma separators for the "
136+
"'MAP' clause has been deprecated"_port_en_US)),
137+
Parser<OmpObjectList>{})))
55138

56139
// [OpenMP 5.0]
57140
// 2.19.7.2 defaultmap(implicit-behavior[:variable-category])

flang/lib/Parser/unparse.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,11 +2073,27 @@ 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+
}
2084+
Walk(type);
2085+
if (typeMod.has_value() || type.has_value()) {
2086+
Put(": ");
2087+
}
20792088
Walk(std::get<OmpObjectList>(x.t));
20802089
}
2090+
void Unparse(const OmpMapClause::TypeModifier &x) {
2091+
if (x == OmpMapClause::TypeModifier::OmpxHold) {
2092+
Word("OMPX_HOLD");
2093+
} else {
2094+
Word(OmpMapClause::EnumToString(x));
2095+
}
2096+
}
20812097
void Unparse(const OmpScheduleModifier &x) {
20822098
Walk(std::get<OmpScheduleModifier::Modifier1>(x.t));
20832099
Walk(",", std::get<std::optional<OmpScheduleModifier::Modifier2>>(x.t));
@@ -2775,7 +2791,6 @@ class UnparseVisitor {
27752791
WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier
27762792
WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier
27772793
WALK_NESTED_ENUM(OmpDependenceType, Type) // OMP dependence-type
2778-
WALK_NESTED_ENUM(OmpMapType, Type) // OMP map-type
27792794
WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
27802795
WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
27812796
WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE
@@ -2785,6 +2800,7 @@ class UnparseVisitor {
27852800
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
27862801
WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type
27872802
WALK_NESTED_ENUM(OmpOrderModifier, Kind) // OMP order-modifier
2803+
WALK_NESTED_ENUM(OmpMapClause, Type) // OMP map-type
27882804
#undef WALK_NESTED_ENUM
27892805
void Unparse(const ReductionOperator::Operator x) {
27902806
switch (x) {

0 commit comments

Comments
 (0)