1 //===========- DirectiveCommonGen.cpp - Directive common info generator -=====// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // OpenMPCommonGen generates utility information from the single OpenMP source 10 // of truth in llvm/lib/Frontend/OpenMP. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "mlir/TableGen/GenInfo.h" 15 16 #include "llvm/ADT/Twine.h" 17 #include "llvm/Support/raw_ostream.h" 18 #include "llvm/TableGen/DirectiveEmitter.h" 19 #include "llvm/TableGen/Record.h" 20 21 using llvm::Clause; 22 using llvm::ClauseVal; 23 using llvm::raw_ostream; 24 using llvm::RecordKeeper; 25 using llvm::Twine; 26 27 // LLVM has multiple places (Clang, Flang, MLIR) where information about 28 // the directives (OpenMP/OpenACC), and clauses are needed. It is good software 29 // engineering to keep the common information in a single place to avoid 30 // duplication, reduce engineering effort and prevent mistakes. 31 // Currently that common place is llvm/include/llvm/Frontend/OpenMP/OMP.td for 32 // OpenMP and llvm/include/llvm/Frontend/OpenACC/ACC.td for OpenACC. 33 // We plan to use this tablegen source to generate all the required 34 // declarations, functions etc. 35 // 36 // Some OpenMP/OpenACC clauses accept only a fixed set of values as inputs. 37 // These can be represented as a String Enum Attribute (StrEnumAttr) in MLIR 38 // ODS. The emitDecls function below currently generates these enumerations. The 39 // name of the enumeration is specified in the enumClauseValue field of 40 // Clause record in OMP.td. This name can be used to specify the type of the 41 // OpenMP operation's operand. The allowedClauseValues field provides the list 42 // of ClauseValues which are part of the enumeration. 43 static bool emitDecls(const RecordKeeper &recordKeeper, raw_ostream &os) { 44 const auto &directiveLanguages = 45 recordKeeper.getAllDerivedDefinitions("DirectiveLanguage"); 46 assert(directiveLanguages.size() != 0 && "DirectiveLanguage missing."); 47 48 const auto &clauses = recordKeeper.getAllDerivedDefinitions("Clause"); 49 50 for (const auto &r : clauses) { 51 Clause c{r}; 52 const auto &clauseVals = c.getClauseVals(); 53 if (clauseVals.size() <= 0) 54 continue; 55 56 const auto enumName = c.getEnumName(); 57 assert(enumName.size() != 0 && "enumClauseValue field not set."); 58 59 std::vector<std::string> cvDefs; 60 for (const auto &cv : clauseVals) { 61 ClauseVal cval{cv}; 62 if (!cval.isUserVisible()) 63 continue; 64 65 const auto name = cval.getFormattedName(); 66 std::string cvDef{(enumName + llvm::Twine(name)).str()}; 67 os << "def " << cvDef << " : StrEnumAttrCase<\"" << name << "\">;\n"; 68 cvDefs.push_back(cvDef); 69 } 70 71 os << "def " << enumName << ": StrEnumAttr<\n"; 72 os << " \"Clause" << enumName << "\",\n"; 73 os << " \"" << enumName << " Clause\",\n"; 74 os << " ["; 75 for (unsigned int i = 0; i < cvDefs.size(); i++) { 76 os << cvDefs[i]; 77 if (i != cvDefs.size() - 1) 78 os << ","; 79 } 80 os << "]> {\n"; 81 os << " let cppNamespace = \"::mlir::" 82 << directiveLanguages[0]->getValueAsString("cppNamespace") << "\";\n"; 83 os << "}\n"; 84 } 85 return false; 86 } 87 88 // Registers the generator to mlir-tblgen. 89 static mlir::GenRegistration genDirectiveDecls( 90 "gen-directive-decl", 91 "Generate declarations for directives (OpenMP/OpenACC etc.)", 92 [](const RecordKeeper &records, raw_ostream &os) { 93 return emitDecls(records, os); 94 }); 95