1 //===- Translation.cpp - Translation registry -----------------------------===// 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 // Definitions of the translation registry. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "mlir/Tools/mlir-translate/Translation.h" 14 #include "mlir/IR/AsmState.h" 15 #include "mlir/IR/BuiltinOps.h" 16 #include "mlir/IR/Dialect.h" 17 #include "mlir/IR/Verifier.h" 18 #include "mlir/Parser/Parser.h" 19 #include "mlir/Tools/ParseUtilities.h" 20 #include "llvm/Support/SourceMgr.h" 21 22 using namespace mlir; 23 24 //===----------------------------------------------------------------------===// 25 // Translation CommandLine Options 26 //===----------------------------------------------------------------------===// 27 28 struct TranslationOptions { 29 llvm::cl::opt<bool> noImplicitModule{ 30 "no-implicit-module", 31 llvm::cl::desc("Disable the parsing of an implicit top-level module op"), 32 llvm::cl::init(false)}; 33 }; 34 35 static llvm::ManagedStatic<TranslationOptions> clOptions; 36 37 void mlir::registerTranslationCLOptions() { *clOptions; } 38 39 //===----------------------------------------------------------------------===// 40 // Translation Registry 41 //===----------------------------------------------------------------------===// 42 43 /// Get the mutable static map between registered file-to-file MLIR 44 /// translations. 45 static llvm::StringMap<Translation> &getTranslationRegistry() { 46 static llvm::StringMap<Translation> translationBundle; 47 return translationBundle; 48 } 49 50 /// Register the given translation. 51 static void registerTranslation(StringRef name, StringRef description, 52 Optional<llvm::Align> inputAlignment, 53 const TranslateFunction &function) { 54 auto ®istry = getTranslationRegistry(); 55 if (registry.count(name)) 56 llvm::report_fatal_error( 57 "Attempting to overwrite an existing <file-to-file> function"); 58 assert(function && 59 "Attempting to register an empty translate <file-to-file> function"); 60 registry[name] = Translation(function, description, inputAlignment); 61 } 62 63 TranslateRegistration::TranslateRegistration( 64 StringRef name, StringRef description, const TranslateFunction &function) { 65 registerTranslation(name, description, /*inputAlignment=*/std::nullopt, 66 function); 67 } 68 69 //===----------------------------------------------------------------------===// 70 // Translation to MLIR 71 //===----------------------------------------------------------------------===// 72 73 // Puts `function` into the to-MLIR translation registry unless there is already 74 // a function registered for the same name. 75 static void registerTranslateToMLIRFunction( 76 StringRef name, StringRef description, Optional<llvm::Align> inputAlignment, 77 const TranslateSourceMgrToMLIRFunction &function) { 78 auto wrappedFn = [function](llvm::SourceMgr &sourceMgr, raw_ostream &output, 79 MLIRContext *context) { 80 OwningOpRef<Operation *> op = function(sourceMgr, context); 81 if (!op || failed(verify(*op))) 82 return failure(); 83 op.get()->print(output); 84 return success(); 85 }; 86 registerTranslation(name, description, inputAlignment, wrappedFn); 87 } 88 89 TranslateToMLIRRegistration::TranslateToMLIRRegistration( 90 StringRef name, StringRef description, 91 const TranslateSourceMgrToMLIRFunction &function, 92 Optional<llvm::Align> inputAlignment) { 93 registerTranslateToMLIRFunction(name, description, inputAlignment, function); 94 } 95 /// Wraps `function` with a lambda that extracts a StringRef from a source 96 /// manager and registers the wrapper lambda as a to-MLIR conversion. 97 TranslateToMLIRRegistration::TranslateToMLIRRegistration( 98 StringRef name, StringRef description, 99 const TranslateStringRefToMLIRFunction &function, 100 Optional<llvm::Align> inputAlignment) { 101 registerTranslateToMLIRFunction( 102 name, description, inputAlignment, 103 [function](llvm::SourceMgr &sourceMgr, MLIRContext *ctx) { 104 const llvm::MemoryBuffer *buffer = 105 sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID()); 106 return function(buffer->getBuffer(), ctx); 107 }); 108 } 109 110 //===----------------------------------------------------------------------===// 111 // Translation from MLIR 112 //===----------------------------------------------------------------------===// 113 114 TranslateFromMLIRRegistration::TranslateFromMLIRRegistration( 115 StringRef name, StringRef description, 116 const TranslateFromMLIRFunction &function, 117 const std::function<void(DialectRegistry &)> &dialectRegistration) { 118 registerTranslation( 119 name, description, /*inputAlignment=*/std::nullopt, 120 [function, dialectRegistration](llvm::SourceMgr &sourceMgr, 121 raw_ostream &output, 122 MLIRContext *context) { 123 DialectRegistry registry; 124 dialectRegistration(registry); 125 context->appendDialectRegistry(registry); 126 bool implicitModule = 127 (!clOptions.isConstructed() || !clOptions->noImplicitModule); 128 OwningOpRef<Operation *> op = 129 parseSourceFileForTool(sourceMgr, context, implicitModule); 130 if (!op || failed(verify(*op))) 131 return failure(); 132 return function(op.get(), output); 133 }); 134 } 135 136 //===----------------------------------------------------------------------===// 137 // Translation Parser 138 //===----------------------------------------------------------------------===// 139 140 TranslationParser::TranslationParser(llvm::cl::Option &opt) 141 : llvm::cl::parser<const Translation *>(opt) { 142 for (const auto &kv : getTranslationRegistry()) 143 addLiteralOption(kv.first(), &kv.second, kv.second.getDescription()); 144 } 145 146 void TranslationParser::printOptionInfo(const llvm::cl::Option &o, 147 size_t globalWidth) const { 148 TranslationParser *tp = const_cast<TranslationParser *>(this); 149 llvm::array_pod_sort(tp->Values.begin(), tp->Values.end(), 150 [](const TranslationParser::OptionInfo *lhs, 151 const TranslationParser::OptionInfo *rhs) { 152 return lhs->Name.compare(rhs->Name); 153 }); 154 llvm::cl::parser<const Translation *>::printOptionInfo(o, globalWidth); 155 } 156