brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · e1c8afb Raw
211 lines · cpp
1//===- MlirTranslateMain.cpp - MLIR Translation entry point ---------------===//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#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"10#include "mlir/IR/AsmState.h"11#include "mlir/Parser/Parser.h"12#include "mlir/Support/FileUtilities.h"13#include "mlir/Support/Timing.h"14#include "mlir/Support/ToolUtilities.h"15#include "mlir/Tools/mlir-translate/Translation.h"16#include "llvm/Support/InitLLVM.h"17#include "llvm/Support/SourceMgr.h"18#include "llvm/Support/ToolOutputFile.h"19 20using namespace mlir;21 22//===----------------------------------------------------------------------===//23// Diagnostic Filter24//===----------------------------------------------------------------------===//25 26namespace {27/// A scoped diagnostic handler that marks non-error diagnostics as handled. As28/// a result, the main diagnostic handler does not print non-error diagnostics.29class ErrorDiagnosticFilter : public ScopedDiagnosticHandler {30public:31  ErrorDiagnosticFilter(MLIRContext *ctx) : ScopedDiagnosticHandler(ctx) {32    setHandler([](Diagnostic &diag) {33      if (diag.getSeverity() != DiagnosticSeverity::Error)34        return success();35      return failure();36    });37  }38};39} // namespace40 41//===----------------------------------------------------------------------===//42// Translate Entry Point43//===----------------------------------------------------------------------===//44 45LogicalResult mlir::mlirTranslateMain(int argc, char **argv,46                                      llvm::StringRef toolName) {47 48  static llvm::cl::opt<std::string> inputFilename(49      llvm::cl::Positional, llvm::cl::desc("<input file>"),50      llvm::cl::init("-"));51 52  static llvm::cl::opt<std::string> outputFilename(53      "o", llvm::cl::desc("Output filename"), llvm::cl::value_desc("filename"),54      llvm::cl::init("-"));55 56  static llvm::cl::opt<bool> allowUnregisteredDialects(57      "allow-unregistered-dialect",58      llvm::cl::desc("Allow operation with no registered dialects (discouraged: testing only!)"),59      llvm::cl::init(false));60 61  static llvm::cl::opt<std::string> inputSplitMarker{62      "split-input-file", llvm::cl::ValueOptional,63      llvm::cl::callback([&](const std::string &str) {64        // Implicit value: use default marker if flag was used without value.65        if (str.empty())66          inputSplitMarker.setValue(kDefaultSplitMarker);67      }),68      llvm::cl::desc("Split the input file into chunks using the given or "69                     "default marker and process each chunk independently"),70      llvm::cl::init("")};71 72  static llvm::cl::opt<SourceMgrDiagnosticVerifierHandler::Level>73      verifyDiagnostics{74          "verify-diagnostics", llvm::cl::ValueOptional,75          llvm::cl::desc("Check that emitted diagnostics match expected-* "76                         "lines on the corresponding line"),77          llvm::cl::values(78              clEnumValN(79                  SourceMgrDiagnosticVerifierHandler::Level::All, "all",80                  "Check all diagnostics (expected, unexpected, near-misses)"),81              // Implicit value: when passed with no arguments, e.g.82              // `--verify-diagnostics` or `--verify-diagnostics=`.83              clEnumValN(84                  SourceMgrDiagnosticVerifierHandler::Level::All, "",85                  "Check all diagnostics (expected, unexpected, near-misses)"),86              clEnumValN(87                  SourceMgrDiagnosticVerifierHandler::Level::OnlyExpected,88                  "only-expected", "Check only expected diagnostics"))};89 90  static llvm::cl::opt<bool> errorDiagnosticsOnly(91      "error-diagnostics-only",92      llvm::cl::desc("Filter all non-error diagnostics "93                     "(discouraged: testing only!)"),94      llvm::cl::init(false));95 96  static llvm::cl::opt<std::string> outputSplitMarker(97      "output-split-marker",98      llvm::cl::desc("Split marker to use for merging the ouput"),99      llvm::cl::init(""));100 101  llvm::InitLLVM y(argc, argv);102 103  // Add flags for all the registered translations.104  llvm::cl::list<const Translation *, bool, TranslationParser>105      translationsRequested("", llvm::cl::desc("Translations to perform"),106                            llvm::cl::Required);107  registerAsmPrinterCLOptions();108  registerMLIRContextCLOptions();109  registerTranslationCLOptions();110  registerDefaultTimingManagerCLOptions();111  llvm::cl::ParseCommandLineOptions(argc, argv, toolName);112 113  // Initialize the timing manager.114  DefaultTimingManager tm;115  applyDefaultTimingManagerCLOptions(tm);116  TimingScope timing = tm.getRootScope();117 118  std::string errorMessage;119  std::unique_ptr<llvm::MemoryBuffer> input;120  if (auto inputAlignment = translationsRequested[0]->getInputAlignment())121    input = openInputFile(inputFilename, *inputAlignment, &errorMessage);122  else123    input = openInputFile(inputFilename, &errorMessage);124  if (!input) {125    llvm::errs() << errorMessage << "\n";126    return failure();127  }128 129  auto output = openOutputFile(outputFilename, &errorMessage);130  if (!output) {131    llvm::errs() << errorMessage << "\n";132    return failure();133  }134 135  // Processes the memory buffer with a new MLIRContext.136  auto processBuffer = [&](std::unique_ptr<llvm::MemoryBuffer> ownedBuffer,137                           raw_ostream &os) {138    // Many of the translations expect a null-terminated buffer while splitting139    // the buffer does not guarantee null-termination. Make a copy of the buffer140    // to ensure null-termination.141    if (!ownedBuffer->getBuffer().ends_with('\0')) {142      ownedBuffer = llvm::MemoryBuffer::getMemBufferCopy(143          ownedBuffer->getBuffer(), ownedBuffer->getBufferIdentifier());144    }145    // Temporary buffers for chained translation processing.146    std::string dataIn;147    std::string dataOut;148    LogicalResult result = LogicalResult::success();149 150    for (size_t i = 0, e = translationsRequested.size(); i < e; ++i) {151      llvm::raw_ostream *stream;152      llvm::raw_string_ostream dataStream(dataOut);153 154      if (i == e - 1) {155        // Output last translation to output.156        stream = &os;157      } else {158        // Output translation to temporary data buffer.159        stream = &dataStream;160      }161 162      const Translation *translationRequested = translationsRequested[i];163      TimingScope translationTiming =164          timing.nest(translationRequested->getDescription());165 166      MLIRContext context;167      context.allowUnregisteredDialects(allowUnregisteredDialects);168      context.printOpOnDiagnostic(verifyDiagnostics.getNumOccurrences() == 0);169      auto sourceMgr = std::make_shared<llvm::SourceMgr>();170      sourceMgr->AddNewSourceBuffer(std::move(ownedBuffer), SMLoc());171 172      if (verifyDiagnostics.getNumOccurrences()) {173        // In the diagnostic verification flow, we ignore whether the174        // translation failed (in most cases, it is expected to fail) and we do175        // not filter non-error diagnostics even if `errorDiagnosticsOnly` is176        // set. Instead, we check if the diagnostics were produced as expected.177        SourceMgrDiagnosticVerifierHandler sourceMgrHandler(178            *sourceMgr, &context, verifyDiagnostics);179        (void)(*translationRequested)(sourceMgr, os, &context);180        result = sourceMgrHandler.verify();181      } else if (errorDiagnosticsOnly) {182        SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context);183        ErrorDiagnosticFilter diagnosticFilter(&context);184        result = (*translationRequested)(sourceMgr, *stream, &context);185      } else {186        SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context);187        result = (*translationRequested)(sourceMgr, *stream, &context);188      }189      if (failed(result))190        return result;191 192      if (i < e - 1) {193        // If there are further translations, create a new buffer with the194        // output data.195        dataIn = dataOut;196        dataOut.clear();197        ownedBuffer = llvm::MemoryBuffer::getMemBuffer(dataIn);198      }199    }200    return result;201  };202 203  if (failed(splitAndProcessBuffer(std::move(input), processBuffer,204                                   output->os(), inputSplitMarker,205                                   outputSplitMarker)))206    return failure();207 208  output->keep();209  return success();210}211