[Mlir-commits] [mlir] 9a87c5d - [mlir][EmitC] Add support for external functions (#80547)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Feb 5 07:58:14 PST 2024
Author: Marius Brehler
Date: 2024-02-05T16:58:10+01:00
New Revision: 9a87c5d440ec16a1116e060829df10bc2a6965ce
URL: https://github.com/llvm/llvm-project/commit/9a87c5d440ec16a1116e060829df10bc2a6965ce
DIFF: https://github.com/llvm/llvm-project/commit/9a87c5d440ec16a1116e060829df10bc2a6965ce.diff
LOG: [mlir][EmitC] Add support for external functions (#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.
Added:
Modified:
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
mlir/lib/Dialect/EmitC/IR/EmitC.cpp
mlir/lib/Target/Cpp/TranslateToCpp.cpp
mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
mlir/test/Dialect/EmitC/invalid_ops.mlir
mlir/test/Dialect/EmitC/ops.mlir
mlir/test/Target/Cpp/func.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 5c8c3c9ce7bb35..6871948d14cfc0 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 ac3d8297953f32..6a8ecb7b00473a 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,22 @@ 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 df489c6d90fb1c..f384fcbefcfdbb 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 c0c6105409f8d8..0e73122dcc0bfa 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -773,19 +773,27 @@ static LogicalResult printOperation(CppEmitter &emitter, ModuleOp moduleOp) {
static LogicalResult printFunctionArgs(CppEmitter &emitter,
Operation *functionOp,
- Region::BlockArgListType arguments) {
+ ArrayRef<Type> arguments) {
raw_indented_ostream &os = emitter.ostream();
- if (failed(interleaveCommaWithError(
- arguments, os, [&](BlockArgument arg) -> LogicalResult {
- if (failed(emitter.emitType(functionOp->getLoc(), arg.getType())))
- return failure();
- os << " " << emitter.getOrCreateName(arg);
- return success();
- })))
- return failure();
+ return (
+ interleaveCommaWithError(arguments, os, [&](Type arg) -> LogicalResult {
+ return emitter.emitType(functionOp->getLoc(), arg);
+ }));
+}
- return success();
+static LogicalResult printFunctionArgs(CppEmitter &emitter,
+ Operation *functionOp,
+ Region::BlockArgListType arguments) {
+ raw_indented_ostream &os = emitter.ostream();
+
+ return (interleaveCommaWithError(
+ arguments, os, [&](BlockArgument arg) -> LogicalResult {
+ if (failed(emitter.emitType(functionOp->getLoc(), arg.getType())))
+ return failure();
+ os << " " << emitter.getOrCreateName(arg);
+ return success();
+ }));
}
static LogicalResult printFunctionBody(CppEmitter &emitter,
@@ -913,6 +921,13 @@ 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 a1c8af2587aa04..5c96cf1ce0d34c 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 707f9a5b23b0b3..6d2471b4d2b486 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 b41333faa4d4eb..e03c3d58c3e847 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 d2e14a9e5a7aeb..a639cae6f623c5 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