2021-01-12 22:42:25 +08:00
|
|
|
//===========- DirectiveCommonGen.cpp - Directive common info generator -=====//
|
2020-07-23 00:28:04 +08:00
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// OpenMPCommonGen generates utility information from the single OpenMP source
|
|
|
|
// of truth in llvm/lib/Frontend/OpenMP.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "mlir/TableGen/GenInfo.h"
|
|
|
|
|
|
|
|
#include "llvm/ADT/Twine.h"
|
2022-01-19 00:53:55 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2020-07-23 00:28:04 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "llvm/TableGen/DirectiveEmitter.h"
|
2022-01-19 00:53:55 +08:00
|
|
|
#include "llvm/TableGen/Error.h"
|
2020-07-23 00:28:04 +08:00
|
|
|
#include "llvm/TableGen/Record.h"
|
|
|
|
|
|
|
|
using llvm::Clause;
|
|
|
|
using llvm::ClauseVal;
|
|
|
|
using llvm::raw_ostream;
|
|
|
|
using llvm::RecordKeeper;
|
|
|
|
|
2020-08-15 05:54:29 +08:00
|
|
|
// LLVM has multiple places (Clang, Flang, MLIR) where information about
|
2021-01-12 22:42:25 +08:00
|
|
|
// the directives (OpenMP/OpenACC), and clauses are needed. It is good software
|
2020-08-15 05:54:29 +08:00
|
|
|
// engineering to keep the common information in a single place to avoid
|
|
|
|
// duplication, reduce engineering effort and prevent mistakes.
|
2021-01-12 22:42:25 +08:00
|
|
|
// Currently that common place is llvm/include/llvm/Frontend/OpenMP/OMP.td for
|
|
|
|
// OpenMP and llvm/include/llvm/Frontend/OpenACC/ACC.td for OpenACC.
|
2020-08-15 05:54:29 +08:00
|
|
|
// We plan to use this tablegen source to generate all the required
|
|
|
|
// declarations, functions etc.
|
|
|
|
//
|
2021-01-12 22:42:25 +08:00
|
|
|
// Some OpenMP/OpenACC clauses accept only a fixed set of values as inputs.
|
[mlir][ods] Remove StrEnumAttr
StrEnumAttr has been deprecated in favour of EnumAttr, a solution based on AttrDef (https://reviews.llvm.org/D115181). This patch removes StrEnumAttr, along with all the custom ODS logic required to handle it.
See https://discourse.llvm.org/t/psa-stop-using-strenumattr-do-use-enumattr/5710 on how to transition to EnumAttr. In short,
```
// Before
def MyEnumAttr : StrEnumAttr<"MyEnum", "", [
StrEnumAttrCase<"A">,
StrEnumAttrCase<"B">
]>;
// After (pick an integer enum of your choice)
def MyEnum : I32EnumAttr<"MyEnum", "", [
I32EnumAttrCase<"A", 0>,
I32EnumAttrCase<"B", 1>
]> {
// Don't generate a C++ class! We want to use the AttrDef
let genSpecializedAttr = 0;
}
// Define the AttrDef
def MyEnum : EnumAttr<MyDialect, MyEnum, "my_enum">;
```
Reviewed By: rriddle, jpienaar
Differential Revision: https://reviews.llvm.org/D120834
2022-03-03 02:00:05 +08:00
|
|
|
// These can be represented as a Enum Attributes (EnumAttrDef) in MLIR
|
2021-01-12 22:42:25 +08:00
|
|
|
// ODS. The emitDecls function below currently generates these enumerations. The
|
2020-08-15 05:54:29 +08:00
|
|
|
// name of the enumeration is specified in the enumClauseValue field of
|
|
|
|
// Clause record in OMP.td. This name can be used to specify the type of the
|
|
|
|
// OpenMP operation's operand. The allowedClauseValues field provides the list
|
|
|
|
// of ClauseValues which are part of the enumeration.
|
2022-01-19 00:53:55 +08:00
|
|
|
static bool emitDecls(const RecordKeeper &recordKeeper, llvm::StringRef dialect,
|
|
|
|
raw_ostream &os) {
|
|
|
|
// A dialect must be selected for the generated attributes.
|
|
|
|
if (dialect.empty()) {
|
|
|
|
llvm::PrintFatalError("a dialect must be selected for the directives via "
|
|
|
|
"'--directives-dialect'");
|
|
|
|
}
|
|
|
|
|
2021-01-12 22:42:25 +08:00
|
|
|
const auto &directiveLanguages =
|
|
|
|
recordKeeper.getAllDerivedDefinitions("DirectiveLanguage");
|
2022-01-02 09:55:30 +08:00
|
|
|
assert(!directiveLanguages.empty() && "DirectiveLanguage missing.");
|
2021-01-12 22:42:25 +08:00
|
|
|
|
2020-07-23 00:28:04 +08:00
|
|
|
const auto &clauses = recordKeeper.getAllDerivedDefinitions("Clause");
|
|
|
|
|
|
|
|
for (const auto &r : clauses) {
|
|
|
|
Clause c{r};
|
|
|
|
const auto &clauseVals = c.getClauseVals();
|
2022-01-02 09:55:30 +08:00
|
|
|
if (clauseVals.empty())
|
2020-07-23 00:28:04 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
const auto enumName = c.getEnumName();
|
2022-01-02 09:55:30 +08:00
|
|
|
assert(!enumName.empty() && "enumClauseValue field not set.");
|
2020-07-23 00:28:04 +08:00
|
|
|
|
|
|
|
std::vector<std::string> cvDefs;
|
2022-01-19 00:53:55 +08:00
|
|
|
for (const auto &it : llvm::enumerate(clauseVals)) {
|
|
|
|
ClauseVal cval{it.value()};
|
2020-07-23 00:28:04 +08:00
|
|
|
if (!cval.isUserVisible())
|
|
|
|
continue;
|
|
|
|
|
2022-03-09 17:33:17 +08:00
|
|
|
std::string name = cval.getFormattedName();
|
|
|
|
std::string enumValName(name.length(), ' ');
|
|
|
|
std::transform(name.begin(), name.end(), enumValName.begin(),
|
|
|
|
llvm::toLower);
|
|
|
|
enumValName[0] = llvm::toUpper(enumValName[0]);
|
2020-07-23 00:28:04 +08:00
|
|
|
std::string cvDef{(enumName + llvm::Twine(name)).str()};
|
2022-03-09 17:33:17 +08:00
|
|
|
os << "def " << cvDef << " : I32EnumAttrCase<\"" << enumValName << "\", "
|
|
|
|
<< it.index() << ", \"" << name << "\">;\n";
|
2020-07-23 00:28:04 +08:00
|
|
|
cvDefs.push_back(cvDef);
|
|
|
|
}
|
|
|
|
|
2022-01-19 00:53:55 +08:00
|
|
|
os << "def " << enumName << ": I32EnumAttr<\n";
|
2020-07-23 00:28:04 +08:00
|
|
|
os << " \"Clause" << enumName << "\",\n";
|
|
|
|
os << " \"" << enumName << " Clause\",\n";
|
|
|
|
os << " [";
|
|
|
|
for (unsigned int i = 0; i < cvDefs.size(); i++) {
|
|
|
|
os << cvDefs[i];
|
|
|
|
if (i != cvDefs.size() - 1)
|
|
|
|
os << ",";
|
|
|
|
}
|
|
|
|
os << "]> {\n";
|
2021-01-12 22:42:25 +08:00
|
|
|
os << " let cppNamespace = \"::mlir::"
|
|
|
|
<< directiveLanguages[0]->getValueAsString("cppNamespace") << "\";\n";
|
2022-01-19 00:53:55 +08:00
|
|
|
os << " let genSpecializedAttr = 0;\n";
|
2020-07-23 00:28:04 +08:00
|
|
|
os << "}\n";
|
2022-01-19 00:53:55 +08:00
|
|
|
llvm::SmallString<16> mnemonic;
|
|
|
|
llvm::transform(enumName, std::back_inserter(mnemonic), llvm::toLower);
|
|
|
|
os << "def " << enumName << "Attr : EnumAttr<" << dialect << "_Dialect, "
|
|
|
|
<< enumName << ", \"" << mnemonic << "\">;\n";
|
2020-07-23 00:28:04 +08:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-01-19 00:53:55 +08:00
|
|
|
static llvm::cl::OptionCategory
|
|
|
|
directiveGenCat("Options for gen-directive-decl");
|
|
|
|
static llvm::cl::opt<std::string>
|
|
|
|
dialect("directives-dialect",
|
|
|
|
llvm::cl::desc("Generate directives for this dialect"),
|
|
|
|
llvm::cl::cat(directiveGenCat), llvm::cl::CommaSeparated);
|
|
|
|
|
2020-07-23 00:28:04 +08:00
|
|
|
// Registers the generator to mlir-tblgen.
|
2021-01-12 22:42:25 +08:00
|
|
|
static mlir::GenRegistration genDirectiveDecls(
|
|
|
|
"gen-directive-decl",
|
|
|
|
"Generate declarations for directives (OpenMP/OpenACC etc.)",
|
|
|
|
[](const RecordKeeper &records, raw_ostream &os) {
|
2022-01-19 00:53:55 +08:00
|
|
|
return emitDecls(records, dialect, os);
|
2021-01-12 22:42:25 +08:00
|
|
|
});
|