Skip to content

Commit c09dc71

Browse files
committed
Improve docs
1 parent 10f0907 commit c09dc71

File tree

2 files changed

+55
-64
lines changed

2 files changed

+55
-64
lines changed

clang/lib/CodeGen/CGCoroutine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ static bool AwaitSuspendStmtCanThrow(const Stmt *S) {
191191
//
192192
// (*) llvm_coro_await_suspend_{void, bool, handle} is lowered to
193193
// helper(&x, frame) when it's certain not to interfere with
194-
// coroutine frame generation. await_suspend expression is
194+
// coroutine transform. await_suspend expression is
195195
// asynchronous to the coroutine body and not all analyses
196196
// and transformations can handle it correctly at the moment.
197197
//

llvm/docs/Coroutines.rst

Lines changed: 54 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,7 +1744,7 @@ a call to ``llvm.coro.suspend.retcon`` after resuming abnormally.
17441744
In a yield-once coroutine, it is undefined behavior if the coroutine
17451745
executes a call to ``llvm.coro.suspend.retcon`` after resuming in any way.
17461746

1747-
.. _coro.await.suspend:
1747+
.. _coro.await.suspend.void:
17481748

17491749
'llvm.coro.await.suspend.void' Intrinsic
17501750
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1758,9 +1758,19 @@ executes a call to ``llvm.coro.suspend.retcon`` after resuming in any way.
17581758
Overview:
17591759
"""""""""
17601760

1761-
The '``llvm.coro.await.suspend.void``' intrinsic hides C++ `await-suspend`
1762-
block code from optimizations on presplit coroutine body
1763-
to avoid miscompilations. This version of intrinsic corresponds to
1761+
The '``llvm.coro.await.suspend.void``' intrinsic encapsulates C++
1762+
`await-suspend` block until it can't interfere with coroutine transform.
1763+
1764+
The `await_suspend` block of `co_await` is essentially asynchronous
1765+
to the execution of the coroutine. Inlining it normally into an unsplit
1766+
coroutine can cause miscompilation because the coroutine CFG misrepresents
1767+
the true control flow of the program: things that happen in the
1768+
await_suspend are not guaranteed to happen prior to the resumption of the
1769+
coroutine, and things that happen after the resumption of the coroutine
1770+
(including its exit and the potential deallocation of the coroutine frame)
1771+
are not guaranteed to happen only after the end of `await_suspend`.
1772+
1773+
This version of intrinsic corresponds to
17641774
'``void awaiter.await_suspend(...)``' variant.
17651775

17661776
Arguments:
@@ -1781,7 +1791,7 @@ Semantics:
17811791
""""""""""
17821792

17831793
The intrinsic must be used between corresponding `coro.save`_ and
1784-
`coro.suspend`_ calls. It is lowered to an inlined
1794+
`coro.suspend`_ calls. It is lowered to a direct
17851795
`await_suspend_function` call during `CoroSplit`_ pass.
17861796

17871797
Example:
@@ -1802,7 +1812,7 @@ Example:
18021812
; after lowering
18031813
await.suspend:
18041814
%save = call token @llvm.coro.save(ptr %hdl)
1805-
; the call to await_suspend_function is inlined
1815+
; the call to await_suspend_function can be inlined
18061816
call void @await_suspend_function(
18071817
ptr %awaiter,
18081818
ptr %hdl)
@@ -1812,19 +1822,7 @@ Example:
18121822
; helper function example
18131823
define void @await_suspend_function(ptr %awaiter, ptr %hdl)
18141824
entry:
1815-
%hdl.tmp = alloca %"struct.std::coroutine_handle"
1816-
%hdl.result.tmp = alloca %"struct.std::coroutine_handle"
1817-
%hdl.promise.tmp = alloca %"struct.std::coroutine_handle.0"
1818-
%hdl.promise = call ptr @"std::corouine_handle<promise_type>::from_address"(ptr %hdl)
1819-
%hdl.promise.tmp.dive = getelementptr inbounds %"struct.std::coroutine_handle.0",
1820-
ptr %hdl.promise.tmp, i32 0, i32 0
1821-
%hdl.promise.tmp.dive2 = getelementptr inbounds %"struct.std::coroutine_handle",
1822-
ptr %hdl.promise.tmp.dive, i32 0, i32 0
1823-
store ptr %hdl.promise, ptr %hdl.promise.tmp.dive2
1824-
call void @llvm.memcpy.p0.p0.i64(ptr %hdl.tmp, ptr %hdl.promise.tmp, i64 8, i1 false)
1825-
%hdl.tmp.dive = getelementptr inbounds %"struct.std::coroutine_handle",
1826-
ptr %hdl.tmp, i32 0, i32 0
1827-
%hdl.arg = load ptr, ptr %hdl.tmp.dive
1825+
%hdl.arg = ... ; construct std::coroutine_handle from %hdl
18281826
call void @"Awaiter::await_suspend"(ptr %awaiter, ptr %hdl.arg)
18291827
ret void
18301828
@@ -1842,9 +1840,19 @@ Example:
18421840
Overview:
18431841
"""""""""
18441842

1845-
The '``llvm.coro.await.suspend.bool``' intrinsic hides C++ `await-suspend`
1846-
block code from optimizations on presplit coroutine body
1847-
to avoid miscompilations. This version of intrinsic corresponds to
1843+
The '``llvm.coro.await.suspend.bool``' intrinsic encapsulates C++
1844+
`await-suspend` block until it can't interfere with coroutine transform.
1845+
1846+
The `await_suspend` block of `co_await` is essentially asynchronous
1847+
to the execution of the coroutine. Inlining it normally into an unsplit
1848+
coroutine can cause miscompilation because the coroutine CFG misrepresents
1849+
the true control flow of the program: things that happen in the
1850+
await_suspend are not guaranteed to happen prior to the resumption of the
1851+
coroutine, and things that happen after the resumption of the coroutine
1852+
(including its exit and the potential deallocation of the coroutine frame)
1853+
are not guaranteed to happen only after the end of `await_suspend`.
1854+
1855+
This version of intrinsic corresponds to
18481856
'``bool awaiter.await_suspend(...)``' variant.
18491857

18501858
Arguments:
@@ -1865,7 +1873,7 @@ Semantics:
18651873
""""""""""
18661874

18671875
The intrinsic must be used between corresponding `coro.save`_ and
1868-
`coro.suspend`_ calls. It is lowered to an inlined
1876+
`coro.suspend`_ calls. It is lowered to a direct
18691877
`await_suspend_function` call during `CoroSplit`_ pass.
18701878

18711879
If `await_suspend_function` call returns `true`, the current coroutine is
@@ -1888,13 +1896,13 @@ Example:
18881896
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
18891897
...
18901898
await.ready:
1891-
call void @"Awaiter::await_ready"(ptr %awaiter)
1899+
call void @"Awaiter::await_resume"(ptr %awaiter)
18921900
...
18931901
18941902
; after lowering
18951903
await.suspend:
18961904
%save = call token @llvm.coro.save(ptr %hdl)
1897-
; the call to await_suspend_function is inlined
1905+
; the call to await_suspend_function can inlined
18981906
%resume = call i1 @await_suspend_function(
18991907
ptr %awaiter,
19001908
ptr %hdl)
@@ -1904,19 +1912,7 @@ Example:
19041912
; helper function example
19051913
define i1 @await_suspend_function(ptr %awaiter, ptr %hdl)
19061914
entry:
1907-
%hdl.tmp = alloca %"struct.std::coroutine_handle"
1908-
%hdl.result.tmp = alloca %"struct.std::coroutine_handle"
1909-
%hdl.promise.tmp = alloca %"struct.std::coroutine_handle.0"
1910-
%hdl.promise = call ptr @"std::corouine_handle<promise_type>::from_address"(ptr %hdl)
1911-
%hdl.promise.tmp.dive = getelementptr inbounds %"struct.std::coroutine_handle.0",
1912-
ptr %hdl.promise.tmp, i32 0, i32 0
1913-
%hdl.promise.tmp.dive2 = getelementptr inbounds %"struct.std::coroutine_handle",
1914-
ptr %hdl.promise.tmp.dive, i32 0, i32 0
1915-
store ptr %hdl.promise, ptr %hdl.promise.tmp.dive2
1916-
call void @llvm.memcpy.p0.p0.i64(ptr %hdl.tmp, ptr %hdl.promise.tmp, i64 8, i1 false)
1917-
%hdl.tmp.dive = getelementptr inbounds %"struct.std::coroutine_handle",
1918-
ptr %hdl.tmp, i32 0, i32 0
1919-
%hdl.arg = load ptr, ptr %hdl.tmp.dive
1915+
%hdl.arg = ... ; construct std::coroutine_handle from %hdl
19201916
%resume = call i1 @"Awaiter::await_suspend"(ptr %awaiter, ptr %hdl.arg)
19211917
ret i1 %resume
19221918
@@ -1934,9 +1930,19 @@ Example:
19341930
Overview:
19351931
"""""""""
19361932

1937-
The '``llvm.coro.await.suspend.handle``' intrinsic hides C++ `await-suspend`
1938-
block code from optimizations on presplit coroutine body
1939-
to avoid miscompilations. This version of intrinsic corresponds to
1933+
The '``llvm.coro.await.suspend.handle``' intrinsic encapsulates C++
1934+
`await-suspend` block until it can't interfere with coroutine transform.
1935+
1936+
The `await_suspend` block of `co_await` is essentially asynchronous
1937+
to the execution of the coroutine. Inlining it normally into an unsplit
1938+
coroutine can cause miscompilation because the coroutine CFG misrepresents
1939+
the true control flow of the program: things that happen in the
1940+
await_suspend are not guaranteed to happen prior to the resumption of the
1941+
coroutine, and things that happen after the resumption of the coroutine
1942+
(including its exit and the potential deallocation of the coroutine frame)
1943+
are not guaranteed to happen only after the end of `await_suspend`.
1944+
1945+
This version of intrinsic corresponds to
19401946
'``std::corouine_handle<> awaiter.await_suspend(...)``' variant.
19411947

19421948
Arguments:
@@ -1957,7 +1963,7 @@ Semantics:
19571963
""""""""""
19581964

19591965
The intrinsic must be used between corresponding `coro.save`_ and
1960-
`coro.suspend`_ calls. It is lowered to an inlined
1966+
`coro.suspend`_ calls. It is lowered to a direct
19611967
`await_suspend_function` call during `CoroSplit`_ pass.
19621968

19631969
`await_suspend_function` must return a pointer to a valid
@@ -1982,7 +1988,7 @@ Example:
19821988
; after lowering
19831989
await.suspend:
19841990
%save = call token @llvm.coro.save(ptr %hdl)
1985-
; the call to await_suspend_function is inlined
1991+
; the call to await_suspend_function can be inlined
19861992
%next = call ptr @await_suspend_function(
19871993
ptr %awaiter,
19881994
ptr %hdl)
@@ -1993,25 +1999,10 @@ Example:
19931999
; helper function example
19942000
define ptr @await_suspend_function(ptr %awaiter, ptr %hdl)
19952001
entry:
1996-
%hdl.tmp = alloca %"struct.std::coroutine_handle"
1997-
%hdl.result.tmp = alloca %"struct.std::coroutine_handle"
1998-
%hdl.promise.tmp = alloca %"struct.std::coroutine_handle.0"
1999-
%hdl.promise = call ptr @"std::corouine_handle<promise_type>::from_address"(ptr %hdl)
2000-
%hdl.promise.tmp.dive = getelementptr inbounds %"struct.std::coroutine_handle.0",
2001-
ptr %hdl.promise.tmp, i32 0, i32 0
2002-
%hdl.promise.tmp.dive2 = getelementptr inbounds %"struct.std::coroutine_handle",
2003-
ptr %hdl.promise.tmp.dive, i32 0, i32 0
2004-
store ptr %hdl.promise, ptr %hdl.promise.tmp.dive2
2005-
call void @llvm.memcpy.p0.p0.i64(ptr %hdl.tmp, ptr %hdl.promise.tmp, i64 8, i1 false)
2006-
%hdl.tmp.dive = getelementptr inbounds %"struct.std::coroutine_handle",
2007-
ptr %hdl.tmp, i32 0, i32 0
2008-
%hdl.arg = load ptr, ptr %hdl.tmp.dive
2009-
%hdl.result = call ptr @"Awaiter::await_suspend"(ptr %awaiter, ptr %hdl.arg)
2010-
%hdl.result.tmp.dive = getelementptr inbounds %"struct.std::coroutine_handle",
2011-
ptr %hdl.result.tmp, i32 0, i32 0
2012-
store ptr %hdl.result, ptr %hdl.result.tmp.dive
2013-
%result.address = call ptr @"std::corouine_handle<>::address"(ptr %hdl.result.tmp)
2014-
ret ptr %result.address
2002+
%hdl.arg = ... ; construct std::coroutine_handle from %hdl
2003+
%hdl.raw = call ptr @"Awaiter::await_suspend"(ptr %awaiter, ptr %hdl.arg)
2004+
%hdl.result = ... ; get address of returned coroutine handle
2005+
ret ptr %hdl.result
20152006
20162007
Coroutine Transformation Passes
20172008
===============================
@@ -2027,7 +2018,7 @@ and `coro.promise`_ intrinsics.
20272018
CoroSplit
20282019
---------
20292020
The pass CoroSplit builds coroutine frame and outlines resume and destroy parts
2030-
into separate functions. This pass also lowers `coro.await.suspend`_,
2021+
into separate functions. This pass also lowers `coro.await.suspend.void`_,
20312022
`coro.await.suspend.bool`_ and `coro.await.suspend.handle`_ intrinsics.
20322023

20332024

0 commit comments

Comments
 (0)