<div class="__aliyun_email_body_block"><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;">I see. It looks you are right. Sorry to disturbing. I would check if the frontend would emit the copies for other arguments passed by value implicitly.</span></div><blockquote  style="margin-right:0;margin-top:0;margin-bottom:0;"><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;">------------------------------------------------------------------</span></div><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;">From:Xun Li <lxfind@gmail.com></span></div><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;">Send Time:2021年5月12日(星期三) 23:07</span></div><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;">To:chuanqi.xcq <yedeng.yd@linux.alibaba.com></span></div><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;">Cc:llvm-dev@lists.llvm.org <llvm-dev@lists.llvm.org>; cfe-dev <cfe-dev@lists.llvm.org>; rjmccall <rjmccall@gmail.com></span></div><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;">Subject:Re: [Coroutines] How to handle arguments passed by value semantically?</span></div><div  style="clear:both;"><span  style="font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#000000;"><br /></span></div>The description of the problem doesn't sound right to me.<br >Even when parameters are in the form of a byval pointer, their content<br >will still be copied into the local stack for coroutines correctly,<br >not just copying pointers. This is currently handled by the front-end.<br >For example: https://godbolt.org/z/EGoaMEje4<br >If you look at the IR of foo, there is a memcpy that copies the<br >parameter to local stack.<br ><br >On Wed, May 12, 2021 at 12:43 AM chuanqi.xcq<br ><yedeng.yd@linux.alibaba.com> wrote:<br >><br >> Hi all,<br >><br >> Recently I am trying to work on coroutine bug here: https://reviews.llvm.org/D101980.<br >> This patch is trying to copy the arguments who had been marked with `byval` into the coroutine frame.<br >> There summary in the link tells some background.<br >> Simply,<br >> (1) By the language standard, the arguments of coroutine should be copied into the `coroutine state`.<br >> (2) The implementation now in LLVM would copy the arguments of coroutine into the coroutine frame if needed.<br >> (3) However, the arguments in IR are not equal to the arguments in the source. For example, the following code in C++<br >> ```<br >> void foo() {<br >>     coro_func(A());<br >> }<br >> ```<br >> would be translated into something like:<br >> ```<br >> void foo() {<br >>      %a = alloca A<br >>      ; initializing for %a<br >>      coro_func(%a);<br >> }<br >> ```<br >> So the actual argument type in IR becomes A* instead of A. And the current implementation in LLVM coroutine<br >> module would only copy the pointer to A into the coroutine frame instead of A, which is the problem I want to solve.<br >><br >> I had thought we could handle these case by handling the arguments marked with `byval`. But as @rjmccall said, there are<br >> cases where arguments are passed by value semantically and passed by reference actually.<br >><br >> So here is the decision we need to make. Should we mark all they arguments passed by value semantically in the frontend?<br >> Or should we just emit the copy in the callee site for coroutines in the frontend?<br >><br >> It looks like the both solution would take many efforts. Then there are drawbacks for each of them.<br >> First, for the solution based on attribute marks. The drawbacks are:<br >> (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<br >>      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<br >>      attributes and metadata in Clang/LLVM now.<br >> (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<br >>      optimization to mitigate the problem.<br >> (3) Multiple destruction problem. I am not sure if this the same problem @rjmccall mentioned about `move semantics`. My understanding is<br >> ```<br >> class A{<br >>      void* data_ptr;<br >>      A(A&&);<br >>      ~A() { if(data_ptr) delete data_ptr; }<br >> };<br >> void foo() {<br >>     A a;<br >>     coro_func(std::move(a));<br >> }<br >> ```<br >>      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<br >> 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.<br >>      The final problem about destruction looks the hardest to handle for the attribute based solutions.<br >><br >>      And for the solution based on emitting the copy in the callee site for coroutines,<br >> (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.<br >>      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.<br >>      And it would make the styles to handle arguments broken in Clang/LLVM.<br >> (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.<br >>      And there may be some bugs remained during this process.<br >> (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:<br >> ```<br >> void coro_func(A* %a) {<br >>     %a.copy = alloca A<br >>     copy %a to %a.copy<br >>     ; use %a.copy instead of %a<br >> }<br >> ```<br >>      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<br >> to many other passes.<br >>      BTW, if we compile C++ code in debug mode, we would see a similar pattern:<br >> ```<br >> void coro_func(A* %a) {<br >>     %a.addr = alloca A*<br >>     store %a, %a.addr<br >>     %a.val = load %a.addr<br >>     ; use %a.copy instead of %a.val<br >> }<br >> ```<br >>      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.<br >><br >>      So it is clearly that both solutions had some drawbacks and not easy to implement. Do you guys have any thoughts?<br >><br >> Thanks,<br >> Chuanqi<br ><br ><br ><br >-- <br >Xun</blockquote></div>