[Mlir-commits] [mlir] [mlir][EmitC] Add support for external functions (PR #80547)
Marius Brehler
llvmlistbot at llvm.org
Sat Feb 3 07:37:37 PST 2024
https://github.com/marbre created https://github.com/llvm/llvm-project/pull/80547
This adds a conversion from an externaly defined `func.func`, a `func.func` without function body, to an `emitc.func` with an `extern` specifier.
>From 5a6975ce1c38a49743eb239a2e7f66425b9f4e8c Mon Sep 17 00:00:00 2001
From: Marius Brehler <marius.brehler at iml.fraunhofer.de>
Date: Sat, 3 Feb 2024 15:22:11 +0000
Subject: [PATCH] [mlir][EmitC] Add support for external functions
This adds a conversion from an externaly defined `func.func`, a
`func.func` without function body, to an `emitc.func` with an `extern`
specifier.
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 3 +++
.../Conversion/FuncToEmitC/FuncToEmitC.cpp | 19 +++++++++-------
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 3 ---
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 22 +++++++++++++++++++
.../Conversion/FuncToEmitC/func-to-emitc.mlir | 5 +++++
mlir/test/Dialect/EmitC/invalid_ops.mlir | 5 -----
mlir/test/Dialect/EmitC/ops.mlir | 2 ++
mlir/test/Target/Cpp/func.mlir | 3 +++
8 files changed, 46 insertions(+), 16 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 5c8c3c9ce7bb3..6871948d14cfc 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -498,6 +498,9 @@ def EmitC_FuncOp : EmitC_Op<"func", [
emitc.return %0 : i32
}
+ // An external function definition:
+ emitc.func private @extern_func(i32)
+ attributes {specifiers = ["extern"]}
```
}];
let arguments = (ins SymbolNameAttr:$sym_name,
diff --git a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
index ac3d8297953f3..658b94613d12b 100644
--- a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
+++ b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
@@ -57,10 +57,6 @@ class FuncOpConversion final : public OpConversionPattern<func::FuncOp> {
return rewriter.notifyMatchFailure(
funcOp, "only functions with zero or one result can be converted");
- if (funcOp.isDeclaration())
- return rewriter.notifyMatchFailure(funcOp,
- "declarations cannot be converted");
-
// Create the converted `emitc.func` op.
emitc::FuncOp newFuncOp = rewriter.create<emitc::FuncOp>(
funcOp.getLoc(), funcOp.getName(), funcOp.getFunctionType());
@@ -72,14 +68,21 @@ class FuncOpConversion final : public OpConversionPattern<func::FuncOp> {
newFuncOp->setAttr(namedAttr.getName(), namedAttr.getValue());
}
- // Add `static` to specifiers if `func.func` is private.
- if (funcOp.isPrivate()) {
+ // Add `extern` to specifiers if `func.func` is declaration only.
+ if (funcOp.isDeclaration()) {
+ ArrayAttr specifiers = rewriter.getStrArrayAttr({"extern"});
+ newFuncOp.setSpecifiersAttr(specifiers);
+ }
+
+ // Add `static` to specifiers if `func.func` is private but not a declaration.
+ if (funcOp.isPrivate() && !funcOp.isDeclaration()) {
ArrayAttr specifiers = rewriter.getStrArrayAttr({"static"});
newFuncOp.setSpecifiersAttr(specifiers);
}
- rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(),
- newFuncOp.end());
+ if (!funcOp.isDeclaration())
+ rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(),
+ newFuncOp.end());
rewriter.eraseOp(funcOp);
return success();
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index df489c6d90fb1..f384fcbefcfdb 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -437,9 +437,6 @@ LogicalResult FuncOp::verify() {
return emitOpError("requires zero or exactly one result, but has ")
<< getNumResults();
- if (isExternal())
- return emitOpError("does not support empty function bodies");
-
return success();
}
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index c0c6105409f8d..0abbce5335278 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -771,6 +771,22 @@ static LogicalResult printOperation(CppEmitter &emitter, ModuleOp moduleOp) {
return success();
}
+static LogicalResult printFunctionArgs(CppEmitter &emitter,
+ Operation *functionOp,
+ ArrayRef<Type> arguments) {
+ raw_indented_ostream &os = emitter.ostream();
+
+ if (failed(interleaveCommaWithError(
+ arguments, os, [&](Type arg) -> LogicalResult {
+ if (failed(emitter.emitType(functionOp->getLoc(), arg)))
+ return failure();
+ return success();
+ })))
+ return failure();
+
+ return success();
+}
+
static LogicalResult printFunctionArgs(CppEmitter &emitter,
Operation *functionOp,
Region::BlockArgListType arguments) {
@@ -913,6 +929,12 @@ static LogicalResult printOperation(CppEmitter &emitter,
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";
diff --git a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
index a1c8af2587aa0..5c96cf1ce0d34 100644
--- a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
+++ b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
@@ -53,3 +53,8 @@ func.func @call(%arg0: i32) -> i32 {
%0 = call @return_i32(%arg0) : (i32) -> (i32)
return %0 : i32
}
+
+// -----
+
+// CHECK-LABEL: emitc.func private @return_i32(i32) -> i32 attributes {specifiers = ["extern"]}
+func.func private @return_i32(%arg0: i32) -> i32
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index 707f9a5b23b0b..6d2471b4d2b48 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -321,8 +321,3 @@ func.func @return_inside_func.func(%0: i32) -> (i32) {
// expected-error at +1 {{expected non-function type}}
emitc.func @func_variadic(...)
-
-// -----
-
-// expected-error at +1 {{'emitc.func' op does not support empty function bodies}}
-emitc.func private @empty()
diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
index b41333faa4d4e..e03c3d58c3e84 100644
--- a/mlir/test/Dialect/EmitC/ops.mlir
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -30,6 +30,8 @@ emitc.func @call() -> i32 {
emitc.return %0 : i32
}
+emitc.func private @extern(i32) attributes {specifiers = ["extern"]}
+
func.func @cast(%arg0: i32) {
%1 = emitc.cast %arg0: i32 to f32
return
diff --git a/mlir/test/Target/Cpp/func.mlir b/mlir/test/Target/Cpp/func.mlir
index d2e14a9e5a7ae..a639cae6f623c 100644
--- a/mlir/test/Target/Cpp/func.mlir
+++ b/mlir/test/Target/Cpp/func.mlir
@@ -37,3 +37,6 @@ emitc.func @emitc_call() -> i32 {
// CPP-DECLTOP-NEXT: int32_t [[V0:[^ ]*]];
// CPP-DECLTOP-NEXT: [[V0:[^ ]*]] = return_i32();
// CPP-DECLTOP-NEXT: return [[V0:[^ ]*]];
+
+emitc.func private @extern_func(i32) attributes {specifiers = ["extern"]}
+// CPP-DEFAULT: extern void extern_func(int32_t);
More information about the Mlir-commits
mailing list