[coroutines] Store an address of destroy OR cleanup part in the coroutine frame.
authorGor Nishanov <GorNishanov@gmail.com>
Sat, 8 Oct 2016 00:22:50 +0000 (00:22 +0000)
committerGor Nishanov <GorNishanov@gmail.com>
Sat, 8 Oct 2016 00:22:50 +0000 (00:22 +0000)
commit1b6aec8e2562e494431b968bad0884e978bc4e2b
tree200bae198f5d76e4bbde91096de906a17a69bd8e
parent1023993a332e47c8fd648d4389336adb9d9e9888
[coroutines] Store an address of destroy OR cleanup part in the coroutine frame.

Summary:
If heap allocation of a coroutine is elided, we need to make sure that we will update an address stored in the coroutine frame from f.destroy to f.cleanup.
Before this change, CoroSplit synthesized these stores after coro.begin:

```
    store void (%f.Frame*)* @f.resume, void (%f.Frame*)** %resume.addr
    store void (%f.Frame*)* @f.destroy, void (%f.Frame*)** %destroy.addr

```

In those cases where we did heap elision, but were not able to devirtualize all indirect calls, destroy call will attempt to "free" the coroutine frame stored on the stack. Oops.

Now we use select to put an appropriate coroutine subfunction in the destroy slot. As bellow:

```
    store void (%f.Frame*)* @f.resume, void (%f.Frame*)** %resume.addr
    %0 = select i1 %need.alloc, void (%f.Frame*)* @f.destroy, void (%f.Frame*)* @f.cleanup
    store void (%f.Frame*)* %0, void (%f.Frame*)** %destroy.addr
```

Reviewers: majnemer

Subscribers: mehdi_amini, llvm-commits

Differential Revision: https://reviews.llvm.org/D25377

llvm-svn: 283625
llvm/lib/Transforms/Coroutines/CoroInstr.h
llvm/lib/Transforms/Coroutines/CoroSplit.cpp
llvm/test/Transforms/Coroutines/coro-split-00.ll