xref: /llvm-project/mlir/tools/mlir-tblgen/DirectiveCommonGen.cpp (revision e813750354bbc08551cf23ff559a54b4a9ea1f29)
10bd9a136SValentin Clement //===========- DirectiveCommonGen.cpp - Directive common info generator -=====//
20bd9a136SValentin Clement //
30bd9a136SValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40bd9a136SValentin Clement // See https://llvm.org/LICENSE.txt for license information.
50bd9a136SValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60bd9a136SValentin Clement //
70bd9a136SValentin Clement //===----------------------------------------------------------------------===//
80bd9a136SValentin Clement //
90bd9a136SValentin Clement // OpenMPCommonGen generates utility information from the single OpenMP source
100bd9a136SValentin Clement // of truth in llvm/lib/Frontend/OpenMP.
110bd9a136SValentin Clement //
120bd9a136SValentin Clement //===----------------------------------------------------------------------===//
130bd9a136SValentin Clement 
140bd9a136SValentin Clement #include "mlir/TableGen/GenInfo.h"
150bd9a136SValentin Clement 
160bd9a136SValentin Clement #include "llvm/ADT/Twine.h"
17aae51255SMogball #include "llvm/Support/CommandLine.h"
180bd9a136SValentin Clement #include "llvm/Support/raw_ostream.h"
190bd9a136SValentin Clement #include "llvm/TableGen/DirectiveEmitter.h"
20aae51255SMogball #include "llvm/TableGen/Error.h"
210bd9a136SValentin Clement #include "llvm/TableGen/Record.h"
220bd9a136SValentin Clement 
230bd9a136SValentin Clement using llvm::Clause;
240bd9a136SValentin Clement using llvm::ClauseVal;
250bd9a136SValentin Clement using llvm::raw_ostream;
26b60c6cbcSRahul Joshi using llvm::Record;
270bd9a136SValentin Clement using llvm::RecordKeeper;
280bd9a136SValentin Clement 
290bd9a136SValentin Clement // LLVM has multiple places (Clang, Flang, MLIR) where information about
300bd9a136SValentin Clement // the directives (OpenMP/OpenACC), and clauses are needed. It is good software
310bd9a136SValentin Clement // engineering to keep the common information in a single place to avoid
320bd9a136SValentin Clement // duplication, reduce engineering effort and prevent mistakes.
330bd9a136SValentin Clement // Currently that common place is llvm/include/llvm/Frontend/OpenMP/OMP.td for
340bd9a136SValentin Clement // OpenMP and llvm/include/llvm/Frontend/OpenACC/ACC.td for OpenACC.
350bd9a136SValentin Clement // We plan to use this tablegen source to generate all the required
360bd9a136SValentin Clement // declarations, functions etc.
370bd9a136SValentin Clement //
380bd9a136SValentin Clement // Some OpenMP/OpenACC clauses accept only a fixed set of values as inputs.
3960e34f8dSMogball // These can be represented as a Enum Attributes (EnumAttrDef) in MLIR
400bd9a136SValentin Clement // ODS. The emitDecls function below currently generates these enumerations. The
410bd9a136SValentin Clement // name of the enumeration is specified in the enumClauseValue field of
420bd9a136SValentin Clement // Clause record in OMP.td. This name can be used to specify the type of the
430bd9a136SValentin Clement // OpenMP operation's operand. The allowedClauseValues field provides the list
440bd9a136SValentin Clement // of ClauseValues which are part of the enumeration.
45*e8137503SRahul Joshi static bool emitDecls(const RecordKeeper &records, llvm::StringRef dialect,
46aae51255SMogball                       raw_ostream &os) {
47aae51255SMogball   // A dialect must be selected for the generated attributes.
48aae51255SMogball   if (dialect.empty()) {
49aae51255SMogball     llvm::PrintFatalError("a dialect must be selected for the directives via "
50aae51255SMogball                           "'--directives-dialect'");
51aae51255SMogball   }
52aae51255SMogball 
53b60c6cbcSRahul Joshi   const auto directiveLanguages =
54*e8137503SRahul Joshi       records.getAllDerivedDefinitions("DirectiveLanguage");
555a1f6077SMehdi Amini   assert(!directiveLanguages.empty() && "DirectiveLanguage missing.");
560bd9a136SValentin Clement 
57*e8137503SRahul Joshi   for (const Clause c : records.getAllDerivedDefinitions("Clause")) {
580bd9a136SValentin Clement     const auto &clauseVals = c.getClauseVals();
595a1f6077SMehdi Amini     if (clauseVals.empty())
600bd9a136SValentin Clement       continue;
610bd9a136SValentin Clement 
620bd9a136SValentin Clement     const auto enumName = c.getEnumName();
635a1f6077SMehdi Amini     assert(!enumName.empty() && "enumClauseValue field not set.");
640bd9a136SValentin Clement 
650bd9a136SValentin Clement     std::vector<std::string> cvDefs;
66aae51255SMogball     for (const auto &it : llvm::enumerate(clauseVals)) {
67fcb5905eSRahul Joshi       const ClauseVal cval{it.value()};
680bd9a136SValentin Clement       if (!cval.isUserVisible())
690bd9a136SValentin Clement         continue;
700bd9a136SValentin Clement 
717c385c4bSShraiysh Vaishay       std::string name = cval.getFormattedName();
727c385c4bSShraiysh Vaishay       std::string enumValName(name.length(), ' ');
73fcb5905eSRahul Joshi       llvm::transform(name, enumValName.begin(), llvm::toLower);
747c385c4bSShraiysh Vaishay       enumValName[0] = llvm::toUpper(enumValName[0]);
750bd9a136SValentin Clement       std::string cvDef{(enumName + llvm::Twine(name)).str()};
767c385c4bSShraiysh Vaishay       os << "def " << cvDef << " : I32EnumAttrCase<\"" << enumValName << "\", "
777c385c4bSShraiysh Vaishay          << it.index() << ", \"" << name << "\">;\n";
780bd9a136SValentin Clement       cvDefs.push_back(cvDef);
790bd9a136SValentin Clement     }
800bd9a136SValentin Clement 
81aae51255SMogball     os << "def " << enumName << ": I32EnumAttr<\n";
820bd9a136SValentin Clement     os << "  \"Clause" << enumName << "\",\n";
830bd9a136SValentin Clement     os << "  \"" << enumName << " Clause\",\n";
840bd9a136SValentin Clement     os << "  [";
85fcb5905eSRahul Joshi     llvm::interleaveComma(cvDefs, os);
860bd9a136SValentin Clement     os << "]> {\n";
870bd9a136SValentin Clement     os << "    let cppNamespace = \"::mlir::"
880bd9a136SValentin Clement        << directiveLanguages[0]->getValueAsString("cppNamespace") << "\";\n";
89aae51255SMogball     os << "    let genSpecializedAttr = 0;\n";
900bd9a136SValentin Clement     os << "}\n";
91aae51255SMogball     llvm::SmallString<16> mnemonic;
92aae51255SMogball     llvm::transform(enumName, std::back_inserter(mnemonic), llvm::toLower);
93aae51255SMogball     os << "def " << enumName << "Attr : EnumAttr<" << dialect << "_Dialect, "
94aae51255SMogball        << enumName << ", \"" << mnemonic << "\">;\n";
950bd9a136SValentin Clement   }
960bd9a136SValentin Clement   return false;
970bd9a136SValentin Clement }
980bd9a136SValentin Clement 
99aae51255SMogball static llvm::cl::OptionCategory
100aae51255SMogball     directiveGenCat("Options for gen-directive-decl");
101aae51255SMogball static llvm::cl::opt<std::string>
102aae51255SMogball     dialect("directives-dialect",
103aae51255SMogball             llvm::cl::desc("Generate directives for this dialect"),
104aae51255SMogball             llvm::cl::cat(directiveGenCat), llvm::cl::CommaSeparated);
105aae51255SMogball 
1060bd9a136SValentin Clement // Registers the generator to mlir-tblgen.
1070bd9a136SValentin Clement static mlir::GenRegistration genDirectiveDecls(
1080bd9a136SValentin Clement     "gen-directive-decl",
1090bd9a136SValentin Clement     "Generate declarations for directives (OpenMP/OpenACC etc.)",
1100bd9a136SValentin Clement     [](const RecordKeeper &records, raw_ostream &os) {
111aae51255SMogball       return emitDecls(records, dialect, os);
1120bd9a136SValentin Clement     });
113