<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [coroutines] Incorrect allocation elision of coroutine-frame when coroutine lifetime outlives stack-frame of caller"
   href="https://bugs.llvm.org/show_bug.cgi?id=34897">34897</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[coroutines] Incorrect allocation elision of coroutine-frame when coroutine lifetime outlives stack-frame of caller
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>C++
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>lewissbaker@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>dgregor@apple.com, llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=19256" name="attach_19256" title="Source for reproducing bug.">attachment 19256</a> <a href="attachment.cgi?id=19256&action=edit" title="Source for reproducing bug.">[details]</a></span>
Source for reproducing bug.

Some recent changes to cppcoro seem to have triggered a bug in the Clang
optimiser that is eliding the allocation of a coroutine frame in cases where
the coroutine outlives the lifetime of the caller.

Compile Coroutine_elision_bug.cpp with: -fcoroutines-ts -stdlib=libc++
-std=c++1z -O3

Inspect the assembly generated for `when_all_ready()` body.
This body should be constructing two 'make_when_all_task()' coroutines and
passing ownership of the coroutine handles to the returned
'when_all_ready_awaitable' object.

However, it seems to be allocating the first of the coroutines in the
stack-frame of the 'when_all_ready' function, while the the second coroutine
frame is correctly heap-allocated. This means the returned
'when_all_ready_awaitable' now has a reference to memory on the stack that is
discarded when the 'when_all_ready' call returns.

------

auto cppcoro::when_all_ready<cppcoro::task<void>, cppcoro::task<void>,
0>(cppcoro::task<void>&&, cppcoro::task<void>&&): # @auto
cppcoro::when_all_ready<cppcoro::task<void>, cppcoro::task<void>,
0>(cppcoro::task<void>&&, cppcoro::task<void>&&)
  push r15
  push r14
  push rbx
  sub rsp, 64
  mov rax, qword ptr [rsi]
  mov qword ptr [rsi], 0
  mov ecx, offset cppcoro::detail::when_all_task<void>
cppcoro::detail::make_when_all_task<cppcoro::task<void>, void,
0>(cppcoro::task<void>) [clone .cleanup]
  movq xmm0, rcx
  mov ecx, offset cppcoro::detail::when_all_task<void>
cppcoro::detail::make_when_all_task<cppcoro::task<void>, void,
0>(cppcoro::task<void>) [clone .resume]
  movq xmm1, rcx
  punpcklqdq xmm1, xmm0 # xmm1 = xmm1[0],xmm0[0]
  movdqa xmmword ptr [rsp], xmm1     <---- First coroutine frame is placed on
the stack
  mov qword ptr [rsp + 56], rax
  mov qword ptr [rsp + 24], 0
  mov byte ptr [rsp + 32], 0
  mov rbx, rdi
  mov r15, qword ptr [rdx]
  mov qword ptr [rdx], 0
  mov edi, 64
  call operator new(unsigned long)   <---- Second coroutine frame is
heap-allocated
  mov qword ptr [rax], offset cppcoro::detail::when_all_task<void>
cppcoro::detail::make_when_all_task<cppcoro::task<void>, void,
0>(cppcoro::task<void>) [clone .resume]
  mov qword ptr [rax + 8], offset cppcoro::detail::when_all_task<void>
cppcoro::detail::make_when_all_task<cppcoro::task<void>, void,
0>(cppcoro::task<void>) [clone .destroy]
  mov qword ptr [rax + 56], r15
  mov qword ptr [rax + 24], 0
  mov byte ptr [rax + 32], 0
  mov qword ptr [rbx], 3
  mov qword ptr [rbx + 8], 0
  mov rcx, rsp                       
  mov qword ptr [rbx + 16], rcx   <-- pointer to stack-frame-allocated
coroutine frame is written to return-value here
  mov qword ptr [rbx + 24], rax
  mov rax, rbx
  add rsp, 64
  pop rbx
  pop r14
  pop r15
  ret</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>