[Mlir-commits] [mlir] Adding mlir models (PR #141158)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu May 22 16:40:52 PDT 2025
https://github.com/Jaddyen created https://github.com/llvm/llvm-project/pull/141158
None
>From 7f603ca713f7177cf3d2a60c9958ed1c9bfa569a Mon Sep 17 00:00:00 2001
From: Jaden Jaden <ajaden at google.com>
Date: Wed, 21 May 2025 23:10:51 +0000
Subject: [PATCH 1/2] Able to get class when you set a class-Name
---
mlir/include/mlir/Target/Cpp/CppEmitter.h | 2 +-
mlir/lib/Target/Cpp/TranslateRegistration.cpp | 7 +-
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 168 +++++++++++++++---
3 files changed, 147 insertions(+), 30 deletions(-)
diff --git a/mlir/include/mlir/Target/Cpp/CppEmitter.h b/mlir/include/mlir/Target/Cpp/CppEmitter.h
index 7c5747a888261..f87fc67662f55 100644
--- a/mlir/include/mlir/Target/Cpp/CppEmitter.h
+++ b/mlir/include/mlir/Target/Cpp/CppEmitter.h
@@ -28,7 +28,7 @@ namespace emitc {
/// with matching id are emitted.
LogicalResult translateToCpp(Operation *op, raw_ostream &os,
bool declareVariablesAtTop = false,
- StringRef fileId = {});
+ StringRef fileId = {}, StringRef className = {});
} // namespace emitc
} // namespace mlir
diff --git a/mlir/lib/Target/Cpp/TranslateRegistration.cpp b/mlir/lib/Target/Cpp/TranslateRegistration.cpp
index 2108ffd414c56..d556927d7f904 100644
--- a/mlir/lib/Target/Cpp/TranslateRegistration.cpp
+++ b/mlir/lib/Target/Cpp/TranslateRegistration.cpp
@@ -33,13 +33,18 @@ void registerToCppTranslation() {
"file-id", llvm::cl::desc("Emit emitc.file ops with matching id"),
llvm::cl::init(""));
+ static llvm::cl::opt<std::string> className(
+ "class-name", llvm::cl::desc("Specify the class name for the generated C++ code"),
+ llvm::cl::init(""));
+
TranslateFromMLIRRegistration reg(
"mlir-to-cpp", "translate from mlir to cpp",
[](Operation *op, raw_ostream &output) {
return emitc::translateToCpp(
op, output,
/*declareVariablesAtTop=*/declareVariablesAtTop,
- /*fileId=*/fileId);
+ /*fileId=*/fileId,
+ /*className=*/className);
},
[](DialectRegistry ®istry) {
// clang-format off
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 0c4975a13d301..4b67233aa7f89 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -9,6 +9,7 @@
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
#include "mlir/Dialect/EmitC/IR/EmitC.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
@@ -68,6 +69,13 @@ inline LogicalResult interleaveCommaWithError(const Container &c,
return interleaveWithError(c.begin(), c.end(), eachFn, [&]() { os << ", "; });
}
+template <typename Container, typename UnaryFunctor>
+inline LogicalResult interleaveWithNewLineWithError(const Container &c,
+ raw_ostream &os,
+ UnaryFunctor eachFn) {
+ return interleaveWithError(c.begin(), c.end(), eachFn, [&]() { os << "\n"; });
+}
+
/// Return the precedence of a operator as an integer, higher values
/// imply higher precedence.
static FailureOr<int> getOperatorPrecedence(Operation *operation) {
@@ -116,7 +124,7 @@ namespace {
/// Emitter that uses dialect specific emitters to emit C++ code.
struct CppEmitter {
explicit CppEmitter(raw_ostream &os, bool declareVariablesAtTop,
- StringRef fileId);
+ StringRef fileId, StringRef className);
/// Emits attribute or returns failure.
LogicalResult emitAttribute(Location loc, Attribute attr);
@@ -233,6 +241,9 @@ struct CppEmitter {
/// be declared at the beginning of a function.
bool shouldDeclareVariablesAtTop() { return declareVariablesAtTop; };
+ // Returns if we should spit out a C++ class
+ std::string shouldSpitClass() { return className; };
+
/// Returns whether this file op should be emitted
bool shouldEmitFile(FileOp file) {
return !fileId.empty() && file.getId() == fileId;
@@ -268,6 +279,9 @@ struct CppEmitter {
/// Only emit file ops whos id matches this value.
std::string fileId;
+ /// Name of the C++ class we will spit
+ std::string className;
+
/// Map from value to name of C++ variable that contain the name.
ValueMapper valueMapper;
@@ -1025,6 +1039,32 @@ static LogicalResult printFunctionArgs(CppEmitter &emitter,
}));
}
+static LogicalResult printAttributes(CppEmitter &emitter,
+ Operation *functionOp,
+ ArrayRef<Type> arguments) {
+ raw_indented_ostream &os = emitter.ostream();
+ for (auto arg : arguments) {
+ os << " ";
+ if (failed(emitter.emitType(functionOp->getLoc(), arg)))
+ return failure();
+ os << " " << arg << ";\n";
+ }
+ return success();
+}
+
+static LogicalResult printAttributes(CppEmitter &emitter,
+ Operation *functionOp,
+ Region::BlockArgListType arguments) {
+ raw_indented_ostream &os = emitter.ostream();
+ for (auto arg : arguments) {
+ os << " ";
+ if (failed(emitter.emitType(functionOp->getLoc(), arg.getType())))
+ return failure();
+ os << " " << emitter.getOrCreateName(arg) << ";\n";
+ }
+ return success();
+}
+
static LogicalResult printFunctionBody(CppEmitter &emitter,
Operation *functionOp,
Region::BlockListType &blocks) {
@@ -1138,35 +1178,107 @@ static LogicalResult printOperation(CppEmitter &emitter,
"with multiple blocks needs variables declared at top");
}
- CppEmitter::Scope scope(emitter);
+ CppEmitter::Scope classScope(emitter);
raw_indented_ostream &os = emitter.ostream();
- if (functionOp.getSpecifiers()) {
- for (Attribute specifier : functionOp.getSpecifiersAttr()) {
- os << cast<StringAttr>(specifier).str() << " ";
+ Operation *operation = functionOp.getOperation();
+ if (!emitter.shouldSpitClass().empty()) {
+ os << "class " << emitter.shouldSpitClass() << " final {\n";
+ os << "public: \n";
+
+ if (functionOp.isExternal()) {
+ if (failed(printAttributes(emitter, operation,
+ functionOp.getArgumentTypes())))
+ return failure();
+ return success();
}
- }
+ if (failed(printAttributes(emitter, operation, functionOp.getArguments())))
+ return failure();
+
+ os << "\n";
+
+ auto argAttrs = functionOp.getArgAttrs();
+ std::map<std::string, Value> fields;
+ if (argAttrs)
+ for (auto [a,v] : zip(*argAttrs, functionOp.getArguments())) {
+ if (auto da = dyn_cast<mlir::DictionaryAttr>(a)) {
+ auto nv = da.getNamed("tf_saved_model.index_path")->getValue();
+ auto name = cast<mlir::StringAttr>(cast<mlir::ArrayAttr>(nv)[0]).str();
+ fields[name] = v;
+ }
+ }
- if (failed(emitter.emitTypes(functionOp.getLoc(),
- functionOp.getFunctionType().getResults())))
- return failure();
- os << " " << functionOp.getName();
+ for (auto & r : functionOp->getRegions())
+ for (auto &b : r.getBlocks())
+ for (auto &opt : b.getOperations())
+ if (auto alloc = dyn_cast<memref::AllocOp>(opt)) {
+ auto name = emitter.getOrCreateName(alloc).str();
+ fields[name] = alloc;
+ if (failed(emitter.emitType(alloc.getLoc(), alloc.getType().getElementType())))
+ return failure();
+ os << " [" << alloc.getType().getNumElements() <<"] ";
+ os << " " << name << ";\n";
+ }
+ os << " std::map<std::string, char*> _buffer_map {";
+ for (auto &[n,v]:fields)
+ os << "{ \"" << n << "\"" << ", reinterpret_cast<char*>(" << emitter.getOrCreateName(v) << ") },";
+ os << " };\n";
+ os << " char* getBufferForName(const std::string& name) const {\n";
+ os << " auto it = _buffer_map.find(name);\n";
+ os << " return (it == _buffer_map.end()) ? nullptr : it->second;\n";
+ os << " }\n\n";
- os << "(";
- Operation *operation = functionOp.getOperation();
- if (functionOp.isExternal()) {
- if (failed(printFunctionArgs(emitter, operation,
- functionOp.getArgumentTypes())))
+ os.indent();
+
+ // Begin defining the main function where we have the actual execution
+ if (functionOp.getSpecifiers()) {
+ for (Attribute specifier : functionOp.getSpecifiersAttr()) {
+ os << cast<StringAttr>(specifier).str() << " ";
+ }
+ }
+
+ if (failed(emitter.emitTypes(functionOp.getLoc(),
+ functionOp.getFunctionType().getResults())))
return failure();
- os << ");";
- return success();
- }
- if (failed(printFunctionArgs(emitter, operation, functionOp.getArguments())))
- return failure();
- os << ") {\n";
- if (failed(printFunctionBody(emitter, operation, functionOp.getBlocks())))
- return failure();
- os << "}\n";
+ os << " " << functionOp.getName();
+ //Defining the functionBody
+ os << "() { \n"; // Begin defining the function header (We need the function name and output type to remain without the rest of the function header)
+ os.indent();
+ if (failed(printFunctionBody(emitter, operation, functionOp.getBlocks())))
+ return failure();
+ os.unindent();
+ os << "}\n";
+ os.unindent();
+ os << "};\n";
+ } else {
+ if (functionOp.getSpecifiers()) {
+ for (Attribute specifier : functionOp.getSpecifiersAttr()) {
+ os << cast<StringAttr>(specifier).str() << " ";
+ }
+ }
+
+ if (failed(emitter.emitTypes(functionOp.getLoc(),
+ functionOp.getFunctionType().getResults())))
+ return failure();
+ os << " " << functionOp.getName();
+
+ os << "(";
+ Operation *operation = functionOp.getOperation();
+ if (functionOp.isExternal()) {
+ if (failed(printFunctionArgs(emitter, operation,
+ functionOp.getArgumentTypes())))
+ return failure();
+ os << ");";
+ return success();
+ }
+ if (failed(printFunctionArgs(emitter, operation, functionOp.getArguments())))
+ return failure();
+ os << ") {\n";
+ if (failed(printFunctionBody(emitter, operation, functionOp.getBlocks())))
+ return failure();
+ os << "}\n";
+ }
+
return success();
}
@@ -1202,9 +1314,9 @@ static LogicalResult printOperation(CppEmitter &emitter,
}
CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop,
- StringRef fileId)
+ StringRef fileId, StringRef className)
: os(os), declareVariablesAtTop(declareVariablesAtTop),
- fileId(fileId.str()) {
+ fileId(fileId.str()), className(className.str()) {
valueInScopeCount.push(0);
labelInScopeCount.push(0);
}
@@ -1787,7 +1899,7 @@ LogicalResult CppEmitter::emitTupleType(Location loc, ArrayRef<Type> types) {
LogicalResult emitc::translateToCpp(Operation *op, raw_ostream &os,
bool declareVariablesAtTop,
- StringRef fileId) {
- CppEmitter emitter(os, declareVariablesAtTop, fileId);
+ StringRef fileId, StringRef className) {
+ CppEmitter emitter(os, declareVariablesAtTop, fileId, className);
return emitter.emitOperation(*op, /*trailingSemicolon=*/false);
}
>From 9d257ce53bdfe3a504e6d28cbed87eeef5a4531a Mon Sep 17 00:00:00 2001
From: Jaden Jaden <ajaden at google.com>
Date: Thu, 22 May 2025 23:17:00 +0000
Subject: [PATCH 2/2] fixes
---
mlir/lib/Target/Cpp/TranslateRegistration.cpp | 4 +-
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 233 ++++++++++--------
2 files changed, 128 insertions(+), 109 deletions(-)
diff --git a/mlir/lib/Target/Cpp/TranslateRegistration.cpp b/mlir/lib/Target/Cpp/TranslateRegistration.cpp
index d556927d7f904..17fcc058eef04 100644
--- a/mlir/lib/Target/Cpp/TranslateRegistration.cpp
+++ b/mlir/lib/Target/Cpp/TranslateRegistration.cpp
@@ -34,7 +34,9 @@ void registerToCppTranslation() {
llvm::cl::init(""));
static llvm::cl::opt<std::string> className(
- "class-name", llvm::cl::desc("Specify the class name for the generated C++ code"),
+ "class-name",
+ llvm::cl::desc("Optional class name. If specified, the output will be a "
+ "class where the function(s) in the module are members."),
llvm::cl::init(""));
TranslateFromMLIRRegistration reg(
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 4b67233aa7f89..08303428b91af 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -9,7 +9,6 @@
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
#include "mlir/Dialect/EmitC/IR/EmitC.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
@@ -73,7 +72,8 @@ template <typename Container, typename UnaryFunctor>
inline LogicalResult interleaveWithNewLineWithError(const Container &c,
raw_ostream &os,
UnaryFunctor eachFn) {
- return interleaveWithError(c.begin(), c.end(), eachFn, [&]() { os << "\n"; });
+ return interleaveWithError(c.begin(), c.end(), eachFn,
+ [&]() { os << ";\n"; });
}
/// Return the precedence of a operator as an integer, higher values
@@ -241,8 +241,11 @@ struct CppEmitter {
/// be declared at the beginning of a function.
bool shouldDeclareVariablesAtTop() { return declareVariablesAtTop; };
- // Returns if we should spit out a C++ class
- std::string shouldSpitClass() { return className; };
+ // Returns whether we should emit a C++ class
+ bool shouldPrintClass() { return !className.empty(); };
+
+ // Returns the class name to emit
+ std::string getClassName() { return className; };
/// Returns whether this file op should be emitted
bool shouldEmitFile(FileOp file) {
@@ -1039,30 +1042,25 @@ static LogicalResult printFunctionArgs(CppEmitter &emitter,
}));
}
-static LogicalResult printAttributes(CppEmitter &emitter,
- Operation *functionOp,
- ArrayRef<Type> arguments) {
+static LogicalResult printFields(CppEmitter &emitter, Operation *functionOp,
+ ArrayRef<Type> arguments) {
raw_indented_ostream &os = emitter.ostream();
- for (auto arg : arguments) {
- os << " ";
- if (failed(emitter.emitType(functionOp->getLoc(), arg)))
- return failure();
- os << " " << arg << ";\n";
- }
- return success();
+
+ return (interleaveWithNewLineWithError(
+ arguments, os, [&](Type arg) -> LogicalResult {
+ return emitter.emitType(functionOp->getLoc(), arg);
+ }));
}
-static LogicalResult printAttributes(CppEmitter &emitter,
- Operation *functionOp,
- Region::BlockArgListType arguments) {
+static LogicalResult printFields(CppEmitter &emitter, Operation *functionOp,
+ Region::BlockArgListType arguments) {
raw_indented_ostream &os = emitter.ostream();
- for (auto arg : arguments) {
- os << " ";
- if (failed(emitter.emitType(functionOp->getLoc(), arg.getType())))
- return failure();
- os << " " << emitter.getOrCreateName(arg) << ";\n";
- }
- return success();
+
+ return (interleaveWithNewLineWithError(
+ arguments, os, [&](BlockArgument arg) -> LogicalResult {
+ return emitter.emitVariableDeclaration(
+ functionOp->getLoc(), arg.getType(), emitter.getOrCreateName(arg));
+ }));
}
static LogicalResult printFunctionBody(CppEmitter &emitter,
@@ -1169,116 +1167,135 @@ static LogicalResult printOperation(CppEmitter &emitter,
return success();
}
-static LogicalResult printOperation(CppEmitter &emitter,
- emitc::FuncOp functionOp) {
- // We need to declare variables at top if the function has multiple blocks.
- if (!emitter.shouldDeclareVariablesAtTop() &&
- functionOp.getBlocks().size() > 1) {
- return functionOp.emitOpError(
- "with multiple blocks needs variables declared at top");
- }
-
- CppEmitter::Scope classScope(emitter);
+static LogicalResult printFunctionHeader(CppEmitter &emitter,
+ emitc::FuncOp functionOp) {
raw_indented_ostream &os = emitter.ostream();
Operation *operation = functionOp.getOperation();
- if (!emitter.shouldSpitClass().empty()) {
- os << "class " << emitter.shouldSpitClass() << " final {\n";
- os << "public: \n";
+ if (functionOp.getSpecifiers()) {
+ for (Attribute specifier : functionOp.getSpecifiersAttr()) {
+ os << cast<StringAttr>(specifier).str() << " ";
+ }
+ }
- if (functionOp.isExternal()) {
- if (failed(printAttributes(emitter, operation,
- functionOp.getArgumentTypes())))
+ if (failed(emitter.emitTypes(functionOp.getLoc(),
+ functionOp.getFunctionType().getResults())))
+ return failure();
+ os << " " << functionOp.getName();
+ if (!emitter.shouldPrintClass()) {
+ os << "(";
+ if (functionOp.isExternal()) {
+ if (failed(printFunctionArgs(emitter, operation,
+ functionOp.getArgumentTypes())))
return failure();
+ os << ");";
return success();
}
- if (failed(printAttributes(emitter, operation, functionOp.getArguments())))
+ if (failed(
+ printFunctionArgs(emitter, operation, functionOp.getArguments())))
return failure();
-
- os << "\n";
-
- auto argAttrs = functionOp.getArgAttrs();
- std::map<std::string, Value> fields;
- if (argAttrs)
- for (auto [a,v] : zip(*argAttrs, functionOp.getArguments())) {
- if (auto da = dyn_cast<mlir::DictionaryAttr>(a)) {
- auto nv = da.getNamed("tf_saved_model.index_path")->getValue();
- auto name = cast<mlir::StringAttr>(cast<mlir::ArrayAttr>(nv)[0]).str();
- fields[name] = v;
- }
- }
+ os << ") {\n";
- for (auto & r : functionOp->getRegions())
- for (auto &b : r.getBlocks())
- for (auto &opt : b.getOperations())
- if (auto alloc = dyn_cast<memref::AllocOp>(opt)) {
- auto name = emitter.getOrCreateName(alloc).str();
- fields[name] = alloc;
- if (failed(emitter.emitType(alloc.getLoc(), alloc.getType().getElementType())))
- return failure();
- os << " [" << alloc.getType().getNumElements() <<"] ";
- os << " " << name << ";\n";
- }
- os << " std::map<std::string, char*> _buffer_map {";
- for (auto &[n,v]:fields)
- os << "{ \"" << n << "\"" << ", reinterpret_cast<char*>(" << emitter.getOrCreateName(v) << ") },";
- os << " };\n";
- os << " char* getBufferForName(const std::string& name) const {\n";
- os << " auto it = _buffer_map.find(name);\n";
- os << " return (it == _buffer_map.end()) ? nullptr : it->second;\n";
- os << " }\n\n";
+ } else {
+ os << "() { \n";
+ }
- os.indent();
+ return success();
+}
- // Begin defining the main function where we have the actual execution
- if (functionOp.getSpecifiers()) {
- for (Attribute specifier : functionOp.getSpecifiersAttr()) {
- os << cast<StringAttr>(specifier).str() << " ";
+static LogicalResult emitClassBody(CppEmitter &emitter,
+ emitc::FuncOp functionOp) {
+ raw_indented_ostream &os = emitter.ostream();
+ Operation *operation = functionOp.getOperation();
+ auto argAttrs = functionOp.getArgAttrs();
+ std::map<std::string, Value> fields;
+ os << "\nstd::map<std::string, char*> _buffer_map {";
+ if (argAttrs) // We can have no argattrs in the case that the function has no
+ // inputs nor outputs -> procedure
+ for (const auto [a, v] : zip(*argAttrs, functionOp.getArguments())) {
+ if (auto da = dyn_cast<mlir::DictionaryAttr>(a)) {
+ auto nv =
+ da.getNamed("tf_saved_model.index_path")
+ ->getValue(); // From what I've seen so far, this is the only
+ // way to have the argAttrs keys. If there is
+ // another way, I need to run the tests to see and
+ // see what cases trigger this change in format.
+ auto name = cast<mlir::StringAttr>(cast<mlir::ArrayAttr>(nv)[0]).str();
+ fields[name] = v; // The only way to not have unique names is in the
+ // case that you have duplicate arguments in your
+ // tensorflow/python function. By python syntax rules,
+ // you're not allowed to have that(Current assumption)
+ os << "{ \"" << name << "\"" << ", reinterpret_cast<char*>("
+ << emitter.getOrCreateName(v) << ") },";
}
}
+ else
+ return failure();
+
+ os << " };\n";
+ os << "char* getBufferForName(const std::string& name) const {\n";
+ os.indent();
+ os.indent();
+ os << "auto it = _buffer_map.find(name);\n";
+ os << "return (it == _buffer_map.end()) ? nullptr : it->second;\n";
+ os.unindent();
+ os.unindent();
+ os << "}\n\n";
+
+ if (failed(printFunctionHeader(emitter, functionOp)))
+ return failure();
+
+ if (failed(printFunctionBody(emitter, operation, functionOp.getBlocks())))
+ return failure();
+ os << "}\n";
+ os.unindent();
+ os << "};\n";
+
+ return success();
+}
+
+static LogicalResult printOperation(CppEmitter &emitter,
+ emitc::FuncOp functionOp) {
+ // We need to declare variables at top if the function has multiple blocks.
+ if (!emitter.shouldDeclareVariablesAtTop() &&
+ functionOp.getBlocks().size() > 1) {
+ return functionOp.emitOpError(
+ "with multiple blocks needs variables declared at top");
+ }
- if (failed(emitter.emitTypes(functionOp.getLoc(),
- functionOp.getFunctionType().getResults())))
+ CppEmitter::Scope classScope(emitter);
+ raw_indented_ostream &os = emitter.ostream();
+ Operation *operation = functionOp.getOperation();
+ if (!emitter.shouldPrintClass()) {
+
+ if (failed(printFunctionHeader(emitter, functionOp)))
return failure();
- os << " " << functionOp.getName();
- //Defining the functionBody
- os << "() { \n"; // Begin defining the function header (We need the function name and output type to remain without the rest of the function header)
- os.indent();
- if (failed(printFunctionBody(emitter, operation, functionOp.getBlocks())))
+ if (failed(printFunctionBody(
+ emitter, operation,
+ functionOp.getBlocks()))) // This is the only similarity between the
+ // function and the class
return failure();
- os.unindent();
os << "}\n";
- os.unindent();
- os << "};\n";
- } else {
- if (functionOp.getSpecifiers()) {
- for (Attribute specifier : functionOp.getSpecifiersAttr()) {
- os << cast<StringAttr>(specifier).str() << " ";
- }
- }
- if (failed(emitter.emitTypes(functionOp.getLoc(),
- functionOp.getFunctionType().getResults())))
- return failure();
- os << " " << functionOp.getName();
+ } else {
+ os << "class " << emitter.getClassName() << " final {\n";
+ os << "public: \n";
+ os.indent();
- os << "(";
- Operation *operation = functionOp.getOperation();
if (functionOp.isExternal()) {
- if (failed(printFunctionArgs(emitter, operation,
- functionOp.getArgumentTypes())))
+ if (failed(
+ printFields(emitter, operation, functionOp.getArgumentTypes())))
return failure();
- os << ");";
return success();
}
- if (failed(printFunctionArgs(emitter, operation, functionOp.getArguments())))
+ if (failed(printFields(emitter, operation, functionOp.getArguments())))
return failure();
- os << ") {\n";
- if (failed(printFunctionBody(emitter, operation, functionOp.getBlocks())))
+ os << ";\n";
+
+ if (failed(emitClassBody(emitter, functionOp)))
return failure();
- os << "}\n";
}
-
+
return success();
}
More information about the Mlir-commits
mailing list