mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
869d544267
Summary: As discussed previously when landing patch for OpenMP in Flang, the idea is to share common part of the OpenMP declaration between the different Frontend. While doing this it was thought that moving to tablegen instead of Macros will also give a cleaner and more powerful way of generating these declaration. This first part of a future series of patches is setting up the base .td file for DirectiveLanguage as well as the OpenMP version of it. The base file is meant to be used by other directive language such as OpenACC. In this first patch, the Directive and Clause enums are generated with tablegen instead of the macros on OMPConstants.h. The next pacth will extend this to other enum and move the Flang frontend to use it. Reviewers: jdoerfert, DavidTruby, fghanim, ABataev, jdenny, hfinkel, jhuber6, kiranchandramohan, kiranktp Reviewed By: jdoerfert, jdenny Subscribers: arphaman, martong, cfe-commits, mgorny, yaxunl, hiraditya, guansong, jfb, sstefan1, aaron.ballman, llvm-commits Tags: #llvm, #openmp, #clang Differential Revision: https://reviews.llvm.org/D81736
116 lines
4.1 KiB
C++
116 lines
4.1 KiB
C++
//===- DirectiveEmitter.cpp - Directive Language Emitter ------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// DirectiveEmitter uses the descriptions of directives and clauses to construct
|
|
// common code declarations to be used in Frontends.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/TableGen/Error.h"
|
|
#include "llvm/TableGen/Record.h"
|
|
#include "llvm/TableGen/TableGenBackend.h"
|
|
|
|
namespace llvm {
|
|
void EmitDirectivesEnums(RecordKeeper &Records, raw_ostream &OS) {
|
|
|
|
const auto &DirectiveLanguages =
|
|
Records.getAllDerivedDefinitions("DirectiveLanguage");
|
|
|
|
if (DirectiveLanguages.size() != 1) {
|
|
PrintError("A single definition of DirectiveLanguage is needed.");
|
|
return;
|
|
}
|
|
|
|
const auto &DirectiveLanguage = DirectiveLanguages[0];
|
|
StringRef languageName = DirectiveLanguage->getValueAsString("name");
|
|
StringRef DirectivePrefix =
|
|
DirectiveLanguage->getValueAsString("directivePrefix");
|
|
StringRef ClausePrefix = DirectiveLanguage->getValueAsString("clausePrefix");
|
|
StringRef CppNamespace = DirectiveLanguage->getValueAsString("cppNamespace");
|
|
bool MakeEnumAvailableInNamespace =
|
|
DirectiveLanguage->getValueAsBit("makeEnumAvailableInNamespace");
|
|
bool EnableBitmaskEnumInNamespace =
|
|
DirectiveLanguage->getValueAsBit("enableBitmaskEnumInNamespace");
|
|
|
|
OS << "#ifndef LLVM_" << languageName << "_INC\n";
|
|
OS << "#define LLVM_" << languageName << "_INC\n";
|
|
|
|
if (EnableBitmaskEnumInNamespace)
|
|
OS << "#include \"llvm/ADT/BitmaskEnum.h\"\n";
|
|
|
|
OS << "namespace llvm {\n";
|
|
|
|
// Open namespaces defined in the directive language
|
|
llvm::SmallVector<StringRef, 2> Namespaces;
|
|
llvm::SplitString(CppNamespace, Namespaces, "::");
|
|
for (auto Ns : Namespaces)
|
|
OS << "namespace " << Ns << " {\n";
|
|
|
|
if (EnableBitmaskEnumInNamespace)
|
|
OS << "LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n";
|
|
|
|
// Emit Directive enumeration
|
|
OS << "enum class Directive {\n";
|
|
const auto &Directives = Records.getAllDerivedDefinitions("Directive");
|
|
for (const auto &D : Directives) {
|
|
const auto Name = D->getValueAsString("name");
|
|
std::string N = Name.str();
|
|
std::replace(N.begin(), N.end(), ' ', '_');
|
|
OS << DirectivePrefix << N << ",\n";
|
|
}
|
|
OS << "};\n";
|
|
|
|
OS << "static constexpr std::size_t Directive_enumSize = "
|
|
<< Directives.size() << ";\n";
|
|
|
|
// Emit Clause enumeration
|
|
OS << "enum class Clause {\n";
|
|
const auto &Clauses = Records.getAllDerivedDefinitions("Clause");
|
|
for (const auto &C : Clauses) {
|
|
const auto Name = C->getValueAsString("name");
|
|
OS << ClausePrefix << Name << ",\n";
|
|
}
|
|
OS << "};\n";
|
|
|
|
OS << "static constexpr std::size_t Clause_enumSize = " << Clauses.size()
|
|
<< ";\n";
|
|
|
|
// Make the enum values available in the defined namespace. This allows us to
|
|
// write something like Enum_X if we have a `using namespace <CppNamespace>`.
|
|
// At the same time we do not loose the strong type guarantees of the enum
|
|
// class, that is we cannot pass an unsigned as Directive without an explicit
|
|
// cast.
|
|
if (MakeEnumAvailableInNamespace) {
|
|
for (const auto &D : Directives) {
|
|
const auto Name = D->getValueAsString("name");
|
|
std::string N = Name.str();
|
|
std::replace(N.begin(), N.end(), ' ', '_');
|
|
OS << "constexpr auto " << DirectivePrefix << N << " = " << CppNamespace
|
|
<< "::Directive::" << DirectivePrefix << N << ";\n";
|
|
}
|
|
|
|
for (const auto &C : Clauses) {
|
|
const auto Name = C->getValueAsString("name");
|
|
OS << "constexpr auto " << ClausePrefix << Name << " = " << CppNamespace
|
|
<< "::Clause::" << ClausePrefix << Name << ";\n";
|
|
}
|
|
}
|
|
|
|
// Closing namespaces
|
|
for (auto Ns : llvm::reverse(Namespaces))
|
|
OS << "} // namespace " << Ns << "\n";
|
|
|
|
OS << "} // namespace llvm\n";
|
|
|
|
OS << "#endif";
|
|
}
|
|
} // namespace llvm
|