#include "flang/Semantics/openmp-modifiers.h"
#include "flang/Parser/parse-tree.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Frontend/OpenMP/OMP.h"
#include <algorithm>
#include <cassert>
#include <map>
namespace Fortran::semantics {
using namespace llvm::omp;
template <typename ValueTy>
static unsigned findVersion(
unsigned version, const std::map<unsigned, ValueTy> &map) {
llvm::ArrayRef<unsigned> versions{llvm::omp::getOpenMPVersions()};
assert(!versions.empty() && "getOpenMPVersions returned empty list");
version = std::clamp(version, versions.front(), versions.back());
unsigned found{0};
for (auto &[v, _] : map) {
if (v <= version) {
found = v;
} else {
break;
}
}
if (found == 0) {
found = !map.empty() ? map.begin()->first : versions.front();
}
return found;
}
const OmpProperties &OmpModifierDescriptor::props(unsigned version) const {
return props_.at(findVersion(version, props_));
}
const OmpClauses &OmpModifierDescriptor::clauses(unsigned version) const {
return clauses_.at(findVersion(version, clauses_));
}
unsigned OmpModifierDescriptor::since(llvm::omp::Clause id) const {
unsigned found{[&]() {
for (auto &[v, cs] : clauses_) {
if (cs.test(id)) {
return v;
}
}
return ~0u;
}()};
return found <= 45 ? 0 : found;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAccessGroup>() {
static const OmpModifierDescriptor desc{
"access-group",
{
{61, {OmpProperty::Unique}},
},
{
{61, {Clause::OMPC_dyn_groupprivate}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlignment>() {
static const OmpModifierDescriptor desc{
"alignment",
{
{45, {OmpProperty::Unique, OmpProperty::Ultimate, OmpProperty::Post}},
},
{
{45, {Clause::OMPC_aligned}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlignModifier>() {
static const OmpModifierDescriptor desc{
"align-modifier",
{
{51, {OmpProperty::Unique}},
},
{
{51, {Clause::OMPC_allocate}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &
OmpGetDescriptor<parser::OmpAllocatorComplexModifier>() {
static const OmpModifierDescriptor desc{
"allocator-complex-modifier",
{
{51, {OmpProperty::Unique}},
},
{
{51, {Clause::OMPC_allocate}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &
OmpGetDescriptor<parser::OmpAllocatorSimpleModifier>() {
static const OmpModifierDescriptor desc{
"allocator-simple-modifier",
{
{50, {OmpProperty::Exclusive, OmpProperty::Unique}},
},
{
{50, {Clause::OMPC_allocate}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlwaysModifier>() {
static const OmpModifierDescriptor desc{
"always-modifier",
{
{45, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_map}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAttachModifier>() {
static const OmpModifierDescriptor desc{
"attach-modifier",
{
{61, {OmpProperty::Unique}},
},
{
{61, {Clause::OMPC_map}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAutomapModifier>() {
static const OmpModifierDescriptor desc{
"automap-modifier",
{
{60, {OmpProperty::Unique}},
},
{
{60, {Clause::OMPC_enter}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpChunkModifier>() {
static const OmpModifierDescriptor desc{
"chunk-modifier",
{
{45, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_schedule}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpCloseModifier>() {
static const OmpModifierDescriptor desc{
"close-modifier",
{
{50, {OmpProperty::Unique}},
},
{
{50, {Clause::OMPC_map}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpContextSelector>() {
static const OmpModifierDescriptor desc{
"context-selector",
{
{50, {OmpProperty::Required, OmpProperty::Unique}},
},
{
{50, {Clause::OMPC_when}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDeleteModifier>() {
static const OmpModifierDescriptor desc{
"delete-modifier",
{
{45, {OmpProperty::Unique, OmpProperty::Ultimate}},
{60, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_map}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDependenceType>() {
static const OmpModifierDescriptor desc{
"dependence-type",
{
{45, {OmpProperty::Required, OmpProperty::Ultimate}},
},
{
{45, {Clause::OMPC_depend}},
{51, {Clause::OMPC_depend, Clause::OMPC_update}},
{52, {Clause::OMPC_doacross}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDeviceModifier>() {
static const OmpModifierDescriptor desc{
"device-modifier",
{
{45, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_device}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &
OmpGetDescriptor<parser::OmpDirectiveNameModifier>() {
static const OmpModifierDescriptor desc{
"directive-name-modifier",
{
{45, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_if}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpExpectation>() {
static const OmpModifierDescriptor desc{
"expectation",
{
{51, {OmpProperty::Unique}},
},
{
{51, {Clause::OMPC_from, Clause::OMPC_to}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpFallbackModifier>() {
static const OmpModifierDescriptor desc{
"fallback-modifier",
{
{61, {OmpProperty::Unique}},
},
{
{61, {Clause::OMPC_dyn_groupprivate}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropPreference>() {
static const OmpModifierDescriptor desc{
"interop-preference",
{
{52, {OmpProperty::Unique}},
},
{
{52, {Clause::OMPC_init}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropType>() {
static const OmpModifierDescriptor desc{
"interop-type",
{
{52, {OmpProperty::Required}},
},
{
{52, {Clause::OMPC_init}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpIterator>() {
static const OmpModifierDescriptor desc{
"iterator",
{
{50, {OmpProperty::Unique}},
},
{
{50, {Clause::OMPC_affinity, Clause::OMPC_depend}},
{51,
{Clause::OMPC_affinity, Clause::OMPC_depend, Clause::OMPC_from,
Clause::OMPC_map, Clause::OMPC_to}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &
OmpGetDescriptor<parser::OmpLastprivateModifier>() {
static const OmpModifierDescriptor desc{
"lastprivate-modifier",
{
{50, {OmpProperty::Unique}},
},
{
{50, {Clause::OMPC_lastprivate}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>() {
static const OmpModifierDescriptor desc{
"linear-modifier",
{
{45, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_linear}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapper>() {
static const OmpModifierDescriptor desc{
"mapper",
{
{50, {OmpProperty::Unique}},
},
{
{50, {Clause::OMPC_from, Clause::OMPC_map, Clause::OMPC_to}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapType>() {
static const OmpModifierDescriptor desc{
"map-type",
{
{45, {OmpProperty::Ultimate}},
{60, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_map}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapTypeModifier>() {
static const OmpModifierDescriptor desc{
"map-type-modifier",
{
{45, {}},
},
{
{45, {Clause::OMPC_map}},
{60, {}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpOrderModifier>() {
static const OmpModifierDescriptor desc{
"order-modifier",
{
{51, {OmpProperty::Unique}},
},
{
{51, {Clause::OMPC_order}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpOrderingModifier>() {
static const OmpModifierDescriptor desc{
"ordering-modifier",
{
{45, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_schedule}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpPrescriptiveness>() {
static const OmpModifierDescriptor desc{
"prescriptiveness",
{
{51, {OmpProperty::Unique}},
},
{
{51, {Clause::OMPC_grainsize, Clause::OMPC_num_tasks}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpPresentModifier>() {
static const OmpModifierDescriptor desc{
"present-modifier",
{
{51, {OmpProperty::Unique}},
},
{
{51, {Clause::OMPC_map}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &
OmpGetDescriptor<parser::OmpReductionIdentifier>() {
static const OmpModifierDescriptor desc{
"reduction-identifier",
{
{45, {OmpProperty::Required, OmpProperty::Ultimate}},
},
{
{45, {Clause::OMPC_reduction}},
{50,
{Clause::OMPC_in_reduction, Clause::OMPC_reduction,
Clause::OMPC_task_reduction}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionModifier>() {
static const OmpModifierDescriptor desc{
"reduction-modifier",
{
{45, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_reduction}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpRefModifier>() {
static const OmpModifierDescriptor desc{
"ref-modifier",
{
{60, {OmpProperty::Unique}},
},
{
{60, {Clause::OMPC_map}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpSelfModifier>() {
static const OmpModifierDescriptor desc{
"self-modifier",
{
{60, {OmpProperty::Unique}},
},
{
{60, {Clause::OMPC_map}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &
OmpGetDescriptor<parser::OmpStepComplexModifier>() {
static const OmpModifierDescriptor desc{
"step-complex-modifier",
{
{52, {OmpProperty::Unique}},
},
{
{52, {Clause::OMPC_linear}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpStepSimpleModifier>() {
static const OmpModifierDescriptor desc{
"step-simple-modifier",
{
{45, {OmpProperty::Unique, OmpProperty::Exclusive}},
},
{
{45, {Clause::OMPC_linear}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpTaskDependenceType>() {
static const OmpModifierDescriptor desc{
"task-dependence-type",
{
{45, {OmpProperty::Required, OmpProperty::Ultimate}},
},
{
{45, {Clause::OMPC_depend}},
{51, {Clause::OMPC_depend, Clause::OMPC_update}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpVariableCategory>() {
static const OmpModifierDescriptor desc{
"variable-category",
{
{45, {OmpProperty::Required, OmpProperty::Unique}},
{50, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_defaultmap}},
},
};
return desc;
}
template <>
const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpxHoldModifier>() {
static const OmpModifierDescriptor desc{
"ompx-hold-modifier",
{
{45, {OmpProperty::Unique}},
},
{
{45, {Clause::OMPC_map}},
},
};
return desc;
}
}