//===========- OpenMPCommonGen.cpp - OpenMP common info generator -===========// // // 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" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/DirectiveEmitter.h" #include "llvm/TableGen/Record.h" using llvm::Clause; using llvm::ClauseVal; using llvm::raw_ostream; using llvm::RecordKeeper; using llvm::Twine; // LLVM has multiple places (Clang, Flang, MLIR) where information about // the OpenMP directives, and clauses are needed. It is good software // engineering to keep the common information in a single place to avoid // duplication, reduce engineering effort and prevent mistakes. // Currently that common place is llvm/include/llvm/Frontend/OpenMP/OMP.td. // We plan to use this tablegen source to generate all the required // declarations, functions etc. // // Some OpenMP clauses accept only a fixed set of values as inputs. These // can be represented as a String Enum Attribute (StrEnumAttr) in MLIR ODS. // The emitDecls function below currently generates these enumerations. The // 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. static bool emitDecls(const RecordKeeper &recordKeeper, raw_ostream &os) { const auto &clauses = recordKeeper.getAllDerivedDefinitions("Clause"); for (const auto &r : clauses) { Clause c{r}; const auto &clauseVals = c.getClauseVals(); if (clauseVals.size() <= 0) continue; const auto enumName = c.getEnumName(); assert(enumName.size() != 0 && "enumClauseValue field not set."); std::vector cvDefs; for (const auto &cv : clauseVals) { ClauseVal cval{cv}; if (!cval.isUserVisible()) continue; const auto name = cval.getFormattedName(); std::string cvDef{(enumName + llvm::Twine(name)).str()}; os << "def " << cvDef << " : StrEnumAttrCase<\"" << name << "\">;\n"; cvDefs.push_back(cvDef); } os << "def " << enumName << ": StrEnumAttr<\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::omp\";\n"; os << "}\n"; } return false; } // Registers the generator to mlir-tblgen. static mlir::GenRegistration genDirectiveDecls("gen-directive-decl", "Generate declarations for directives (OpenMP etc.)", [](const RecordKeeper &records, raw_ostream &os) { return emitDecls(records, os); });