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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This is a command line utility that translates an IRDL dialect definition
10// 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 LogicalResult
32processBuffer(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(F: std::move(ownedBuffer), IncludeLoc: SMLoc());
38
39 DialectRegistry registry;
40 registry.insert<irdl::IRDLDialect>();
41 MLIRContext ctx(registry);
42
43 ctx.printOpOnDiagnostic(enable: !verifyDiagnostics);
44
45 auto runTranslation = [&]() {
46 ParserConfig parseConfig(&ctx);
47 OwningOpRef<Operation *> op =
48 parseSourceFileForTool(sourceMgr, config: parseConfig, insertImplicitModule: 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 for
67 // 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(Val: "-"));
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(Val: "-"));
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(Val: false));
87
88 static llvm::cl::opt<std::string> splitInputFile(
89 "split-input-file", llvm::cl::ValueOptional,
90 llvm::cl::callback(CB: [&](const std::string &str) {
91 // Implicit value: use default marker if flag was used without
92 // value.
93 if (str.empty())
94 splitInputFile.setValue(V: 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(Val: ""));
99
100 llvm::InitLLVM y(argc, argv);
101
102 llvm::cl::ParseCommandLineOptions(argc, argv, Overview: "mlir-irdl-to-cpp");
103
104 std::string errorMessage;
105 std::unique_ptr<llvm::MemoryBuffer> input =
106 openInputFile(inputFilename, errorMessage: &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: &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(os&: output->os(), ownedBuffer: std::move(chunkBuffer),
123 verifyDiagnostics, threadPool: nullptr);
124 };
125
126 auto &splitInputFileDelimiter = splitInputFile.getValue();
127 if (splitInputFileDelimiter.size())
128 return splitAndProcessBuffer(originalBuffer: std::move(input), processChunkBuffer: chunkFn, os&: output->os(),
129 inputSplitMarker: splitInputFileDelimiter,
130 outputSplitMarker: splitInputFileDelimiter);
131
132 if (failed(Result: 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(Result: translateIRDLToCpp(argc, argv));
143}
144

source code of mlir/tools/mlir-irdl-to-cpp/mlir-irdl-to-cpp.cpp