#include "mlir/TableGen/GenInfo.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/DirectiveEmitter.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
using llvm::Clause;
using llvm::ClauseVal;
using llvm::raw_ostream;
using llvm::RecordKeeper;
static bool emitDecls(const RecordKeeper &recordKeeper, llvm::StringRef dialect,
raw_ostream &os) {
if (dialect.empty()) {
llvm::PrintFatalError("a dialect must be selected for the directives via "
"'--directives-dialect'");
}
const auto &directiveLanguages =
recordKeeper.getAllDerivedDefinitions("DirectiveLanguage");
assert(!directiveLanguages.empty() && "DirectiveLanguage missing.");
const auto &clauses = recordKeeper.getAllDerivedDefinitions("Clause");
for (const auto &r : clauses) {
Clause c{r};
const auto &clauseVals = c.getClauseVals();
if (clauseVals.empty())
continue;
const auto enumName = c.getEnumName();
assert(!enumName.empty() && "enumClauseValue field not set.");
std::vector<std::string> cvDefs;
for (const auto &it : llvm::enumerate(clauseVals)) {
ClauseVal cval{it.value()};
if (!cval.isUserVisible())
continue;
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]);
std::string cvDef{(enumName + llvm::Twine(name)).str()};
os << "def " << cvDef << " : I32EnumAttrCase<\"" << enumValName << "\", "
<< it.index() << ", \"" << name << "\">;\n";
cvDefs.push_back(cvDef);
}
os << "def " << enumName << ": I32EnumAttr<\n";
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";
os << " let cppNamespace = \"::mlir::"
<< directiveLanguages[0]->getValueAsString("cppNamespace") << "\";\n";
os << " let genSpecializedAttr = 0;\n";
os << "}\n";
llvm::SmallString<16> mnemonic;
llvm::transform(enumName, std::back_inserter(mnemonic), llvm::toLower);
os << "def " << enumName << "Attr : EnumAttr<" << dialect << "_Dialect, "
<< enumName << ", \"" << mnemonic << "\">;\n";
}
return false;
}
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);
static mlir::GenRegistration genDirectiveDecls(
"gen-directive-decl",
"Generate declarations for directives (OpenMP/OpenACC etc.)",
[](const RecordKeeper &records, raw_ostream &os) {
return emitDecls(records, dialect, os);
});