[Mlir-commits] [mlir] 698bb5f - [mlir][docs] Add C example for C-compatible wrapper for LLVM IR (#120955)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Dec 26 03:58:15 PST 2024
Author: Hongren Zheng
Date: 2024-12-26T12:58:11+01:00
New Revision: 698bb5f239f50e8217cbec1d19bf8e0bba8c5d11
URL: https://github.com/llvm/llvm-project/commit/698bb5f239f50e8217cbec1d19bf8e0bba8c5d11
DIFF: https://github.com/llvm/llvm-project/commit/698bb5f239f50e8217cbec1d19bf8e0bba8c5d11.diff
LOG: [mlir][docs] Add C example for C-compatible wrapper for LLVM IR (#120955)
`TargetLLVMIR` documentation 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
* `MemrefDescriptor` should be passed as _pointer_.
+ For example, MLIR function could return a new Descriptor, so pointer
is a must.
+ Surprisingly, directly pass the struct, by C convention, is also a
pointer so some function will work, but that is implicit and
error-prone.
* for `@foo() -> memref<>`, the return type becomes the first argument
in `_mlir_ciface_foo(%arg0: !llvm.ptr)`.
+ This is described in
https://github.com/llvm/llvm-project/blob/f70ab7d909d6861c7eec5ab40679bde16ab826c6/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp#L110-L167
Especially by code `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
*
https://discourse.llvm.org/t/how-to-compile-and-link-with-other-c-c-programs/4835/10
*
https://discourse.llvm.org/t/segmentation-fault-on-memref-store/80286/3
* https://discourse.llvm.org/t/memref-store-storing-a-memref-load/80307
Cc @ftynse for relevent commit history. Cc @charitha22 and @Wheest from
discourse post.
Added:
Modified:
mlir/docs/TargetLLVMIR.md
Removed:
################################################################################
diff --git a/mlir/docs/TargetLLVMIR.md b/mlir/docs/TargetLLVMIR.md
index 96a4589eb80e75..3a2f44f46f782e 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: 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
More information about the Mlir-commits
mailing list