diff --git a/mlir/examples/standalone/CMakeLists.txt b/mlir/examples/standalone/CMakeLists.txt --- a/mlir/examples/standalone/CMakeLists.txt +++ b/mlir/examples/standalone/CMakeLists.txt @@ -44,3 +44,4 @@ add_subdirectory(lib) add_subdirectory(test) add_subdirectory(standalone-opt) +add_subdirectory(standalone-translate) diff --git a/mlir/examples/standalone/standalone-translate/CMakeLists.txt b/mlir/examples/standalone/standalone-translate/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/mlir/examples/standalone/standalone-translate/CMakeLists.txt @@ -0,0 +1,24 @@ +set(LLVM_LINK_COMPONENTS + Support + ) + +get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) +get_property(translation_libs GLOBAL PROPERTY MLIR_TRANSLATION_LIBS) + +add_llvm_tool(standalone-translate + standalone-translate.cpp + ) +llvm_update_compile_flags(standalone-translate) +target_link_libraries(standalone-translate + PRIVATE + ${dialect_libs} + ${translation_libs} + MLIRIR + MLIRParser + MLIRPass + MLIRSPIRV + MLIRTranslation + MLIRSupport + ) + +mlir_check_link_libraries(standalone-translate) diff --git a/mlir/examples/standalone/standalone-translate/standalone-translate.cpp b/mlir/examples/standalone/standalone-translate/standalone-translate.cpp new file mode 100644 --- /dev/null +++ b/mlir/examples/standalone/standalone-translate/standalone-translate.cpp @@ -0,0 +1,114 @@ +//===- standalone-translate.cpp ---------------------------------*- C++ -*-===// +// +// This file is licensed 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 +// +//===----------------------------------------------------------------------===// +// +// This is a command line utility that translates a file from/to MLIR using one +// of the registered translations. +// +//===----------------------------------------------------------------------===// + +#include "mlir/IR/AsmState.h" +#include "mlir/IR/Diagnostics.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/InitAllDialects.h" +#include "mlir/InitAllTranslations.h" +#include "mlir/Support/FileUtilities.h" +#include "mlir/Support/LogicalResult.h" +#include "mlir/Support/ToolUtilities.h" +#include "mlir/Translation.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/ToolOutputFile.h" + +#include "Standalone/StandaloneDialect.h" + +static llvm::cl::opt inputFilename(llvm::cl::Positional, + llvm::cl::desc(""), + llvm::cl::init("-")); + +static llvm::cl::opt + outputFilename("o", llvm::cl::desc("Output filename"), + llvm::cl::value_desc("filename"), llvm::cl::init("-")); + +static llvm::cl::opt + splitInputFile("split-input-file", + llvm::cl::desc("Split the input file into pieces and " + "process each chunk independently"), + llvm::cl::init(false)); + +static llvm::cl::opt verifyDiagnostics( + "verify-diagnostics", + llvm::cl::desc("Check that emitted diagnostics match " + "expected-* lines on the corresponding line"), + llvm::cl::init(false)); + +int main(int argc, char **argv) { + mlir::registerAllDialects(); + mlir::registerAllTranslations(); + + mlir::registerDialect(); + // TODO: Register standalone translations here. + + llvm::InitLLVM y(argc, argv); + + // Add flags for all the registered translations. + llvm::cl::opt + translationRequested("", llvm::cl::desc("Translation to perform"), + llvm::cl::Required); + mlir::registerAsmPrinterCLOptions(); + mlir::registerMLIRContextCLOptions(); + llvm::cl::ParseCommandLineOptions(argc, argv, "MLIR translation driver\n"); + + std::string errorMessage; + auto input = mlir::openInputFile(inputFilename, &errorMessage); + if (!input) { + llvm::errs() << errorMessage << "\n"; + return 1; + } + + auto output = mlir::openOutputFile(outputFilename, &errorMessage); + if (!output) { + llvm::errs() << errorMessage << "\n"; + return 1; + } + + // Processes the memory buffer with a new MLIRContext. + auto processBuffer = [&](std::unique_ptr ownedBuffer, + llvm::raw_ostream &os) { + mlir::MLIRContext context; + context.allowUnregisteredDialects(); + context.printOpOnDiagnostic(!verifyDiagnostics); + llvm::SourceMgr sourceMgr; + sourceMgr.AddNewSourceBuffer(std::move(ownedBuffer), llvm::SMLoc()); + + if (!verifyDiagnostics) { + mlir::SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, &context); + return (*translationRequested)(sourceMgr, os, &context); + } + + // In the diagnostic verification flow, we ignore whether the translation + // failed (in most cases, it is expected to fail). Instead, we check if the + // diagnostics were produced as expected. + mlir::SourceMgrDiagnosticVerifierHandler sourceMgrHandler(sourceMgr, + &context); + (*translationRequested)(sourceMgr, os, &context); + return sourceMgrHandler.verify(); + }; + + if (splitInputFile) { + if (failed(mlir::splitAndProcessBuffer(std::move(input), processBuffer, + output->os()))) + return 1; + } else { + if (failed(processBuffer(std::move(input), output->os()))) + return 1; + } + + output->keep(); + return 0; +}