@@ -1744,7 +1744,7 @@ a call to ``llvm.coro.suspend.retcon`` after resuming abnormally.
1744
1744
In a yield-once coroutine, it is undefined behavior if the coroutine
1745
1745
executes a call to ``llvm.coro.suspend.retcon `` after resuming in any way.
1746
1746
1747
- .. _coro.await.suspend :
1747
+ .. _coro.await.suspend.void :
1748
1748
1749
1749
'llvm.coro.await.suspend.void' Intrinsic
1750
1750
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1758,9 +1758,19 @@ executes a call to ``llvm.coro.suspend.retcon`` after resuming in any way.
1758
1758
Overview:
1759
1759
"""""""""
1760
1760
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
1764
1774
'``void awaiter.await_suspend(...) ``' variant.
1765
1775
1766
1776
Arguments:
@@ -1781,7 +1791,7 @@ Semantics:
1781
1791
""""""""""
1782
1792
1783
1793
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
1785
1795
`await_suspend_function ` call during `CoroSplit `_ pass.
1786
1796
1787
1797
Example:
@@ -1802,7 +1812,7 @@ Example:
1802
1812
; after lowering
1803
1813
await.suspend:
1804
1814
%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
1806
1816
call void @await_suspend_function(
1807
1817
ptr %awaiter,
1808
1818
ptr %hdl)
@@ -1812,19 +1822,7 @@ Example:
1812
1822
; helper function example
1813
1823
define void @await_suspend_function(ptr %awaiter, ptr %hdl)
1814
1824
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
1828
1826
call void @"Awaiter::await_suspend"(ptr %awaiter, ptr %hdl.arg)
1829
1827
ret void
1830
1828
@@ -1842,9 +1840,19 @@ Example:
1842
1840
Overview:
1843
1841
"""""""""
1844
1842
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
1848
1856
'``bool awaiter.await_suspend(...) ``' variant.
1849
1857
1850
1858
Arguments:
@@ -1865,7 +1873,7 @@ Semantics:
1865
1873
""""""""""
1866
1874
1867
1875
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
1869
1877
`await_suspend_function ` call during `CoroSplit `_ pass.
1870
1878
1871
1879
If `await_suspend_function ` call returns `true `, the current coroutine is
@@ -1888,13 +1896,13 @@ Example:
1888
1896
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
1889
1897
...
1890
1898
await.ready:
1891
- call void @"Awaiter::await_ready "(ptr %awaiter)
1899
+ call void @"Awaiter::await_resume "(ptr %awaiter)
1892
1900
...
1893
1901
1894
1902
; after lowering
1895
1903
await.suspend:
1896
1904
%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
1898
1906
%resume = call i1 @await_suspend_function(
1899
1907
ptr %awaiter,
1900
1908
ptr %hdl)
@@ -1904,19 +1912,7 @@ Example:
1904
1912
; helper function example
1905
1913
define i1 @await_suspend_function(ptr %awaiter, ptr %hdl)
1906
1914
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
1920
1916
%resume = call i1 @"Awaiter::await_suspend"(ptr %awaiter, ptr %hdl.arg)
1921
1917
ret i1 %resume
1922
1918
@@ -1934,9 +1930,19 @@ Example:
1934
1930
Overview:
1935
1931
"""""""""
1936
1932
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
1940
1946
'``std::corouine_handle<> awaiter.await_suspend(...) ``' variant.
1941
1947
1942
1948
Arguments:
@@ -1957,7 +1963,7 @@ Semantics:
1957
1963
""""""""""
1958
1964
1959
1965
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
1961
1967
`await_suspend_function ` call during `CoroSplit `_ pass.
1962
1968
1963
1969
`await_suspend_function ` must return a pointer to a valid
@@ -1982,7 +1988,7 @@ Example:
1982
1988
; after lowering
1983
1989
await.suspend:
1984
1990
%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
1986
1992
%next = call ptr @await_suspend_function(
1987
1993
ptr %awaiter,
1988
1994
ptr %hdl)
@@ -1993,25 +1999,10 @@ Example:
1993
1999
; helper function example
1994
2000
define ptr @await_suspend_function(ptr %awaiter, ptr %hdl)
1995
2001
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
2015
2006
2016
2007
Coroutine Transformation Passes
2017
2008
===============================
@@ -2027,7 +2018,7 @@ and `coro.promise`_ intrinsics.
2027
2018
CoroSplit
2028
2019
---------
2029
2020
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 `_,
2031
2022
`coro.await.suspend.bool `_ and `coro.await.suspend.handle `_ intrinsics.
2032
2023
2033
2024
0 commit comments