Skip to content
3 changes: 1 addition & 2 deletions flang/examples/FeatureList/FeatureList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ struct NodeVisitor {
READ_FEATURE(ObjectDecl)
READ_FEATURE(OldParameterStmt)
READ_FEATURE(OmpAlignedClause)
READ_FEATURE(OmpAllocateDirective)
READ_FEATURE(OmpBeginDirective)
READ_FEATURE(OmpBeginLoopDirective)
READ_FEATURE(OmpBeginSectionsDirective)
Expand Down Expand Up @@ -541,7 +542,6 @@ struct NodeVisitor {
READ_FEATURE(OpenMPCancellationPointConstruct)
READ_FEATURE(OpenMPConstruct)
READ_FEATURE(OpenMPCriticalConstruct)
READ_FEATURE(OpenMPDeclarativeAllocate)
READ_FEATURE(OpenMPDeclarativeConstruct)
READ_FEATURE(OpenMPDeclareReductionConstruct)
READ_FEATURE(OpenMPDeclareSimdConstruct)
Expand All @@ -550,7 +550,6 @@ struct NodeVisitor {
READ_FEATURE(OmpAtomicDefaultMemOrderClause)
READ_FEATURE(OpenMPFlushConstruct)
READ_FEATURE(OpenMPLoopConstruct)
READ_FEATURE(OpenMPExecutableAllocate)
READ_FEATURE(OpenMPAllocatorsConstruct)
READ_FEATURE(OpenMPRequiresConstruct)
READ_FEATURE(OpenMPSimpleStandaloneConstruct)
Expand Down
3 changes: 1 addition & 2 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ class ParseTreeDumper {
NODE(parser, OmpAlignModifier)
NODE(parser, OmpAllocateClause)
NODE(OmpAllocateClause, Modifier)
NODE(parser, OmpAllocateDirective)
NODE(parser, OmpAllocatorComplexModifier)
NODE(parser, OmpAllocatorSimpleModifier)
NODE(parser, OmpAlwaysModifier)
Expand Down Expand Up @@ -739,7 +740,6 @@ class ParseTreeDumper {
NODE(parser, OpenMPCancellationPointConstruct)
NODE(parser, OpenMPConstruct)
NODE(parser, OpenMPCriticalConstruct)
NODE(parser, OpenMPDeclarativeAllocate)
NODE(parser, OpenMPDeclarativeAssumes)
NODE(parser, OpenMPDeclarativeConstruct)
NODE(parser, OpenMPDeclareMapperConstruct)
Expand All @@ -748,7 +748,6 @@ class ParseTreeDumper {
NODE(parser, OpenMPDeclareTargetConstruct)
NODE(parser, OpenMPDepobjConstruct)
NODE(parser, OpenMPDispatchConstruct)
NODE(parser, OpenMPExecutableAllocate)
NODE(parser, OpenMPFlushConstruct)
NODE(parser, OpenMPGroupprivate)
NODE(parser, OpenMPLoopConstruct)
Expand Down
31 changes: 11 additions & 20 deletions flang/include/flang/Parser/openmp-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>

namespace Fortran::parser::omp {

Expand All @@ -33,23 +34,6 @@ template <typename T> constexpr auto addr_if(const std::optional<T> &x) {
}

namespace detail {
using D = llvm::omp::Directive;

template <typename Construct> //
struct ConstructId {
static constexpr llvm::omp::Directive id{D::OMPD_unknown};
};

#define MAKE_CONSTR_ID(Construct, Id) \
template <> struct ConstructId<Construct> { \
static constexpr llvm::omp::Directive id{Id}; \
}

MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);

#undef MAKE_CONSTR_ID

struct DirectiveNameScope {
static OmpDirectiveName MakeName(CharBlock source = {},
llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown) {
Expand Down Expand Up @@ -97,9 +81,6 @@ struct DirectiveNameScope {
} else if constexpr (TupleTrait<T>) {
if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
return std::get<OmpBeginDirective>(x.t).DirName();
} else if constexpr (std::is_same_v<T, OpenMPDeclarativeAllocate> ||
std::is_same_v<T, OpenMPExecutableAllocate>) {
return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id);
} else {
return GetFromTuple(
x.t, std::make_index_sequence<std::tuple_size_v<decltype(x.t)>>{});
Expand Down Expand Up @@ -139,6 +120,9 @@ template <typename T> OmpDirectiveName GetOmpDirectiveName(const T &x) {
return detail::DirectiveNameScope::GetOmpDirectiveName(x);
}

const OpenMPDeclarativeConstruct *GetOmp(const DeclarationConstruct &x);
const OpenMPConstruct *GetOmp(const ExecutionPartConstruct &x);

const OmpObjectList *GetOmpObjectList(const OmpClause &clause);

template <typename T>
Expand All @@ -158,6 +142,13 @@ const OmpCombinerExpression *GetCombinerExpr(
const OmpReductionSpecifier &rspec);
const OmpInitializerExpression *GetInitializerExpr(const OmpClause &init);

struct OmpAllocateInfo {
std::vector<const OmpAllocateDirective *> dirs;
const ExecutionPartConstruct *body{nullptr};
};

OmpAllocateInfo SplitOmpAllocate(const OmpAllocateDirective &x);

} // namespace Fortran::parser::omp

#endif // FORTRAN_PARSER_OPENMP_UTILS_H
56 changes: 34 additions & 22 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -5151,17 +5151,42 @@ struct OpenMPThreadprivate {
CharBlock source;
};

// 2.11.3 allocate -> ALLOCATE (variable-name-list) [clause]
struct OpenMPDeclarativeAllocate {
TUPLE_CLASS_BOILERPLATE(OpenMPDeclarativeAllocate);
CharBlock source;
std::tuple<Verbatim, std::optional<OmpObjectList>, OmpClauseList> t;
// Ref: [4.5:310-312], [5.0:156-158], [5.1:181-184], [5.2:176-177],
// [6.0:310-312]
//
// allocate-directive ->
// ALLOCATE (variable-list-item...) | // since 4.5
// ALLOCATE (variable-list-item...) // since 5.0, until 5.1
// ...
// allocate-stmt
//
// The first form is the "declarative-allocate", and is a declarative
// directive. The second is the "executable-allocate" and is an executable
// directive. The executable form was deprecated in 5.2.
//
// The executable-allocate consists of several ALLOCATE directives. Since
// in the parse tree every type corresponding to a directive only corresponds
// to a single directive, the executable form is represented by a sequence
// of nested OmpAlocateDirectives, e.g.
// !$OMP ALLOCATE(x)
// !$OMP ALLOCATE(y)
// ALLOCATE(x, y)
// will become
// OmpAllocateDirective
// |- ALLOCATE(x) // begin directive
// `- OmpAllocateDirective // block
// |- ALLOCATE(y) // begin directive
// `- ALLOCATE(x, y) // block
//
// The block in the declarative-allocate will be empty.
struct OmpAllocateDirective : public OmpBlockConstruct {
INHERITED_TUPLE_CLASS_BOILERPLATE(OmpAllocateDirective, OmpBlockConstruct);
};

struct OpenMPDeclarativeConstruct {
UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct);
CharBlock source;
std::variant<OpenMPDeclarativeAllocate, OpenMPDeclarativeAssumes,
std::variant<OmpAllocateDirective, OpenMPDeclarativeAssumes,
OpenMPDeclareMapperConstruct, OpenMPDeclareReductionConstruct,
OpenMPDeclareSimdConstruct, OpenMPDeclareTargetConstruct,
OmpDeclareVariantDirective, OpenMPGroupprivate, OpenMPThreadprivate,
Expand All @@ -5174,19 +5199,6 @@ struct OpenMPCriticalConstruct : public OmpBlockConstruct {
INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPCriticalConstruct, OmpBlockConstruct);
};

// 2.11.3 allocate -> ALLOCATE [(variable-name-list)] [clause]
// [ALLOCATE (variable-name-list) [clause] [...]]
// allocate-statement
// clause -> allocator-clause
struct OpenMPExecutableAllocate {
TUPLE_CLASS_BOILERPLATE(OpenMPExecutableAllocate);
CharBlock source;
std::tuple<Verbatim, std::optional<OmpObjectList>, OmpClauseList,
std::optional<std::list<OpenMPDeclarativeAllocate>>,
Statement<AllocateStmt>>
t;
};

// Ref: [5.2:180-181], [6.0:315]
//
// allocators-construct ->
Expand Down Expand Up @@ -5342,9 +5354,9 @@ struct OpenMPConstruct {
UNION_CLASS_BOILERPLATE(OpenMPConstruct);
std::variant<OpenMPStandaloneConstruct, OpenMPSectionsConstruct,
OpenMPSectionConstruct, OpenMPLoopConstruct, OmpBlockConstruct,
OpenMPAtomicConstruct, OpenMPDeclarativeAllocate, OpenMPDispatchConstruct,
OpenMPUtilityConstruct, OpenMPExecutableAllocate,
OpenMPAllocatorsConstruct, OpenMPAssumeConstruct, OpenMPCriticalConstruct>
OpenMPAtomicConstruct, OmpAllocateDirective, OpenMPDispatchConstruct,
OpenMPUtilityConstruct, OpenMPAllocatorsConstruct, OpenMPAssumeConstruct,
OpenMPCriticalConstruct>
u;
};

Expand Down
18 changes: 5 additions & 13 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3503,12 +3503,12 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
lower::pft::Evaluation &eval,
const parser::OpenMPUtilityConstruct &);

static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
const parser::OpenMPDeclarativeAllocate &declarativeAllocate) {
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OmpAllocateDirective &allocate) {
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate");
TODO(converter.getCurrentLocation(), "OmpAllocateDirective");
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
Expand Down Expand Up @@ -3899,14 +3899,6 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
TODO(converter.getCurrentLocation(), "OpenMPDispatchConstruct");
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPExecutableAllocate &execAllocConstruct) {
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPExecutableAllocate");
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
Expand Down
46 changes: 28 additions & 18 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1778,6 +1778,31 @@ struct OmpBlockConstructParser {
llvm::omp::Directive dir_;
};

struct OmpDeclarativeAllocateParser {
using resultType = OmpAllocateDirective;

std::optional<resultType> Parse(ParseState &state) const {
constexpr llvm::omp::Directive dir{llvm::omp::Directive::OMPD_allocate};
if (auto &&begin{attempt(OmpBeginDirectiveParser(dir)).Parse(state)}) {
Block empty;
auto end{maybe(OmpEndDirectiveParser{dir}).Parse(state)};
return OmpAllocateDirective{std::move(*begin), std::move(empty),
llvm::transformOptional(std::move(*end),
[](auto &&s) { return OmpEndDirective(std::move(s)); })};
}
return std::nullopt;
}
};

struct OmpExecutableAllocateParser {
using resultType = OmpAllocateDirective;

std::optional<resultType> Parse(ParseState &state) const {
OmpStatementConstructParser p{llvm::omp::Directive::OMPD_allocate};
return construct<OmpAllocateDirective>(p).Parse(state);
}
};

TYPE_PARSER(sourced(construct<OpenMPAllocatorsConstruct>(
OmpStatementConstructParser{llvm::omp::Directive::OMPD_allocators})))

Expand Down Expand Up @@ -2044,14 +2069,6 @@ TYPE_PARSER(construct<OmpInitializerExpression>(OmpStylizedExpressionParser{}))
TYPE_PARSER(sourced(construct<OpenMPCriticalConstruct>(
OmpBlockConstructParser{llvm::omp::Directive::OMPD_critical})))

// 2.11.3 Executable Allocate directive
TYPE_PARSER(sourced(construct<OpenMPExecutableAllocate>(
verbatim("ALLOCATE"_tok), maybe(parenthesized(Parser<OmpObjectList>{})),
Parser<OmpClauseList>{},
maybe(nonemptyList(startOmpLine >> Parser<OpenMPDeclarativeAllocate>{})) /
endOmpLine,
statement(allocateStmt))))

// 2.8.2 Declare Simd construct
TYPE_PARSER(sourced(construct<OpenMPDeclareSimdConstruct>(
predicated(Parser<OmpDirectiveName>{},
Expand All @@ -2077,13 +2094,6 @@ TYPE_PARSER(sourced( //
IsDirective(llvm::omp::Directive::OMPD_threadprivate)) >=
Parser<OmpDirectiveSpecification>{})))

// 2.11.3 Declarative Allocate directive
TYPE_PARSER(
sourced(construct<OpenMPDeclarativeAllocate>(verbatim("ALLOCATE"_tok),
maybe(parenthesized(Parser<OmpObjectList>{})),
Parser<OmpClauseList>{})) /
lookAhead(endOmpLine / !statement(allocateStmt)))

// Assumes Construct
TYPE_PARSER(sourced(construct<OpenMPDeclarativeAssumes>(
predicated(OmpDirectiveNameParser{},
Expand All @@ -2106,7 +2116,7 @@ TYPE_PARSER(
construct<OpenMPDeclarativeConstruct>(
Parser<OmpDeclareVariantDirective>{}) ||
construct<OpenMPDeclarativeConstruct>(
Parser<OpenMPDeclarativeAllocate>{}) ||
sourced(OmpDeclarativeAllocateParser{})) ||
construct<OpenMPDeclarativeConstruct>(
Parser<OpenMPGroupprivate>{}) ||
construct<OpenMPDeclarativeConstruct>(
Expand Down Expand Up @@ -2194,16 +2204,16 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
withMessage("expected OpenMP construct"_err_en_US,
first(construct<OpenMPConstruct>(Parser<OpenMPSectionsConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPLoopConstruct>{}),
construct<OpenMPConstruct>(
sourced(OmpExecutableAllocateParser{})),
construct<OpenMPConstruct>(Parser<OmpBlockConstruct>{}),
// OmpBlockConstruct is attempted before
// OpenMPStandaloneConstruct to resolve !$OMP ORDERED
construct<OpenMPConstruct>(Parser<OpenMPStandaloneConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPAtomicConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPUtilityConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPDispatchConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPExecutableAllocate>{}),
construct<OpenMPConstruct>(Parser<OpenMPAllocatorsConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPDeclarativeAllocate>{}),
construct<OpenMPConstruct>(Parser<OpenMPAssumeConstruct>{}),
construct<OpenMPConstruct>(Parser<OpenMPCriticalConstruct>{}))))

Expand Down
39 changes: 39 additions & 0 deletions flang/lib/Parser/openmp-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,25 @@

namespace Fortran::parser::omp {

const OpenMPDeclarativeConstruct *GetOmp(const DeclarationConstruct &x) {
if (auto *y = std::get_if<SpecificationConstruct>(&x.u)) {
if (auto *z{std::get_if<common::Indirection<OpenMPDeclarativeConstruct>>(
&y->u)}) {
return &z->value();
}
}
return nullptr;
}

const OpenMPConstruct *GetOmp(const ExecutionPartConstruct &x) {
if (auto *y{std::get_if<ExecutableConstruct>(&x.u)}) {
if (auto *z{std::get_if<common::Indirection<OpenMPConstruct>>(&y->u)}) {
return &z->value();
}
}
return nullptr;
}

const OmpObjectList *GetOmpObjectList(const OmpClause &clause) {
// Clauses with OmpObjectList as its data member
using MemberObjectListClauses = std::tuple<OmpClause::Copyin,
Expand Down Expand Up @@ -86,4 +105,24 @@ const OmpInitializerExpression *GetInitializerExpr(const OmpClause &init) {
return nullptr;
}

static void SplitOmpAllocateHelper(
OmpAllocateInfo &n, const OmpAllocateDirective &x) {
n.dirs.push_back(&x);
const Block &body{std::get<Block>(x.t)};
if (!body.empty()) {
if (auto *omp{GetOmp(body.front())}) {
if (auto *ad{std::get_if<OmpAllocateDirective>(&omp->u)}) {
return SplitOmpAllocateHelper(n, *ad);
}
}
n.body = &body.front();
}
}

OmpAllocateInfo SplitOmpAllocate(const OmpAllocateDirective &x) {
OmpAllocateInfo info;
SplitOmpAllocateHelper(info, x);
return info;
}

} // namespace Fortran::parser::omp
Loading