ychen marked 5 inline comments as done.
ychen added a comment.

In D97915#2829581 <https://reviews.llvm.org/D97915#2829581>, @ChuanqiXu wrote:

> A remained question.
>
> - what's the semantics if user specified their allocation/deallocation 
> functions?
>
> Previously, we discussed for the ::operator new and ::operator delete. But 
> what would we do for user specified allocation/deallocation functions?
> It looks like we would treat them just like `::operator new`. And it makes 
> sense at the first glance. But the problem comes from that we judge whether
> or not to over allocate a frame by this condition:
>
>   coro.align > align of new
>
> But if the user uses their new, it makes no sense to use the `align of new` 
> as the condition. On the other hand, if user specified their new function and 
> the 
> alignment requirement for their promise type, would it be better really that 
> the compiler do the extra transformation?
>
> May be we need to discuss with other guys who are more familiar with the C++ 
> standard to answer this.

I think @rjmccall could answer these. My understanding is that user-specified 
allocation/deallocation has the same semantics as their standard library's 
counterparts. `align of new` (aka __STDCPP_DEFAULT_NEW_ALIGNMENT__) should 
apply to both.



================
Comment at: clang/lib/CodeGen/CGCoroutine.cpp:743-744
+        CGM.getIntrinsic(llvm::Intrinsic::coro_align, SizeTy));
+    auto *AlignedUpAddr = EmitBuiltinAlignTo(AlignedAllocateCall, CoroAlign,
+                                             S.getAlignedAllocate(), true);
+    // rawFrame = frame;
----------------
ChuanqiXu wrote:
> ychen wrote:
> > ChuanqiXu wrote:
> > > ychen wrote:
> > > > ChuanqiXu wrote:
> > > > > Maybe we could calculate it in place instead of trying to call a 
> > > > > function which is not designed for llvm::value*. It looks like the 
> > > > > calculation isn't too complex.
> > > > I'm open to not calling `EmitBuiltinAlignTo`, which basically inline 
> > > > the useful parts of `EmitBuiltinAlignTo`.  The initial intention is 
> > > > code sharing and easy readability. What's the benefit of not calling it?
> > > Reusing code is good. But my main concern is that the design for the 
> > > interfaces. The current design smells bad to me. Another reason for 
> > > implement it in place is I think it is not very complex and easy to 
> > > understand.
> > > 
> > > Another option I got is to implement `EmitBuitinAlign` in LLVM (someplace 
> > > like `Local`), then the CodeGenFunction:: EmitBuitinAlign and this 
> > > function could use it.
> > > Reusing code is good. But my main concern is that the design for the 
> > > interfaces. The current design smells bad to me. Another reason for 
> > > implement it in place is I think it is not very complex and easy to 
> > > understand.
> > > 
> > > Another option I got is to implement `EmitBuitinAlign` in LLVM (someplace 
> > > like `Local`), then the CodeGenFunction:: EmitBuitinAlign and this 
> > > function could use it.
> > 
> > 
> I guess you forgot to reply what you want to say.
Yep, I meant to say the use of "void *" is removed.


================
Comment at: clang/lib/CodeGen/CGCoroutine.cpp:431-433
+  auto *Diff = Builder.CreateNSWSub(AlignCall, AlignOfNewInt);
+  auto *NewCoroSize = Builder.CreateAdd(CI->getArgOperand(CoroSizeIdx), Diff);
+  CI->setArgOperand(CoroSizeIdx, NewCoroSize);
----------------
ChuanqiXu wrote:
> In other comments, I find 'size += align - NEW_ALIGN + sizeof(void*);'. But I 
> don't find sizeof(void*) in this function.
Sorry, that's a stale comment. It should be `size += align - NEW_ALIGN`. The 
`sizeof(void*)` was supposed for the newly added raw memory pointer stored in 
the frame. In the current implementation, `sizeof(void*)` is factored into the 
`llvm.coro.size()` calculation because CoroFrame is responsible for allocating 
the extra raw memory pointer if it is needed at all.


================
Comment at: clang/lib/CodeGen/CGCoroutine.cpp:452-461
+  llvm::Function *RawFramePtrOffsetIntrin = CGF.CGM.getIntrinsic(
+      llvm::Intrinsic::coro_raw_frame_ptr_offset, CGF.Int32Ty);
+  auto *RawFramePtrOffset = CGF.Builder.CreateCall(RawFramePtrOffsetIntrin);
+  auto *FramePtrAddrStart =
+      CGF.Builder.CreateInBoundsGEP(CoroFree, {RawFramePtrOffset});
+  auto *FramePtrAddr = CGF.Builder.CreatePointerCast(
+      FramePtrAddrStart, CGF.Int8PtrTy->getPointerTo());
----------------
ChuanqiXu wrote:
> We allocate overaligned-frame like:
> ```
> | --- for align --- | --- true frame --- |
> ```
> And here we set the argument to the address of true frame. Then I wonder how 
> about the memory for the `for align` part. Would we still free them 
> correctly? Maybe I missed something.
> Would we still free them correctly? 
Yes, that's the tricky part. Using `f0` of `coro-alloc.cpp` as an example, 
`llvm.coro.raw.frame.ptr.addr` is called at alloc time to save the raw memory 
pointer to the coroutine frame.  Later at dealloc time, 
`llvm.coro.raw.frame.ptr.addr` is called again to load the raw memory pointer 
back and free it.


================
Comment at: clang/lib/CodeGen/CGCoroutine.cpp:466-472
+  if (Dealloc->getNumArgOperands() > 1) {
+    // Size may only be the second argument of allocator call.
+    if (auto *CoroSize =
+            dyn_cast<llvm::IntrinsicInst>(Dealloc->getArgOperand(1)))
+      if (CoroSize->getIntrinsicID() == llvm::Intrinsic::coro_size)
+        OverAllocateFrame(CGF, Dealloc, /*IsAlloc*/ false);
+  }
----------------
ChuanqiXu wrote:
> We don't need to handle this condition in this patch.
This handling is for `sized delete` (`void T::operator delete  ( void* ptr, 
std::size_t sz );`) instead of `aligned delete`. `sized delete` needs the same 
`size` that is used for `new`. Please check the `f3` test in `coro-alloc.cpp` 
(The test was missing the CHECK lines for this, I've added it.).


================
Comment at: llvm/lib/Transforms/Coroutines/CoroFrame.cpp:1133-1137
   // Create an entry for every spilled value.
   for (auto &S : FrameData.Spills) {
     FieldIDType Id = B.addField(S.first->getType(), None);
     FrameData.setFieldIndex(S.first, Id);
   }
----------------
ChuanqiXu wrote:
> Why we move this snippet to the front? Although it is not defined, the layout 
> for the current frame would be:
> ```
> | resume func addr | destroy func addr | promise | other things needed |
> ```
> Move this to the front may break this.
The intent is to structure the code better, no intention to change the frame 
layout here. My understanding is that `promise` already has a fixed offset 
ahead of this. `FrameData::Allocas` is ordered but there is no defined 
semantics. There seem no tests failing due to reordered frame layout. However, 
I might be wrong. Could you describe how it changes the layout?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97915/new/

https://reviews.llvm.org/D97915

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to