[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