Depends on https://reviews.llvm.org/D42605.
An implementation of the behavior described in [dcl.fct.def.coroutine]/7:
when a promise type overloads operator new using a "placement new"
that takes the same argument types as the coroutine function, that
overload is used when allocating the coroutine frame.
Simply passing references to the coroutine function parameters directly
to operator new results in invariant violations in LLVM's coroutine
splitting pass, so this implementation modifies Clang codegen to
produce allocator-specific alloc/store/loads for each parameter being
forwarded to the allocator.
Test Plan: check-clang
First, thank you for doing this change!
Second, I am not sure that this part (CGCoroutine.cpp change) belongs in clang.
llvm CoroFrame is doing an unsafe transformation (it was safe until we got the arguments to operator new :-) ).
Moving the stores after the new that loads from those stores is an incorrect transformation. I think it needs to be addressed in llvm. getNotRelocatableInstructions function in CoroSplit.cpp needs to add special handling for AllocaInst and freeze the stores to that Alloca in the blocks preceeding the one with CoroBegin (getCoroBeginPredBlocks).
Also, for this to work for cases where parameter is used both in allocating function and in the body of the coroutine we need to have a copy. Currently, front-end does not create copies for scalar types (see CoroutineStmtBuilder::makeParamMoves() in SemaCoroutine.cpp). I think if we always create copies for all parameters, it will make this change more straightforward.
Third, this code does not handle cases where scalar values passed by reference to an allocation function or a struct passed by value:
Try this code on these:
or
I think if this code is changed according to my earlier suggestion of doing copies in clang and freezing stores in the llvm, it should take care the cases above.
These cases need to be added as tests to llvm\tests\Transforms\Coroutines