[PATCH] D25258: [coroutines] Create allocation and deallocation sub-statements.
GorNishanov abandoned this revision. GorNishanov added a comment. I'll simplify and split it into super tiny microscopic patches to have a better chance of being reviewed. https://reviews.llvm.org/D25258 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25258: [coroutines] Create allocation and deallocation sub-statements.
GorNishanov added a comment. friendly ping https://reviews.llvm.org/D25258 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25258: [coroutines] Create allocation and deallocation sub-statements.
GorNishanov added a comment. friendly ping https://reviews.llvm.org/D25258 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25258: [coroutines] Create allocation and deallocation sub-statements.
GorNishanov updated this revision to Diff 73835. GorNishanov added a comment. Addressed review comments. Anything else, @rsmith? 1. compute default new align and pass it to coro.id 2. fix typo in comment https://reviews.llvm.org/D25258 Files: include/clang/AST/StmtCXX.h include/clang/Basic/DiagnosticSemaKinds.td lib/CodeGen/CGCoroutine.cpp lib/CodeGen/CGStmt.cpp lib/CodeGen/CodeGenFunction.h lib/Sema/SemaCoroutine.cpp test/CodeGenCoroutines/coro-alloc.cpp test/SemaCXX/coroutines.cpp Index: test/SemaCXX/coroutines.cpp === --- test/SemaCXX/coroutines.cpp +++ test/SemaCXX/coroutines.cpp @@ -143,13 +143,12 @@ } void only_coreturn() { - co_return; // expected-warning {{'co_return' used in a function that uses neither 'co_await' nor 'co_yield'}} + co_return; // OK } void mixed_coreturn(bool b) { if (b) -// expected-warning@+1 {{'co_return' used in a function that uses neither}} -co_return; // expected-note {{use of 'co_return'}} +co_return; // expected-note {{use of 'co_return' here}} else return; // expected-error {{not allowed in coroutine}} } Index: test/CodeGenCoroutines/coro-alloc.cpp === --- /dev/null +++ test/CodeGenCoroutines/coro-alloc.cpp @@ -0,0 +1,118 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s + +namespace std { +namespace experimental { +template +struct coroutine_traits; // expected-note {{declared here}} +} +} + +struct suspend_always { + bool await_ready() { return false; } + void await_suspend() {} + void await_resume() {} +}; + +struct global_new_delete_tag {}; + +template<> +struct std::experimental::coroutine_traits{ + struct promise_type { +void get_return_object() {} +suspend_always initial_suspend() { return {}; } +suspend_always final_suspend() { return {}; } +void return_void() {} + }; +}; + +// CHECK-LABEL: f0( +extern "C" void f0(global_new_delete_tag) { + // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16 + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call i8* @_Znwm(i64 %[[SIZE]]) + + // CHECK: coro.destroy.label: + // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame() + // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) + // CHECK: call void @_ZdlPv(i8* %[[MEM]]) + co_return; +} + +struct promise_new_tag {}; + +template<> +struct std::experimental::coroutine_traits { + struct promise_type { +void *operator new(unsigned long); +void get_return_object() {} +suspend_always initial_suspend() { return {}; } +suspend_always final_suspend() { return {}; } +void return_void() {} + }; +}; + +// CHECK-LABEL: f1( +extern "C" void f1(promise_new_tag ) { + // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16 + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call i8* @_ZNSt12experimental16coroutine_traitsIJv15promise_new_tagEE12promise_typenwEm(i64 %[[SIZE]]) + + // CHECK: coro.destroy.label: + // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame() + // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) + // CHECK: call void @_ZdlPv(i8* %[[MEM]]) + co_return; +} + +struct promise_delete_tag {}; + +template<> +struct std::experimental::coroutine_traits { + struct promise_type { +void operator delete(void*); +void get_return_object() {} +suspend_always initial_suspend() { return {}; } +suspend_always final_suspend() { return {}; } +void return_void() {} + }; +}; + +// CHECK-LABEL: f2( +extern "C" void f2(promise_delete_tag) { + // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16 + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call i8* @_Znwm(i64 %[[SIZE]]) + + // CHECK: coro.destroy.label: + // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame() + // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) + // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJv18promise_delete_tagEE12promise_typedlEPv(i8* %[[MEM]]) + co_return; +} + +struct promise_sized_delete_tag {}; + +template<> +struct std::experimental::coroutine_traits { + struct promise_type { +void operator delete(void*, unsigned long); +void get_return_object() {} +suspend_always initial_suspend() { return {}; } +suspend_always final_suspend() { return {}; } +void return_void() {} + }; +}; + +// CHECK-LABEL: f3( +extern "C" void f3(promise_sized_delete_tag) { + // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16 + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call i8* @_Znwm(i64 %[[SIZE]]) + + // CHECK: coro.destroy.label: + // CHECK: %[[FRAME:.+]] = call i8*
[PATCH] D25258: [coroutines] Create allocation and deallocation sub-statements.
GorNishanov added inline comments. > majnemer wrote in CGCoroutine.cpp:68-69 > I think that's just `CGM.getContext().getTargetInfo().getSuitableAlign() / > CGM.getContext().getTargetInfo().getCharWidth()` Yay! One less FIXME. I think I will make it to match __STDCPP_DEFAULT_NEW_ALIGNMENT__: Builder.defineMacro("__STDCPP_DEFAULT_NEW_ALIGNMENT__", Twine(TI.getNewAlign() / TI.getCharWidth()) + TI.getTypeConstantSuffix(TI.getSizeType())); > SemaCoroutine.cpp:570 > + > + // Build allocation function and deallocation expressions. > + Expr *Allocation = nullptr; Remove 'function' from the comment to read: // Build allocation and deallocation expressions. https://reviews.llvm.org/D25258 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25258: [coroutines] Create allocation and deallocation sub-statements.
majnemer added inline comments. > CGCoroutine.cpp:68-69 > +void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt ) { > + auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy()); > + // FIXME: Instead of 0, pass an equivalent of alignas(maxalign_t). > + auto *CoroId = I think that's just `CGM.getContext().getTargetInfo().getSuitableAlign() / CGM.getContext().getTargetInfo().getCharWidth()` https://reviews.llvm.org/D25258 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D25258: [coroutines] Create allocation and deallocation sub-statements.
GorNishanov created this revision. GorNishanov added reviewers: rsmith, EricWF. GorNishanov added a subscriber: cfe-commits. Herald added a subscriber: mehdi_amini. 1. Sema: Add allocation / deallocation substatements. 2. Sema: Add labels to final-suspend and deallocation substatements. 3. Sema: Allow co_return in a coroutine all by itself 4. CG: Emit allocation and deallocation + test https://reviews.llvm.org/D25258 Files: include/clang/AST/StmtCXX.h include/clang/Basic/DiagnosticSemaKinds.td lib/CodeGen/CGCoroutine.cpp lib/CodeGen/CGStmt.cpp lib/CodeGen/CodeGenFunction.h lib/Sema/SemaCoroutine.cpp test/CodeGenCoroutines/coro-alloc.cpp test/SemaCXX/coroutines.cpp Index: test/SemaCXX/coroutines.cpp === --- test/SemaCXX/coroutines.cpp +++ test/SemaCXX/coroutines.cpp @@ -143,13 +143,12 @@ } void only_coreturn() { - co_return; // expected-warning {{'co_return' used in a function that uses neither 'co_await' nor 'co_yield'}} + co_return; // OK } void mixed_coreturn(bool b) { if (b) -// expected-warning@+1 {{'co_return' used in a function that uses neither}} -co_return; // expected-note {{use of 'co_return'}} +co_return; // expected-note {{use of 'co_return' here}} else return; // expected-error {{not allowed in coroutine}} } Index: test/CodeGenCoroutines/coro-alloc.cpp === --- /dev/null +++ test/CodeGenCoroutines/coro-alloc.cpp @@ -0,0 +1,118 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s + +namespace std { +namespace experimental { +template +struct coroutine_traits; // expected-note {{declared here}} +} +} + +struct suspend_always { + bool await_ready() { return false; } + void await_suspend() {} + void await_resume() {} +}; + +struct global_new_delete_tag {}; + +template<> +struct std::experimental::coroutine_traits{ + struct promise_type { +void get_return_object() {} +suspend_always initial_suspend() { return {}; } +suspend_always final_suspend() { return {}; } +void return_void() {} + }; +}; + +// CHECK-LABEL: f0( +extern "C" void f0(global_new_delete_tag) { + // CHECK: %[[ID:.+]] = call token @llvm.coro.id( + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call i8* @_Znwm(i64 %[[SIZE]]) + + // CHECK: coro.destroy.label: + // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame() + // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) + // CHECK: call void @_ZdlPv(i8* %[[MEM]]) + co_return; +} + +struct promise_new_tag {}; + +template<> +struct std::experimental::coroutine_traits { + struct promise_type { +void *operator new(unsigned long); +void get_return_object() {} +suspend_always initial_suspend() { return {}; } +suspend_always final_suspend() { return {}; } +void return_void() {} + }; +}; + +// CHECK-LABEL: f1( +extern "C" void f1(promise_new_tag ) { + // CHECK: %[[ID:.+]] = call token @llvm.coro.id( + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call i8* @_ZNSt12experimental16coroutine_traitsIJv15promise_new_tagEE12promise_typenwEm(i64 %[[SIZE]]) + + // CHECK: coro.destroy.label: + // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame() + // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) + // CHECK: call void @_ZdlPv(i8* %[[MEM]]) + co_return; +} + +struct promise_delete_tag {}; + +template<> +struct std::experimental::coroutine_traits { + struct promise_type { +void operator delete(void*); +void get_return_object() {} +suspend_always initial_suspend() { return {}; } +suspend_always final_suspend() { return {}; } +void return_void() {} + }; +}; + +// CHECK-LABEL: f2( +extern "C" void f2(promise_delete_tag) { + // CHECK: %[[ID:.+]] = call token @llvm.coro.id( + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call i8* @_Znwm(i64 %[[SIZE]]) + + // CHECK: coro.destroy.label: + // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame() + // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) + // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJv18promise_delete_tagEE12promise_typedlEPv(i8* %[[MEM]]) + co_return; +} + +struct promise_sized_delete_tag {}; + +template<> +struct std::experimental::coroutine_traits { + struct promise_type { +void operator delete(void*, unsigned long); +void get_return_object() {} +suspend_always initial_suspend() { return {}; } +suspend_always final_suspend() { return {}; } +void return_void() {} + }; +}; + +// CHECK-LABEL: f3( +extern "C" void f3(promise_sized_delete_tag) { + // CHECK: %[[ID:.+]] = call token @llvm.coro.id( + // CHECK: