144 lines · cpp
1//===- mlir-irdl-to-cpp.cpp - IRDL to C++ conversion tool -----------------===//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// This is a command line utility that translates an IRDL dialect definition10// into a C++ implementation to be included in MLIR.11//12//===----------------------------------------------------------------------===//13 14#include "mlir/Dialect/IRDL/IR/IRDL.h"15#include "mlir/IR/AsmState.h"16#include "mlir/IR/DialectRegistry.h"17#include "mlir/IR/MLIRContext.h"18#include "mlir/Support/FileUtilities.h"19#include "mlir/Support/ToolUtilities.h"20#include "mlir/Target/IRDLToCpp/IRDLToCpp.h"21#include "mlir/Tools/ParseUtilities.h"22#include "llvm/Support/Casting.h"23#include "llvm/Support/CommandLine.h"24#include "llvm/Support/InitLLVM.h"25#include "llvm/Support/MemoryBuffer.h"26#include "llvm/Support/SourceMgr.h"27#include "llvm/Support/ToolOutputFile.h"28 29using namespace mlir;30 31static LogicalResult32processBuffer(llvm::raw_ostream &os,33 std::unique_ptr<llvm::MemoryBuffer> ownedBuffer,34 bool verifyDiagnostics, llvm::ThreadPoolInterface *threadPool) {35 // Tell sourceMgr about this buffer, which is what the parser will pick up.36 auto sourceMgr = std::make_shared<llvm::SourceMgr>();37 sourceMgr->AddNewSourceBuffer(std::move(ownedBuffer), SMLoc());38 39 DialectRegistry registry;40 registry.insert<irdl::IRDLDialect>();41 MLIRContext ctx(registry);42 43 ctx.printOpOnDiagnostic(!verifyDiagnostics);44 45 auto runTranslation = [&]() {46 ParserConfig parseConfig(&ctx);47 OwningOpRef<Operation *> op =48 parseSourceFileForTool(sourceMgr, parseConfig, true);49 if (!op)50 return failure();51 52 auto moduleOp = llvm::cast<ModuleOp>(*op);53 llvm::SmallVector<irdl::DialectOp> dialects{54 moduleOp.getOps<irdl::DialectOp>(),55 };56 57 return irdl::translateIRDLDialectToCpp(dialects, os);58 };59 60 if (!verifyDiagnostics) {61 // If no errors are expected, return translation result.62 SourceMgrDiagnosticHandler srcManagerHandler(*sourceMgr, &ctx);63 return runTranslation();64 }65 66 // If errors are expected, ignore translation result and check for67 // diagnostics.68 SourceMgrDiagnosticVerifierHandler srcManagerHandler(*sourceMgr, &ctx);69 (void)runTranslation();70 return srcManagerHandler.verify();71}72 73static LogicalResult translateIRDLToCpp(int argc, char **argv) {74 static llvm::cl::opt<std::string> inputFilename(75 llvm::cl::Positional, llvm::cl::desc("<input file>"),76 llvm::cl::init("-"));77 78 static llvm::cl::opt<std::string> outputFilename(79 "o", llvm::cl::desc("Output filename"), llvm::cl::value_desc("filename"),80 llvm::cl::init("-"));81 82 static llvm::cl::opt<bool> verifyDiagnostics(83 "verify-diagnostics",84 llvm::cl::desc("Check that emitted diagnostics match "85 "expected-* lines on the corresponding line"),86 llvm::cl::init(false));87 88 static llvm::cl::opt<std::string> splitInputFile(89 "split-input-file", llvm::cl::ValueOptional,90 llvm::cl::callback([&](const std::string &str) {91 // Implicit value: use default marker if flag was used without92 // value.93 if (str.empty())94 splitInputFile.setValue(kDefaultSplitMarker);95 }),96 llvm::cl::desc("Split the input file into chunks using the given or "97 "default marker and process each chunk independently"),98 llvm::cl::init(""));99 100 llvm::InitLLVM y(argc, argv);101 102 llvm::cl::ParseCommandLineOptions(argc, argv, "mlir-irdl-to-cpp");103 104 std::string errorMessage;105 std::unique_ptr<llvm::MemoryBuffer> input =106 openInputFile(inputFilename, &errorMessage);107 if (!input) {108 llvm::errs() << errorMessage << "\n";109 return failure();110 }111 112 std::unique_ptr<llvm::ToolOutputFile> output =113 openOutputFile(outputFilename, &errorMessage);114 115 if (!output) {116 llvm::errs() << errorMessage << "\n";117 return failure();118 }119 120 auto chunkFn = [&](std::unique_ptr<llvm::MemoryBuffer> chunkBuffer,121 raw_ostream &os) {122 return processBuffer(output->os(), std::move(chunkBuffer),123 verifyDiagnostics, nullptr);124 };125 126 auto &splitInputFileDelimiter = splitInputFile.getValue();127 if (splitInputFileDelimiter.size())128 return splitAndProcessBuffer(std::move(input), chunkFn, output->os(),129 splitInputFileDelimiter,130 splitInputFileDelimiter);131 132 if (failed(chunkFn(std::move(input), output->os())))133 return failure();134 135 if (!verifyDiagnostics)136 output->keep();137 138 return success();139}140 141int main(int argc, char **argv) {142 return failed(translateIRDLToCpp(argc, argv));143}144