summaryrefslogtreecommitdiffstats
path: root/llvm/docs/Coroutines.rst
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/docs/Coroutines.rst')
-rw-r--r--llvm/docs/Coroutines.rst85
1 files changed, 67 insertions, 18 deletions
diff --git a/llvm/docs/Coroutines.rst b/llvm/docs/Coroutines.rst
index 0e7cde7aa38..d330d715f7c 100644
--- a/llvm/docs/Coroutines.rst
+++ b/llvm/docs/Coroutines.rst
@@ -110,7 +110,7 @@ The LLVM IR for this coroutine looks like this:
call void @free(i8* %mem)
br label %suspend
suspend:
- call void @llvm.coro.end(i8* %hdl, i1 false)
+ %unused = call i1 @llvm.coro.end(i8* %hdl, i1 false)
ret i8* %hdl
}
@@ -440,7 +440,7 @@ store the current value produced by a coroutine.
call void @free(i8* %mem)
br label %suspend
suspend:
- call void @llvm.coro.end(i8* %hdl, i1 false)
+ %unused = call i1 @llvm.coro.end(i8* %hdl, i1 false)
ret i8* %hdl
}
@@ -955,41 +955,90 @@ A frontend should emit exactly one `coro.id` intrinsic per coroutine.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- declare void @llvm.coro.end(i8* <handle>, i1 <unwind>)
+ declare i1 @llvm.coro.end(i8* <handle>, i1 <unwind>)
Overview:
"""""""""
The '``llvm.coro.end``' marks the point where execution of the resume part of
-the coroutine should end and control returns back to the caller.
+the coroutine should end and control should return to the caller.
Arguments:
""""""""""
-The first argument should refer to the coroutine handle of the enclosing coroutine.
+The first argument should refer to the coroutine handle of the enclosing
+coroutine. A frontend is allowed to supply null as the first parameter, in this
+case `coro-early` pass will replace the null with an appropriate coroutine
+handle value.
The second argument should be `true` if this coro.end is in the block that is
-part of the unwind sequence leaving the coroutine body due to exception prior to
-the first reaching any suspend points, and `false` otherwise.
+part of the unwind sequence leaving the coroutine body due to an exception and
+`false` otherwise.
Semantics:
""""""""""
-The `coro.end`_ intrinsic is a no-op during an initial invocation of the
-coroutine. When the coroutine resumes, the intrinsic marks the point when
-coroutine need to return control back to the caller.
+The purpose of this intrinsic is to allow frontends to mark the cleanup and
+other code that is only relevant during the initial invocation of the coroutine
+and should not be present in resume and destroy parts.
-This intrinsic is removed by the CoroSplit pass when a coroutine is split into
-the start, resume and destroy parts. In start part, the intrinsic is removed,
-in resume and destroy parts, it is replaced with `ret void` instructions and
+This intrinsic is lowered when a coroutine is split into
+the start, resume and destroy parts. In the start part, it is a no-op,
+in resume and destroy parts, it is replaced with `ret void` instruction and
the rest of the block containing `coro.end` instruction is discarded.
-
In landing pads it is replaced with an appropriate instruction to unwind to
-caller.
+caller. The handling of coro.end differs depending on whether the target is
+using landingpad or WinEH exception model.
+
+For landingpad based exception model, it is expected that frontend uses the
+`coro.end`_ intrinsic as follows:
+
+.. code-block:: llvm
+
+ ehcleanup:
+ %InResumePart = call i1 @llvm.coro.end(i8* null, i1 true)
+ br i1 %InResumePart, label %eh.resume, label %cleanup.cont
+
+ cleanup.cont:
+ ; rest of the cleanup
+
+ eh.resume:
+ %exn = load i8*, i8** %exn.slot, align 8
+ %sel = load i32, i32* %ehselector.slot, align 4
+ %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn, 0
+ %lpad.val29 = insertvalue { i8*, i32 } %lpad.val, i32 %sel, 1
+ resume { i8*, i32 } %lpad.val29
+
+The `CoroSpit` pass replaces `coro.end` with ``True`` in the resume functions,
+thus leading to immediate unwind to the caller, whereas in start function it
+is replaced with ``False``, thus allowing to proceed to the rest of the cleanup
+code that is only needed during initial invocation of the coroutine.
+
+For Windows Exception handling model, a frontend should attach a funclet bundle
+referring to an enclosing cleanuppad as follows:
+
+.. code-block:: text
-A frontend is allowed to supply null as the first parameter, in this case
-`coro-early` pass will replace the null with an appropriate coroutine handle
-value.
+ ehcleanup:
+ %tok = cleanuppad within none []
+ %unused = call i1 @llvm.coro.end(i8* null, i1 true) [ "funclet"(token %tok) ]
+ cleanupret from %tok unwind label %RestOfTheCleanup
+
+The `CoroSplit` pass, if the funclet bundle is present, will insert
+``cleanupret from %tok unwind to caller`` before
+the `coro.end`_ intrinsic and will remove the rest of the block.
+
+The following table summarizes the handling of `coro.end`_ intrinsic.
+
++--------------------------+-------------------+-------------------------------+
+| | In Start Function | In Resume/Destroy Functions |
++--------------------------+-------------------+-------------------------------+
+|unwind=false | nothing |``ret void`` |
++------------+-------------+-------------------+-------------------------------+
+| | WinEH | nothing |``cleanupret unwind to caller``|
+|unwind=true +-------------+-------------------+-------------------------------+
+| | Landingpad | nothing | nothing |
++------------+-------------+-------------------+-------------------------------+
.. _coro.suspend:
.. _suspend points:
OpenPOWER on IntegriCloud