-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[mlir][docs] Add C example for C-compatible wrapper for LLVM IR #120955
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-mlir Author: Hongren Zheng (ZenithalHourlyRate) Changes
The C function signature is not obvious, in that
Users using the wrong signature will get incorrect results. LLVM discourse has some example of it
Cc @ftynse for relevent commit history. Cc @charitha22 and @Wheest from discourse post. Full diff: https://github.com/llvm/llvm-project/pull/120955.diff 1 Files Affected:
diff --git a/mlir/docs/TargetLLVMIR.md b/mlir/docs/TargetLLVMIR.md
index 96a4589eb80e75..ed58040e1abbb8 100644
--- a/mlir/docs/TargetLLVMIR.md
+++ b/mlir/docs/TargetLLVMIR.md
@@ -646,7 +646,7 @@ Examples:
```mlir
-func.func @qux(%arg0: memref<?x?xf32>)
+func.func @qux(%arg0: memref<?x?xf32>) attributes {llvm.emit_c_interface}
// Gets converted into the following
// (using type alias for brevity):
@@ -683,8 +683,18 @@ llvm.func @qux(%arg0: !llvm.ptr, %arg1: !llvm.ptr,
llvm.func @_mlir_ciface_qux(!llvm.ptr)
```
+
+```cpp
+// The C function implementation for the interface function
+extern "C" {
+void _mlir_ciface_qux(MemRefDescriptor<float, 2> *input) {
+ // detailed impl
+}
+}
+```
+
```mlir
-func.func @foo(%arg0: memref<?x?xf32>) {
+func.func @foo(%arg0: memref<?x?xf32>) attributes {llvm.emit_c_interface} {
return
}
@@ -719,8 +729,15 @@ llvm.func @_mlir_ciface_foo(%arg0: !llvm.ptr) {
}
```
+```cpp
+// The C function signature for the interface function
+extern "C" {
+void _mlir_ciface_foo(MemRefDescriptor<float, 2> *input);
+}
+```
+
```mlir
-func.func @foo(%arg0: memref<?x?xf32>) -> memref<?x?xf32> {
+func.func @foo(%arg0: memref<?x?xf32>) -> memref<?x?xf32> attributes {llvm.emit_c_interface} {
return %arg0 : memref<?x?xf32>
}
@@ -744,6 +761,7 @@ llvm.func @foo(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: i64,
}
// Interface function callable from C.
+// NOTE that the returned memref becomes the first argument
llvm.func @_mlir_ciface_foo(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {
%0 = llvm.load %arg1 : !llvm.ptr
%1 = llvm.extractvalue %0[0] : !llvm.memref_2d
@@ -760,6 +778,14 @@ llvm.func @_mlir_ciface_foo(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {
}
```
+```cpp
+// The C function signature for the interface function
+extern "C" {
+void _mlir_ciface_foo(MemRefDescriptor<float, 2> *output,
+ MemRefDescriptor<float, 2> *input);
+}
+```
+
Rationale: Introducing auxiliary functions for C-compatible interfaces is
preferred to modifying the calling convention since it will minimize the effect
of C compatibility on intra-module calls or calls between MLIR-generated
|
|
Thanks, documentation improvements are always appreciated! Let me know if you need help merging this. |
5d468bb to
c828fb8
Compare
|
Addressed the review comment
I do not have commit access for now. I'd appreciate it if you could do me the favor. |
TargetLLVMIRdocumentation introduced the C-compatible wrapper function for a MLIR function and ways to generate it, but did not demonstrate the corresponding C function signature for them.The C function signature is not obvious, in that
MemrefDescriptorshould be passed as pointer.@foo() -> memref<>, the return type becomes the first argument in_mlir_ciface_foo(%arg0: !llvm.ptr).llvm-project/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
Lines 110 to 167 in f70ab7d
size_t argOffset = resultStructType ? 1 : 0;saying the actual argument starts at 1 when result is a struct (memref)Users using the wrong signature will get incorrect results. LLVM discourse has some example of it
Cc @ftynse for relevent commit history. Cc @charitha22 and @Wheest from discourse post.