<div class="__aliyun_email_body_block"><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;">Hi all,</span></div><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;"><br ></span></div><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;">Recently I am trying to work on coroutine bug here: https://reviews.llvm.org/D101980.</span></div><div  style="clear:both;">This patch is trying to copy the arguments who had been marked with `byval` into the coroutine frame. </div><div  style="clear:both;">There summary in the link tells some background. </div><div  style="clear:both;">Simply,</div><div  style="clear:both;">(1) By the language standard, the arguments of coroutine should be copied into the `coroutine state`.</div><div  style="clear:both;">(2) The implementation now in LLVM would copy the arguments of coroutine into the coroutine frame if needed.</div><div  style="clear:both;">(3) However, the arguments in IR are not equal to the arguments in the source. For example, the following code in C++</div><div  style="clear:both;">```</div><div  style="clear:both;">void foo() {</div><div  style="clear:both;">    coro_func(A());</div><div  style="clear:both;">}</div><div  style="clear:both;">```</div><div  style="clear:both;">would be translated into something like:</div><div  style="clear:both;">```</div><div  style="clear:both;"><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;">void foo() {</div></div><div  style="clear:both;"><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;"></div><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;">     %a = alloca A</div></div><div  style="clear:both;"><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;">     ; initializing for %a</div></div><div  style="clear:both;"><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;">     coro_func(%a);</div><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;">}</div></div><div  style="clear:both;">```</div><div  style="clear:both;">So the actual argument type in IR becomes A* instead of A. And the current implementation in LLVM coroutine </div><div  style="clear:both;">module would only copy the pointer to A into the coroutine frame instead of A, which is the problem I want to solve.</div><div  style="clear:both;"><br ></div><div  style="clear:both;">I had thought we could handle these case by handling the arguments marked with `byval`. But as <span  class="__aliyun_at_block_1620801586290 __aliyun_at_block_" title="rjmccall@gmail.com" style="border:none;margin:0 2.0px 0 0;background-color:transparent;color:#0284c0;">@rjmccall</span> said, there are</div><div  style="clear:both;">cases where arguments are passed by value semantically and passed by reference actually. </div><div  style="clear:both;"><br ></div><div  style="clear:both;">So here is the decision we need to make. Should we mark all they arguments passed by value semantically in the frontend?</div><div  style="clear:both;">Or should we just emit the copy in the callee site for coroutines in the frontend?</div><div  style="clear:both;"><br ></div><div  style="clear:both;">It looks like the both solution would take many efforts. Then there are drawbacks for each of them.</div><div  style="clear:both;">First, for the solution based on attribute marks. The drawbacks are:</div><div  style="clear:both;">(1) What's the attribute should we use? The `byval` is deprecated actually. So we need to design a new attribute to mark the arguments</div><div  style="clear:both;">     of coroutine. I am not sure if it is a good idea to use a new attribute when we meet a new problem. It looks like there are too many</div><div  style="clear:both;">     attributes and metadata in Clang/LLVM now.</div><div  style="clear:both;">(2) The extra copy. There would be an extra copy in the coroutine to copy the arguments to the frame. Maybe we can do some peephole</div><div  style="clear:both;">     optimization to mitigate the problem.</div><div  style="clear:both;">(3) Multiple destruction problem. I am not sure if this the same problem <span  class="__aliyun_at_block_1620801586290 __aliyun_at_block_" title="rjmccall@gmail.com" style="border:none;margin:0 2.0px 0 0;background-color:transparent;color:#0284c0;">@rjmccall</span> mentioned about `move semantics`. My understanding is</div><div  style="clear:both;">```</div><div  style="clear:both;">class A{</div><div  style="clear:both;">     void* data_ptr;</div><div  style="clear:both;">     A(A&&);</div><div  style="clear:both;">     ~A() { if(data_ptr) delete data_ptr; }</div><div  style="clear:both;">};</div><div  style="clear:both;">void foo() {</div><div  style="clear:both;">    A a;</div><div  style="clear:both;">    coro_func(std::move(a));</div><div  style="clear:both;">}</div><div  style="clear:both;">```</div><div  style="clear:both;">     The problem here is that the data_ptr of A copied in the coroutine frame may be invalided by the destruction in the temporary produced</div><div  style="clear:both;">in the caller site if we choose to copy A into the frame instead of move. But we can't get the semantics about move in the middle end.</div><div  style="clear:both;">     The final problem about destruction looks the hardest to handle for the attribute based solutions.</div><div  style="clear:both;"><br ></div><div  style="clear:both;">     And for the solution based on emitting the copy in the callee site for coroutines,</div><div  style="clear:both;">(1) It would violate the principle of LLVM to handle the copy of arguments. LLVM would emit the copy in the caller site instead of callee site.</div><div  style="clear:both;">     I believe there must be some reasons that LLVM decides to emit the copy in the caller site. I hope someone could tell me if any one knows.</div><div  style="clear:both;"><span  style="font-size:14.0px;">     And it would make the styles to handle arguments broken in Clang/LLVM.</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">(2) It looks not easy to refactor this even only for coroutine. This is not a strong argument. I just say that we need a long time to do this refactoring.</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">     And there may be some bugs remained during this process.</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">(3) We need to teach other passes. If we choose to emit the copy in the callee site, the IR for coroutine now would look like:</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">```</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">void coro_func(A* %a) {</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">    %a.copy = alloca A</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">    copy %a to %a.copy</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">    ; use %a.copy instead of %a</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">}</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">```</span></div><div  style="clear:both;"><span  style="font-size:14.0px;">     This pattern should be eliminated by LLVM passes. So we need to teach LLVM passes to remain this structure, which means we need to insear guard codes</span></div><div  style="clear:both;">to many other passes.</div><div  style="clear:both;">     BTW, if we compile C++ code in debug mode, we would see a similar pattern:</div><div  style="clear:both;">```</div><div  style="clear:both;"><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;"><span  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:14.0px;">void coro_func(A* %a) {</span></div><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;"><span  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:14.0px;">    %a.addr = alloca A*</span></div><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;"><span  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:14.0px;">    store %a, %a.addr</span></div></div><div  style="clear:both;"><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;"><span  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:14.0px;">    %a.val = load %a.addr</span></div></div><div  style="clear:both;"><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;"><span  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:14.0px;"></span></div><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;"><span  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:14.0px;">    ; use %a.copy instead of %a.val</span></div><div  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;caret-color:#000000;color:#000000;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;font-style:normal;font-variant-caps:normal;font-weight:normal;text-align:start;text-indent:.0px;text-transform:none;background-color:#ffffff;text-decoration:none;clear:both;"><span  style="margin:.0px;padding:.0px;border:.0px;outline:.0px;font-size:14.0px;">}</span></div></div><div  style="clear:both;">```</div><div  style="clear:both;">     This pattern only copies the address of %a into the new allocated variables instead of copying the contents. I don't know the meaning of doing so now.</div><div  style="clear:both;"><br ></div><div  style="clear:both;">     So it is clearly that both solutions had some drawbacks and not easy to implement. Do you guys have any thoughts?</div><div  style="clear:both;"><br ></div><div  style="clear:both;">Thanks,</div><div  style="clear:both;">Chuanqi</div></div>