[llvm-bugs] [Bug 34897] New: [coroutines] Incorrect allocation elision of coroutine-frame when coroutine lifetime outlives stack-frame of caller

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Oct 9 17:31:56 PDT 2017


https://bugs.llvm.org/show_bug.cgi?id=34897

            Bug ID: 34897
           Summary: [coroutines] Incorrect allocation elision of
                    coroutine-frame when coroutine lifetime outlives
                    stack-frame of caller
           Product: clang
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++
          Assignee: unassignedclangbugs at nondot.org
          Reporter: lewissbaker at gmail.com
                CC: dgregor at apple.com, llvm-bugs at lists.llvm.org

Created attachment 19256
  --> https://bugs.llvm.org/attachment.cgi?id=19256&action=edit
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

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20171010/0c1c0836/attachment-0001.html>


More information about the llvm-bugs mailing list