176 lines · cpp
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-exception6//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/Verifier.h"16#include "mlir/Parser/Parser.h"17#include "mlir/Tools/ParseUtilities.h"18#include "llvm/Support/ManagedStatic.h"19#include "llvm/Support/SourceMgr.h"20#include <optional>21 22using namespace mlir;23 24//===----------------------------------------------------------------------===//25// Translation CommandLine Options26//===----------------------------------------------------------------------===//27 28struct 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 35static llvm::ManagedStatic<TranslationOptions> clOptions;36 37void mlir::registerTranslationCLOptions() { *clOptions; }38 39//===----------------------------------------------------------------------===//40// Translation Registry41//===----------------------------------------------------------------------===//42 43/// Get the mutable static map between registered file-to-file MLIR44/// translations.45static llvm::StringMap<Translation> &getTranslationRegistry() {46 static llvm::StringMap<Translation> translationBundle;47 return translationBundle;48}49 50/// Register the given translation.51static void registerTranslation(StringRef name, StringRef description,52 std::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 63TranslateRegistration::TranslateRegistration(64 StringRef name, StringRef description, const TranslateFunction &function) {65 registerTranslation(name, description, /*inputAlignment=*/std::nullopt,66 function);67}68 69//===----------------------------------------------------------------------===//70// Translation to MLIR71//===----------------------------------------------------------------------===//72 73// Puts `function` into the to-MLIR translation registry unless there is already74// a function registered for the same name.75static void registerTranslateToMLIRFunction(76 StringRef name, StringRef description,77 const DialectRegistrationFunction &dialectRegistration,78 std::optional<llvm::Align> inputAlignment,79 const TranslateSourceMgrToMLIRFunction &function) {80 auto wrappedFn = [function, dialectRegistration](81 const std::shared_ptr<llvm::SourceMgr> &sourceMgr,82 raw_ostream &output, MLIRContext *context) {83 DialectRegistry registry;84 dialectRegistration(registry);85 context->appendDialectRegistry(registry);86 OwningOpRef<Operation *> op = function(sourceMgr, context);87 if (!op || failed(verify(*op)))88 return failure();89 op.get()->print(output);90 return success();91 };92 registerTranslation(name, description, inputAlignment, wrappedFn);93}94 95TranslateToMLIRRegistration::TranslateToMLIRRegistration(96 StringRef name, StringRef description,97 const TranslateSourceMgrToMLIRFunction &function,98 const DialectRegistrationFunction &dialectRegistration,99 std::optional<llvm::Align> inputAlignment) {100 registerTranslateToMLIRFunction(name, description, dialectRegistration,101 inputAlignment, function);102}103TranslateToMLIRRegistration::TranslateToMLIRRegistration(104 StringRef name, StringRef description,105 const TranslateRawSourceMgrToMLIRFunction &function,106 const DialectRegistrationFunction &dialectRegistration,107 std::optional<llvm::Align> inputAlignment) {108 registerTranslateToMLIRFunction(109 name, description, dialectRegistration, inputAlignment,110 [function](const std::shared_ptr<llvm::SourceMgr> &sourceMgr,111 MLIRContext *ctx) { return function(*sourceMgr, ctx); });112}113/// Wraps `function` with a lambda that extracts a StringRef from a source114/// manager and registers the wrapper lambda as a to-MLIR conversion.115TranslateToMLIRRegistration::TranslateToMLIRRegistration(116 StringRef name, StringRef description,117 const TranslateStringRefToMLIRFunction &function,118 const DialectRegistrationFunction &dialectRegistration,119 std::optional<llvm::Align> inputAlignment) {120 registerTranslateToMLIRFunction(121 name, description, dialectRegistration, inputAlignment,122 [function](const std::shared_ptr<llvm::SourceMgr> &sourceMgr,123 MLIRContext *ctx) {124 const llvm::MemoryBuffer *buffer =125 sourceMgr->getMemoryBuffer(sourceMgr->getMainFileID());126 return function(buffer->getBuffer(), ctx);127 });128}129 130//===----------------------------------------------------------------------===//131// Translation from MLIR132//===----------------------------------------------------------------------===//133 134TranslateFromMLIRRegistration::TranslateFromMLIRRegistration(135 StringRef name, StringRef description,136 const TranslateFromMLIRFunction &function,137 const DialectRegistrationFunction &dialectRegistration) {138 registerTranslation(139 name, description, /*inputAlignment=*/std::nullopt,140 [function,141 dialectRegistration](const std::shared_ptr<llvm::SourceMgr> &sourceMgr,142 raw_ostream &output, MLIRContext *context) {143 DialectRegistry registry;144 dialectRegistration(registry);145 context->appendDialectRegistry(registry);146 bool implicitModule =147 (!clOptions.isConstructed() || !clOptions->noImplicitModule);148 OwningOpRef<Operation *> op =149 parseSourceFileForTool(sourceMgr, context, implicitModule);150 if (!op || failed(verify(*op)))151 return failure();152 return function(op.get(), output);153 });154}155 156//===----------------------------------------------------------------------===//157// Translation Parser158//===----------------------------------------------------------------------===//159 160TranslationParser::TranslationParser(llvm::cl::Option &opt)161 : llvm::cl::parser<const Translation *>(opt) {162 for (const auto &kv : getTranslationRegistry())163 addLiteralOption(kv.first(), &kv.second, kv.second.getDescription());164}165 166void TranslationParser::printOptionInfo(const llvm::cl::Option &o,167 size_t globalWidth) const {168 TranslationParser *tp = const_cast<TranslationParser *>(this);169 llvm::array_pod_sort(tp->Values.begin(), tp->Values.end(),170 [](const TranslationParser::OptionInfo *lhs,171 const TranslationParser::OptionInfo *rhs) {172 return lhs->Name.compare(rhs->Name);173 });174 llvm::cl::parser<const Translation *>::printOptionInfo(o, globalWidth);175}176