blob: f303f29d0796b03e62288e5f9477d8f305cc63e8 [file] [edit]
//===-- OMPDescriptors.cpp - OpenMP descriptors ------------------- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file contains descriptors of OpenMP elements.
//
//===----------------------------------------------------------------------===//
#include "llvm/Frontend/OpenMP/OMPDescriptors.h"
#include <map>
// For unassociated directives the .inc file uses an "Unassociated" enum
// (since it's the name used in the OpenMP spec), while the existing enum
// (in OMP.h.inc) uses "None". Redefine the token "Unassociated" to "None"
// in this file to allow the reuse of the pre-existing enum.
#define Unassociated None
namespace llvm::omp {
const DescriptorMap<Clause, descriptor::Clause> &getClauseMap() {
static const DescriptorMap<Clause, descriptor::Clause> Map{
#define GEN_OMP_CLAUSE_DESCRIPTORS
#include "OMPDescriptors.inc"
#undef GEN_OMP_CLAUSE_DESCRIPTORS
};
return Map;
}
const DescriptorMap<ClauseSet, descriptor::ClauseSet> &getClauseSetMap() {
static const DescriptorMap<ClauseSet, descriptor::ClauseSet> Map{
#define GEN_OMP_CLAUSE_GROUP_DESCRIPTORS
#include "OMPDescriptors.inc"
#undef GEN_OMP_CLAUSE_GROUP_DESCRIPTORS
#define GEN_OMP_CLAUSE_SET_DESCRIPTORS
#include "OMPDescriptors.inc"
#undef GEN_OMP_CLAUSE_SET_DESCRIPTORS
};
return Map;
}
const DescriptorMap<Directive, descriptor::Directive> &getDirectiveMap() {
static const DescriptorMap<Directive, descriptor::Directive> Map{
#define GEN_OMP_DIRECTIVE_DESCRIPTORS
#include "OMPDescriptors.inc"
#undef GEN_OMP_DIRECTIVE_DESCRIPTORS
};
return Map;
}
const DescriptorMap<Modifier, descriptor::Modifier> &getModifierMap() {
static const DescriptorMap<Modifier, descriptor::Modifier> Map{
#define GEN_OMP_MODIFIER_DESCRIPTORS
#include "OMPDescriptors.inc"
#undef GEN_OMP_MODIFIER_DESCRIPTORS
};
return Map;
}
const DescriptorMap<ModifierSet, descriptor::ModifierSet> &getModifierSetMap() {
static const DescriptorMap<ModifierSet, descriptor::ModifierSet> Map{
#define GEN_OMP_MODIFIER_GROUP_DESCRIPTORS
#include "OMPDescriptors.inc"
#undef GEN_OMP_MODIFIER_GROUP_DESCRIPTORS
#define GEN_OMP_MODIFIER_SET_DESCRIPTORS
#include "OMPDescriptors.inc"
#undef GEN_OMP_MODIFIER_SET_DESCRIPTORS
};
return Map;
}
#define GET_THING_OR_EMPTY(Thing, Member) \
template <typename DetailsTy> \
static Thing get##Thing##OrEmpty(const DetailsTy &D, Version V) { \
V = std::max(V, Version(45)); \
if (auto Found = D.find(V); Found != D.end()) \
return Found->second.Member; \
return Thing{}; \
}
GET_THING_OR_EMPTY(Clauses, Cls)
GET_THING_OR_EMPTY(ClauseSets, ClsSets)
GET_THING_OR_EMPTY(Directives, Dirs)
GET_THING_OR_EMPTY(Modifiers, Mods)
GET_THING_OR_EMPTY(ModifierSets, ModSets)
GET_THING_OR_EMPTY(Properties, Props)
#undef GET_THING_OR_EMPTY
// Clause
Properties descriptor::Clause::getProperties(Version V) const {
return getPropertiesOrEmpty(Details, V);
}
Directives descriptor::Clause::getDirectives(Version V) const {
return getDirectivesOrEmpty(Details, V);
}
Modifiers descriptor::Clause::getModifiers(Version V) const {
return getModifiersOrEmpty(Details, V);
}
ModifierSets descriptor::Clause::getModifierSets(Version V) const {
return getModifierSetsOrEmpty(Details, V);
}
// ClauseSet
Properties descriptor::ClauseSet::getProperties(Version V) const {
return getPropertiesOrEmpty(Details, V);
}
Clauses descriptor::ClauseSet::getClauses(Version V) const {
return getClausesOrEmpty(Details, V);
}
Directives descriptor::ClauseSet::getDirectives(Version V) const {
return getDirectivesOrEmpty(Details, V);
}
// Directive
Properties descriptor::Directive::getProperties(Version V) const {
return getPropertiesOrEmpty(Details, V);
}
Association descriptor::Directive::getAssociation(Version V) const {
return Details.at(std::max(V, Version(45))).Assoc;
}
Category descriptor::Directive::getCategory(Version V) const {
return Details.at(std::max(V, Version(45))).Cat;
}
Clauses descriptor::Directive::getClauses(Version V) const {
return getClausesOrEmpty(Details, V);
}
ClauseSets descriptor::Directive::getClauseSets(Version V) const {
return getClauseSetsOrEmpty(Details, V);
}
// Modifier
Properties descriptor::Modifier::getProperties(Version V) const {
return getPropertiesOrEmpty(Details, V);
}
Clauses descriptor::Modifier::getClauses(Version V) const {
return getClausesOrEmpty(Details, V);
}
// ModifierSet
Properties descriptor::ModifierSet::getProperties(Version V) const {
return getPropertiesOrEmpty(Details, V);
}
Modifiers descriptor::ModifierSet::getModifiers(Version V) const {
return getModifiersOrEmpty(Details, V);
}
Clauses descriptor::ModifierSet::getClauses(Version V) const {
return getClausesOrEmpty(Details, V);
}
const descriptor::Clause &getDescriptor(Clause C) {
return getClauseMap().at(C);
}
const descriptor::ClauseSet &getDescriptor(ClauseSet S) {
return getClauseSetMap().at(S);
}
const descriptor::Directive &getDescriptor(Directive D) {
ArrayRef<llvm::omp::Directive> Leafs = llvm::omp::getLeafConstructsOrSelf(D);
if (Leafs.size() == 1)
return getDirectiveMap().at(Leafs[0]);
static std::map<Directive, descriptor::Directive> Compound;
if (auto F = Compound.find(D); F != Compound.end())
return F->second;
// Combine details from all leafs into a single map and create a descriptor
// from it.
using Details = descriptor::details::Directive;
using DetailsMap = descriptor::DetailsMap<Details>;
DetailsMap Det;
// The name of the descriptor will be the spelling from the latest supported
// version.
llvm::omp::Version MaxV(0);
for (llvm::omp::Directive L : Leafs) {
const auto &Desc{getDescriptor(L)};
for (auto &[V, T] : Desc.getDetails()) {
MaxV = std::max(MaxV, V); // Used for descriptor's name.
auto F = Det.insert({V, Details{}}).first;
// Compound directives do not have properties. Their semantics or
// restrictions need to be inferred from the properties of their
// constituents.
F->second.Spelling = getOpenMPDirectiveName(D, V);
// The category should be the same for all of them (i.e. executable),
// the association of the last one is the association of the whole
// directive. Since the leafs are ordered from the outermost to the
// innermost it is safe to simply overwrite the non-set members each
// time.
F->second.Assoc = T.Assoc;
F->second.Cat = T.Cat;
F->second.Cls |= T.Cls;
F->second.ClsSets |= T.ClsSets;
}
}
auto At =
Compound.try_emplace(D, getOpenMPDirectiveName(D, MaxV), std::move(Det));
return At.first->second;
}
const descriptor::Modifier &getDescriptor(Modifier M) {
return getModifierMap().at(M);
}
const descriptor::ModifierSet &getDescriptor(ModifierSet S) {
return getModifierSetMap().at(S);
}
Properties getProperties(Clause C, Version V) {
return getDescriptor(C).getProperties(std::max(V, Version(45)));
}
} // namespace llvm::omp
#undef Unassociated