264 lines
11 KiB
C++
264 lines
11 KiB
C++
//===-- 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 "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 "llvm/Frontend/OpenMP/ClauseT.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 TypeTy = SomeType;
|
|
using IdTy = semantics::Symbol *;
|
|
using ExprTy = SomeExpr;
|
|
|
|
template <typename T>
|
|
using List = tomp::ListT<T>;
|
|
} // namespace Fortran::lower::omp
|
|
|
|
namespace tomp::type {
|
|
template <>
|
|
struct ObjectT<Fortran::lower::omp::IdTy, Fortran::lower::omp::ExprTy> {
|
|
using IdTy = Fortran::lower::omp::IdTy;
|
|
using ExprTy = Fortran::lower::omp::ExprTy;
|
|
|
|
const IdTy &id() const { return symbol; }
|
|
const std::optional<ExprTy> &ref() const { return designator; }
|
|
|
|
IdTy symbol;
|
|
std::optional<ExprTy> designator;
|
|
};
|
|
} // namespace tomp::type
|
|
|
|
namespace Fortran::lower::omp {
|
|
|
|
using Object = tomp::ObjectT<IdTy, ExprTy>;
|
|
using ObjectList = tomp::ObjectListT<IdTy, ExprTy>;
|
|
|
|
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 makeObjects(const parser::OmpObjectList &objects,
|
|
semantics::SemanticsContext &semaCtx) {
|
|
return makeList(objects.v, makeObjectFn(semaCtx));
|
|
}
|
|
|
|
template <typename FuncTy, //
|
|
typename ArgTy, //
|
|
typename ResultTy = std::invoke_result_t<FuncTy, ArgTy>>
|
|
std::optional<ResultTy> maybeApply(FuncTy &&func,
|
|
const std::optional<ArgTy> &arg) {
|
|
if (!arg)
|
|
return std::nullopt;
|
|
return std::move(func(*arg));
|
|
}
|
|
|
|
std::optional<Object>
|
|
getBaseObject(const Object &object,
|
|
Fortran::semantics::SemanticsContext &semaCtx);
|
|
|
|
namespace clause {
|
|
using DefinedOperator = tomp::type::DefinedOperatorT<IdTy, ExprTy>;
|
|
using ProcedureDesignator = tomp::type::ProcedureDesignatorT<IdTy, ExprTy>;
|
|
using ReductionOperator = tomp::type::ReductionIdentifierT<IdTy, ExprTy>;
|
|
|
|
// "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 AcqRel = tomp::clause::AcqRelT<TypeTy, IdTy, ExprTy>;
|
|
using Acquire = tomp::clause::AcquireT<TypeTy, IdTy, ExprTy>;
|
|
using AdjustArgs = tomp::clause::AdjustArgsT<TypeTy, IdTy, ExprTy>;
|
|
using Affinity = tomp::clause::AffinityT<TypeTy, IdTy, ExprTy>;
|
|
using Aligned = tomp::clause::AlignedT<TypeTy, IdTy, ExprTy>;
|
|
using Align = tomp::clause::AlignT<TypeTy, IdTy, ExprTy>;
|
|
using Allocate = tomp::clause::AllocateT<TypeTy, IdTy, ExprTy>;
|
|
using Allocator = tomp::clause::AllocatorT<TypeTy, IdTy, ExprTy>;
|
|
using AppendArgs = tomp::clause::AppendArgsT<TypeTy, IdTy, ExprTy>;
|
|
using AtomicDefaultMemOrder =
|
|
tomp::clause::AtomicDefaultMemOrderT<TypeTy, IdTy, ExprTy>;
|
|
using At = tomp::clause::AtT<TypeTy, IdTy, ExprTy>;
|
|
using Bind = tomp::clause::BindT<TypeTy, IdTy, ExprTy>;
|
|
using Capture = tomp::clause::CaptureT<TypeTy, IdTy, ExprTy>;
|
|
using Collapse = tomp::clause::CollapseT<TypeTy, IdTy, ExprTy>;
|
|
using Compare = tomp::clause::CompareT<TypeTy, IdTy, ExprTy>;
|
|
using Copyin = tomp::clause::CopyinT<TypeTy, IdTy, ExprTy>;
|
|
using Copyprivate = tomp::clause::CopyprivateT<TypeTy, IdTy, ExprTy>;
|
|
using Defaultmap = tomp::clause::DefaultmapT<TypeTy, IdTy, ExprTy>;
|
|
using Default = tomp::clause::DefaultT<TypeTy, IdTy, ExprTy>;
|
|
using Depend = tomp::clause::DependT<TypeTy, IdTy, ExprTy>;
|
|
using Destroy = tomp::clause::DestroyT<TypeTy, IdTy, ExprTy>;
|
|
using Detach = tomp::clause::DetachT<TypeTy, IdTy, ExprTy>;
|
|
using Device = tomp::clause::DeviceT<TypeTy, IdTy, ExprTy>;
|
|
using DeviceType = tomp::clause::DeviceTypeT<TypeTy, IdTy, ExprTy>;
|
|
using DistSchedule = tomp::clause::DistScheduleT<TypeTy, IdTy, ExprTy>;
|
|
using Doacross = tomp::clause::DoacrossT<TypeTy, IdTy, ExprTy>;
|
|
using DynamicAllocators =
|
|
tomp::clause::DynamicAllocatorsT<TypeTy, IdTy, ExprTy>;
|
|
using Enter = tomp::clause::EnterT<TypeTy, IdTy, ExprTy>;
|
|
using Exclusive = tomp::clause::ExclusiveT<TypeTy, IdTy, ExprTy>;
|
|
using Fail = tomp::clause::FailT<TypeTy, IdTy, ExprTy>;
|
|
using Filter = tomp::clause::FilterT<TypeTy, IdTy, ExprTy>;
|
|
using Final = tomp::clause::FinalT<TypeTy, IdTy, ExprTy>;
|
|
using Firstprivate = tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>;
|
|
using From = tomp::clause::FromT<TypeTy, IdTy, ExprTy>;
|
|
using Full = tomp::clause::FullT<TypeTy, IdTy, ExprTy>;
|
|
using Grainsize = tomp::clause::GrainsizeT<TypeTy, IdTy, ExprTy>;
|
|
using HasDeviceAddr = tomp::clause::HasDeviceAddrT<TypeTy, IdTy, ExprTy>;
|
|
using Hint = tomp::clause::HintT<TypeTy, IdTy, ExprTy>;
|
|
using If = tomp::clause::IfT<TypeTy, IdTy, ExprTy>;
|
|
using Inbranch = tomp::clause::InbranchT<TypeTy, IdTy, ExprTy>;
|
|
using Inclusive = tomp::clause::InclusiveT<TypeTy, IdTy, ExprTy>;
|
|
using Indirect = tomp::clause::IndirectT<TypeTy, IdTy, ExprTy>;
|
|
using Init = tomp::clause::InitT<TypeTy, IdTy, ExprTy>;
|
|
using InReduction = tomp::clause::InReductionT<TypeTy, IdTy, ExprTy>;
|
|
using IsDevicePtr = tomp::clause::IsDevicePtrT<TypeTy, IdTy, ExprTy>;
|
|
using Lastprivate = tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy>;
|
|
using Linear = tomp::clause::LinearT<TypeTy, IdTy, ExprTy>;
|
|
using Link = tomp::clause::LinkT<TypeTy, IdTy, ExprTy>;
|
|
using Map = tomp::clause::MapT<TypeTy, IdTy, ExprTy>;
|
|
using Match = tomp::clause::MatchT<TypeTy, IdTy, ExprTy>;
|
|
using Mergeable = tomp::clause::MergeableT<TypeTy, IdTy, ExprTy>;
|
|
using Message = tomp::clause::MessageT<TypeTy, IdTy, ExprTy>;
|
|
using Nocontext = tomp::clause::NocontextT<TypeTy, IdTy, ExprTy>;
|
|
using Nogroup = tomp::clause::NogroupT<TypeTy, IdTy, ExprTy>;
|
|
using Nontemporal = tomp::clause::NontemporalT<TypeTy, IdTy, ExprTy>;
|
|
using Notinbranch = tomp::clause::NotinbranchT<TypeTy, IdTy, ExprTy>;
|
|
using Novariants = tomp::clause::NovariantsT<TypeTy, IdTy, ExprTy>;
|
|
using Nowait = tomp::clause::NowaitT<TypeTy, IdTy, ExprTy>;
|
|
using NumTasks = tomp::clause::NumTasksT<TypeTy, IdTy, ExprTy>;
|
|
using NumTeams = tomp::clause::NumTeamsT<TypeTy, IdTy, ExprTy>;
|
|
using NumThreads = tomp::clause::NumThreadsT<TypeTy, IdTy, ExprTy>;
|
|
using OmpxAttribute = tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy>;
|
|
using OmpxBare = tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy>;
|
|
using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT<TypeTy, IdTy, ExprTy>;
|
|
using Ordered = tomp::clause::OrderedT<TypeTy, IdTy, ExprTy>;
|
|
using Order = tomp::clause::OrderT<TypeTy, IdTy, ExprTy>;
|
|
using Partial = tomp::clause::PartialT<TypeTy, IdTy, ExprTy>;
|
|
using Priority = tomp::clause::PriorityT<TypeTy, IdTy, ExprTy>;
|
|
using Private = tomp::clause::PrivateT<TypeTy, IdTy, ExprTy>;
|
|
using ProcBind = tomp::clause::ProcBindT<TypeTy, IdTy, ExprTy>;
|
|
using Read = tomp::clause::ReadT<TypeTy, IdTy, ExprTy>;
|
|
using Reduction = tomp::clause::ReductionT<TypeTy, IdTy, ExprTy>;
|
|
using Relaxed = tomp::clause::RelaxedT<TypeTy, IdTy, ExprTy>;
|
|
using Release = tomp::clause::ReleaseT<TypeTy, IdTy, ExprTy>;
|
|
using ReverseOffload = tomp::clause::ReverseOffloadT<TypeTy, IdTy, ExprTy>;
|
|
using Safelen = tomp::clause::SafelenT<TypeTy, IdTy, ExprTy>;
|
|
using Schedule = tomp::clause::ScheduleT<TypeTy, IdTy, ExprTy>;
|
|
using SeqCst = tomp::clause::SeqCstT<TypeTy, IdTy, ExprTy>;
|
|
using Severity = tomp::clause::SeverityT<TypeTy, IdTy, ExprTy>;
|
|
using Shared = tomp::clause::SharedT<TypeTy, IdTy, ExprTy>;
|
|
using Simdlen = tomp::clause::SimdlenT<TypeTy, IdTy, ExprTy>;
|
|
using Simd = tomp::clause::SimdT<TypeTy, IdTy, ExprTy>;
|
|
using Sizes = tomp::clause::SizesT<TypeTy, IdTy, ExprTy>;
|
|
using TaskReduction = tomp::clause::TaskReductionT<TypeTy, IdTy, ExprTy>;
|
|
using ThreadLimit = tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy>;
|
|
using Threads = tomp::clause::ThreadsT<TypeTy, IdTy, ExprTy>;
|
|
using To = tomp::clause::ToT<TypeTy, IdTy, ExprTy>;
|
|
using UnifiedAddress = tomp::clause::UnifiedAddressT<TypeTy, IdTy, ExprTy>;
|
|
using UnifiedSharedMemory =
|
|
tomp::clause::UnifiedSharedMemoryT<TypeTy, IdTy, ExprTy>;
|
|
using Uniform = tomp::clause::UniformT<TypeTy, IdTy, ExprTy>;
|
|
using Unknown = tomp::clause::UnknownT<TypeTy, IdTy, ExprTy>;
|
|
using Untied = tomp::clause::UntiedT<TypeTy, IdTy, ExprTy>;
|
|
using Update = tomp::clause::UpdateT<TypeTy, IdTy, ExprTy>;
|
|
using UseDeviceAddr = tomp::clause::UseDeviceAddrT<TypeTy, IdTy, ExprTy>;
|
|
using UseDevicePtr = tomp::clause::UseDevicePtrT<TypeTy, IdTy, ExprTy>;
|
|
using UsesAllocators = tomp::clause::UsesAllocatorsT<TypeTy, IdTy, ExprTy>;
|
|
using Use = tomp::clause::UseT<TypeTy, IdTy, ExprTy>;
|
|
using Weak = tomp::clause::WeakT<TypeTy, IdTy, ExprTy>;
|
|
using When = tomp::clause::WhenT<TypeTy, IdTy, ExprTy>;
|
|
using Write = tomp::clause::WriteT<TypeTy, IdTy, ExprTy>;
|
|
} // namespace clause
|
|
|
|
struct CancellationConstructType {
|
|
using EmptyTrait = std::true_type;
|
|
};
|
|
struct Depobj {
|
|
using EmptyTrait = std::true_type;
|
|
};
|
|
struct Flush {
|
|
using EmptyTrait = std::true_type;
|
|
};
|
|
struct MemoryOrder {
|
|
using EmptyTrait = std::true_type;
|
|
};
|
|
struct Threadprivate {
|
|
using EmptyTrait = std::true_type;
|
|
};
|
|
|
|
using ClauseBase = tomp::ClauseT<TypeTy, IdTy, ExprTy,
|
|
// Extras...
|
|
CancellationConstructType, Depobj, Flush,
|
|
MemoryOrder, Threadprivate>;
|
|
|
|
struct Clause : public ClauseBase {
|
|
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> makeClauses(const parser::OmpClauseList &clauses,
|
|
semantics::SemanticsContext &semaCtx);
|
|
} // namespace Fortran::lower::omp
|
|
|
|
#endif // FORTRAN_LOWER_OPENMP_CLAUSES_H
|