blob: 1d1a112aac3be6f995f9ea16ee27d7a3e1c6aa49 [file] [log] [blame]
//===-- Clauses.h -- OpenMP clause handling -------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef FORTRAN_LOWER_OPENMP_CLAUSES_H
#define FORTRAN_LOWER_OPENMP_CLAUSES_H
#include "ClauseT.h"
#include "flang/Evaluate/expression.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/semantics.h"
#include "flang/Semantics/symbol.h"
#include "llvm/ADT/STLExtras.h"
#include <optional>
#include <type_traits>
#include <utility>
namespace Fortran::lower::omp {
using namespace Fortran;
using SomeType = evaluate::SomeType;
using SomeExpr = semantics::SomeExpr;
using MaybeExpr = semantics::MaybeExpr;
using SymIdent = semantics::Symbol *;
using SymReference = SomeExpr;
template <typename T>
using List = tomp::ListT<T>;
} // namespace Fortran::lower::omp
namespace tomp {
template <>
struct ObjectT<Fortran::lower::omp::SymIdent,
Fortran::lower::omp::SymReference> {
using IdType = Fortran::lower::omp::SymIdent;
using ExprType = Fortran::lower::omp::SymReference;
const IdType &id() const { return symbol; }
const std::optional<ExprType> &ref() const { return designator; }
IdType symbol;
std::optional<ExprType> designator;
};
} // namespace tomp
namespace Fortran::lower::omp {
using Object = tomp::ObjectT<SymIdent, SymReference>;
using ObjectList = tomp::ObjectListT<SymIdent, SymReference>;
Object makeObject(const parser::OmpObject &object,
semantics::SemanticsContext &semaCtx);
Object makeObject(const parser::Name &name,
semantics::SemanticsContext &semaCtx);
Object makeObject(const parser::Designator &dsg,
semantics::SemanticsContext &semaCtx);
Object makeObject(const parser::StructureComponent &comp,
semantics::SemanticsContext &semaCtx);
inline auto makeObjectFn(semantics::SemanticsContext &semaCtx) {
return [&](auto &&s) { return makeObject(s, semaCtx); };
}
template <typename T>
SomeExpr makeExpr(T &&pftExpr, semantics::SemanticsContext &semaCtx) {
auto maybeExpr = evaluate::ExpressionAnalyzer(semaCtx).Analyze(pftExpr);
assert(maybeExpr);
return std::move(*maybeExpr);
}
inline auto makeExprFn(semantics::SemanticsContext &semaCtx) {
return [&](auto &&s) { return makeExpr(s, semaCtx); };
}
template <
typename ContainerTy, typename FunctionTy,
typename ElemTy = typename llvm::remove_cvref_t<ContainerTy>::value_type,
typename ResultTy = std::invoke_result_t<FunctionTy, ElemTy>>
List<ResultTy> makeList(ContainerTy &&container, FunctionTy &&func) {
List<ResultTy> v;
llvm::transform(container, std::back_inserter(v), func);
return v;
}
inline ObjectList makeList(const parser::OmpObjectList &objects,
semantics::SemanticsContext &semaCtx) {
return makeList(objects.v, makeObjectFn(semaCtx));
}
template <typename FuncTy, typename ElemTy,
typename ResultTy = std::invoke_result_t<FuncTy, ElemTy>>
std::optional<ResultTy> maybeApply(FuncTy &&func,
const std::optional<ElemTy> &inp) {
if (!inp)
return std::nullopt;
return std::move(func(*inp));
}
std::optional<Object>
getBaseObject(const Object &object,
Fortran::semantics::SemanticsContext &semaCtx);
namespace clause {
#ifdef EMPTY_CLASS
#undef EMPTY_CLASS
#endif
#define EMPTY_CLASS(cls) \
using cls = tomp::clause::cls##T<SymIdent, SymReference>
#ifdef WRAPPER_CLASS
#undef WRAPPER_CLASS
#endif
#define WRAPPER_CLASS(cls, content) \
[[maybe_unused]] extern int xyzzy_semicolon_absorber
#define GEN_FLANG_CLAUSE_PARSER_CLASSES
#include "llvm/Frontend/OpenMP/OMP.inc"
#undef EMPTY_CLASS
#undef WRAPPER_CLASS
using DefinedOperator = tomp::clause::DefinedOperatorT<SymIdent, SymReference>;
using ProcedureDesignator =
tomp::clause::ProcedureDesignatorT<SymIdent, SymReference>;
using ReductionOperator =
tomp::clause::ReductionOperatorT<SymIdent, SymReference>;
// "Requires" clauses are handled early on, and the aggregated information
// is stored in the Symbol details of modules, programs, and subprograms.
// These clauses are still handled here to cover all alternatives in the
// main clause variant.
using Aligned = tomp::clause::AlignedT<SymIdent, SymReference>;
using Allocate = tomp::clause::AllocateT<SymIdent, SymReference>;
using Allocator = tomp::clause::AllocatorT<SymIdent, SymReference>;
using AtomicDefaultMemOrder =
tomp::clause::AtomicDefaultMemOrderT<SymIdent, SymReference>;
using Collapse = tomp::clause::CollapseT<SymIdent, SymReference>;
using Copyin = tomp::clause::CopyinT<SymIdent, SymReference>;
using Copyprivate = tomp::clause::CopyprivateT<SymIdent, SymReference>;
using Defaultmap = tomp::clause::DefaultmapT<SymIdent, SymReference>;
using Default = tomp::clause::DefaultT<SymIdent, SymReference>;
using Depend = tomp::clause::DependT<SymIdent, SymReference>;
using Device = tomp::clause::DeviceT<SymIdent, SymReference>;
using DeviceType = tomp::clause::DeviceTypeT<SymIdent, SymReference>;
using DistSchedule = tomp::clause::DistScheduleT<SymIdent, SymReference>;
using Enter = tomp::clause::EnterT<SymIdent, SymReference>;
using Filter = tomp::clause::FilterT<SymIdent, SymReference>;
using Final = tomp::clause::FinalT<SymIdent, SymReference>;
using Firstprivate = tomp::clause::FirstprivateT<SymIdent, SymReference>;
using From = tomp::clause::FromT<SymIdent, SymReference>;
using Grainsize = tomp::clause::GrainsizeT<SymIdent, SymReference>;
using HasDeviceAddr = tomp::clause::HasDeviceAddrT<SymIdent, SymReference>;
using Hint = tomp::clause::HintT<SymIdent, SymReference>;
using If = tomp::clause::IfT<SymIdent, SymReference>;
using InReduction = tomp::clause::InReductionT<SymIdent, SymReference>;
using IsDevicePtr = tomp::clause::IsDevicePtrT<SymIdent, SymReference>;
using Lastprivate = tomp::clause::LastprivateT<SymIdent, SymReference>;
using Linear = tomp::clause::LinearT<SymIdent, SymReference>;
using Link = tomp::clause::LinkT<SymIdent, SymReference>;
using Map = tomp::clause::MapT<SymIdent, SymReference>;
using Nocontext = tomp::clause::NocontextT<SymIdent, SymReference>;
using Nontemporal = tomp::clause::NontemporalT<SymIdent, SymReference>;
using Novariants = tomp::clause::NovariantsT<SymIdent, SymReference>;
using NumTasks = tomp::clause::NumTasksT<SymIdent, SymReference>;
using NumTeams = tomp::clause::NumTeamsT<SymIdent, SymReference>;
using NumThreads = tomp::clause::NumThreadsT<SymIdent, SymReference>;
using OmpxDynCgroupMem =
tomp::clause::OmpxDynCgroupMemT<SymIdent, SymReference>;
using Ordered = tomp::clause::OrderedT<SymIdent, SymReference>;
using Order = tomp::clause::OrderT<SymIdent, SymReference>;
using Partial = tomp::clause::PartialT<SymIdent, SymReference>;
using Priority = tomp::clause::PriorityT<SymIdent, SymReference>;
using Private = tomp::clause::PrivateT<SymIdent, SymReference>;
using ProcBind = tomp::clause::ProcBindT<SymIdent, SymReference>;
using Reduction = tomp::clause::ReductionT<SymIdent, SymReference>;
using Safelen = tomp::clause::SafelenT<SymIdent, SymReference>;
using Schedule = tomp::clause::ScheduleT<SymIdent, SymReference>;
using Shared = tomp::clause::SharedT<SymIdent, SymReference>;
using Simdlen = tomp::clause::SimdlenT<SymIdent, SymReference>;
using Sizes = tomp::clause::SizesT<SymIdent, SymReference>;
using TaskReduction = tomp::clause::TaskReductionT<SymIdent, SymReference>;
using ThreadLimit = tomp::clause::ThreadLimitT<SymIdent, SymReference>;
using To = tomp::clause::ToT<SymIdent, SymReference>;
using Uniform = tomp::clause::UniformT<SymIdent, SymReference>;
using UseDeviceAddr = tomp::clause::UseDeviceAddrT<SymIdent, SymReference>;
using UseDevicePtr = tomp::clause::UseDevicePtrT<SymIdent, SymReference>;
} // namespace clause
struct Clause : public tomp::ClauseT<SymIdent, SymReference> {
parser::CharBlock source;
};
template <typename Specific>
Clause makeClause(llvm::omp::Clause id, Specific &&specific,
parser::CharBlock source = {}) {
return Clause{{id, specific}, source};
}
Clause makeClause(const Fortran::parser::OmpClause &cls,
semantics::SemanticsContext &semaCtx);
List<Clause> makeList(const parser::OmpClauseList &clauses,
semantics::SemanticsContext &semaCtx);
} // namespace Fortran::lower::omp
#endif // FORTRAN_LOWER_OPENMP_CLAUSES_H