<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] escaping alloca from inlined function should not be included in the coroutine frame"
   href="https://bugs.llvm.org/show_bug.cgi?id=41877">41877</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[coroutines] escaping alloca from inlined function should not be included in the coroutine frame
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>new-bugs
          </td>
        </tr>

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

        <tr>
          <th>Hardware</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </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>new bugs
          </td>
        </tr>

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

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

        <tr>
          <th>CC</th>
          <td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre><a href="https://godbolt.org/z/CCl-bg">https://godbolt.org/z/CCl-bg</a>

CoroFrame analysis needs to pay attention to the lifetime.begin and .end
markers when deciding whether an escaping alloca should become part of the
coroutine frame or not.

In the example linked an pasted here for convenience:

// -std=c++2a -stdlib=libc++ -S -emit-llvm -g0 -O2
#include <experimental/coroutine>

using namespace std::experimental;

struct coro {
  struct promise_type {
    suspend_always initial_suspend() { return {};}
    suspend_always final_suspend() { return {};}
    void return_void() {}
    void unhandled_exception() {}
    coro get_return_object(){ return{}; }
  };
};

struct A {
    ~A();
};

void async(void*) noexcept;

struct Awaiter{
  bool await_ready() { return false; }    
  void await_resume() {}
  void await_suspend(coroutine_handle<> h) {
      A a;
      async(h.address());
  }
};

coro f() {
  co_await Awaiter{};
}

await_suspend will get inlined into "f".
Address of a local variable "a" escapes (to a destructor call).

The correct lowering is that A should no be included into the coroutine frame,
since its lifetime ends after the call to "async".

However, currently CoroFrame does not pay attention to the lifetime markers and
will make A to be part of the coroutine frame that may get destroyed before
async returns leading to bad outcomes.

CoroFrame needs to be improved to take advantage of lifetime marker
information. If we go there, and completely understand the lifetime of very
variable, we could also pack variables tighter in the coroutine frame.

Looking at the IR emitted right now, we can observe the problem:

1) Struct A is included in the coroutine frame

%_Z1fv.Frame = type { void (%_Z1fv.Frame*)*, void (%_Z1fv.Frame*)*,
%"struct.coro::promise_type", i2, %struct.A }

2) A is touched after we called async (and coroutine frame could be destroyed
there)

define internal fastcc void @_Z1fv.resume(%_Z1fv.Frame*) #0 personality i8* ...
                                               ; preds = %1
  %6 = bitcast %_Z1fv.Frame* %0 to i8*
  store i2 1, i2* %2, align 1
  %7 = getelementptr inbounds %_Z1fv.Frame, %_Z1fv.Frame* %0, i64 0, i32 4
  %8 = getelementptr inbounds %struct.A, %struct.A* %7, i64 0, i32 0
  tail call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %8) #2
  tail call void @_Z5asyncPv(i8* %6) #2
  tail call void @_ZN1AD1Ev(%struct.A* nonnull %7) #2 ; <==== BOOM
  tail call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %8) #2
...
}</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>