C++ Coroutines
This page describes the GCC implementation state for the C++ coroutines TS.
The objective of this work is to provide an implementation of the coroutines facility as accepted into the C++20 working draft.
Coroutines are part of C++ 20 and implemented in GCC 10. Much of this page describes the moving target and status during development.
Implementation State
Development branch: 'c++-coroutines' (svn://gcc.gnu.org/svn/gcc/branches/c++-coroutines). Reporting bugs
The branch was created, by Iain Sandoe, Sept 2018
The specification is fairly stable now [IS for C++20] as is the design. However, the implementation is ongoing and at a given time an area you might be interested could be unimplemented or incomplete/fragile.
Notable events:
- Sept 2018 - Project started.
- Jan 2019 - Trivial coroutines supporting only co_return.
- Feb 2019 - Basic coroutines without function arguments or local variables live across suspend points.
- Mar 2019
- WG21 votes to merge the coroutines TS into the IS draft for C++20.
- Drafted an ABI document and circulated to possible interested parties.
- May 2019
- function params usable in the coroutines.
- June 2019
- Function params with CTORs usable in coroutines.
- local scalar variables usable across suspend points
- July 2019
- Example generator including multiple layers of templates and local state works.
- coroutines move forward in the draft standard for C++20 without amendment
- 2020
- Merged to trunk, released in GCC 10
Invoking the Compiler
g++ -fcoroutines
Bugs
Bugs should be reported by the usual mechanism.
Design
Interoperation goals
- With other compilers at the binary level [i.e. that coroutines can call other coroutines compiled by other toolchains on the same platform]. This motivates an agreed ABI between "vendors" (in practice: MSVC, clang and GCC).
- With other compilers at the library level [i.e. that, for example, the libc++ should be buildable by GCC and, in so far as it is possible libstdc++ by clang]. This motivates using the same builtin function names (where these are exposed at the user level) or, alternately, proposing changes/new names should the GCC implementation show such a need.
Design Outline
The design is split along three lines (the implementation is in the C++ front end and the tree passes in the middle end):
- Process the IS requirements for semantic content in the Front End retaining library builtins, but lowering control flow to a "IFN_CO_YIELD()" which wraps the suspend / resume deferring the split until a later lowering. The intention here is that we present the middle end with mostly unspecialized code, and that the placement of EH edges can be done by the "normal" front end code. One difference from other implementations is that we outline the "ramp" function early so that GCC's ME incliners can get a good view of its size in the analysis phases that precede LTO.
- Lower the builtins early in the ME pipeline (mostly trivial inspection of coroutine frame offsets)
- Re-write IFN_CO_YIELD, deferred to post-LTO (this was expected to produce the best opportunities for optimisation, but it's a CHECK-ME to compare pre and post). This rewrites the actor function so that the suspend/resume paths are distinct from the destruction ones, allowing the ME optimiser to inline the functionality separately and DCE the unused portions.
- Frame allocation, deferred to very late in the tree passes, so that the frame can be revised (with elimination of dead entries) or allocated in the caller's stack frame, should that be possible [NOTE: this is a future objective, not part of the current work].
- Library support. This is a single header (there's no object code in the current designs, although future library additions are planned once the coroutines implementation is available).
Examples
Without an existing library header (currently unimplemented), the best place to look for examples of coroutines that are functional with the on-going implementation is in the testsuite.
For general testcases (e.g. of syntax or error reporting) the examples are found in svn://gcc.gnu.org/svn/gcc/branches/c++-coroutines/gcc/testsuite/g++.dg/coroutines
For testcases that involve code generation that might be optimisation-level-sensitive, the examples are found in svn://gcc.gnu.org/svn/gcc/branches/c++-coroutines/gcc/testsuite/g++.dg/coroutines/torture (a conventional name in GCC testing to indicate that a test is exercised for a number of different optimisations and with LTO etc.)
Once the library header is implemented and installs with libstdc++, it will be feasible to add some small examples here.
Timeline
- September 21st 2018 - Branch creation.
- January 23rd 2019 - Trivial coroutines supporting only co_return.
- February 12th 2019 - Basic coroutines without function arguments or local variables live across suspend points.
- June 2nd, 2019 - Function parameters.
- June 12th, 2019 - Function local scalar values.
- June 22nd, 2019 - Function parameters with CTORs.
- July 7th, 2019 - Mid-suspend destruction.
- July 17th, 2019 - Generator with multiple levels of template instantiation and contained iterator state work.
Related Events
- LLVM conference October 2018. Design discussion with the clang implementors.
- ISO WG21 November 2018. Contributed to analysis and discussion of the proposed designs
- ISO WG21 February 2019.
- Contributed to analysis and discussion of the ongoing design
co-authored a paper on the implementation constraints (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1492r0.pdf)
contributed editorial input to a second paper on use cases (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1493r0.pdf)
- euroLLVM ABI discussion with clang implementors.
- ISO WG21 July 2019 Contributed to design discussion, reviewed ABI decisions with clang and MSVC engineers.
Documentation
http://wg21.link/n4775 Working Draft, C++ Coroutines.
- Draft ABI document "Coroutines: ABI discussion" (please ask me if you need a link to this, it is not yet public)