Skip to content

Commit 29e192a

Browse files
authored
[Coroutines] Documentation for custom ABIs (llvm#111781)
Update the llvm/docs/Coroutines.rst docs to include a full description of Custom ABI objects. This documentation describes the how ABI objects allow users (plugin libraries) to create custom ABI objects for their needs.
1 parent d832a1c commit 29e192a

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

llvm/docs/Coroutines.rst

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ lowered to a constant representing the size required for the coroutine frame.
312312
The `coro.begin`_ intrinsic initializes the coroutine frame and returns the
313313
coroutine handle. The second parameter of `coro.begin` is given a block of memory
314314
to be used if the coroutine frame needs to be allocated dynamically.
315+
315316
The `coro.id`_ intrinsic serves as coroutine identity useful in cases when the
316317
`coro.begin`_ intrinsic get duplicated by optimization passes such as
317318
jump-threading.
@@ -749,6 +750,65 @@ and python iterator `__next__` would look like:
749750
return *(int*)coro.promise(hdl, 4, false);
750751
}
751752

753+
Custom ABIs and Plugin Libraries
754+
--------------------------------
755+
756+
Plugin libraries can extend coroutine lowering enabling a wide variety of users
757+
to utilize the coroutine transformation passes. An existing coroutine lowering
758+
is extended by:
759+
760+
#. defining custom ABIs that inherit from the existing ABIs,
761+
#. give a list of generators for the custom ABIs when constructing the `CoroSplit`_ pass, and
762+
#. use `coro.begin.custom.abi`_ in place of `coro.begin`_ that has an additional parameter for the index of the generator/ABI to be used for the coroutine.
763+
764+
A custom ABI overriding the SwitchABI's materialization looks like:
765+
766+
.. code-block:: c++
767+
768+
class CustomSwitchABI : public coro::SwitchABI {
769+
public:
770+
CustomSwitchABI(Function &F, coro::Shape &S)
771+
: coro::SwitchABI(F, S, ExtraMaterializable) {}
772+
};
773+
774+
Giving a list of custom ABI generators while constructing the `CoroSplit`
775+
pass looks like:
776+
777+
.. code-block:: c++
778+
779+
CoroSplitPass::BaseABITy GenCustomABI = [](Function &F, coro::Shape &S) {
780+
return std::make_unique<CustomSwitchABI>(F, S);
781+
};
782+
783+
CGSCCPassManager CGPM;
784+
CGPM.addPass(CoroSplitPass({GenCustomABI}));
785+
786+
The LLVM IR for a coroutine using a Coroutine with a custom ABI looks like:
787+
788+
.. code-block:: llvm
789+
790+
define ptr @f(i32 %n) presplitcoroutine_custom_abi {
791+
entry:
792+
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
793+
%size = call i32 @llvm.coro.size.i32()
794+
%alloc = call ptr @malloc(i32 %size)
795+
%hdl = call noalias ptr @llvm.coro.begin.custom.abi(token %id, ptr %alloc, i32 0)
796+
br label %loop
797+
loop:
798+
%n.val = phi i32 [ %n, %entry ], [ %inc, %loop ]
799+
%inc = add nsw i32 %n.val, 1
800+
call void @print(i32 %n.val)
801+
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
802+
switch i8 %0, label %suspend [i8 0, label %loop
803+
i8 1, label %cleanup]
804+
cleanup:
805+
%mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
806+
call void @free(ptr %mem)
807+
br label %suspend
808+
suspend:
809+
%unused = call i1 @llvm.coro.end(ptr %hdl, i1 false, token none)
810+
ret ptr %hdl
811+
}
752812
753813
Intrinsics
754814
==========
@@ -1007,6 +1067,36 @@ with small positive and negative offsets).
10071067

10081068
A frontend should emit exactly one `coro.begin` intrinsic per coroutine.
10091069

1070+
.. _coro.begin.custom.abi:
1071+
1072+
'llvm.coro.begin.custom.abi' Intrinsic
1073+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1074+
::
1075+
1076+
declare ptr @llvm.coro.begin.custom.abi(token <id>, ptr <mem>, i32)
1077+
1078+
Overview:
1079+
"""""""""
1080+
1081+
The '``llvm.coro.begin.custom.abi``' intrinsic is used in place of the
1082+
`coro.begin` intrinsic that has an additional parameter to specify the custom
1083+
ABI for the coroutine. The return is identical to that of the `coro.begin`
1084+
intrinsic.
1085+
1086+
Arguments:
1087+
""""""""""
1088+
1089+
The first and second arguments are identical to those of the `coro.begin`
1090+
intrinsic.
1091+
1092+
The third argument is an i32 index of the generator list given to the
1093+
`CoroSplit` pass specifying the custom ABI generator lor this coroutine.
1094+
1095+
Semantics:
1096+
""""""""""
1097+
1098+
The semantics are identical to those of the `coro.begin` intrinsic.
1099+
10101100
.. _coro.free:
10111101

10121102
'llvm.coro.free' Intrinsic

0 commit comments

Comments
 (0)