r333379 - [coroutines] Pass implicit object parameter to promise ctor (fix BUG37604)

2018-05-28 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon May 28 11:08:47 2018
New Revision: 79

URL: http://llvm.org/viewvc/llvm-project?rev=79&view=rev
Log:
[coroutines] Pass implicit object parameter to promise ctor (fix BUG37604)

Summary:
Complete the implementation of p0914r1.
Implicit object parameter should be passed to a promise constructor.

Fixes: https://bugs.llvm.org/show_bug.cgi?id=37604

Reviewers: modocache, rsmith, lewissbaker

Reviewed By: modocache

Subscribers: cfe-commits, EricWF

Differential Revision: https://reviews.llvm.org/D47454

Modified:
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-params.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=79&r1=78&r2=79&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Mon May 28 11:08:47 2018
@@ -510,6 +510,20 @@ VarDecl *Sema::buildCoroutinePromise(Sou
   // Build a list of arguments, based on the coroutine functions arguments,
   // that will be passed to the promise type's constructor.
   llvm::SmallVector CtorArgExprs;
+
+  // Add implicit object parameter.
+  if (auto *MD = dyn_cast(FD)) {
+if (MD->isInstance() && !isLambdaCallOperator(MD)) {
+  ExprResult ThisExpr = ActOnCXXThis(Loc);
+  if (ThisExpr.isInvalid())
+return nullptr;
+  ThisExpr = CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
+  if (ThisExpr.isInvalid())
+return nullptr;
+  CtorArgExprs.push_back(ThisExpr.get());
+}
+  }
+
   auto &Moves = ScopeInfo->CoroutineParameterMoves;
   for (auto *PD : FD->parameters()) {
 if (PD->getType()->isDependentType())

Modified: cfe/trunk/test/CodeGenCoroutines/coro-params.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-params.cpp?rev=79&r1=78&r2=79&view=diff
==
--- cfe/trunk/test/CodeGenCoroutines/coro-params.cpp (original)
+++ cfe/trunk/test/CodeGenCoroutines/coro-params.cpp Mon May 28 11:08:47 2018
@@ -156,3 +156,28 @@ void coroutine_matching_promise_construc
   // CHECK: invoke void 
@_ZNSt12experimental16coroutine_traitsIJv28promise_matching_constructorifdEE12promise_typeC1ES1_ifd(%"struct.std::experimental::coroutine_traits::promise_type"* %__promise, 
i32 %[[INT]], float %[[FLOAT]], double %[[DOUBLE]])
   co_return;
 }
+
+struct some_class;
+
+struct method {};
+
+template  struct std::experimental::coroutine_traits {
+  struct promise_type {
+promise_type(some_class&, float);
+method get_return_object();
+suspend_always initial_suspend();
+suspend_always final_suspend();
+void return_void();
+void unhandled_exception();
+  };
+};
+
+struct some_class {
+  method good_coroutine_calls_custom_constructor(float);
+};
+
+// CHECK-LABEL: define void 
@_ZN10some_class39good_coroutine_calls_custom_constructorEf(%struct.some_class*
+method some_class::good_coroutine_calls_custom_constructor(float) {
+  // CHECK: invoke void 
@_ZNSt12experimental16coroutine_traitsIJ6methodR10some_classfEE12promise_typeC1ES3_f(%"struct.std::experimental::coroutine_traits::promise_type"* %__promise, %struct.some_class* 
dereferenceable(1) %{{.+}}, float
+  co_return;
+}

Modified: cfe/trunk/test/SemaCXX/coroutines.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/coroutines.cpp?rev=79&r1=78&r2=79&view=diff
==
--- cfe/trunk/test/SemaCXX/coroutines.cpp (original)
+++ cfe/trunk/test/SemaCXX/coroutines.cpp Mon May 28 11:08:47 2018
@@ -831,7 +831,7 @@ struct std::experimental::coroutine_trai
   };
 };
 
-extern "C" int f(mismatch_gro_type_tag1) { 
+extern "C" int f(mismatch_gro_type_tag1) {
   // expected-error@-1 {{cannot initialize return object of type 'int' with an 
rvalue of type 'void'}}
   co_return; //expected-note {{function is a coroutine due to use of 
'co_return' here}}
 }
@@ -848,7 +848,7 @@ struct std::experimental::coroutine_trai
   };
 };
 
-extern "C" int f(mismatch_gro_type_tag2) { 
+extern "C" int f(mismatch_gro_type_tag2) {
   // expected-error@-1 {{cannot initialize return object of type 'int' with an 
lvalue of type 'void *'}}
   co_return; //expected-note {{function is a coroutine due to use of 
'co_return' here}}
 }
@@ -866,7 +866,7 @@ struct std::experimental::coroutine_trai
   };
 };
 
-extern "C" int f(mismatch_gro_type_tag3) { 
+extern "C" int f(mismatch_gro_type_tag3) {
   // expected-error@-1 {{cannot initialize return object of type 'int' with an 
rvalue of type 'void'}}
   co_return; //expected-note {{function is a coroutine due to use of 
'co_return' here}}
 }
@@ -885,7 +885,7 @@ struct std::experimental::coroutine_trai
   };
 };
 
-extern "C" int 

r303714 - [coroutines] Fix leak in CGCoroutine.cpp

2017-05-23 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Tue May 23 20:54:37 2017
New Revision: 303714

URL: http://llvm.org/viewvc/llvm-project?rev=303714&view=rev
Log:
[coroutines] Fix leak in CGCoroutine.cpp

FinalBB need to be emitted even when unused to make sure it is deleted

Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=303714&r1=303713&r2=303714&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Tue May 23 20:54:37 2017
@@ -430,6 +430,10 @@ void CodeGenFunction::EmitCoroutineBody(
   CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
   EmitStmt(S.getFinalSuspendStmt());
 }
+else {
+  // We don't need FinalBB. Emit it to make sure the block is deleted.
+  EmitBlock(FinalBB, /*IsFinished=*/true);
+}
   }
 
   EmitBlock(RetBB);


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


r303716 - [coroutines] Implement correct GRO lifetime

2017-05-23 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Tue May 23 21:38:26 2017
New Revision: 303716

URL: http://llvm.org/viewvc/llvm-project?rev=303716&view=rev
Log:
[coroutines] Implement correct GRO lifetime

Summary:
Sema creates a declaration for gro variable as:

auto $gro = $promise.get_return_object();

However, gro variable has to outlive coroutine frame and coroutine promise, but,
it can only be initialized after the coroutine promise was created, thus, we
split its emission in two parts: EmitGroAlloca emits an alloca and sets up
the cleanups. Later when the coroutine promise is available we initialize
the gro and set the flag that the cleanup is now active.

Duplicate of: https://reviews.llvm.org/D31670 (which arc patch refuses to apply 
for some reason)

Reviewers: GorNishanov, rsmith

Reviewed By: GorNishanov

Subscribers: EricWF, cfe-commits

Differential Revision: https://reviews.llvm.org/D33477

Added:
cfe/trunk/test/CodeGenCoroutines/coro-gro.cpp
Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=303716&r1=303715&r2=303716&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Tue May 23 21:38:26 2017
@@ -11,6 +11,7 @@
 //
 
//===--===//
 
+#include "CGCleanup.h"
 #include "CodeGenFunction.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "clang/AST/StmtCXX.h"
@@ -326,6 +327,72 @@ struct CallCoroDelete final : public EHS
 };
 }
 
+namespace {
+struct GetReturnObjectManager {
+  CodeGenFunction &CGF;
+  CGBuilderTy &Builder;
+  const CoroutineBodyStmt &S;
+
+  Address GroActiveFlag;
+  CodeGenFunction::AutoVarEmission GroEmission;
+
+  GetReturnObjectManager(CodeGenFunction &CGF, const CoroutineBodyStmt &S)
+  : CGF(CGF), Builder(CGF.Builder), S(S), 
GroActiveFlag(Address::invalid()),
+GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {}
+
+  // The gro variable has to outlive coroutine frame and coroutine promise, 
but,
+  // it can only be initialized after coroutine promise was created, thus, we
+  // split its emission in two parts. EmitGroAlloca emits an alloca and sets up
+  // cleanups. Later when coroutine promise is available we initialize the gro
+  // and sets the flag that the cleanup is now active.
+
+  void EmitGroAlloca() {
+auto *GroDeclStmt = dyn_cast(S.getResultDecl());
+if (!GroDeclStmt) {
+  // If get_return_object returns void, no need to do an alloca.
+  return;
+}
+
+auto *GroVarDecl = cast(GroDeclStmt->getSingleDecl());
+
+// Set GRO flag that it is not initialized yet
+GroActiveFlag =
+  CGF.CreateTempAlloca(Builder.getInt1Ty(), CharUnits::One(), 
"gro.active");
+Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
+
+GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl);
+
+// Remember the top of EHStack before emitting the cleanup.
+auto old_top = CGF.EHStack.stable_begin();
+CGF.EmitAutoVarCleanups(GroEmission);
+auto top = CGF.EHStack.stable_begin();
+
+// Make the cleanup conditional on gro.active
+for (auto b = CGF.EHStack.find(top), e = CGF.EHStack.find(old_top);
+  b != e; b++) {
+  if (auto *Cleanup = dyn_cast(&*b)) {
+assert(!Cleanup->hasActiveFlag() && "cleanup already has active 
flag?");
+Cleanup->setActiveFlag(GroActiveFlag);
+Cleanup->setTestFlagInEHCleanup();
+Cleanup->setTestFlagInNormalCleanup();
+  }
+}
+  }
+
+  void EmitGroInit() {
+if (!GroActiveFlag.isValid()) {
+  // No Gro variable was allocated. Simply emit the call to
+  // get_return_object.
+  CGF.EmitStmt(S.getResultDecl());
+  return;
+}
+
+CGF.EmitAutoVarInit(GroEmission);
+Builder.CreateStore(Builder.getTrue(), GroActiveFlag);
+  }
+};
+}
+
 static void emitBodyAndFallthrough(CodeGenFunction &CGF,
const CoroutineBodyStmt &S, Stmt *Body) {
   CGF.EmitStmt(Body);
@@ -390,14 +457,18 @@ void CodeGenFunction::EmitCoroutineBody(
   CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi});
   CurCoro.Data->CoroBegin = CoroBegin;
 
+  GetReturnObjectManager GroManager(*this, S);
+  GroManager.EmitGroAlloca();
+
   CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB);
   {
 CodeGenFunction::RunCleanupsScope ResumeScope(*this);
 EHStack.pushCleanup(NormalAndEHCleanup, S.getDeallocate());
 
 EmitStmt(S.getPromiseDeclStmt());
-EmitStmt(S.getResultDecl()); // FIXME: Gro lifetime is wrong.
 
+// Now we have the promise, initialize the GRO
+GroManager.EmitGroInit();
 EHStack.pushCleanup(EHCleanup);
 
 CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);

Added: cfe/trunk/test/CodeGenCoroutines/coro-gro.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe

r303748 - [coroutines] [NFC] Add tests for return_void, unhandled_exception and promise dtor

2017-05-24 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed May 24 09:19:48 2017
New Revision: 303748

URL: http://llvm.org/viewvc/llvm-project?rev=303748&view=rev
Log:
[coroutines] [NFC] Add tests for return_void, unhandled_exception and promise 
dtor

Summary:
* Test that coroutine promise destructor is called.
* Test that we call return_void on fallthrough
* Test that we call unhandled exception in a try catch surrounding the body

Reviewers: EricWF, GorNishanov

Reviewed By: GorNishanov

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D33479

Added:
cfe/trunk/test/CodeGenCoroutines/Inputs/
cfe/trunk/test/CodeGenCoroutines/Inputs/coroutine.h
cfe/trunk/test/CodeGenCoroutines/coro-promise-dtor.cpp
cfe/trunk/test/CodeGenCoroutines/coro-ret-void.cpp
cfe/trunk/test/CodeGenCoroutines/coro-unhandled-exception.cpp

Added: cfe/trunk/test/CodeGenCoroutines/Inputs/coroutine.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/Inputs/coroutine.h?rev=303748&view=auto
==
--- cfe/trunk/test/CodeGenCoroutines/Inputs/coroutine.h (added)
+++ cfe/trunk/test/CodeGenCoroutines/Inputs/coroutine.h Wed May 24 09:19:48 2017
@@ -0,0 +1,80 @@
+#pragma once
+
+namespace std { namespace experimental { inline namespace coroutines_v1 {
+
+template  struct coroutine_traits {
+  using promise_type = typename R::promise_type;
+};
+
+template  struct coroutine_handle;
+
+template <> struct coroutine_handle {
+  static coroutine_handle from_address(void *addr) noexcept {
+coroutine_handle me;
+me.ptr = addr;
+return me;
+  }
+  void operator()() { resume(); }
+  void *address() const { return ptr; }
+  void resume() const { __builtin_coro_resume(ptr); }
+  void destroy() const { __builtin_coro_destroy(ptr); }
+  bool done() const { return __builtin_coro_done(ptr); }
+  coroutine_handle &operator=(decltype(nullptr)) {
+ptr = nullptr;
+return *this;
+  }
+  coroutine_handle(decltype(nullptr)) : ptr(nullptr) {}
+  coroutine_handle() : ptr(nullptr) {}
+//  void reset() { ptr = nullptr; } // add to P0057?
+  explicit operator bool() const { return ptr; }
+
+protected:
+  void *ptr;
+};
+
+template  struct coroutine_handle : coroutine_handle<> {
+  using coroutine_handle<>::operator=;
+
+  static coroutine_handle from_address(void *addr) noexcept {
+coroutine_handle me;
+me.ptr = addr;
+return me;
+  }
+
+  Promise &promise() const {
+return *reinterpret_cast(
+__builtin_coro_promise(ptr, alignof(Promise), false));
+  }
+  static coroutine_handle from_promise(Promise &promise) {
+coroutine_handle p;
+p.ptr = __builtin_coro_promise(&promise, alignof(Promise), true);
+return p;
+  }
+};
+
+  template 
+  bool operator==(coroutine_handle<_PromiseT> const& _Left,
+coroutine_handle<_PromiseT> const& _Right) noexcept
+  {
+return _Left.address() == _Right.address();
+  }
+
+  template 
+  bool operator!=(coroutine_handle<_PromiseT> const& _Left,
+coroutine_handle<_PromiseT> const& _Right) noexcept
+  {
+return !(_Left == _Right);
+  }
+
+struct suspend_always {
+  bool await_ready() { return false; }
+  void await_suspend(coroutine_handle<>) {}
+  void await_resume() {}
+};
+struct suspend_never {
+  bool await_ready() { return true; }
+  void await_suspend(coroutine_handle<>) {}
+  void await_resume() {}
+};
+
+}}}

Added: cfe/trunk/test/CodeGenCoroutines/coro-promise-dtor.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-promise-dtor.cpp?rev=303748&view=auto
==
--- cfe/trunk/test/CodeGenCoroutines/coro-promise-dtor.cpp (added)
+++ cfe/trunk/test/CodeGenCoroutines/coro-promise-dtor.cpp Wed May 24 09:19:48 
2017
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts 
-triple=x86_64-pc-windows-msvc18.0.0 -emit-llvm -o - %s -fexceptions 
-fcxx-exceptions -disable-llvm-passes | FileCheck %s
+// -triple=x86_64-unknown-linux-gnu
+
+#include "Inputs/coroutine.h"
+
+namespace coro = std::experimental::coroutines_v1;
+
+struct coro_t {
+  void* p;
+  ~coro_t();
+  struct promise_type {
+coro_t get_return_object();
+coro::suspend_never initial_suspend();
+coro::suspend_never final_suspend();
+void return_void();
+promise_type();
+~promise_type();
+void unhandled_exception();
+  };
+};
+
+struct Cleanup { ~Cleanup(); };
+void may_throw();
+
+coro_t f() {
+  Cleanup cleanup;
+  may_throw();
+  co_return;
+}
+
+// CHECK-LABEL: define void @"\01?f@@YA?AUcoro_t@@XZ"(
+// CHECK:  %gro.active = alloca i1
+// CHECK:  store i1 false, i1* %gro.active
+
+// CHECK:  invoke %"struct.coro_t::promise_type"* 
@"\01??0promise_type@coro_t@@QEAA@XZ"(
+// CHECK:  invoke void 
@"\01?get_return_object@promise_type@coro_t@@QEAA?AU2@XZ"(
+// CHECK:  store i1 true, i1* %gro.active
+
+// CHECK:  %[[IS_ACTIVE:.+]] = load i1, i1* %gro.active
+// CHECK:  br i

r303752 - [coroutines] Improved diagnostics when unhandled_exception is missing in the promise_type

2017-05-24 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed May 24 09:34:19 2017
New Revision: 303752

URL: http://llvm.org/viewvc/llvm-project?rev=303752&view=rev
Log:
[coroutines] Improved diagnostics when unhandled_exception is missing in the 
promise_type

Summary: Now we helpfully provide a note pointing at the promise_type in 
question.

Reviewers: EricWF, GorNishanov

Reviewed By: GorNishanov

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D33481

Modified:
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/test/SemaCXX/coroutine-unhandled_exception-warning.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=303752&r1=303751&r2=303752&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Wed May 24 09:34:19 2017
@@ -120,8 +120,7 @@ static QualType lookupPromiseType(Sema &
   return PromiseType;
 }
 
-/// Look up the std::coroutine_traits<...>::promise_type for the given
-/// function type.
+/// Look up the std::experimental::coroutine_handle.
 static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
   SourceLocation Loc) {
   if (PromiseType.isNull())
@@ -729,8 +728,7 @@ void Sema::CheckCompletedCoroutineBody(F
   }
 
   if (isa(Body)) {
-// FIXME(EricWF): Nothing todo. the body is already a transformed coroutine
-// body statement.
+// Nothing todo. the body is already a transformed coroutine body 
statement.
 return;
   }
 
@@ -1030,6 +1028,8 @@ bool CoroutineStmtBuilder::makeOnExcepti
 : diag::
   
warn_coroutine_promise_unhandled_exception_required_with_exceptions;
 S.Diag(Loc, DiagID) << PromiseRecordDecl;
+S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)
+<< PromiseRecordDecl;
 return !RequireUnhandledException;
   }
 

Modified: cfe/trunk/test/SemaCXX/coroutine-unhandled_exception-warning.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/coroutine-unhandled_exception-warning.cpp?rev=303752&r1=303751&r2=303752&view=diff
==
--- cfe/trunk/test/SemaCXX/coroutine-unhandled_exception-warning.cpp (original)
+++ cfe/trunk/test/SemaCXX/coroutine-unhandled_exception-warning.cpp Wed May 24 
09:34:19 2017
@@ -16,7 +16,11 @@
 using std::experimental::suspend_always;
 using std::experimental::suspend_never;
 
+#ifndef DISABLE_WARNING
+struct promise_void { // expected-note {{defined here}}
+#else
 struct promise_void {
+#endif
   void get_return_object();
   suspend_always initial_suspend();
   suspend_always final_suspend();

Modified: cfe/trunk/test/SemaCXX/coroutines.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/coroutines.cpp?rev=303752&r1=303751&r2=303752&view=diff
==
--- cfe/trunk/test/SemaCXX/coroutines.cpp (original)
+++ cfe/trunk/test/SemaCXX/coroutines.cpp Wed May 24 09:34:19 2017
@@ -540,7 +540,7 @@ coro bad_implicit_return_dependent(T)
 }
 template coro bad_implicit_return_dependent(bad_promise_6); // 
expected-note {{in instantiation}}
 
-struct bad_promise_7 {
+struct bad_promise_7 { // expected-note 2 {{defined here}}
   coro get_return_object();
   suspend_always initial_suspend();
   suspend_always final_suspend();


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


r303764 - [coroutines] Make generic lambda coroutines work

2017-05-24 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed May 24 10:44:57 2017
New Revision: 303764

URL: http://llvm.org/viewvc/llvm-project?rev=303764&view=rev
Log:
[coroutines] Make generic lambda coroutines work

Summary:
1. Coroutine cannot be constexpr (added a check in SemaLambda.cpp not to mark 
coroutine as constexpr)
2. TransformCoroutineBodyStmt should transform ResultDecl and ReturnStmt

Reviewers: rsmith, GorNishanov

Reviewed By: GorNishanov

Subscribers: EricWF, cfe-commits

Differential Revision: https://reviews.llvm.org/D33498

Added:
cfe/trunk/test/CodeGenCoroutines/coro-lambda.cpp
Modified:
cfe/trunk/lib/Sema/SemaLambda.cpp
cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=303764&r1=303763&r2=303764&view=diff
==
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Wed May 24 10:44:57 2017
@@ -1591,6 +1591,7 @@ ExprResult Sema::BuildLambdaExpr(SourceL
   // its constexpr-ness, supressing diagnostics while doing so.
   if (getLangOpts().CPlusPlus1z && !CallOperator->isInvalidDecl() &&
   !CallOperator->isConstexpr() &&
+  !isa(CallOperator->getBody()) &&
   !Class->getDeclContext()->isDependentContext()) {
 TentativeAnalysisScope DiagnosticScopeGuard(*this);
 CallOperator->setConstexpr(

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=303764&r1=303763&r2=303764&view=diff
==
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed May 24 10:44:57 2017
@@ -6945,6 +6945,19 @@ TreeTransform::TransformCorouti
 if (DeallocRes.isInvalid())
   return StmtError();
 Builder.Deallocate = DeallocRes.get();
+
+assert(S->getResultDecl() && "ResultDecl must already be built");
+StmtResult ResultDecl = getDerived().TransformStmt(S->getResultDecl());
+if (ResultDecl.isInvalid())
+  return StmtError();
+Builder.ResultDecl = ResultDecl.get();
+
+if (auto *ReturnStmt = S->getReturnStmt()) {
+  StmtResult Res = getDerived().TransformStmt(ReturnStmt);
+  if (Res.isInvalid())
+return StmtError();
+  Builder.ReturnStmt = Res.get();
+}
   }
 
   return getDerived().RebuildCoroutineBodyStmt(Builder);

Added: cfe/trunk/test/CodeGenCoroutines/coro-lambda.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-lambda.cpp?rev=303764&view=auto
==
--- cfe/trunk/test/CodeGenCoroutines/coro-lambda.cpp (added)
+++ cfe/trunk/test/CodeGenCoroutines/coro-lambda.cpp Wed May 24 10:44:57 2017
@@ -0,0 +1,58 @@
+// Verify that we synthesized the coroutine for a lambda inside of a function 
template.
+// RUN: %clang_cc1 -std=c++1z -fcoroutines-ts -triple=x86_64-unknown-linux-gnu 
-emit-llvm -o - %s -fexceptions -fcxx-exceptions -disable-llvm-passes | 
FileCheck %s
+
+namespace std::experimental {
+template  struct coroutine_traits {
+  using promise_type = typename R::promise_type;
+};
+
+template  struct coroutine_handle;
+template <> struct coroutine_handle {
+  static coroutine_handle from_address(void *) noexcept;
+  coroutine_handle() = default;
+  template 
+  coroutine_handle(coroutine_handle) noexcept;
+};
+template  struct coroutine_handle : coroutine_handle {
+  coroutine_handle() = default;
+  static coroutine_handle from_address(void *) noexcept;
+};
+}
+
+struct suspend_always {
+  bool await_ready() noexcept;
+  void await_suspend(std::experimental::coroutine_handle<>) noexcept;
+  void await_resume() noexcept;
+};
+
+struct Task {
+  struct promise_type {
+Task get_return_object();
+void return_void() {}
+suspend_always initial_suspend() noexcept;
+suspend_always final_suspend() noexcept;
+void unhandled_exception() noexcept;
+  };
+};
+
+template  auto SyncAwait(_AwrT &&A) {
+  if (!A.await_ready()) {
+auto AwaitAsync = [&]() -> Task {
+  try { (void)(co_await A); } catch (...) {}
+};
+Task t = AwaitAsync();
+  }
+  return A.await_resume();
+}
+
+void f() {
+  suspend_always test;
+  SyncAwait(test);
+}
+
+// Verify that we synthesized the coroutine for a lambda inside SyncAwait
+// CHECK-LABEL: define linkonce_odr void 
@_ZZ9SyncAwaitIR14suspend_alwaysEDaOT_ENKUlvE_clEv(
+//   CHECK: alloca %"struct.Task::promise_type"
+//   CHECK: call token @llvm.coro.id(
+//   CHECK: call i8 @llvm.coro.suspend(
+//   CHECK: call i1 @llvm.coro.end(


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


r303803 - [coroutines] Add support for coroutines with non-scalar parameters

2017-05-24 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed May 24 15:09:14 2017
New Revision: 303803

URL: http://llvm.org/viewvc/llvm-project?rev=303803&view=rev
Log:
[coroutines] Add support for coroutines with non-scalar parameters

Summary:
Simple types like int are handled by LLVM Coroutines just fine.
But for non-scalar parameters we need to create copies of those parameters in 
the coroutine frame and make all uses of those parameters to refer to parameter 
copies.

Reviewers: rsmith, EricWF, GorNishanov

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D33507

Added:
cfe/trunk/test/CodeGenCoroutines/coro-params.cpp
Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/lib/Sema/SemaCoroutine.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=303803&r1=303802&r2=303803&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Wed May 24 15:09:14 2017
@@ -15,6 +15,7 @@
 #include "CodeGenFunction.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtVisitor.h"
 
 using namespace clang;
 using namespace CodeGen;
@@ -239,7 +240,67 @@ void CodeGenFunction::EmitCoreturnStmt(C
   EmitBranchThroughCleanup(CurCoro.Data->FinalJD);
 }
 
-// For WinEH exception representation backend need to know what funclet 
coro.end
+// Hunts for the parameter reference in the parameter copy/move declaration.
+namespace {
+struct GetParamRef : public StmtVisitor {
+public:
+  DeclRefExpr *Expr = nullptr;
+  GetParamRef() {}
+  void VisitDeclRefExpr(DeclRefExpr *E) {
+assert(Expr == nullptr && "multilple declref in param move");
+Expr = E;
+  }
+  void VisitStmt(Stmt *S) {
+for (auto *C : S->children()) {
+  if (C)
+Visit(C);
+}
+  }
+};
+}
+
+// This class replaces references to parameters to their copies by changing
+// the addresses in CGF.LocalDeclMap and restoring back the original values in
+// its destructor.
+
+namespace {
+  struct ParamReferenceReplacerRAII {
+CodeGenFunction::DeclMapTy SavedLocals;
+CodeGenFunction::DeclMapTy& LocalDeclMap;
+
+ParamReferenceReplacerRAII(CodeGenFunction::DeclMapTy &LocalDeclMap)
+: LocalDeclMap(LocalDeclMap) {}
+
+void addCopy(DeclStmt const *PM) {
+  // Figure out what param it refers to.
+
+  assert(PM->isSingleDecl());
+  VarDecl const*VD = static_cast(PM->getSingleDecl());
+  Expr const *InitExpr = VD->getInit();
+  GetParamRef Visitor;
+  Visitor.Visit(const_cast(InitExpr));
+  assert(Visitor.Expr);
+  auto *DREOrig = cast(Visitor.Expr);
+  auto *PD = DREOrig->getDecl();
+
+  auto it = LocalDeclMap.find(PD);
+  assert(it != LocalDeclMap.end() && "parameter is not found");
+  SavedLocals.insert({ PD, it->second });
+
+  auto copyIt = LocalDeclMap.find(VD);
+  assert(copyIt != LocalDeclMap.end() && "parameter copy is not found");
+  it->second = copyIt->getSecond();
+}
+
+~ParamReferenceReplacerRAII() {
+  for (auto&& SavedLocal : SavedLocals) {
+LocalDeclMap.insert({SavedLocal.first, SavedLocal.second});
+  }
+}
+  };
+}
+
+// For WinEH exception representation backend needs to know what funclet 
coro.end
 // belongs to. That information is passed in a funclet bundle.
 static SmallVector
 getBundlesForCoroEnd(CodeGenFunction &CGF) {
@@ -462,21 +523,38 @@ void CodeGenFunction::EmitCoroutineBody(
 
   CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB);
   {
+ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap);
 CodeGenFunction::RunCleanupsScope ResumeScope(*this);
 EHStack.pushCleanup(NormalAndEHCleanup, S.getDeallocate());
 
+// Create parameter copies. We do it before creating a promise, since an
+// evolution of coroutine TS may allow promise constructor to observe
+// parameter copies.
+for (auto *PM : S.getParamMoves()) {
+  EmitStmt(PM);
+  ParamReplacer.addCopy(cast(PM));
+  // TODO: if(CoroParam(...)) need to surround ctor and dtor
+  // for the copy, so that llvm can elide it if the copy is
+  // not needed.
+}
+
 EmitStmt(S.getPromiseDeclStmt());
 
+Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl());
+auto *PromiseAddrVoidPtr =
+new llvm::BitCastInst(PromiseAddr.getPointer(), VoidPtrTy, "", CoroId);
+// Update CoroId to refer to the promise. We could not do it earlier 
because
+// promise local variable was not emitted yet.
+CoroId->setArgOperand(1, PromiseAddrVoidPtr);
+
 // Now we have the promise, initialize the GRO
 GroManager.EmitGroInit();
-EHStack.pushCleanup(EHCleanup);
 
-CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
-
-// FIXME: Emit param moves.
+EHStack.pushCleanup(EHCleanup);
 
 CurCoro.Data->CurrentAwaitKind = AwaitKind

r304081 - [coroutines] Mark cxx_status.html of Coroutines TS as (SVN)

2017-05-27 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Sat May 27 17:54:52 2017
New Revision: 304081

URL: http://llvm.org/viewvc/llvm-project?rev=304081&view=rev
Log:
[coroutines] Mark cxx_status.html of Coroutines TS as (SVN)

Summary: It is time!

Reviewers: GorNishanov, rsmith

Reviewed By: GorNishanov, rsmith

Subscribers: EricWF, rsmith, cfe-commits

Differential Revision: https://reviews.llvm.org/D33624

Modified:
cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/www/cxx_status.html
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=304081&r1=304080&r2=304081&view=diff
==
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Sat May 27 17:54:52 2017
@@ -831,9 +831,9 @@ and library features that are not part o
 
 
   [DRAFT TS] Coroutines
-  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0057r7.pdf";>P0057R7
-  
-  WIP
+  https://isocpp.org/files/papers/N4663.pdf";>N4663
+  -fcoroutines-ts-stdlib=libc++
+  SVN
 
 
   [TS] Library Fundamentals, Version 1 (invocation type traits)


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


r304091 - [coroutines] www/cxx_status.html: add non-breaking hyphen

2017-05-28 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Sun May 28 11:25:31 2017
New Revision: 304091

URL: http://llvm.org/viewvc/llvm-project?rev=304091&view=rev
Log:
[coroutines] www/cxx_status.html: add non-breaking hyphen

Reviewers: GorNishanov

Reviewed By: GorNishanov

Subscribers: EricWF, rsmith, cfe-commits

Differential Revision: https://reviews.llvm.org/D33632

Modified:
cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/www/cxx_status.html
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=304091&r1=304090&r2=304091&view=diff
==
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Sun May 28 11:25:31 2017
@@ -832,7 +832,7 @@ and library features that are not part o
 
   [DRAFT TS] Coroutines
   https://isocpp.org/files/papers/N4663.pdf";>N4663
-  -fcoroutines-ts-stdlib=libc++
+  -fcoroutines‑ts-stdlib=libc++
   SVN
 
 


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


r304092 - [coroutines] www/cxx_status.html: add non-breaking hyphen

2017-05-28 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Sun May 28 12:35:23 2017
New Revision: 304092

URL: http://llvm.org/viewvc/llvm-project?rev=304092&view=rev
Log:
[coroutines] www/cxx_status.html: add non-breaking hyphen

Reviewers: GorNishanov

Reviewed By: GorNishanov

Subscribers: EricWF, rsmith, cfe-commits

Differential Revision: https://reviews.llvm.org/D33632

Modified:
cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/www/cxx_status.html
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=304092&r1=304091&r2=304092&view=diff
==
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Sun May 28 12:35:23 2017
@@ -832,7 +832,7 @@ and library features that are not part o
 
   [DRAFT TS] Coroutines
   https://isocpp.org/files/papers/N4663.pdf";>N4663
-  -fcoroutines‑ts-stdlib=libc++
+  ‑fcoroutines‑ts-stdlib=libc++
   SVN
 
 


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


Re: r303714 - [coroutines] Fix leak in CGCoroutine.cpp

2017-05-29 Thread Gor Nishanov via cfe-commits
It is not known in advance whether the final block is needed or not. It
will become known once the user-authored body of the coroutine is emitted.
I cannot defer creation of it up until that point, since final bb acts as a
jump target for co_returns which could be in the user authored body and I
need it to set up a jump destination beforehand.

Ack on formatting change.

On Mon, May 29, 2017 at 12:11 PM, David Blaikie  wrote:

> Could you avoid creating the FinalBB unless it's needed rather than
> creating it and then adding it so it can be removed? (or, if the creation
> can't be avoided, maybe it's OK to 'delete FinalBB' here, rather than
> adding it for it to be removed later?)
>
> (also bracing seems off - could you run your changes through clang-format?
> I'd expect '} else {' on the same line.
>
> On Tue, May 23, 2017 at 6:54 PM Gor Nishanov via cfe-commits <
> cfe-commits@lists.llvm.org> wrote:
>
>> Author: gornishanov
>> Date: Tue May 23 20:54:37 2017
>> New Revision: 303714
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=303714&view=rev
>> Log:
>> [coroutines] Fix leak in CGCoroutine.cpp
>>
>> FinalBB need to be emitted even when unused to make sure it is deleted
>>
>> Modified:
>> cfe/trunk/lib/CodeGen/CGCoroutine.cpp
>>
>> Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
>> CGCoroutine.cpp?rev=303714&r1=303713&r2=303714&view=diff
>> 
>> ==
>> --- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Tue May 23 20:54:37 2017
>> @@ -430,6 +430,10 @@ void CodeGenFunction::EmitCoroutineBody(
>>CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
>>EmitStmt(S.getFinalSuspendStmt());
>>  }
>> +else {
>> +  // We don't need FinalBB. Emit it to make sure the block is
>> deleted.
>> +  EmitBlock(FinalBB, /*IsFinished=*/true);
>> +}
>>}
>>
>>EmitBlock(RetBB);
>>
>>
>> ___
>> cfe-commits mailing list
>> cfe-commits@lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r304176 - CGCoroutine.cpp: (NFC) clang-format misplaced brace

2017-05-29 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon May 29 16:15:31 2017
New Revision: 304176

URL: http://llvm.org/viewvc/llvm-project?rev=304176&view=rev
Log:
CGCoroutine.cpp: (NFC) clang-format misplaced brace

Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=304176&r1=304175&r2=304176&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Mon May 29 16:15:31 2017
@@ -578,8 +578,7 @@ void CodeGenFunction::EmitCoroutineBody(
   EmitBlock(FinalBB);
   CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
   EmitStmt(S.getFinalSuspendStmt());
-}
-else {
+} else {
   // We don't need FinalBB. Emit it to make sure the block is deleted.
   EmitBlock(FinalBB, /*IsFinished=*/true);
 }


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


Re: r303714 - [coroutines] Fix leak in CGCoroutine.cpp

2017-05-29 Thread Gor Nishanov via cfe-commits
My clang-foo is not strong enough :) .

I wanted to make sure that: "CurCoro.Data->FinalJD =
getJumpDestInCurrentScope(FinalBB);" is in the correct scope where I want
it. As opposed to creating it in whatever scope co_return statement is
encountered. But that could be simply my misundersanding of the
frontend/scopes/etc and it is quite possible that the code can be
refactored along the lines you are thinking about.

On Mon, May 29, 2017 at 3:44 PM, David Blaikie  wrote:

>
>
> On Mon, May 29, 2017 at 2:12 PM Gor Nishanov 
> wrote:
>
>> It is not known in advance whether the final block is needed or not. It
>> will become known once the user-authored body of the coroutine is emitted.
>> I cannot defer creation of it up until that point, since final bb acts as a
>> jump target for co_returns which could be in the user authored body and I
>> need it to set up a jump destination beforehand.
>>
>
> Not sure I follow - presumably those jumps could only be emitted if the
> block would be emitted - so if the entity is created the first time it's
> needed as a jump destination,then that should be OK?
>
>
>>
>> Ack on formatting change.
>>
>> On Mon, May 29, 2017 at 12:11 PM, David Blaikie 
>> wrote:
>>
>>> Could you avoid creating the FinalBB unless it's needed rather than
>>> creating it and then adding it so it can be removed? (or, if the creation
>>> can't be avoided, maybe it's OK to 'delete FinalBB' here, rather than
>>> adding it for it to be removed later?)
>>>
>>> (also bracing seems off - could you run your changes through
>>> clang-format? I'd expect '} else {' on the same line.
>>>
>>> On Tue, May 23, 2017 at 6:54 PM Gor Nishanov via cfe-commits <
>>> cfe-commits@lists.llvm.org> wrote:
>>>
>>>> Author: gornishanov
>>>> Date: Tue May 23 20:54:37 2017
>>>> New Revision: 303714
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=303714&view=rev
>>>> Log:
>>>> [coroutines] Fix leak in CGCoroutine.cpp
>>>>
>>>> FinalBB need to be emitted even when unused to make sure it is deleted
>>>>
>>>> Modified:
>>>> cfe/trunk/lib/CodeGen/CGCoroutine.cpp
>>>>
>>>> Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/
>>>> CGCoroutine.cpp?rev=303714&r1=303713&r2=303714&view=diff
>>>> 
>>>> ==
>>>> --- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
>>>> +++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Tue May 23 20:54:37 2017
>>>> @@ -430,6 +430,10 @@ void CodeGenFunction::EmitCoroutineBody(
>>>>CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
>>>>EmitStmt(S.getFinalSuspendStmt());
>>>>  }
>>>> +else {
>>>> +  // We don't need FinalBB. Emit it to make sure the block is
>>>> deleted.
>>>> +  EmitBlock(FinalBB, /*IsFinished=*/true);
>>>> +}
>>>>}
>>>>
>>>>EmitBlock(RetBB);
>>>>
>>>>
>>>> ___
>>>> cfe-commits mailing list
>>>> cfe-commits@lists.llvm.org
>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>>
>>>
>>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r304380 - CGCleanup: (NFC) add another test for r304335 - Don't try to spill static allocas

2017-05-31 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed May 31 20:15:25 2017
New Revision: 304380

URL: http://llvm.org/viewvc/llvm-project?rev=304380&view=rev
Log:
CGCleanup: (NFC) add another test for r304335 - Don't try to spill static 
allocas

Summary:
Coroutine related test that used to trigger broken IR prior to r304335.

```
%x = alloca i32, align 4
store i32* %x, i32** %tmp.exprcleanup, align 4 ; <= HERE
%ref.tmp3 = alloca %struct.A, align 1
%agg.tmp5 = alloca 
%"struct.std::experimental::coroutines_v1::coroutine_handle.0", align 4
%tmp.exprcleanup = alloca i32*, align 4
%allocapt = bitcast i32 undef to i32
store i32 %0, i32* %.addr, align 4
```

Fixed with r304335

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D33750

Added:
cfe/trunk/test/CodeGenCoroutines/coro-await-domination.cpp

Added: cfe/trunk/test/CodeGenCoroutines/coro-await-domination.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-await-domination.cpp?rev=304380&view=auto
==
--- cfe/trunk/test/CodeGenCoroutines/coro-await-domination.cpp (added)
+++ cfe/trunk/test/CodeGenCoroutines/coro-await-domination.cpp Wed May 31 
20:15:25 2017
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 
-emit-llvm %s -o - | FileCheck %s
+#include "Inputs/coroutine.h"
+
+using namespace std::experimental;
+
+struct coro {
+  struct promise_type {
+coro get_return_object();
+suspend_never initial_suspend();
+suspend_never final_suspend();
+void return_void();
+static void unhandled_exception();
+  };
+};
+
+struct A {
+  ~A();
+  bool await_ready();
+  int await_resume() { return 8; }
+  template  void await_suspend(F);
+};
+
+extern "C" void consume(int);
+
+// Verifies that domination is properly built during cleanup.
+// Without CGCleanup.cpp fix verifier was reporting:
+// Instruction does not dominate all uses!
+//  %tmp.exprcleanup = alloca i32*, align 8
+//  store i32* %x, i32** %tmp.exprcleanup, align 8
+
+
+// CHECK-LABEL: f(
+extern "C" coro f(int) {
+  int x = 42;
+  x = co_await A{};
+  consume(x);
+}
+


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


Re: [libcxx] r304591 - Mark two coroutine tests as unsupported under ubsan, again

2017-06-02 Thread Gor Nishanov via cfe-commits
Cool. Thanks for checking.

On Fri, Jun 2, 2017 at 1:12 PM, Vedant Kumar  wrote:

> Hm, sorry, the compiler on the bot could not have picked up r304518, so I
> jumped the gun here. I'll try again later and report back in PR33271.
>
> vedant
>
> > On Jun 2, 2017, at 1:09 PM, Vedant Kumar via cfe-commits <
> cfe-commits@lists.llvm.org> wrote:
> >
> > Hi Gor,
> >
> > This is just a heads-up that I tried re-enabling ubsan for the two tests
> affected by PR33271, but saw some similar failures. The commit message
> below has more details about what was tested and what went wrong.
> >
> > best,
> > vedant
> >
> >
> >> On Jun 2, 2017, at 1:06 PM, Vedant Kumar via cfe-commits <
> cfe-commits@lists.llvm.org> wrote:
> >>
> >> Author: vedantk
> >> Date: Fri Jun  2 15:06:49 2017
> >> New Revision: 304591
> >>
> >> URL: http://llvm.org/viewvc/llvm-project?rev=304591&view=rev
> >> Log:
> >> Mark two coroutine tests as unsupported under ubsan, again
> >>
> >> This reverts commit r304580, making bool_await_suspend.pass.cpp and
> >> generator.pass.cpp unsupported on ubsan again. The host compiler is
> >> based on r304329, which has the change from PR33271 (r304277). However,
> >> this was not enough to address the issue.
> >>
> >> Bot Failure:
> >> http://lab.llvm.org:8011/builders/libcxx-libcxxabi-x86_
> 64-linux-ubuntu-ubsan/builds/628
> >>
> >> Unknown type!
> >> UNREACHABLE executed at /home/eric/full-llvm/llvm/lib/
> IR/ValueTypes.cpp:287!
> >> llvm::EVT::getEVT(llvm::Type*, bool) (/usr/local/bin/clang-5.0+
> 0x17e7a07)
> >> llvm::TargetLoweringBase::getValueType(llvm::DataLayout const&,
> llvm::Type*, bool) const (/usr/local/bin/clang-5.0+0x852c4a)
> >> llvm::ComputeValueVTs(llvm::TargetLowering const&, llvm::DataLayout
> const&, llvm::Type*, llvm::SmallVectorImpl&,
> llvm::SmallVectorImpl*, unsigned long)
> (/usr/local/bin/clang-5.0+0x141b6e9)
> >> llvm::SelectionDAGBuilder::visitTargetIntrinsic(llvm::CallInst const&,
> unsigned int) (/usr/local/bin/clang-5.0+0x237b1ca)
> >>
> >> clang-5.0: 
> >> /home/eric/full-llvm/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp:1236:
> virtual void llvm::DwarfDebug::endFunctionImpl(const
> llvm::MachineFunction *): Assertion `LScopes.getAbstractScopesList().size()
> == NumAbstractScopes && "ensureAbstractVariableIsCreated inserted
> abstract scopes"' failed.
> >> __assert_fail_base /build/glibc-9tT8Do/glibc-2.23/assert/assert.c:92:0
> >> (/lib/x86_64-linux-gnu/libc.so.6+0x2dc82)
> >> llvm::DwarfDebug::endFunctionImpl(llvm::MachineFunction const*)
> (/usr/local/bin/clang-5.0+0x223f86b)
> >> llvm::DebugHandlerBase::endFunction(llvm::MachineFunction const*)
> (/usr/local/bin/clang-5.0+0x227a5a1)
> >> llvm::AsmPrinter::EmitFunctionBody() (/usr/local/bin/clang-5.0+
> 0x222522f)
> >>
> >> Modified:
> >>   libcxx/trunk/test/std/experimental/language.support/
> support.coroutines/end.to.end/bool_await_suspend.pass.cpp
> >>   libcxx/trunk/test/std/experimental/language.support/
> support.coroutines/end.to.end/generator.pass.cpp
> >>
> >> Modified: libcxx/trunk/test/std/experimental/language.support/
> support.coroutines/end.to.end/bool_await_suspend.pass.cpp
> >> URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/
> experimental/language.support/support.coroutines/end.to.end/
> bool_await_suspend.pass.cpp?rev=304591&r1=304590&r2=304591&view=diff
> >> 
> ==
> >> --- libcxx/trunk/test/std/experimental/language.support/
> support.coroutines/end.to.end/bool_await_suspend.pass.cpp (original)
> >> +++ libcxx/trunk/test/std/experimental/language.support/
> support.coroutines/end.to.end/bool_await_suspend.pass.cpp Fri Jun  2
> 15:06:49 2017
> >> @@ -10,6 +10,9 @@
> >>
> >> // UNSUPPORTED: c++98, c++03, c++11
> >>
> >> +// See https://bugs.llvm.org/show_bug.cgi?id=33271
> >> +// UNSUPPORTED: ubsan
> >> +
> >> #include 
> >> #include 
> >>
> >>
> >> Modified: libcxx/trunk/test/std/experimental/language.support/
> support.coroutines/end.to.end/generator.pass.cpp
> >> URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/
> experimental/language.support/support.coroutines/end.to.end/
> generator.pass.cpp?rev=304591&r1=304590&r2=304591&view=diff
> >> 
> ==
> >> --- libcxx/trunk/test/std/experimental/language.support/
> support.coroutines/end.to.end/generator.pass.cpp (original)
> >> +++ libcxx/trunk/test/std/experimental/language.support/
> support.coroutines/end.to.end/generator.pass.cpp Fri Jun  2 15:06:49 2017
> >> @@ -10,6 +10,9 @@
> >>
> >> // UNSUPPORTED: c++98, c++03, c++11
> >>
> >> +// See https://bugs.llvm.org/show_bug.cgi?id=33271
> >> +// UNSUPPORTED: ubsan
> >> +
> >> #include 
> >> #include 
> >> #include 
> >>
> >>
> >> ___
> >> cfe-commits mailing list
> >> cfe-commits@lists.llvm.org
> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
> >
> > 

Re: [PATCH] D33750: CGCleanup: (NFC) add a test that used to trigger broken IR

2017-06-07 Thread Gor Nishanov via cfe-commits
Sure thing. I'll expand the test to verify that frontend emit expected IR
for this case.
Thank you for the feedback

On Mon, Jun 5, 2017 at 9:58 AM, David Blaikie  wrote:

>
>
> On Wed, May 31, 2017 at 5:45 PM Gor Nishanov via Phabricator via
> cfe-commits  wrote:
>
>> GorNishanov created this revision.
>>
>> Coroutine related test that used to trigger broken IR prior to r304335.
>>
>>
>> https://reviews.llvm.org/D33750
>>
>> Files:
>>   test/CodeGenCoroutines/coro-await-domination.cpp
>>
>>
>> Index: test/CodeGenCoroutines/coro-await-domination.cpp
>> ===
>> --- /dev/null
>> +++ test/CodeGenCoroutines/coro-await-domination.cpp
>> @@ -0,0 +1,38 @@
>> +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts
>> -std=c++14 -emit-llvm %s -o - | FileCheck %s
>
> +#include "Inputs/coroutine.h"
>> +
>> +using namespace std::experimental;
>> +
>> +struct coro {
>> +  struct promise_type {
>> +coro get_return_object();
>> +suspend_never initial_suspend();
>> +suspend_never final_suspend();
>> +void return_void();
>> +static void unhandled_exception();
>> +  };
>> +};
>> +
>> +struct A {
>> +  ~A();
>> +  bool await_ready();
>> +  int await_resume() { return 8; }
>> +  template  void await_suspend(F);
>> +};
>> +
>> +extern "C" void consume(int);
>> +
>> +// Verifies that domination is properly built during cleanup.
>> +// Without CGCleanup.cpp fix verifier was reporting:
>> +// Instruction does not dominate all uses!
>> +//  %tmp.exprcleanup = alloca i32*, align 8
>> +//  store i32* %x, i32** %tmp.exprcleanup, align 8
>> +
>> +
>> +// CHECK-LABEL: f(
>>
>
> This doesn't seem to check much. Should this test check that the IR
> instructions have the 'good' layout, more than that the verifier doesn't
> fail?
>
> Or is that already tested by the test case added in r304335? In that case
> I wouldn't add this test. If the change can/is tested in isolation in
> Clang, that should be sufficient/tends to be how testing is done in the
> regression test suites in the LLVM project. (the test-suite is the place
> for broader/end-to-end testing)
>
>
>> +extern "C" coro f(int) {
>> +  int x = 42;
>> +  x = co_await A{};
>> +  consume(x);
>> +}
>> +
>>
>>
>> ___
>> cfe-commits mailing list
>> cfe-commits@lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r348209 - NFC: Add .vscode to .gitignore

2018-12-03 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon Dec  3 14:51:07 2018
New Revision: 348209

URL: http://llvm.org/viewvc/llvm-project?rev=348209&view=rev
Log:
NFC: Add .vscode to .gitignore

Modified:
cfe/trunk/.gitignore

Modified: cfe/trunk/.gitignore
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/.gitignore?rev=348209&r1=348208&r2=348209&view=diff
==
--- cfe/trunk/.gitignore (original)
+++ cfe/trunk/.gitignore Mon Dec  3 14:51:07 2018
@@ -36,3 +36,8 @@ docs/_build
 docs/analyzer/_build
 # debug info testsuite
 test/debuginfo-tests
+
+# VS2017 and VSCode config files.
+.vscode
+.vs
+


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


r312565 - [coroutines] Make sure auto return type of await_resume is properly handled

2017-09-05 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Tue Sep  5 12:31:52 2017
New Revision: 312565

URL: http://llvm.org/viewvc/llvm-project?rev=312565&view=rev
Log:
[coroutines] Make sure auto return type of await_resume is properly handled

Reviewers: rsmith, EricWF

Reviewed By: rsmith

Subscribers: javed.absar, cfe-commits

Differential Revision: https://reviews.llvm.org/D37454

Modified:
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=312565&r1=312564&r2=312565&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Tue Sep  5 12:31:52 2017
@@ -438,14 +438,14 @@ static ReadySuspendResumeResult buildCoa
 //   - await-suspend is the expression e.await_suspend(h), which shall be
 // a prvalue of type void or bool.
 QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
+
 // Experimental support for coroutine_handle returning await_suspend.
 if (Expr *TailCallSuspend = maybeTailCall(S, RetType, AwaitSuspend, Loc))
   Calls.Results[ACT::ACT_Suspend] = TailCallSuspend;
 else {
   // non-class prvalues always have cv-unqualified types
-  QualType AdjRetType = RetType.getUnqualifiedType();
   if (RetType->isReferenceType() ||
-  (AdjRetType != S.Context.BoolTy && AdjRetType != S.Context.VoidTy)) {
+  (!RetType->isBooleanType() && !RetType->isVoidType())) {
 S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
diag::err_await_suspend_invalid_return_type)
 << RetType;

Modified: cfe/trunk/test/SemaCXX/coroutines.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/coroutines.cpp?rev=312565&r1=312564&r2=312565&view=diff
==
--- cfe/trunk/test/SemaCXX/coroutines.cpp (original)
+++ cfe/trunk/test/SemaCXX/coroutines.cpp Tue Sep  5 12:31:52 2017
@@ -66,6 +66,12 @@ struct suspend_never {
   void await_resume() {}
 };
 
+struct auto_await_suspend {
+  bool await_ready();
+  template  auto await_suspend(F) {}
+  void await_resume();
+};
+
 struct DummyVoidTag {};
 DummyVoidTag no_specialization() { // expected-error {{this function cannot be 
a coroutine: 'std::experimental::coroutine_traits' has no member 
named 'promise_type'}}
   co_await a;
@@ -159,6 +165,10 @@ void yield() {
   co_yield yield; // expected-error {{no member named 'await_ready' in 
'not_awaitable'}}
 }
 
+void check_auto_await_suspend() {
+  co_await auto_await_suspend{}; // Should compile successfully.
+}
+
 void coreturn(int n) {
   co_await a;
   if (n == 0)


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


Re: [PATCH] D24373: [Coroutines] Adding builtins for coroutine intrinsics and backendutil support.

2016-09-27 Thread Gor Nishanov via cfe-commits
GorNishanov updated the summary for this revision.
GorNishanov removed a reviewer: majnemer.
GorNishanov updated this revision to Diff 72732.
GorNishanov added a comment.
Herald added a subscriber: mgorny.

1. Added documentation for builtins
2. Added a couple of tests with -disable-llvm-passes to check that builtins are 
emitted correctly


https://reviews.llvm.org/D24373

Files:
  docs/LanguageExtensions.rst
  include/clang/Basic/Builtins.def
  lib/CodeGen/BackendUtil.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGCoroutine.cpp
  lib/CodeGen/CMakeLists.txt
  lib/CodeGen/CodeGenFunction.h
  test/CodeGenCoroutines/Inputs/coro.h
  test/CodeGenCoroutines/O2-coro.c
  test/CodeGenCoroutines/coro-builtins-err.c
  test/CodeGenCoroutines/coro-builtins.c

Index: test/CodeGenCoroutines/coro-builtins.c
===
--- /dev/null
+++ test/CodeGenCoroutines/coro-builtins.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s
+
+// CHECK-LABEL: f( 
+void f() {
+  // CHECK: %0 = call token @llvm.coro.id(i32 32, i8* null, i8* null, i8* null)
+  __builtin_coro_id(32, 0, 0, 0);
+  // CHECK-NEXT: %1 = call i1 @llvm.coro.alloc(token %0)
+  __builtin_coro_alloc();
+  // CHECK-NEXT: %2 = call i64 @llvm.coro.size.i64()
+  __builtin_coro_size();
+  // CHECK-NEXT: %3 = call i8* @llvm.coro.begin(token %0, i8* null)
+  __builtin_coro_begin(0);
+  // CHECK-NEXT: %4 = call i8* @llvm.coro.frame() 
+  __builtin_coro_frame();
+  // CHECK-NEXT: call void @llvm.coro.resume(i8* null)
+  __builtin_coro_resume(0);
+  // CHECK-NEXT: call void @llvm.coro.destroy(i8* null)
+  __builtin_coro_destroy(0);
+  // CHECK-NEXT: %5 = call i1 @llvm.coro.done(i8* null)
+  __builtin_coro_done(0);
+  // CHECK-NEXT: %6 = call i8* @llvm.coro.promise(i8* null, i32 32, i1 false)
+  __builtin_coro_promise(0, 32, 0);
+  // CHECK-NEXT: %7 = call i8* @llvm.coro.free(token %0, i8* null)
+  __builtin_coro_free(0);
+  // CHECK-NEXT: call void @llvm.coro.end(i8* null, i1 false)
+  __builtin_coro_end(0, 0);
+  // CHECK-NEXT: %8 = call i8 @llvm.coro.suspend(token none, i1 false)
+  __builtin_coro_suspend(0);
+  // CHECK-NEXT: %9 = call i1 @llvm.coro.param(i8* null, i8* null)
+  __builtin_coro_param(0, 0);
+}
Index: test/CodeGenCoroutines/coro-builtins-err.c
===
--- /dev/null
+++ test/CodeGenCoroutines/coro-builtins-err.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines -emit-llvm %s -o - -verify
+
+void f() {
+  __builtin_coro_alloc(); // expected-error {{this builtin expect that __builtin_coro_id}}
+  __builtin_coro_begin(0); // expected-error {{this builtin expect that __builtin_coro_id}}
+  __builtin_coro_free(0); // expected-error {{this builtin expect that __builtin_coro_id}}
+
+  __builtin_coro_id(32, 0, 0, 0);
+  __builtin_coro_id(32, 0, 0, 0); // expected-error {{only one __builtin_coro_id}}
+}
Index: test/CodeGenCoroutines/O2-coro.c
===
--- /dev/null
+++ test/CodeGenCoroutines/O2-coro.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines -emit-llvm %s -o - -O3 | FileCheck %s
+#include "Inputs/coro.h"
+void print(int);
+
+void* f() {
+  CORO_BEGIN(malloc);
+
+  for (int i = 0;; ++i) {
+print(i);
+CORO_SUSPEND();
+  }
+
+  CORO_END(free);
+}
+
+// CHECK-LABEL: @main
+int main() {
+  void* coro = f();
+  CORO_RESUME(coro);
+  CORO_RESUME(coro);
+  CORO_DESTROY(coro);
+// CHECK: call void @print(i32 0)
+// CHECK: call void @print(i32 1)
+// CHECK: call void @print(i32 2)
+}
Index: test/CodeGenCoroutines/Inputs/coro.h
===
--- /dev/null
+++ test/CodeGenCoroutines/Inputs/coro.h
@@ -0,0 +1,37 @@
+void free(void *ptr);
+void *malloc(unsigned int);
+
+#define CORO_SUSPEND_IMPL(IsFinal) \
+  switch (__builtin_coro_suspend(IsFinal)) {   \
+  case 0:  \
+if (IsFinal)   \
+  __builtin_trap();\
+break; \
+  case 1:  \
+goto coro_Cleanup; \
+  default: \
+goto coro_Suspend; \
+  }
+
+#define CORO_SUSPEND() CORO_SUSPEND_IMPL(0)
+#define CORO_FINAL_SUSPEND() CORO_SUSPEND_IMPL(1)
+
+#define CORO_BEGIN(AllocFunc)  \
+  void *coro_hdl = 

Re: [PATCH] D24373: [Coroutines] Adding builtins for coroutine intrinsics and backendutil support.

2016-09-27 Thread Gor Nishanov via cfe-commits
GorNishanov marked an inline comment as done.


Comment at: include/clang/Basic/Builtins.def:1293
@@ +1292,3 @@
+
+BUILTIN(__builtin_coro_id, "v*Iiv*v*v*", "n")
+BUILTIN(__builtin_coro_alloc, "bv*", "n")

rsmith wrote:
> I don't really like having builtins which will result in errors from the 
> middle-end in some cases; there are a bunch of side-conditions on 
> llvm.coro.id that aren't being enforced here. In particular, this call must 
> be present in any function that also calls coro.alloc and friends, and must 
> dominate those other calls.
> 
> Modeling the 'token' value as a `void*` also seems problematic. If the user 
> uses that value for anything other than the argument to a builtin that wants 
> the token, bad things are going to happen.
> 
> (From dinner discussion:) one possible way to deal with this would be to 
> generate the call to @llvm.coro.id implicitly in the entry block, in a 
> function that uses the other builtins. The challenge then is communicating 
> the promise object to the intrinsic, which is problematic if we allow an 
> arbitrary pointer value to be passed in.
> 
> However, we're only interested in supporting a stack variable as the promise 
> object, so here's one possible approach:
> 
> - add an attribute that can be applied to a local variable to mark it as the 
> promise object for the current function
> - remove the `__builtin_coro_id` builtin, and instead implicitly generate the 
> `llvm.coro.id` intrinsic call in the entry block when we need its token or 
> see a promise object
> - when we emit a local variable with the promise-object attribute, update the 
> `llvm.coro.id` call to pass its alloca as the promise object
> - remove the 'token' parameter from `__builtin_coro_alloc` etc, and instead 
> implicitly provide it from the result of the implicit `llvm.coro.id` call
I added clarification to the documentation that all but four builtins are for 
internal compiler use and for the use as development tools for the coroutine 
feature, so, possibly we should not worry too much about people misusing them.

Alternatively, I can get rid of most of the coroutine builtins, apart from the 
ones that are intended to be used to implement coroutine standard library 
facilities.

At the moment, I think, we should prioritize getting C++ Coroutines online. We 
can polish C coroutine story later.


Comment at: test/Coroutines/coro.c:1
@@ +1,2 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines -emit-llvm %s 
-o - -O3 | FileCheck %s
+#include "Inputs/coro.h"

rsmith wrote:
> Please just check the IR generated by the frontend is correct for each of the 
> intrinsics rather than using an end-to-end test that depends on the LLVM IR 
> optimizations. You can use `-disable-llvm-optzns` to see the IR coming out of 
> clang before the mandatory coroutine passes monkey with it.
I added two tests to check that builtins are lowered to coro intrinsics 
correctly. I would like to keep a small number of "-O2" tests as a sanity 
end-to-end testing. 


https://reviews.llvm.org/D24373



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


[PATCH] D25045: [Coroutines] Add proper mangling for operator co_await for MicrosoftABI

2016-09-28 Thread Gor Nishanov via cfe-commits
GorNishanov created this revision.
GorNishanov added reviewers: rsmith, rnk.
GorNishanov added a subscriber: cfe-commits.
Herald added a subscriber: mehdi_amini.

https://reviews.llvm.org/D25045

Files:
  lib/AST/MicrosoftMangle.cpp
  test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp

Index: test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
===
--- /dev/null
+++ test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines 
-emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+struct no_suspend {
+  bool await_ready() { return true; }
+  template  void await_suspend(F) {}
+  void await_resume() {}
+};
+
+struct A {
+  no_suspend operator co_await() { return {}; }
+};
+
+struct B {};
+
+no_suspend operator co_await(B const&) { return {}; }
+
+// CHECK-LABEL: f(
+extern "C" void f() {
+  A a;
+  B b;
+  // CHECK: call void @"\01??__LA@@QEAA?AUno_suspend@@XZ"(
+  a.operator co_await();
+  // CHECK-NEXT: call i8 @"\01??__L@YA?AUno_suspend@@AEBUB@@@Z"(
+  operator co_await(b);
+}
+
Index: lib/AST/MicrosoftMangle.cpp
===
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -1089,6 +1089,8 @@
   case OO_Array_New: Out << "?_U"; break;
   //  ::= ?_V # delete[]
   case OO_Array_Delete: Out << "?_V"; break;
+  //  ::= ?__L # co_await
+  case OO_Coawait: Out << "?__L"; break;
 
   case OO_Conditional: {
 DiagnosticsEngine &Diags = Context.getDiags();
@@ -1098,14 +1100,6 @@
 break;
   }
 
-  case OO_Coawait: {
-DiagnosticsEngine &Diags = Context.getDiags();
-unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
-  "cannot mangle this operator co_await yet");
-Diags.Report(Loc, DiagID);
-break;
-  }
-
   case OO_None:
   case NUM_OVERLOADED_OPERATORS:
 llvm_unreachable("Not an overloaded operator");


Index: test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
===
--- /dev/null
+++ test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+struct no_suspend {
+  bool await_ready() { return true; }
+  template  void await_suspend(F) {}
+  void await_resume() {}
+};
+
+struct A {
+  no_suspend operator co_await() { return {}; }
+};
+
+struct B {};
+
+no_suspend operator co_await(B const&) { return {}; }
+
+// CHECK-LABEL: f(
+extern "C" void f() {
+  A a;
+  B b;
+  // CHECK: call void @"\01??__LA@@QEAA?AUno_suspend@@XZ"(
+  a.operator co_await();
+  // CHECK-NEXT: call i8 @"\01??__L@YA?AUno_suspend@@AEBUB@@@Z"(
+  operator co_await(b);
+}
+
Index: lib/AST/MicrosoftMangle.cpp
===
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -1089,6 +1089,8 @@
   case OO_Array_New: Out << "?_U"; break;
   //  ::= ?_V # delete[]
   case OO_Array_Delete: Out << "?_V"; break;
+  //  ::= ?__L # co_await
+  case OO_Coawait: Out << "?__L"; break;
 
   case OO_Conditional: {
 DiagnosticsEngine &Diags = Context.getDiags();
@@ -1098,14 +1100,6 @@
 break;
   }
 
-  case OO_Coawait: {
-DiagnosticsEngine &Diags = Context.getDiags();
-unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
-  "cannot mangle this operator co_await yet");
-Diags.Report(Loc, DiagID);
-break;
-  }
-
   case OO_None:
   case NUM_OVERLOADED_OPERATORS:
 llvm_unreachable("Not an overloaded operator");
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r282645 - [Coroutines] Add proper mangling for operator co_await for MicrosoftABI

2016-09-28 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed Sep 28 17:37:17 2016
New Revision: 282645

URL: http://llvm.org/viewvc/llvm-project?rev=282645&view=rev
Log:
[Coroutines] Add proper mangling for operator co_await for MicrosoftABI

Reviewers: rnk, rsmith

Subscribers: mehdi_amini, cfe-commits

Differential Revision: https://reviews.llvm.org/D25045

Added:
cfe/trunk/test/CodeGenCoroutines/
cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
Modified:
cfe/trunk/lib/AST/MicrosoftMangle.cpp

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=282645&r1=282644&r2=282645&view=diff
==
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Wed Sep 28 17:37:17 2016
@@ -1089,6 +1089,8 @@ void MicrosoftCXXNameMangler::mangleOper
   case OO_Array_New: Out << "?_U"; break;
   //  ::= ?_V # delete[]
   case OO_Array_Delete: Out << "?_V"; break;
+  //  ::= ?__L # co_await
+  case OO_Coawait: Out << "?__L"; break;
 
   case OO_Conditional: {
 DiagnosticsEngine &Diags = Context.getDiags();
@@ -1097,14 +1099,6 @@ void MicrosoftCXXNameMangler::mangleOper
 Diags.Report(Loc, DiagID);
 break;
   }
-
-  case OO_Coawait: {
-DiagnosticsEngine &Diags = Context.getDiags();
-unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
-  "cannot mangle this operator co_await yet");
-Diags.Report(Loc, DiagID);
-break;
-  }
 
   case OO_None:
   case NUM_OVERLOADED_OPERATORS:

Added: cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp?rev=282645&view=auto
==
--- cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp (added)
+++ cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp Wed Sep 
28 17:37:17 2016
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines 
-emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+struct no_suspend {
+  bool await_ready() { return true; }
+  template  void await_suspend(F) {}
+  void await_resume() {}
+};
+
+struct A {
+  no_suspend operator co_await() { return {}; }
+};
+
+struct B {};
+
+no_suspend operator co_await(B const&) { return {}; }
+
+// CHECK-LABEL: f(
+extern "C" void f() {
+  A a;
+  B b;
+  // CHECK: call void @"\01??__LA@@QEAA?AUno_suspend@@XZ"(
+  a.operator co_await();
+  // CHECK-NEXT: call i8 @"\01??__L@YA?AUno_suspend@@AEBUB@@@Z"(
+  operator co_await(b);
+}
+


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


Re: [PATCH] D25045: [Coroutines] Add proper mangling for operator co_await for MicrosoftABI

2016-09-28 Thread Gor Nishanov via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL282645: [Coroutines] Add proper mangling for operator 
co_await for MicrosoftABI (authored by GorNishanov).

Changed prior to commit:
  https://reviews.llvm.org/D25045?vs=72900&id=72916#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D25045

Files:
  cfe/trunk/lib/AST/MicrosoftMangle.cpp
  cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp

Index: cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
===
--- cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
+++ cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines 
-emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+struct no_suspend {
+  bool await_ready() { return true; }
+  template  void await_suspend(F) {}
+  void await_resume() {}
+};
+
+struct A {
+  no_suspend operator co_await() { return {}; }
+};
+
+struct B {};
+
+no_suspend operator co_await(B const&) { return {}; }
+
+// CHECK-LABEL: f(
+extern "C" void f() {
+  A a;
+  B b;
+  // CHECK: call void @"\01??__LA@@QEAA?AUno_suspend@@XZ"(
+  a.operator co_await();
+  // CHECK-NEXT: call i8 @"\01??__L@YA?AUno_suspend@@AEBUB@@@Z"(
+  operator co_await(b);
+}
+
Index: cfe/trunk/lib/AST/MicrosoftMangle.cpp
===
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp
@@ -1089,6 +1089,8 @@
   case OO_Array_New: Out << "?_U"; break;
   //  ::= ?_V # delete[]
   case OO_Array_Delete: Out << "?_V"; break;
+  //  ::= ?__L # co_await
+  case OO_Coawait: Out << "?__L"; break;
 
   case OO_Conditional: {
 DiagnosticsEngine &Diags = Context.getDiags();
@@ -1098,14 +1100,6 @@
 break;
   }
 
-  case OO_Coawait: {
-DiagnosticsEngine &Diags = Context.getDiags();
-unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
-  "cannot mangle this operator co_await yet");
-Diags.Report(Loc, DiagID);
-break;
-  }
-
   case OO_None:
   case NUM_OVERLOADED_OPERATORS:
 llvm_unreachable("Not an overloaded operator");


Index: cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
===
--- cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
+++ cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+struct no_suspend {
+  bool await_ready() { return true; }
+  template  void await_suspend(F) {}
+  void await_resume() {}
+};
+
+struct A {
+  no_suspend operator co_await() { return {}; }
+};
+
+struct B {};
+
+no_suspend operator co_await(B const&) { return {}; }
+
+// CHECK-LABEL: f(
+extern "C" void f() {
+  A a;
+  B b;
+  // CHECK: call void @"\01??__LA@@QEAA?AUno_suspend@@XZ"(
+  a.operator co_await();
+  // CHECK-NEXT: call i8 @"\01??__L@YA?AUno_suspend@@AEBUB@@@Z"(
+  operator co_await(b);
+}
+
Index: cfe/trunk/lib/AST/MicrosoftMangle.cpp
===
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp
@@ -1089,6 +1089,8 @@
   case OO_Array_New: Out << "?_U"; break;
   //  ::= ?_V # delete[]
   case OO_Array_Delete: Out << "?_V"; break;
+  //  ::= ?__L # co_await
+  case OO_Coawait: Out << "?__L"; break;
 
   case OO_Conditional: {
 DiagnosticsEngine &Diags = Context.getDiags();
@@ -1098,14 +1100,6 @@
 break;
   }
 
-  case OO_Coawait: {
-DiagnosticsEngine &Diags = Context.getDiags();
-unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
-  "cannot mangle this operator co_await yet");
-Diags.Report(Loc, DiagID);
-break;
-  }
-
   case OO_None:
   case NUM_OVERLOADED_OPERATORS:
 llvm_unreachable("Not an overloaded operator");
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] [coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

2016-09-29 Thread Gor Nishanov via cfe-commits
Currently the -fcoroutines flag is a CC1 only flag. It really should be
both a Driver and CC1 flag. This patch fixes the option and adds tests for
the new options.

Also adds a __has_feature for coroutines.
Patch is mostly by Eric Fiselier
.
Meticulous and painstaking extraction from the larger coroutine branch by
Gor Nishanov

P.S.

Switching to lowercase [coroutines] tag in the title, as most of the
coroutine commits in cfe were done with lowercase tag.
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 66e1ad6..73ab5e6 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -638,10 +638,6 @@ def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">,
 def finclude_default_header : Flag<["-"], "finclude-default-header">,
   HelpText<"Include the default header file for OpenCL">;
 
-// C++ TSes.
-def fcoroutines : Flag<["-"], "fcoroutines">,
-  HelpText<"Enable support for the C++ Coroutines TS">;
-
 //===--===//
 // Header Search Options
 //===--===//
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 6090304..dba95c7 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -481,6 +481,13 @@ def fno_autolink : Flag <["-"], "fno-autolink">, Group,
   Flags<[DriverOption, CC1Option]>,
   HelpText<"Disable generation of linker directives for automatic library linking">;
 
+// C++ Coroutines TS
+def fcoroutines : Flag <["-"], "fcoroutines-ts">, Group,
+  Flags<[DriverOption, CC1Option]>,
+  HelpText<"Enable support for the C++ Coroutines TS">;
+def fno_coroutines : Flag <["-"], "fno-coroutines-ts">, Group,
+  Flags<[DriverOption]>;
+
 def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">,
 Group, Flags<[DriverOption, CC1Option]>, MetaVarName<"">,
 HelpText<"Embed LLVM bitcode (option: off, all, bitcode, marker)">;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index d806efd..18891cf 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -5423,6 +5423,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   CmdArgs.push_back("-fblocks-runtime-optional");
   }
 
+  if (Args.hasFlag(options::OPT_fcoroutines, options::OPT_fno_coroutines, false)
+  && types::isCXX(InputType)) {
+CmdArgs.push_back("-fcoroutines-ts");
+  }
+
   // -fmodules enables the use of precompiled modules (off by default).
   // Users can pass -fno-cxx-modules to turn off modules support for
   // C++/Objective-C++ programs.
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 940192b..838f769 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -1213,6 +1213,7 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
   // Type traits
   // N.B. Additional type traits should not be added to the following list.
   // Instead, they should be detected by has_extension.
+  .Case("coroutines", LangOpts.Coroutines)
   .Case("has_nothrow_assign", LangOpts.CPlusPlus)
   .Case("has_nothrow_copy", LangOpts.CPlusPlus)
   .Case("has_nothrow_constructor", LangOpts.CPlusPlus)
diff --git a/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp b/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
index e87fed0..1921c06 100644
--- a/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
+++ b/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
 struct no_suspend {
   bool await_ready() { return true; }
   template  void await_suspend(F) {}
diff --git a/test/Driver/coroutines.m b/test/Driver/coroutines.m
new file mode 100644
index 000..d610234
--- /dev/null
+++ b/test/Driver/coroutines.m
@@ -0,0 +1,6 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// CHECK-NO-CORO-NOT: -fcoroutines-ts
+
diff --git a/test/Driver/coroutines.mm b/test/Driver/coroutines.mm
new file mode 100644
index 000..99e0ff5
--- /dev/null
+++ b/test/Driver/coroutines.mm
@@ -0,0 +1,9 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-

Re: [PATCH] [coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

2016-09-29 Thread Gor Nishanov via cfe-commits
Let's see if renaming the attachment to *.txt helps.

On Thu, Sep 29, 2016 at 5:42 PM, Gor Nishanov  wrote:

> Currently the -fcoroutines flag is a CC1 only flag. It really should be
> both a Driver and CC1 flag. This patch fixes the option and adds tests for
> the new options.
>
> Also adds a __has_feature for coroutines.
> Patch is mostly by Eric Fiselier
> .
> Meticulous and painstaking extraction from the larger coroutine branch by
> Gor Nishanov
>
> P.S.
>
> Switching to lowercase [coroutines] tag in the title, as most of the
> coroutine commits in cfe were done with lowercase tag.
>
diff --git a/include/clang/Driver/CC1Options.td 
b/include/clang/Driver/CC1Options.td
index 66e1ad6..73ab5e6 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -638,10 +638,6 @@ def fdefault_calling_conv_EQ : Joined<["-"], 
"fdefault-calling-conv=">,
 def finclude_default_header : Flag<["-"], "finclude-default-header">,
   HelpText<"Include the default header file for OpenCL">;
 
-// C++ TSes.
-def fcoroutines : Flag<["-"], "fcoroutines">,
-  HelpText<"Enable support for the C++ Coroutines TS">;
-
 
//===--===//
 // Header Search Options
 
//===--===//
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 6090304..dba95c7 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -481,6 +481,13 @@ def fno_autolink : Flag <["-"], "fno-autolink">, 
Group,
   Flags<[DriverOption, CC1Option]>,
   HelpText<"Disable generation of linker directives for automatic library 
linking">;
 
+// C++ Coroutines TS
+def fcoroutines : Flag <["-"], "fcoroutines-ts">, Group,
+  Flags<[DriverOption, CC1Option]>,
+  HelpText<"Enable support for the C++ Coroutines TS">;
+def fno_coroutines : Flag <["-"], "fno-coroutines-ts">, Group,
+  Flags<[DriverOption]>;
+
 def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">,
 Group, Flags<[DriverOption, CC1Option]>, MetaVarName<"">,
 HelpText<"Embed LLVM bitcode (option: off, all, bitcode, marker)">;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index d806efd..18891cf 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -5423,6 +5423,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   CmdArgs.push_back("-fblocks-runtime-optional");
   }
 
+  if (Args.hasFlag(options::OPT_fcoroutines, options::OPT_fno_coroutines, 
false)
+  && types::isCXX(InputType)) {
+CmdArgs.push_back("-fcoroutines-ts");
+  }
+
   // -fmodules enables the use of precompiled modules (off by default).
   // Users can pass -fno-cxx-modules to turn off modules support for
   // C++/Objective-C++ programs.
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 940192b..838f769 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -1213,6 +1213,7 @@ static bool HasFeature(const Preprocessor &PP, StringRef 
Feature) {
   // Type traits
   // N.B. Additional type traits should not be added to the following list.
   // Instead, they should be detected by has_extension.
+  .Case("coroutines", LangOpts.Coroutines)
   .Case("has_nothrow_assign", LangOpts.CPlusPlus)
   .Case("has_nothrow_copy", LangOpts.CPlusPlus)
   .Case("has_nothrow_constructor", LangOpts.CPlusPlus)
diff --git a/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp 
b/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
index e87fed0..1921c06 100644
--- a/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
+++ b/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines 
-emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts 
-emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
 struct no_suspend {
   bool await_ready() { return true; }
   template  void await_suspend(F) {}
diff --git a/test/Driver/coroutines.m b/test/Driver/coroutines.m
new file mode 100644
index 000..d610234
--- /dev/null
+++ b/test/Driver/coroutines.m
@@ -0,0 +1,6 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -### %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -### %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -fcoroutines-ts -### %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-CORO %s
+// CHECK-NO-CORO-NOT: -fcoroutines-ts
+
diff --git a/test/Driver/coroutines.mm b/test/Driver/coroutines.mm
new file mode 100644
index 000..99e0ff5
--- /dev/null
+++ b/test/Driver/coroutines.mm
@@ -0,0 +1,9 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -fno-co

Re: [PATCH] [coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

2016-09-29 Thread Gor Nishanov via cfe-commits
You beat me to it, Eric. :) I'll add mine for review, too. Let's see which
one Richard will respond :) .

1. Remove __has_feature
2. Rename fcoroutines => fcoroutines_TS
3. Rename __cpp_coroutines => __cpp_experimental_coroutines

Since phabricator is down, here is a handy diff on a github
https://github.com/GorNishanov/clang/commit/e129083a73cf82e0bcea0817045ae6baaadccbb7




On Thu, Sep 29, 2016 at 6:22 PM, Eric Fiselier  wrote:

> I've attached an updated patch which addresses the comments.
>
> 1. Remove __has_feature changes.
> 2. Rename OPT_fcoroutines -> OPT_fcoroutines_TS.
>
> /Eric
>
> On Thu, Sep 29, 2016 at 6:58 PM, Richard Smith 
> wrote:
>
>> +def fcoroutines : Flag <["-"], "fcoroutines-ts">, Group,
>> +  Flags<[DriverOption, CC1Option]>,
>> +  HelpText<"Enable support for the C++ Coroutines TS">;
>> +def fno_coroutines : Flag <["-"], "fno-coroutines-ts">, Group,
>>
>> These should be named fcoroutines_ts, fno_coroutines_ts (see comment at
>> the top of the file for the naming scheme).
>>
>> +  .Case("coroutines", LangOpts.Coroutines)
>>
>> We should use the SD-6 macro name (__cpp_coroutines) rather than
>> __has_feature for new features that are covered by SD-6. However, we
>> shouldn't be defining this until we have a complete implementation. (Code
>> using this for a feature test wants to test whether the feature works, not
>> just whether it's enabled on the command line.)
>>
>> On Thu, Sep 29, 2016 at 5:45 PM, Gor Nishanov 
>> wrote:
>>
>>> Let's see if renaming the attachment to *.txt helps.
>>>
>>> On Thu, Sep 29, 2016 at 5:42 PM, Gor Nishanov 
>>> wrote:
>>>
 Currently the -fcoroutines flag is a CC1 only flag. It really should be
 both a Driver and CC1 flag. This patch fixes the option and adds tests for
 the new options.

 Also adds a __has_feature for coroutines.
 Patch is mostly by Eric Fiselier
 .
 Meticulous and painstaking extraction from the larger coroutine branch
 by Gor Nishanov

 P.S.

 Switching to lowercase [coroutines] tag in the title, as most of the
 coroutine commits in cfe were done with lowercase tag.

>>>
>>>
>>
>
diff --git a/include/clang/Basic/LangOptions.def 
b/include/clang/Basic/LangOptions.def
index b738f83..fc8ce78 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -133,7 +133,7 @@ LANGOPT(Freestanding, 1, 0, "freestanding implementation")
 LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
 LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
 LANGOPT(GNUAsm, 1, 1, "GNU-style inline assembly")
-LANGOPT(Coroutines, 1, 0, "C++ coroutines")
+LANGOPT(CoroutinesTS  , 1, 0, "C++ coroutines TS")
 
 BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
 LANGOPT(POSIXThreads  , 1, 0, "POSIX thread support")
diff --git a/include/clang/Driver/CC1Options.td 
b/include/clang/Driver/CC1Options.td
index 66e1ad6..73ab5e6 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -638,10 +638,6 @@ def fdefault_calling_conv_EQ : Joined<["-"], 
"fdefault-calling-conv=">,
 def finclude_default_header : Flag<["-"], "finclude-default-header">,
   HelpText<"Include the default header file for OpenCL">;
 
-// C++ TSes.
-def fcoroutines : Flag<["-"], "fcoroutines">,
-  HelpText<"Enable support for the C++ Coroutines TS">;
-
 
//===--===//
 // Header Search Options
 
//===--===//
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 6090304..dc3567a 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -481,6 +481,13 @@ def fno_autolink : Flag <["-"], "fno-autolink">, 
Group,
   Flags<[DriverOption, CC1Option]>,
   HelpText<"Disable generation of linker directives for automatic library 
linking">;
 
+// C++ Coroutines TS
+def fcoroutines_ts : Flag <["-"], "fcoroutines-ts">, Group,
+  Flags<[DriverOption, CC1Option]>,
+  HelpText<"Enable support for the C++ Coroutines TS">;
+def fno_coroutines_ts : Flag <["-"], "fno-coroutines-ts">, Group,
+  Flags<[DriverOption]>;
+
 def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">,
 Group, Flags<[DriverOption, CC1Option]>, MetaVarName<"">,
 HelpText<"Embed LLVM bitcode (option: off, all, bitcode, marker)">;
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 537a2b7..dcd1e8b 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -150,7 +150,7 @@ static KeywordStatus getKeywordStatus(const LangOptions 
&LangOpts,
   if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
   if (LangOpts.ObjC2 && (Flags & KEYOBJC2)) return KS_Enabled;
   if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
-  if (LangOpts.Coroutines && (Flags & KEYCOROUTINES)) return KS_

[PATCH] [Request, 69 lines] D25068: [coroutines] Switch to using std::experimental namespace per P0057R5

2016-09-29 Thread Gor Nishanov via cfe-commits
GorNishanov created this revision.GorNishanov added reviewers: EricWF, rsmith, cfe-commits.Herald added a subscriber: mehdi_amini.
View RevisionLook for coroutine_traits and friends in std::experimental namespace.
Patch (mostly) by EricWF.https://reviews.llvm.org/D25068Files:include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/SemaCoroutine.cpp
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/coroutines.cppIndex: test/SemaCXX/coroutines.cpp
===
--- test/SemaCXX/coroutines.cpp
+++ test/SemaCXX/coroutines.cpp
@@ -1,18 +1,18 @@
 // RUN: %clang_cc1 -std=c++14 -fcoroutines -verify %s
 
 void no_coroutine_traits_bad_arg_await() {
-  co_await a; // expected-error {{include }}
+  co_await a; // expected-error {{include }}
   // expected-error@-1 {{use of undeclared identifier 'a'}}
 }
 
 void no_coroutine_traits_bad_arg_yield() {
-  co_yield a; // expected-error {{include }}
+  co_yield a; // expected-error {{include }}
   // expected-error@-1 {{use of undeclared identifier 'a'}}
 }
 
 
 void no_coroutine_traits_bad_arg_return() {
-  co_return a; // expected-error {{include }}
+  co_return a; // expected-error {{include }}
   // expected-error@-1 {{use of undeclared identifier 'a'}}
 }
 
@@ -36,43 +36,48 @@
 };
 
 void no_coroutine_traits() {
-  co_await a; // expected-error {{need to include }}
+  co_await a; // expected-error {{need to include }}
 }
 
-namespace std {
+namespace std { namespace experimental {
   template struct coroutine_traits; // expected-note {{declared here}}
-};
+}}
 
 template struct coro {};
 template
-struct std::coroutine_traits, Ps...> {
+struct std::experimental::coroutine_traits, Ps...> {
   using promise_type = Promise;
 };
 
 void no_specialization() {
-  co_await a; // expected-error {{implicit instantiation of undefined template 'std::coroutine_traits'}}
+  co_await a; // expected-error {{implicit instantiation of undefined template 'std::experimental::coroutine_traits'}}
 }
 
-template struct std::coroutine_traits {};
+template struct std::experimental::coroutine_traits {};
 
 int no_promise_type() {
-  co_await a; // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits' has no member named 'promise_type'}}
+  co_await a; // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits' has no member named 'promise_type'}}
 }
 
-template<> struct std::coroutine_traits { typedef int promise_type; };
+template<> struct std::experimental::coroutine_traits { typedef int promise_type; };
 double bad_promise_type(double) {
-  co_await a; // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits::promise_type' (aka 'int') is not a class}}
+  co_await a; // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits::promise_type' (aka 'int') is not a class}}
 }
 
-template<> struct std::coroutine_traits {
+template<> struct std::experimental::coroutine_traits {
   struct promise_type {};
 };
 double bad_promise_type_2(int) {
-  co_yield 0; // expected-error {{no member named 'yield_value' in 'std::coroutine_traits::promise_type'}}
+  co_yield 0; // expected-error {{no member named 'yield_value' in 'std::experimental::coroutine_traits::promise_type'}}
 }
 
 struct promise; // expected-note 2{{forward declaration}}
-template struct std::coroutine_traits { using promise_type = promise; };
+template struct std::experimental::coroutine_traits { using promise_type = promise; };
+
+
+namespace std { namespace experimental {
+  template  struct coroutine_handle;
+}}
 
   // FIXME: This diagnostic is terrible.
 void undefined_promise() { // expected-error {{variable has incomplete type 'promise_type'}}
@@ -200,7 +205,7 @@
 }
 
 struct yield_fn_tag {};
-template<> struct std::coroutine_traits {
+template<> struct std::experimental::coroutine_traits {
   struct promise_type {
 // FIXME: add an await_transform overload for functions
 awaitable yield_value(int());
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -8111,6 +8111,7 @@
   bool IsInline = InlineLoc.isValid();
   bool IsInvalid = false;
   bool IsStd = false;
+  bool IsStdExperimental = false;
   bool AddToKnown = false;
   Scope *DeclRegionScope = NamespcScope->getParent();
 
@@ -8152,6 +8153,11 @@
   PrevNS = getStdNamespace();
   IsStd = true;
   AddToKnown = !IsInline;
+} else if (II->isStr("experimental") &&
+  CurContext->getRedeclContext()->isStdNamespace()) {
+  PrevNS = getStdExperimentalNamespace();
+  IsStdExperimental = true;
+  AddToKnown = !IsInline;
 } else {
   // We've seen this namespace for the first time.
   AddToKnown = !IsInline;
@@ -8186,6 +8192,8 @@
 
   if (IsStd)
 StdNamespace = Namespc;
+  if (IsStdExperimental)
+StdExperimentalNamespace = Namespc;
   if (AddT

[PATCH] D25078: [Coroutines] Diagnose when 'main' is declared as a coroutine.

2016-09-30 Thread Gor Nishanov via cfe-commits
GorNishanov added inline comments.


> DiagnosticSemaKinds.td:8569
>"'%0' cannot be used in a varargs function">;
>  def ext_coroutine_without_co_await_co_yield : ExtWarn<
>"'co_return' used in a function "

I am wondering, if we can handle all four cases when function can be a 
coroutine.

co_await
co_yield
co_return
for co_await

future f() { co_return 42; } // is a valid coroutine per P0057R5

https://reviews.llvm.org/D25078



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


Re: [PATCH] [coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

2016-09-30 Thread Gor Nishanov via cfe-commits
I noticed that other TSes has experimental in their SD-6 macro name, hence,
I changed it to match the concepts TS macro __cpp_experimental_concepts.
We are reviewing the wording coming Monday and can tweak the SD-6 macro as
needed.

Also, Richard mentioned in the feedback that:

>> However, we *shouldn't be* defining this until we have a complete
implementation. (Code using this for a feature test wants to test whether
the feature works, not just whether it's enabled on the command line.)

Richard, do you want us to take out __cpp_coroutines completely until all
of the parts are pushed upstream?

On Thu, Sep 29, 2016 at 9:59 PM, Eric Fiselier  wrote:

> On Sep 29, 2016 8:23 PM, "Gor Nishanov"  wrote:
> >
> > You beat me to it, Eric. :) I'll add mine for review, too. Let's see
> which one Richard will respond :) .
> >
> > 1. Remove __has_feature
> > 2. Rename fcoroutines => fcoroutines_TS
> > 3. Rename __cpp_coroutines => __cpp_experimental_coroutines
>
> The TS spec uses __cpp_coroutines. What's the reason for changing it?
>
> >
> > Since phabricator is down, here is a handy diff on a github
> > https://github.com/GorNishanov/clang/commit/
> e129083a73cf82e0bcea0817045ae6baaadccbb7
> >
> >
> >
> >
> > On Thu, Sep 29, 2016 at 6:22 PM, Eric Fiselier  wrote:
> >>
> >> I've attached an updated patch which addresses the comments.
> >>
> >> 1. Remove __has_feature changes.
> >> 2. Rename OPT_fcoroutines -> OPT_fcoroutines_TS.
> >>
> >> /Eric
> >>
> >> On Thu, Sep 29, 2016 at 6:58 PM, Richard Smith 
> wrote:
> >>>
> >>> +def fcoroutines : Flag <["-"], "fcoroutines-ts">, Group, +
> Flags<[DriverOption, CC1Option]>, + HelpText<"Enable support for the C++
> Coroutines TS">; +def fno_coroutines : Flag <["-"], "fno-coroutines-ts">,
> Group,
> >>>
> >>> These should be named fcoroutines_ts, fno_coroutines_ts (see comment
> at the top of the file for the naming scheme).
> >>>
> >>> + .Case("coroutines", LangOpts.Coroutines)
> >>>
> >>> We should use the SD-6 macro name (__cpp_coroutines) rather than
> __has_feature for new features that are covered by SD-6. However, we
> shouldn't be defining this until we have a complete implementation. (Code
> using this for a feature test wants to test whether the feature works, not
> just whether it's enabled on the command line.)
> >>>
> >>> On Thu, Sep 29, 2016 at 5:45 PM, Gor Nishanov 
> wrote:
> 
>  Let's see if renaming the attachment to *.txt helps.
> 
>  On Thu, Sep 29, 2016 at 5:42 PM, Gor Nishanov 
> wrote:
> >
> > Currently the -fcoroutines flag is a CC1 only flag. It really should
> be both a Driver and CC1 flag. This patch fixes the option and adds tests
> for the new options.
> >
> > Also adds a __has_feature for coroutines.
> >
> > Patch is mostly by Eric Fiselier
> > .
> > Meticulous and painstaking extraction from the larger coroutine
> branch by Gor Nishanov
> >
> > P.S.
> >
> > Switching to lowercase [coroutines] tag in the title, as most of the
> coroutine commits in cfe were done with lowercase tag.
> 
> 
> >>>
> >>
> >
>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D25078: [coroutines] Diagnose when 'main' is declared as a coroutine.

2016-09-30 Thread Gor Nishanov via cfe-commits
GorNishanov added a comment.

LGTM

I am happy either way. Fixes for co_return can come later.


https://reviews.llvm.org/D25078



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


[PATCH] D25130: [coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

2016-09-30 Thread Gor Nishanov via cfe-commits
GorNishanov created this revision.
GorNishanov added reviewers: rsmith, rnk, EricWF, cfe-commits.
Herald added a subscriber: mehdi_amini.

Also makes -fcoroutines_ts to be both a Driver and CC1 flag.

Patch mostly by EricWF.


https://reviews.llvm.org/D25130

Files:
  include/clang/Basic/LangOptions.def
  include/clang/Driver/CC1Options.td
  include/clang/Driver/Options.td
  lib/Basic/IdentifierTable.cpp
  lib/Driver/Tools.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Frontend/InitPreprocessor.cpp
  lib/Sema/SemaDecl.cpp
  test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
  test/Driver/coroutines.m
  test/Driver/coroutines.mm
  test/Lexer/coroutines.cpp
  test/Lexer/cxx-features.cpp
  test/Parser/cxx1z-coroutines.cpp
  test/SemaCXX/coroutines.cpp

Index: test/SemaCXX/coroutines.cpp
===
--- test/SemaCXX/coroutines.cpp
+++ test/SemaCXX/coroutines.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++14 -fcoroutines -verify %s
+// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s
 
 void no_coroutine_traits_bad_arg_await() {
   co_await a; // expected-error {{include }}
Index: test/Parser/cxx1z-coroutines.cpp
===
--- test/Parser/cxx1z-coroutines.cpp
+++ test/Parser/cxx1z-coroutines.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fcoroutines %s -verify
+// RUN: %clang_cc1 -std=c++11 -fcoroutines-ts %s -verify
 
 template
 U f(T t) {
Index: test/Lexer/cxx-features.cpp
===
--- test/Lexer/cxx-features.cpp
+++ test/Lexer/cxx-features.cpp
@@ -5,7 +5,7 @@
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -verify %s
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s
 // RUN: %clang_cc1 -fno-rtti -verify %s -DNO_EXCEPTIONS -DNO_RTTI
-// RUN: %clang_cc1 -fcoroutines -DNO_EXCEPTIONS -DCOROUTINES -verify %s
+// RUN: %clang_cc1 -fcoroutines-ts -DNO_EXCEPTIONS -DCOROUTINES -verify %s
 
 // expected-no-diagnostics
 
Index: test/Lexer/coroutines.cpp
===
--- test/Lexer/coroutines.cpp
+++ test/Lexer/coroutines.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only %s
-// RUN: %clang_cc1 -fcoroutines -DCORO -fsyntax-only %s
+// RUN: %clang_cc1 -fcoroutines-ts -DCORO -fsyntax-only %s
 
 #ifdef CORO
 #define CORO_KEYWORD(NAME) _Static_assert(!__is_identifier(NAME), #NAME)
Index: test/Driver/coroutines.mm
===
--- /dev/null
+++ test/Driver/coroutines.mm
@@ -0,0 +1,9 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// CHECK-NO-CORO-NOT: -fcoroutines-ts
+
+// RUN: %clang -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-HAS-CORO  %s
+// RUN: %clang -fno-coroutines-ts -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-HAS-CORO %s
+// CHECK-HAS-CORO: -fcoroutines-ts
+
Index: test/Driver/coroutines.m
===
--- /dev/null
+++ test/Driver/coroutines.m
@@ -0,0 +1,6 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// CHECK-NO-CORO-NOT: -fcoroutines-ts
+
Index: test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
===
--- test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
+++ test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
 struct no_suspend {
   bool await_ready() { return true; }
   template  void await_suspend(F) {}
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -11602,7 +11602,7 @@
   sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
   sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
 
-  if (getLangOpts().Coroutines && !getCurFunction()->CoroutineStmts.empty())
+  if (getLangOpts().CoroutinesTS && !getCurFunction()->CoroutineStmts.empty())
 CheckCompletedCoroutineBody(FD, Body);
 
   if (FD) {
Index: lib/Fronten

Re: [PATCH] [coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

2016-09-30 Thread Gor Nishanov via cfe-commits
Uploaded to phabricator as https://reviews.llvm.org/D25130

__cpp_coroutines stays as it is.

On Fri, Sep 30, 2016 at 10:11 AM, Gor Nishanov 
wrote:

> I noticed that other TSes has experimental in their SD-6 macro name,
> hence, I changed it to match the concepts TS macro
> __cpp_experimental_concepts.
> We are reviewing the wording coming Monday and can tweak the SD-6 macro as
> needed.
>
> Also, Richard mentioned in the feedback that:
>
> >> However, we *shouldn't be* defining this until we have a complete
> implementation. (Code using this for a feature test wants to test whether
> the feature works, not just whether it's enabled on the command line.)
>
> Richard, do you want us to take out __cpp_coroutines completely until all
> of the parts are pushed upstream?
>
> On Thu, Sep 29, 2016 at 9:59 PM, Eric Fiselier  wrote:
>
>> On Sep 29, 2016 8:23 PM, "Gor Nishanov"  wrote:
>> >
>> > You beat me to it, Eric. :) I'll add mine for review, too. Let's see
>> which one Richard will respond :) .
>> >
>> > 1. Remove __has_feature
>> > 2. Rename fcoroutines => fcoroutines_TS
>> > 3. Rename __cpp_coroutines => __cpp_experimental_coroutines
>>
>> The TS spec uses __cpp_coroutines. What's the reason for changing it?
>>
>> >
>> > Since phabricator is down, here is a handy diff on a github
>> > https://github.com/GorNishanov/clang/commit/e129083a73cf82e0
>> bcea0817045ae6baaadccbb7
>> >
>> >
>> >
>> >
>> > On Thu, Sep 29, 2016 at 6:22 PM, Eric Fiselier  wrote:
>> >>
>> >> I've attached an updated patch which addresses the comments.
>> >>
>> >> 1. Remove __has_feature changes.
>> >> 2. Rename OPT_fcoroutines -> OPT_fcoroutines_TS.
>> >>
>> >> /Eric
>> >>
>> >> On Thu, Sep 29, 2016 at 6:58 PM, Richard Smith 
>> wrote:
>> >>>
>> >>> +def fcoroutines : Flag <["-"], "fcoroutines-ts">, Group, +
>> Flags<[DriverOption, CC1Option]>, + HelpText<"Enable support for the C++
>> Coroutines TS">; +def fno_coroutines : Flag <["-"], "fno-coroutines-ts">,
>> Group,
>> >>>
>> >>> These should be named fcoroutines_ts, fno_coroutines_ts (see comment
>> at the top of the file for the naming scheme).
>> >>>
>> >>> + .Case("coroutines", LangOpts.Coroutines)
>> >>>
>> >>> We should use the SD-6 macro name (__cpp_coroutines) rather than
>> __has_feature for new features that are covered by SD-6. However, we
>> shouldn't be defining this until we have a complete implementation. (Code
>> using this for a feature test wants to test whether the feature works, not
>> just whether it's enabled on the command line.)
>> >>>
>> >>> On Thu, Sep 29, 2016 at 5:45 PM, Gor Nishanov 
>> wrote:
>> 
>>  Let's see if renaming the attachment to *.txt helps.
>> 
>>  On Thu, Sep 29, 2016 at 5:42 PM, Gor Nishanov 
>> wrote:
>> >
>> > Currently the -fcoroutines flag is a CC1 only flag. It really
>> should be both a Driver and CC1 flag. This patch fixes the option and adds
>> tests for the new options.
>> >
>> > Also adds a __has_feature for coroutines.
>> >
>> > Patch is mostly by Eric Fiselier
>> > .
>> > Meticulous and painstaking extraction from the larger coroutine
>> branch by Gor Nishanov
>> >
>> > P.S.
>> >
>> > Switching to lowercase [coroutines] tag in the title, as most of
>> the coroutine commits in cfe were done with lowercase tag.
>> 
>> 
>> >>>
>> >>
>> >
>>
>
>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D24373: [Coroutines] Adding builtins for coroutine intrinsics and backendutil support.

2016-09-30 Thread Gor Nishanov via cfe-commits
GorNishanov added reviewers: rnk, EricWF.
GorNishanov updated this revision to Diff 73155.
GorNishanov marked an inline comment as done.
GorNishanov added a comment.

Improved diagnostics in CGCoroutine and ping...


https://reviews.llvm.org/D24373

Files:
  docs/LanguageExtensions.rst
  include/clang/Basic/Builtins.def
  lib/CodeGen/BackendUtil.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGCoroutine.cpp
  lib/CodeGen/CMakeLists.txt
  lib/CodeGen/CodeGenFunction.h
  test/CodeGenCoroutines/Inputs/coro.h
  test/CodeGenCoroutines/O2-coro.c
  test/CodeGenCoroutines/coro-builtins-err.c
  test/CodeGenCoroutines/coro-builtins.c

Index: test/CodeGenCoroutines/coro-builtins.c
===
--- /dev/null
+++ test/CodeGenCoroutines/coro-builtins.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s
+
+// CHECK-LABEL: f( 
+void f() {
+  // CHECK: %0 = call token @llvm.coro.id(i32 32, i8* null, i8* null, i8* null)
+  __builtin_coro_id(32, 0, 0, 0);
+  // CHECK-NEXT: %1 = call i1 @llvm.coro.alloc(token %0)
+  __builtin_coro_alloc();
+  // CHECK-NEXT: %2 = call i64 @llvm.coro.size.i64()
+  __builtin_coro_size();
+  // CHECK-NEXT: %3 = call i8* @llvm.coro.begin(token %0, i8* null)
+  __builtin_coro_begin(0);
+  // CHECK-NEXT: %4 = call i8* @llvm.coro.frame() 
+  __builtin_coro_frame();
+  // CHECK-NEXT: call void @llvm.coro.resume(i8* null)
+  __builtin_coro_resume(0);
+  // CHECK-NEXT: call void @llvm.coro.destroy(i8* null)
+  __builtin_coro_destroy(0);
+  // CHECK-NEXT: %5 = call i1 @llvm.coro.done(i8* null)
+  __builtin_coro_done(0);
+  // CHECK-NEXT: %6 = call i8* @llvm.coro.promise(i8* null, i32 32, i1 false)
+  __builtin_coro_promise(0, 32, 0);
+  // CHECK-NEXT: %7 = call i8* @llvm.coro.free(token %0, i8* null)
+  __builtin_coro_free(0);
+  // CHECK-NEXT: call void @llvm.coro.end(i8* null, i1 false)
+  __builtin_coro_end(0, 0);
+  // CHECK-NEXT: %8 = call i8 @llvm.coro.suspend(token none, i1 false)
+  __builtin_coro_suspend(0);
+  // CHECK-NEXT: %9 = call i1 @llvm.coro.param(i8* null, i8* null)
+  __builtin_coro_param(0, 0);
+}
Index: test/CodeGenCoroutines/coro-builtins-err.c
===
--- /dev/null
+++ test/CodeGenCoroutines/coro-builtins-err.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines -emit-llvm %s -o - -verify
+
+void f() {
+  __builtin_coro_alloc(); // expected-error {{this builtin expect that __builtin_coro_id}}
+  __builtin_coro_begin(0); // expected-error {{this builtin expect that __builtin_coro_id}}
+  __builtin_coro_free(0); // expected-error {{this builtin expect that __builtin_coro_id}}
+
+  __builtin_coro_id(32, 0, 0, 0);
+  __builtin_coro_id(32, 0, 0, 0); // expected-error {{only one __builtin_coro_id}}
+}
Index: test/CodeGenCoroutines/O2-coro.c
===
--- /dev/null
+++ test/CodeGenCoroutines/O2-coro.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines -emit-llvm %s -o - -O3 | FileCheck %s
+#include "Inputs/coro.h"
+void print(int);
+
+void* f() {
+  CORO_BEGIN(malloc);
+
+  for (int i = 0;; ++i) {
+print(i);
+CORO_SUSPEND();
+  }
+
+  CORO_END(free);
+}
+
+// CHECK-LABEL: @main
+int main() {
+  void* coro = f();
+  CORO_RESUME(coro);
+  CORO_RESUME(coro);
+  CORO_DESTROY(coro);
+// CHECK: call void @print(i32 0)
+// CHECK: call void @print(i32 1)
+// CHECK: call void @print(i32 2)
+}
Index: test/CodeGenCoroutines/Inputs/coro.h
===
--- /dev/null
+++ test/CodeGenCoroutines/Inputs/coro.h
@@ -0,0 +1,37 @@
+void free(void *ptr);
+void *malloc(unsigned int);
+
+#define CORO_SUSPEND_IMPL(IsFinal) \
+  switch (__builtin_coro_suspend(IsFinal)) {   \
+  case 0:  \
+if (IsFinal)   \
+  __builtin_trap();\
+break; \
+  case 1:  \
+goto coro_Cleanup; \
+  default: \
+goto coro_Suspend; \
+  }
+
+#define CORO_SUSPEND() CORO_SUSPEND_IMPL(0)
+#define CORO_FINAL_SUSPEND() CORO_SUSPEND_IMPL(1)
+
+#define CORO_BEGIN(AllocFunc)  \
+  void *coro_hdl = \
+  (__builtin_coro_id(0, 0, 0, 0),  \
+   __built

[PATCH] D25130: [coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

2016-10-01 Thread Gor Nishanov via cfe-commits
GorNishanov marked an inline comment as done.
GorNishanov added inline comments.


> rsmith wrote in coroutines.m:1
> Is there any reason you're testing Objective-C and Objective-C++ inputs here 
> (`.m` and `.mm`) rather than C and C++ inputs?

No particular reason (cut and paste from module tests). I'll rename to .c / 
.cpp an commit.

https://reviews.llvm.org/D25130



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


[PATCH] D25130: [coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

2016-10-01 Thread Gor Nishanov via cfe-commits
GorNishanov updated this revision to Diff 73206.
GorNishanov marked an inline comment as done.
GorNishanov added a comment.

rename .m and .mm to .c and .cpp


https://reviews.llvm.org/D25130

Files:
  include/clang/Basic/LangOptions.def
  include/clang/Driver/CC1Options.td
  include/clang/Driver/Options.td
  lib/Basic/IdentifierTable.cpp
  lib/Driver/Tools.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Frontend/InitPreprocessor.cpp
  lib/Sema/SemaDecl.cpp
  test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
  test/Driver/coroutines.c
  test/Driver/coroutines.cpp
  test/Lexer/coroutines.cpp
  test/Lexer/cxx-features.cpp
  test/Parser/cxx1z-coroutines.cpp
  test/SemaCXX/coroutines.cpp

Index: test/SemaCXX/coroutines.cpp
===
--- test/SemaCXX/coroutines.cpp
+++ test/SemaCXX/coroutines.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++14 -fcoroutines -verify %s
+// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s
 
 void no_coroutine_traits_bad_arg_await() {
   co_await a; // expected-error {{include }}
Index: test/Parser/cxx1z-coroutines.cpp
===
--- test/Parser/cxx1z-coroutines.cpp
+++ test/Parser/cxx1z-coroutines.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fcoroutines %s -verify
+// RUN: %clang_cc1 -std=c++11 -fcoroutines-ts %s -verify
 
 template
 U f(T t) {
Index: test/Lexer/cxx-features.cpp
===
--- test/Lexer/cxx-features.cpp
+++ test/Lexer/cxx-features.cpp
@@ -5,7 +5,7 @@
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -verify %s
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s
 // RUN: %clang_cc1 -fno-rtti -verify %s -DNO_EXCEPTIONS -DNO_RTTI
-// RUN: %clang_cc1 -fcoroutines -DNO_EXCEPTIONS -DCOROUTINES -verify %s
+// RUN: %clang_cc1 -fcoroutines-ts -DNO_EXCEPTIONS -DCOROUTINES -verify %s
 
 // expected-no-diagnostics
 
Index: test/Lexer/coroutines.cpp
===
--- test/Lexer/coroutines.cpp
+++ test/Lexer/coroutines.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only %s
-// RUN: %clang_cc1 -fcoroutines -DCORO -fsyntax-only %s
+// RUN: %clang_cc1 -fcoroutines-ts -DCORO -fsyntax-only %s
 
 #ifdef CORO
 #define CORO_KEYWORD(NAME) _Static_assert(!__is_identifier(NAME), #NAME)
Index: test/Driver/coroutines.cpp
===
--- /dev/null
+++ test/Driver/coroutines.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// CHECK-NO-CORO-NOT: -fcoroutines-ts
+
+// RUN: %clang -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-HAS-CORO  %s
+// RUN: %clang -fno-coroutines-ts -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-HAS-CORO %s
+// CHECK-HAS-CORO: -fcoroutines-ts
+
Index: test/Driver/coroutines.c
===
--- /dev/null
+++ test/Driver/coroutines.c
@@ -0,0 +1,6 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// CHECK-NO-CORO-NOT: -fcoroutines-ts
+
Index: test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
===
--- test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
+++ test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
 struct no_suspend {
   bool await_ready() { return true; }
   template  void await_suspend(F) {}
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -11602,7 +11602,7 @@
   sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
   sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
 
-  if (getLangOpts().Coroutines && !getCurFunction()->CoroutineStmts.empty())
+  if (getLangOpts().CoroutinesTS && !getCurFunction()->CoroutineStmts.empty())
 CheckCompletedCoroutineBody(FD, Body);
 
   if (FD) {
Index: lib/Frontend/InitPreprocessor.cpp
=

[PATCH] D25130: [coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

2016-10-01 Thread Gor Nishanov via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL283064: [coroutines] Rename driver flag -fcoroutines to 
-fcoroutines-ts (authored by GorNishanov).

Changed prior to commit:
  https://reviews.llvm.org/D25130?vs=73206&id=73208#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D25130

Files:
  cfe/trunk/include/clang/Basic/LangOptions.def
  cfe/trunk/include/clang/Driver/CC1Options.td
  cfe/trunk/include/clang/Driver/Options.td
  cfe/trunk/lib/Basic/IdentifierTable.cpp
  cfe/trunk/lib/Driver/Tools.cpp
  cfe/trunk/lib/Frontend/CompilerInvocation.cpp
  cfe/trunk/lib/Frontend/InitPreprocessor.cpp
  cfe/trunk/lib/Sema/SemaDecl.cpp
  cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
  cfe/trunk/test/Driver/coroutines.c
  cfe/trunk/test/Driver/coroutines.cpp
  cfe/trunk/test/Lexer/coroutines.cpp
  cfe/trunk/test/Lexer/cxx-features.cpp
  cfe/trunk/test/Parser/cxx1z-coroutines.cpp
  cfe/trunk/test/SemaCXX/coroutines.cpp

Index: cfe/trunk/include/clang/Driver/CC1Options.td
===
--- cfe/trunk/include/clang/Driver/CC1Options.td
+++ cfe/trunk/include/clang/Driver/CC1Options.td
@@ -638,10 +638,6 @@
 def finclude_default_header : Flag<["-"], "finclude-default-header">,
   HelpText<"Include the default header file for OpenCL">;
 
-// C++ TSes.
-def fcoroutines : Flag<["-"], "fcoroutines">,
-  HelpText<"Enable support for the C++ Coroutines TS">;
-
 //===--===//
 // Header Search Options
 //===--===//
Index: cfe/trunk/include/clang/Driver/Options.td
===
--- cfe/trunk/include/clang/Driver/Options.td
+++ cfe/trunk/include/clang/Driver/Options.td
@@ -481,6 +481,13 @@
   Flags<[DriverOption, CC1Option]>,
   HelpText<"Disable generation of linker directives for automatic library linking">;
 
+// C++ Coroutines TS
+def fcoroutines_ts : Flag <["-"], "fcoroutines-ts">, Group,
+  Flags<[DriverOption, CC1Option]>,
+  HelpText<"Enable support for the C++ Coroutines TS">;
+def fno_coroutines_ts : Flag <["-"], "fno-coroutines-ts">, Group,
+  Flags<[DriverOption]>;
+
 def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">,
 Group, Flags<[DriverOption, CC1Option]>, MetaVarName<"">,
 HelpText<"Embed LLVM bitcode (option: off, all, bitcode, marker)">;
Index: cfe/trunk/include/clang/Basic/LangOptions.def
===
--- cfe/trunk/include/clang/Basic/LangOptions.def
+++ cfe/trunk/include/clang/Basic/LangOptions.def
@@ -133,7 +133,7 @@
 LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
 LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
 LANGOPT(GNUAsm, 1, 1, "GNU-style inline assembly")
-LANGOPT(Coroutines, 1, 0, "C++ coroutines")
+LANGOPT(CoroutinesTS  , 1, 0, "C++ coroutines TS")
 
 BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
 LANGOPT(POSIXThreads  , 1, 0, "POSIX thread support")
Index: cfe/trunk/test/Parser/cxx1z-coroutines.cpp
===
--- cfe/trunk/test/Parser/cxx1z-coroutines.cpp
+++ cfe/trunk/test/Parser/cxx1z-coroutines.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fcoroutines %s -verify
+// RUN: %clang_cc1 -std=c++11 -fcoroutines-ts %s -verify
 
 template
 U f(T t) {
Index: cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
===
--- cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
+++ cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
 struct no_suspend {
   bool await_ready() { return true; }
   template  void await_suspend(F) {}
Index: cfe/trunk/test/Driver/coroutines.cpp
===
--- cfe/trunk/test/Driver/coroutines.cpp
+++ cfe/trunk/test/Driver/coroutines.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// CHECK-NO-CORO-NOT: -fcoroutines-ts
+
+// RUN: %clang -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-HAS-CORO  %s
+// RUN: %clang -fno-coroutines-ts -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-HAS-CORO %s
+// CHECK-HAS-CORO: -fcoroutines-ts
+
Index: cfe/trunk/test/

r283064 - [coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

2016-10-01 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Sat Oct  1 22:31:58 2016
New Revision: 283064

URL: http://llvm.org/viewvc/llvm-project?rev=283064&view=rev
Log:
[coroutines] Rename driver flag -fcoroutines to -fcoroutines-ts

Summary:
Also makes -fcoroutines_ts to be both a Driver and CC1 flag.

Patch mostly by EricWF.

Reviewers: rnk, cfe-commits, rsmith, EricWF

Subscribers: mehdi_amini

Differential Revision: https://reviews.llvm.org/D25130

Added:
cfe/trunk/test/Driver/coroutines.c
cfe/trunk/test/Driver/coroutines.cpp
Modified:
cfe/trunk/include/clang/Basic/LangOptions.def
cfe/trunk/include/clang/Driver/CC1Options.td
cfe/trunk/include/clang/Driver/Options.td
cfe/trunk/lib/Basic/IdentifierTable.cpp
cfe/trunk/lib/Driver/Tools.cpp
cfe/trunk/lib/Frontend/CompilerInvocation.cpp
cfe/trunk/lib/Frontend/InitPreprocessor.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
cfe/trunk/test/Lexer/coroutines.cpp
cfe/trunk/test/Lexer/cxx-features.cpp
cfe/trunk/test/Parser/cxx1z-coroutines.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/include/clang/Basic/LangOptions.def
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=283064&r1=283063&r2=283064&view=diff
==
--- cfe/trunk/include/clang/Basic/LangOptions.def (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.def Sat Oct  1 22:31:58 2016
@@ -133,7 +133,7 @@ LANGOPT(Freestanding, 1, 0, "freestandin
 LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
 LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
 LANGOPT(GNUAsm, 1, 1, "GNU-style inline assembly")
-LANGOPT(Coroutines, 1, 0, "C++ coroutines")
+LANGOPT(CoroutinesTS  , 1, 0, "C++ coroutines TS")
 
 BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
 LANGOPT(POSIXThreads  , 1, 0, "POSIX thread support")

Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=283064&r1=283063&r2=283064&view=diff
==
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Sat Oct  1 22:31:58 2016
@@ -638,10 +638,6 @@ def fdefault_calling_conv_EQ : Joined<["
 def finclude_default_header : Flag<["-"], "finclude-default-header">,
   HelpText<"Include the default header file for OpenCL">;
 
-// C++ TSes.
-def fcoroutines : Flag<["-"], "fcoroutines">,
-  HelpText<"Enable support for the C++ Coroutines TS">;
-
 
//===--===//
 // Header Search Options
 
//===--===//

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=283064&r1=283063&r2=283064&view=diff
==
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Sat Oct  1 22:31:58 2016
@@ -481,6 +481,13 @@ def fno_autolink : Flag <["-"], "fno-aut
   Flags<[DriverOption, CC1Option]>,
   HelpText<"Disable generation of linker directives for automatic library 
linking">;
 
+// C++ Coroutines TS
+def fcoroutines_ts : Flag <["-"], "fcoroutines-ts">, Group,
+  Flags<[DriverOption, CC1Option]>,
+  HelpText<"Enable support for the C++ Coroutines TS">;
+def fno_coroutines_ts : Flag <["-"], "fno-coroutines-ts">, Group,
+  Flags<[DriverOption]>;
+
 def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">,
 Group, Flags<[DriverOption, CC1Option]>, MetaVarName<"">,
 HelpText<"Embed LLVM bitcode (option: off, all, bitcode, marker)">;

Modified: cfe/trunk/lib/Basic/IdentifierTable.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/IdentifierTable.cpp?rev=283064&r1=283063&r2=283064&view=diff
==
--- cfe/trunk/lib/Basic/IdentifierTable.cpp (original)
+++ cfe/trunk/lib/Basic/IdentifierTable.cpp Sat Oct  1 22:31:58 2016
@@ -150,7 +150,7 @@ static KeywordStatus getKeywordStatus(co
   if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
   if (LangOpts.ObjC2 && (Flags & KEYOBJC2)) return KS_Enabled;
   if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
-  if (LangOpts.Coroutines && (Flags & KEYCOROUTINES)) return KS_Enabled;
+  if (LangOpts.CoroutinesTS && (Flags & KEYCOROUTINES)) return KS_Enabled;
   if (LangOpts.ModulesTS && (Flags & KEYMODULES)) return KS_Enabled;
   if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) return KS_Future;
   return KS_Disabled;

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: 
http://llvm.org/viewvc/llvm-pro

[PATCH] D24373: [coroutines] Adding builtins for coroutine intrinsics and backendutil support.

2016-10-01 Thread Gor Nishanov via cfe-commits
GorNishanov updated this revision to Diff 73213.
GorNishanov added a comment.

rebase on top of the trunk


https://reviews.llvm.org/D24373

Files:
  docs/LanguageExtensions.rst
  include/clang/Basic/Builtins.def
  lib/CodeGen/BackendUtil.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGCoroutine.cpp
  lib/CodeGen/CMakeLists.txt
  lib/CodeGen/CodeGenFunction.h
  test/CodeGenCoroutines/Inputs/coro.h
  test/CodeGenCoroutines/O2-coro.c
  test/CodeGenCoroutines/coro-builtins-err.c
  test/CodeGenCoroutines/coro-builtins.c

Index: test/CodeGenCoroutines/coro-builtins.c
===
--- /dev/null
+++ test/CodeGenCoroutines/coro-builtins.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s
+
+// CHECK-LABEL: f( 
+void f() {
+  // CHECK: %0 = call token @llvm.coro.id(i32 32, i8* null, i8* null, i8* null)
+  __builtin_coro_id(32, 0, 0, 0);
+  // CHECK-NEXT: %1 = call i1 @llvm.coro.alloc(token %0)
+  __builtin_coro_alloc();
+  // CHECK-NEXT: %2 = call i64 @llvm.coro.size.i64()
+  __builtin_coro_size();
+  // CHECK-NEXT: %3 = call i8* @llvm.coro.begin(token %0, i8* null)
+  __builtin_coro_begin(0);
+  // CHECK-NEXT: %4 = call i8* @llvm.coro.frame() 
+  __builtin_coro_frame();
+  // CHECK-NEXT: call void @llvm.coro.resume(i8* null)
+  __builtin_coro_resume(0);
+  // CHECK-NEXT: call void @llvm.coro.destroy(i8* null)
+  __builtin_coro_destroy(0);
+  // CHECK-NEXT: %5 = call i1 @llvm.coro.done(i8* null)
+  __builtin_coro_done(0);
+  // CHECK-NEXT: %6 = call i8* @llvm.coro.promise(i8* null, i32 32, i1 false)
+  __builtin_coro_promise(0, 32, 0);
+  // CHECK-NEXT: %7 = call i8* @llvm.coro.free(token %0, i8* null)
+  __builtin_coro_free(0);
+  // CHECK-NEXT: call void @llvm.coro.end(i8* null, i1 false)
+  __builtin_coro_end(0, 0);
+  // CHECK-NEXT: %8 = call i8 @llvm.coro.suspend(token none, i1 false)
+  __builtin_coro_suspend(0);
+  // CHECK-NEXT: %9 = call i1 @llvm.coro.param(i8* null, i8* null)
+  __builtin_coro_param(0, 0);
+}
Index: test/CodeGenCoroutines/coro-builtins-err.c
===
--- /dev/null
+++ test/CodeGenCoroutines/coro-builtins-err.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -verify
+
+void f() {
+  __builtin_coro_alloc(); // expected-error {{this builtin expect that __builtin_coro_id}}
+  __builtin_coro_begin(0); // expected-error {{this builtin expect that __builtin_coro_id}}
+  __builtin_coro_free(0); // expected-error {{this builtin expect that __builtin_coro_id}}
+
+  __builtin_coro_id(32, 0, 0, 0);
+  __builtin_coro_id(32, 0, 0, 0); // expected-error {{only one __builtin_coro_id}}
+}
Index: test/CodeGenCoroutines/O2-coro.c
===
--- /dev/null
+++ test/CodeGenCoroutines/O2-coro.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -emit-llvm %s -o - -O3 | FileCheck %s
+#include "Inputs/coro.h"
+void print(int);
+
+void* f() {
+  CORO_BEGIN(malloc);
+
+  for (int i = 0;; ++i) {
+print(i);
+CORO_SUSPEND();
+  }
+
+  CORO_END(free);
+}
+
+// CHECK-LABEL: @main
+int main() {
+  void* coro = f();
+  CORO_RESUME(coro);
+  CORO_RESUME(coro);
+  CORO_DESTROY(coro);
+// CHECK: call void @print(i32 0)
+// CHECK: call void @print(i32 1)
+// CHECK: call void @print(i32 2)
+}
Index: test/CodeGenCoroutines/Inputs/coro.h
===
--- /dev/null
+++ test/CodeGenCoroutines/Inputs/coro.h
@@ -0,0 +1,37 @@
+void free(void *ptr);
+void *malloc(unsigned int);
+
+#define CORO_SUSPEND_IMPL(IsFinal) \
+  switch (__builtin_coro_suspend(IsFinal)) {   \
+  case 0:  \
+if (IsFinal)   \
+  __builtin_trap();\
+break; \
+  case 1:  \
+goto coro_Cleanup; \
+  default: \
+goto coro_Suspend; \
+  }
+
+#define CORO_SUSPEND() CORO_SUSPEND_IMPL(0)
+#define CORO_FINAL_SUSPEND() CORO_SUSPEND_IMPL(1)
+
+#define CORO_BEGIN(AllocFunc)  \
+  void *coro_hdl = \
+  (__builtin_coro_id(0, 0, 0, 0),  \
+   __builtin_coro_begin((__builtin_coro_alloc()\
+

[PATCH] D25068: [coroutines] Switch to using std::experimental namespace per P0057R5

2016-10-03 Thread Gor Nishanov via cfe-commits
GorNishanov requested changes to this revision.
GorNishanov added a comment.
This revision now requires changes to proceed.





> coroutines.cpp:1
>  // RUN: %clang_cc1 -std=c++14 -fcoroutines -verify %s
>  

Change to -fcoroutines-ts

https://reviews.llvm.org/D25068



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


[PATCH] D24373: [coroutines] Adding builtins for coroutine intrinsics and backendutil support.

2016-10-03 Thread Gor Nishanov via cfe-commits
GorNishanov updated this revision to Diff 73350.
GorNishanov added a comment.
Herald added a subscriber: modocache.

1. https://reviews.llvm.org/owners/package/2/ test removed
2. Update LanguageExtensions.rst with suggested edits
3. coro-builtins.c test now passes useful arguments and pattern matches that 
proper arguments are passed in emitted intrinsics.


https://reviews.llvm.org/D24373

Files:
  docs/LanguageExtensions.rst
  include/clang/Basic/Builtins.def
  lib/CodeGen/BackendUtil.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CGCoroutine.cpp
  lib/CodeGen/CMakeLists.txt
  lib/CodeGen/CodeGenFunction.h
  test/CodeGenCoroutines/coro-builtins-err.c
  test/CodeGenCoroutines/coro-builtins.c

Index: test/CodeGenCoroutines/coro-builtins.c
===
--- /dev/null
+++ test/CodeGenCoroutines/coro-builtins.c
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s
+
+void *myAlloc(long long);
+
+// CHECK-LABEL: f( 
+void f(int n) {
+  // CHECK: %n.addr = alloca i32
+  // CHECK: %n_copy = alloca i32
+  // CHECK: %promise = alloca i32
+  int n_copy;
+  int promise;
+
+  // CHECK: %[[PROM_ADDR:.+]] = bitcast i32* %promise to i8*
+  // CHECK-NEXT: %[[COROID:.+]] = call token @llvm.coro.id(i32 32, i8* %[[PROM_ADDR]], i8* null, i8* null)
+  __builtin_coro_id(32, &promise, 0, 0);
+
+  // CHECK-NEXT: call i1 @llvm.coro.alloc(token %[[COROID]])
+  __builtin_coro_alloc();
+
+  // CHECK-NEXT: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
+  // CHECK-NEXT: %[[MEM:.+]] = call i8* @myAlloc(i64 %[[SIZE]])
+  // CHECK-NEXT: %[[BEG:.+]] = call i8* @llvm.coro.begin(token %[[COROID]], i8* %[[MEM]])
+  __builtin_coro_begin(myAlloc(__builtin_coro_size()));
+
+  // CHECK-NEXT: %[[FRAME1:.+]] = call i8* @llvm.coro.frame() 
+  // CHECK-NEXT: call void @llvm.coro.resume(i8* %[[FRAME1]])
+  __builtin_coro_resume(__builtin_coro_frame());
+
+  // CHECK-NEXT: %[[FRAME2:.+]] = call i8* @llvm.coro.frame() 
+  // CHECK-NEXT: call void @llvm.coro.destroy(i8* %[[FRAME2]])
+  __builtin_coro_destroy(__builtin_coro_frame());
+
+  // CHECK-NEXT: %[[FRAME3:.+]] = call i8* @llvm.coro.frame() 
+  // CHECK-NEXT: call i1 @llvm.coro.done(i8* %[[FRAME3]])
+  __builtin_coro_done(__builtin_coro_frame());
+
+  // CHECK-NEXT: %[[FRAME4:.+]] = call i8* @llvm.coro.frame() 
+  // CHECK-NEXT: call i8* @llvm.coro.promise(i8* %[[FRAME4]], i32 48, i1 false)
+  __builtin_coro_promise(__builtin_coro_frame(), 48, 0);
+
+  // CHECK-NEXT: %[[FRAME5:.+]] = call i8* @llvm.coro.frame() 
+  // CHECK-NEXT: call i8* @llvm.coro.free(token %[[COROID]], i8* %[[FRAME5]])
+  __builtin_coro_free(__builtin_coro_frame());
+
+  // CHECK-NEXT: %[[FRAME6:.+]] = call i8* @llvm.coro.frame() 
+  // CHECK-NEXT: call void @llvm.coro.end(i8* %[[FRAME6]], i1 false)
+  __builtin_coro_end(__builtin_coro_frame(), 0);
+
+  // CHECK-NEXT: call i8 @llvm.coro.suspend(token none, i1 true)
+  __builtin_coro_suspend(1);
+
+  // CHECK-NEXT: %[[N_ADDR:.+]] = bitcast i32* %n.addr to i8*
+  // CHECK-NEXT: %[[N_COPY_ADDR:.+]] = bitcast i32* %n_copy to i8*
+  // CHECK-NEXT: call i1 @llvm.coro.param(i8* %[[N_ADDR]], i8* %[[N_COPY_ADDR]])
+  __builtin_coro_param(&n, &n_copy);
+}
Index: test/CodeGenCoroutines/coro-builtins-err.c
===
--- /dev/null
+++ test/CodeGenCoroutines/coro-builtins-err.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -verify
+
+void f() {
+  __builtin_coro_alloc(); // expected-error {{this builtin expect that __builtin_coro_id}}
+  __builtin_coro_begin(0); // expected-error {{this builtin expect that __builtin_coro_id}}
+  __builtin_coro_free(0); // expected-error {{this builtin expect that __builtin_coro_id}}
+
+  __builtin_coro_id(32, 0, 0, 0);
+  __builtin_coro_id(32, 0, 0, 0); // expected-error {{only one __builtin_coro_id}}
+}
Index: lib/CodeGen/CodeGenFunction.h
===
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -88,6 +88,7 @@
 class RegionCodeGenTy;
 class TargetCodeGenInfo;
 struct OMPTaskDataTy;
+struct CGCoroData;
 
 /// The kind of evaluation to perform on values of a particular
 /// type.  Basically, is the code in CGExprScalar, CGExprComplex, or
@@ -155,6 +156,16 @@
   QualType FnRetTy;
   llvm::Function *CurFn;
 
+  // Holds coroutine data if the current function is a coroutine. We use a
+  // wrapper to manage its lifetime, so that we don't have to define CGCoroData
+  // in this header.
+  struct CGCoroInfo {
+std::unique_ptr Data;
+CGCoroInfo();
+~CGCoroInfo();
+  };
+  CGCoroInfo CurCoro;
+
   /// CurGD - The GlobalDecl for the current function being compiled.
   GlobalDecl CurGD;
 
@@ -2290,6 +2301,8 @@
   void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);
   void EmitObjCAutoreleasePoolStmt(c

r283155 - [coroutines] Adding builtins for coroutine intrinsics and backendutil support.

2016-10-03 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon Oct  3 17:44:48 2016
New Revision: 283155

URL: http://llvm.org/viewvc/llvm-project?rev=283155&view=rev
Log:
[coroutines] Adding builtins for coroutine intrinsics and backendutil support.

Summary:
With this commit simple coroutines can be created in plain C using coroutine 
builtins.

Reviewers: rnk, EricWF, rsmith

Subscribers: modocache, mgorny, mehdi_amini, beanz, cfe-commits

Differential Revision: https://reviews.llvm.org/D24373

Added:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-builtins-err.c
cfe/trunk/test/CodeGenCoroutines/coro-builtins.c
Modified:
cfe/trunk/docs/LanguageExtensions.rst
cfe/trunk/include/clang/Basic/Builtins.def
cfe/trunk/lib/CodeGen/BackendUtil.cpp
cfe/trunk/lib/CodeGen/CGBuiltin.cpp
cfe/trunk/lib/CodeGen/CMakeLists.txt
cfe/trunk/lib/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/docs/LanguageExtensions.rst
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=283155&r1=283154&r2=283155&view=diff
==
--- cfe/trunk/docs/LanguageExtensions.rst (original)
+++ cfe/trunk/docs/LanguageExtensions.rst Mon Oct  3 17:44:48 2016
@@ -1865,6 +1865,82 @@ The types ``T`` currently supported are:
 Note that the compiler does not guarantee that non-temporal loads or stores
 will be used.
 
+C++ Coroutines support builtins
+
+
+.. warning::
+  This is a work in progress. Compatibility across Clang/LLVM releases is not 
+  guaranteed.
+
+Clang provides experimental builtins to support C++ Coroutines as defined by
+http://wg21.link/P0057. The following four are intended to be used by the
+standard library to implement `std::experimental::coroutine_handle` type.
+
+**Syntax**:
+
+.. code-block:: c
+
+  void  __builtin_coro_resume(void *addr);
+  void  __builtin_coro_destroy(void *addr);
+  bool  __builtin_coro_done(void *addr);
+  void *__builtin_coro_promise(void *addr, int alignment, bool from_promise)
+
+**Example of use**:
+
+.. code-block:: c++
+
+  template <> struct coroutine_handle {
+void resume() const { __builtin_coro_resume(ptr); }
+void destroy() const { __builtin_coro_destroy(ptr); }
+bool done() const { return __builtin_coro_done(ptr); }
+// ...
+  protected:
+void *ptr;
+  };
+
+  template  struct coroutine_handle : coroutine_handle<> {
+// ...
+Promise &promise() const {
+  return *reinterpret_cast(
+__builtin_coro_promise(ptr, alignof(Promise), /*from-promise=*/false));
+}
+static coroutine_handle from_promise(Promise &promise) {
+  coroutine_handle p;
+  p.ptr = __builtin_coro_promise(&promise, alignof(Promise),
+  /*from-promise=*/true);
+  return p;
+}
+  };
+
+
+Other coroutine builtins are either for internal clang use or for use during
+development of the coroutine feature. See `Coroutines in LLVM
+`_ for
+more information on their semantics. Note that builtins matching the intrinsics
+that take token as the first parameter (llvm.coro.begin, llvm.coro.alloc, 
+llvm.coro.free and llvm.coro.suspend) omit the token parameter and fill it to
+an appropriate value during the emission.
+
+**Syntax**:
+
+.. code-block:: c
+
+  size_t __builtin_coro_size()
+  void  *__builtin_coro_frame()
+  void  *__builtin_coro_free(void *coro_frame)
+
+  void  *__builtin_coro_id(int align, void *promise, void *fnaddr, void *parts)
+  bool   __builtin_coro_alloc()
+  void  *__builtin_coro_begin(void *memory)
+  void   __builtin_coro_end(void *coro_frame, bool unwind)
+  char   __builtin_coro_suspend(bool final)
+  bool   __builtin_coro_param(void *original, void *copy)
+
+Note that there is no builtin matching the `llvm.coro.save` intrinsic. LLVM
+automatically will insert one if the first argument to `llvm.coro.suspend` is
+token `none`. If a user calls `__builin_suspend`, clang will insert `token 
none`
+as the first argument to the intrinsic.
+
 Non-standard C++11 Attributes
 =
 

Modified: cfe/trunk/include/clang/Basic/Builtins.def
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=283155&r1=283154&r2=283155&view=diff
==
--- cfe/trunk/include/clang/Basic/Builtins.def (original)
+++ cfe/trunk/include/clang/Basic/Builtins.def Mon Oct  3 17:44:48 2016
@@ -1330,6 +1330,22 @@ BUILTIN(__builtin___get_unsafe_stack_ptr
 BUILTIN(__builtin_nontemporal_store, "v.", "t")
 BUILTIN(__builtin_nontemporal_load, "v.", "t")
 
+// Coroutine intrinsics.
+BUILTIN(__builtin_coro_resume, "vv*", "")
+BUILTIN(__builtin_coro_destroy, "vv*", "")
+BUILTIN(__builtin_coro_done, "bv*", "n")
+BUILTIN(__builtin_coro_promise, "v*v*IiIb", "n")
+
+BUILTIN(__builtin_coro_size, "z", "n")
+BUILTIN(__bui

[PATCH] D24373: [coroutines] Adding builtins for coroutine intrinsics and backendutil support.

2016-10-03 Thread Gor Nishanov via cfe-commits
GorNishanov closed this revision.
GorNishanov added a comment.

Closed by commit r283155 - [coroutines] Adding builtins for coroutine 
intrinsics and backendutil support.

For some reason phabricator did not close it automatically.


https://reviews.llvm.org/D24373



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


[PATCH] D25068: [coroutines] Switch to using std::experimental namespace per P0057R5

2016-10-03 Thread Gor Nishanov via cfe-commits
GorNishanov updated this revision to Diff 73378.
GorNishanov marked an inline comment as done.
GorNishanov added a comment.

Implemented review feedback. Landing is imminent.


https://reviews.llvm.org/D25068

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/Sema.cpp
  lib/Sema/SemaCoroutine.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/SemaCXX/coroutines.cpp

Index: test/SemaCXX/coroutines.cpp
===
--- test/SemaCXX/coroutines.cpp
+++ test/SemaCXX/coroutines.cpp
@@ -1,18 +1,18 @@
 // RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s
 
 void no_coroutine_traits_bad_arg_await() {
-  co_await a; // expected-error {{include }}
+  co_await a; // expected-error {{include }}
   // expected-error@-1 {{use of undeclared identifier 'a'}}
 }
 
 void no_coroutine_traits_bad_arg_yield() {
-  co_yield a; // expected-error {{include }}
+  co_yield a; // expected-error {{include }}
   // expected-error@-1 {{use of undeclared identifier 'a'}}
 }
 
 
 void no_coroutine_traits_bad_arg_return() {
-  co_return a; // expected-error {{include }}
+  co_return a; // expected-error {{include }}
   // expected-error@-1 {{use of undeclared identifier 'a'}}
 }
 
@@ -36,45 +36,59 @@
 };
 
 void no_coroutine_traits() {
-  co_await a; // expected-error {{need to include }}
+  co_await a; // expected-error {{need to include }}
 }
 
 namespace std {
-  template struct coroutine_traits; // expected-note {{declared here}}
-};
+namespace experimental {
+template 
+struct coroutine_traits; // expected-note {{declared here}}
+}
+}
 
 template struct coro {};
-template
-struct std::coroutine_traits, Ps...> {
+template 
+struct std::experimental::coroutine_traits, Ps...> {
   using promise_type = Promise;
 };
 
 void no_specialization() {
-  co_await a; // expected-error {{implicit instantiation of undefined template 'std::coroutine_traits'}}
+  co_await a; // expected-error {{implicit instantiation of undefined template 'std::experimental::coroutine_traits'}}
 }
 
-template struct std::coroutine_traits {};
+template 
+struct std::experimental::coroutine_traits {};
 
 int no_promise_type() {
-  co_await a; // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits' has no member named 'promise_type'}}
+  co_await a; // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits' has no member named 'promise_type'}}
 }
 
-template<> struct std::coroutine_traits { typedef int promise_type; };
+template <>
+struct std::experimental::coroutine_traits { typedef int promise_type; };
 double bad_promise_type(double) {
-  co_await a; // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits::promise_type' (aka 'int') is not a class}}
+  co_await a; // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits::promise_type' (aka 'int') is not a class}}
 }
 
-template<> struct std::coroutine_traits {
+template <>
+struct std::experimental::coroutine_traits {
   struct promise_type {};
 };
 double bad_promise_type_2(int) {
-  co_yield 0; // expected-error {{no member named 'yield_value' in 'std::coroutine_traits::promise_type'}}
+  co_yield 0; // expected-error {{no member named 'yield_value' in 'std::experimental::coroutine_traits::promise_type'}}
 }
 
 struct promise; // expected-note 2{{forward declaration}}
-template struct std::coroutine_traits { using promise_type = promise; };
+template 
+struct std::experimental::coroutine_traits { using promise_type = promise; };
+
+namespace std {
+namespace experimental {
+template 
+struct coroutine_handle;
+}
+}
 
-  // FIXME: This diagnostic is terrible.
+// FIXME: This diagnostic is terrible.
 void undefined_promise() { // expected-error {{variable has incomplete type 'promise_type'}}
   // FIXME: This diagnostic doesn't make any sense.
   // expected-error@-2 {{incomplete definition of type 'promise'}}
@@ -200,7 +214,8 @@
 }
 
 struct yield_fn_tag {};
-template<> struct std::coroutine_traits {
+template <>
+struct std::experimental::coroutine_traits {
   struct promise_type {
 // FIXME: add an await_transform overload for functions
 awaitable yield_value(int());
@@ -285,7 +300,7 @@
 }
 
 
-template<> struct std::coroutine_traits
+template<> struct std::experimental::coroutine_traits
 { using promise_type = promise; };
 
 int main(int, const char**) { // expected-error {{'main' cannot be a coroutine}}
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -8275,6 +8275,20 @@
  StdNamespace.get(Context.getExternalSource()));
 }
 
+NamespaceDecl *Sema::lookupStdExperimentalNamespace() {
+  if (!StdExperimentalNamespaceCache) {
+if (auto Std = getStdNamespace()) {
+  LookupResult Result(*this, &PP.getIdentifierTable().get("experimental"),
+  

r283170 - [coroutines] Switch to using std::experimental namespace per P0057R5

2016-10-03 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon Oct  3 19:31:16 2016
New Revision: 283170

URL: http://llvm.org/viewvc/llvm-project?rev=283170&view=rev
Log:
[coroutines] Switch to using std::experimental namespace per P0057R5

Summary:
Look for coroutine_traits and friends in std::experimental namespace.
Patch (mostly) by EricWF.

Reviewers: cfe-commits, EricWF, rsmith

Subscribers: majnemer, mehdi_amini

Differential Revision: https://reviews.llvm.org/D25068

Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=283170&r1=283169&r2=283170&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Oct  3 19:31:16 
2016
@@ -8572,9 +8572,9 @@ def ext_coroutine_without_co_await_co_yi
   "that uses neither 'co_await' nor 'co_yield'">,
   InGroup>;
 def err_implied_std_coroutine_traits_not_found : Error<
-  "you need to include  before defining a coroutine">;
+  "you need to include  before defining a coroutine">;
 def err_malformed_std_coroutine_traits : Error<
-  "'std::coroutine_traits' must be a class template">;
+  "'std::experimental::coroutine_traits' must be a class template">;
 def err_implied_std_coroutine_traits_promise_type_not_found : Error<
   "this function cannot be a coroutine: %q0 has no member named 
'promise_type'">;
 def err_implied_std_coroutine_traits_promise_type_not_class : Error<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=283170&r1=283169&r2=283170&view=diff
==
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct  3 19:31:16 2016
@@ -725,6 +725,10 @@ public:
   /// standard library.
   LazyDeclPtr StdAlignValT;
 
+  /// \brief The C++ "std::experimental" namespace, where the experimental 
parts
+  /// of the standard library resides.
+  NamespaceDecl *StdExperimentalNamespaceCache;
+
   /// \brief The C++ "std::initializer_list" template, which is defined in
   /// \.
   ClassTemplateDecl *StdInitializerList;
@@ -4255,6 +4259,8 @@ public:
   NamespaceDecl *getStdNamespace() const;
   NamespaceDecl *getOrCreateStdNamespace();
 
+  NamespaceDecl *lookupStdExperimentalNamespace();
+
   CXXRecordDecl *getStdBadAlloc() const;
   EnumDecl *getStdAlignValT() const;
 

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=283170&r1=283169&r2=283170&view=diff
==
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Mon Oct  3 19:31:16 2016
@@ -88,8 +88,8 @@ Sema::Sema(Preprocessor &pp, ASTContext
 VisContext(nullptr),
 IsBuildingRecoveryCallExpr(false),
 Cleanup{}, LateTemplateParser(nullptr),
-LateTemplateParserCleanup(nullptr),
-OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr),
+LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
+StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
 CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr),
 NSNumberDecl(nullptr), NSValueDecl(nullptr),
 NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=283170&r1=283169&r2=283170&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Mon Oct  3 19:31:16 2016
@@ -26,15 +26,15 @@ using namespace sema;
 static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
   SourceLocation Loc) {
   // FIXME: Cache std::coroutine_traits once we've found it.
-  NamespaceDecl *Std = S.getStdNamespace();
-  if (!Std) {
+  NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace();
+  if (!StdExp) {
 S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
 return QualType();
   }
 
   LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
   Loc, Sema::LookupOrdinaryName);
-  if (!S.LookupQualifiedName(Result, Std)) {
+  if (!S.LookupQualifiedName(Result, StdExp)) {
 S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
 return QualType();
   }
@@ -86,7 +86,7 @@ static QualType lookupPromiseType(Sema &

[PATCH] D25068: [coroutines] Switch to using std::experimental namespace per P0057R5

2016-10-03 Thread Gor Nishanov via cfe-commits
GorNishanov closed this revision.
GorNishanov added a comment.

Closed by:  r283170 - [coroutines] Switch to using std::experimental namespace 
per P0057R5


https://reviews.llvm.org/D25068



___
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.

2016-10-04 Thread Gor Nishanov via cfe-commits
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: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
+  // CHECK: call i8* @_Znwm(i64 %[[SIZE]])
+
+  // CHECK: coro.dest

[PATCH] D25258: [coroutines] Create allocation and deallocation sub-statements.

2016-10-04 Thread Gor Nishanov via cfe-commits
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] D25296: [coroutines] Fix co_return statement for initializer list arguments

2016-10-06 Thread Gor Nishanov via cfe-commits
GorNishanov added a comment.

LGTM, but, I cannot approve clang patches. Let's wait on @rsmith to give the go 
ahead.


https://reviews.llvm.org/D25296



___
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.

2016-10-06 Thread Gor Nishanov via cfe-commits
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* @llvm.coro.frame()
+  // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
+  // CHE

[PATCH] D25349: [coroutines] Build fallthrough and set_exception statements.

2016-10-06 Thread Gor Nishanov via cfe-commits
GorNishanov added a comment.

shipit 



> coreturn.cpp:36
> +  suspend_always final_suspend();
> +  awaitable yield_value(int);
> +  void return_void();

No need to hve yield_value here, unless you want to use co_yield expression in 
the coroutine. In this file, we are using co_await only.  (Same comment for 
promise_float and promise_int)

https://reviews.llvm.org/D25349



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


[PATCH] D25349: [coroutines] Build fallthrough and set_exception statements.

2016-10-06 Thread Gor Nishanov via cfe-commits
GorNishanov added a comment.

LGTM, but, will need to wait for @rsmith to sign off.


https://reviews.llvm.org/D25349



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


r311762 - [coroutines] Support coroutine-handle returning await-suspend (i.e symmetric control transfer)

2017-08-24 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Thu Aug 24 21:46:54 2017
New Revision: 311762

URL: http://llvm.org/viewvc/llvm-project?rev=311762&view=rev
Log:
[coroutines] Support coroutine-handle returning await-suspend (i.e symmetric 
control transfer)

Summary:
If await_suspend returns a coroutine_handle, as in the example below:
```
  coroutine_handle<> await_suspend(coroutine_handle<> h) {
coro.promise().waiter = h;
return coro;
  }
```
suspensionExpression processing will resume the coroutine pointed at by that 
handle.
Related LLVM change rL311751 makes resume calls of this kind `musttail` at any 
optimization level.

This enables unlimited symmetric control transfer from coroutine to coroutine 
without blowing up the stack.

Reviewers: GorNishanov

Reviewed By: GorNishanov

Subscribers: rsmith, EricWF, cfe-commits

Differential Revision: https://reviews.llvm.org/D37131

Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-await.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=311762&r1=311761&r2=311762&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Thu Aug 24 21:46:54 2017
@@ -181,10 +181,8 @@ static LValueOrRValue emitSuspendExpress
   auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
 
   auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr());
-  if (SuspendRet != nullptr) {
+  if (SuspendRet != nullptr && SuspendRet->getType()->isIntegerTy(1)) {
 // Veto suspension if requested by bool returning await_suspend.
-assert(SuspendRet->getType()->isIntegerTy(1) &&
-   "Sema should have already checked that it is void or bool");
 BasicBlock *RealSuspendBlock =
 CGF.createBasicBlock(Prefix + Twine(".suspend.bool"));
 CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=311762&r1=311761&r2=311762&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Thu Aug 24 21:46:54 2017
@@ -363,6 +363,32 @@ static ExprResult buildMemberCall(Sema &
   return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
 }
 
+// See if return type is coroutine-handle and if so, invoke builtin coro-resume
+// on its address. This is to enable experimental support for coroutine-handle
+// returning await_suspend that results in a guranteed tail call to the target
+// coroutine.
+static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
+   SourceLocation Loc) {
+  if (RetType->isReferenceType())
+return nullptr;
+  Type const *T = RetType.getTypePtr();
+  if (!T->isClassType() && !T->isStructureType())
+return nullptr;
+
+  // FIXME: Add convertability check to coroutine_handle<>. Possibly via
+  // EvaluateBinaryTypeTrait(BTT_IsConvertible, ...) which is at the moment
+  // a private function in SemaExprCXX.cpp
+
+  ExprResult AddressExpr = buildMemberCall(S, E, Loc, "address", None);
+  if (AddressExpr.isInvalid())
+return nullptr;
+
+  Expr *JustAddress = AddressExpr.get();
+  // FIXME: Check that the type of AddressExpr is void*
+  return buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_resume,
+  JustAddress);
+}
+
 /// Build calls to await_ready, await_suspend, and await_resume for a co_await
 /// expression.
 static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl 
*CoroPromise,
@@ -412,16 +438,21 @@ static ReadySuspendResumeResult buildCoa
 //   - await-suspend is the expression e.await_suspend(h), which shall be
 // a prvalue of type void or bool.
 QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
-// non-class prvalues always have cv-unqualified types
-QualType AdjRetType = RetType.getUnqualifiedType();
-if (RetType->isReferenceType() ||
-(AdjRetType != S.Context.BoolTy && AdjRetType != S.Context.VoidTy)) {
-  S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
- diag::err_await_suspend_invalid_return_type)
-  << RetType;
-  S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
-  << AwaitSuspend->getDirectCallee();
-  Calls.IsInvalid = true;
+// Experimental support for coroutine_handle returning await_suspend.
+if (Expr *TailCallSuspend = maybeTailCall(S, RetType, AwaitSuspend, Loc))
+  Calls.Results[ACT::ACT_Suspend] = TailCallSuspend;
+else {
+  // non-class prvalues always have cv-unqualified types
+  QualType AdjRetType = RetType.getUnqualifiedType();
+  if (RetType->isReferenceType() ||
+

r328663 - [coroutines] Do not attempt to typo-correct when coroutine is looking for required members

2018-03-27 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Tue Mar 27 13:38:19 2018
New Revision: 328663

URL: http://llvm.org/viewvc/llvm-project?rev=328663&view=rev
Log:
[coroutines] Do not attempt to typo-correct when coroutine is looking for 
required members

When SemaCoroutine looks for await_resume, it means it. No need for helpful: 
"Did you mean await_ready?" messages.

Fixes PR33477 and a couple of FIXMEs in test/SemaCXX/coroutines.cpp

Modified:
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=328663&r1=328662&r2=328663&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Tue Mar 27 13:38:19 2018
@@ -362,6 +362,15 @@ static ExprResult buildMemberCall(Sema &
   if (Result.isInvalid())
 return ExprError();
 
+  // We meant exactly what we asked for. No need for typo correction.
+  if (auto *TE = dyn_cast(Result.get())) {
+S.clearDelayedTypo(TE);
+S.Diag(Loc, diag::err_no_member)
+<< NameInfo.getName() << Base->getType()->getAsCXXRecordDecl()
+<< Base->getSourceRange();
+return ExprError();
+  }
+
   return S.ActOnCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
 }
 

Modified: cfe/trunk/test/SemaCXX/coroutines.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/coroutines.cpp?rev=328663&r1=328662&r2=328663&view=diff
==
--- cfe/trunk/test/SemaCXX/coroutines.cpp (original)
+++ cfe/trunk/test/SemaCXX/coroutines.cpp Tue Mar 27 13:38:19 2018
@@ -510,8 +510,7 @@ coro missing_get_return_o
 
 struct bad_promise_2 {
   coro get_return_object();
-  // FIXME: We shouldn't offer a typo-correction here!
-  suspend_always final_suspend(); // expected-note {{here}}
+  suspend_always final_suspend();
   void unhandled_exception();
   void return_void();
 };
@@ -522,8 +521,7 @@ coro missing_initial_susp
 
 struct bad_promise_3 {
   coro get_return_object();
-  // FIXME: We shouldn't offer a typo-correction here!
-  suspend_always initial_suspend(); // expected-note {{here}}
+  suspend_always initial_suspend();
   void unhandled_exception();
   void return_void();
 };
@@ -1378,3 +1376,22 @@ test_unused_warning() {
   co_await awaitable_unused_warn(); // expected-warning {{ignoring return 
value of function declared with 'nodiscard' attribute}}
   co_yield 42; // expected-warning {{ignoring return value of function 
declared with 'nodiscard' attribute}}
 }
+
+struct missing_await_ready {
+  void await_suspend(std::experimental::coroutine_handle<>);
+  void await_resume();
+};
+struct missing_await_suspend {
+  bool await_ready();
+  void await_resume();
+};
+struct missing_await_resume {
+  bool await_ready();
+  void await_suspend(std::experimental::coroutine_handle<>);
+};
+
+void test_missing_awaitable_members() {
+  co_await missing_await_ready{}; // expected-error {{no member named 
'await_ready' in 'missing_await_ready'}}
+  co_await missing_await_suspend{}; // expected-error {{no member named 
'await_suspend' in 'missing_await_suspend'}}
+  co_await missing_await_resume{}; // expected-error {{no member named 
'await_resume' in 'missing_await_resume'}}
+}


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


r328993 - [coroutines] Add __builtin_coro_noop => llvm.coro.noop

2018-04-02 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon Apr  2 10:35:37 2018
New Revision: 328993

URL: http://llvm.org/viewvc/llvm-project?rev=328993&view=rev
Log:
[coroutines] Add __builtin_coro_noop => llvm.coro.noop

A recent addition to Coroutines TS (https://wg21.link/p0913) adds a pre-defined
coroutine noop_coroutine that does nothing. To implement this feature, we 
implemented
an llvm.coro.noop intrinsic that returns a coroutine handle to a coroutine that
does nothing when resumed or destroyed.

This patch adds a builtin __builtin_coro_noop() that maps to llvm.coro.noop 
intrinsic.

Related llvm change: https://reviews.llvm.org/D45114

Modified:
cfe/trunk/include/clang/Basic/Builtins.def
cfe/trunk/lib/CodeGen/CGBuiltin.cpp
cfe/trunk/test/CodeGenCoroutines/coro-builtins.c

Modified: cfe/trunk/include/clang/Basic/Builtins.def
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=328993&r1=328992&r2=328993&view=diff
==
--- cfe/trunk/include/clang/Basic/Builtins.def (original)
+++ cfe/trunk/include/clang/Basic/Builtins.def Mon Apr  2 10:35:37 2018
@@ -1391,6 +1391,7 @@ BUILTIN(__builtin_coro_promise, "v*v*IiI
 
 BUILTIN(__builtin_coro_size, "z", "n")
 BUILTIN(__builtin_coro_frame, "v*", "n")
+BUILTIN(__builtin_coro_noop, "v*", "n")
 BUILTIN(__builtin_coro_free, "v*v*", "n")
 
 BUILTIN(__builtin_coro_id, "v*Iiv*v*v*", "n")

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=328993&r1=328992&r2=328993&view=diff
==
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Apr  2 10:35:37 2018
@@ -2796,6 +2796,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(
 return EmitCoroutineIntrinsic(E, Intrinsic::coro_resume);
   case Builtin::BI__builtin_coro_frame:
 return EmitCoroutineIntrinsic(E, Intrinsic::coro_frame);
+  case Builtin::BI__builtin_coro_noop:
+return EmitCoroutineIntrinsic(E, Intrinsic::coro_noop);
   case Builtin::BI__builtin_coro_free:
 return EmitCoroutineIntrinsic(E, Intrinsic::coro_free);
   case Builtin::BI__builtin_coro_destroy:

Modified: cfe/trunk/test/CodeGenCoroutines/coro-builtins.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-builtins.c?rev=328993&r1=328992&r2=328993&view=diff
==
--- cfe/trunk/test/CodeGenCoroutines/coro-builtins.c (original)
+++ cfe/trunk/test/CodeGenCoroutines/coro-builtins.c Mon Apr  2 10:35:37 2018
@@ -17,6 +17,9 @@ void f(int n) {
   // CHECK-NEXT: call i1 @llvm.coro.alloc(token %[[COROID]])
   __builtin_coro_alloc();
 
+  // CHECK-NEXT: call i8* @llvm.coro.noop()
+  __builtin_coro_noop();
+
   // CHECK-NEXT: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
   // CHECK-NEXT: %[[MEM:.+]] = call i8* @myAlloc(i64 %[[SIZE]])
   // CHECK-NEXT: %[[FRAME:.+]] = call i8* @llvm.coro.begin(token %[[COROID]], 
i8* %[[MEM]])


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


[libcxx] r329237 - [coroutines] Add noop_coroutine to

2018-04-04 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed Apr  4 15:18:03 2018
New Revision: 329237

URL: http://llvm.org/viewvc/llvm-project?rev=329237&view=rev
Log:
[coroutines] Add noop_coroutine to 

A recent addition to Coroutines TS (https://wg21.link/p0913) adds a pre-defined
coroutine noop_coroutine that does nothing.

This patch implements require library types in 

Related clang and llvm patches:

https://reviews.llvm.org/D45114
https://reviews.llvm.org/D45120

Added:

libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/

libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp
Modified:
libcxx/trunk/include/experimental/coroutine

Modified: libcxx/trunk/include/experimental/coroutine
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/experimental/coroutine?rev=329237&r1=329236&r2=329237&view=diff
==
--- libcxx/trunk/include/experimental/coroutine (original)
+++ libcxx/trunk/include/experimental/coroutine Wed Apr  4 15:18:03 2018
@@ -93,28 +93,28 @@ class _LIBCPP_TEMPLATE_VIS coroutine_han
 template <>
 class _LIBCPP_TEMPLATE_VIS coroutine_handle {
 public:
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 _LIBCPP_CONSTEXPR coroutine_handle() _NOEXCEPT : __handle_(nullptr) {}
 
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 _LIBCPP_CONSTEXPR coroutine_handle(nullptr_t) _NOEXCEPT : 
__handle_(nullptr) {}
 
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 coroutine_handle& operator=(nullptr_t) _NOEXCEPT {
 __handle_ = nullptr;
 return *this;
 }
 
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 _LIBCPP_CONSTEXPR void* address() const _NOEXCEPT { return __handle_; }
 
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 _LIBCPP_CONSTEXPR explicit operator bool() const _NOEXCEPT { return 
__handle_; }
 
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 void operator()() { resume(); }
 
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 void resume() {
   _LIBCPP_ASSERT(__is_suspended(),
  "resume() can only be called on suspended coroutines");
@@ -123,14 +123,14 @@ public:
   __builtin_coro_resume(__handle_);
 }
 
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 void destroy() {
   _LIBCPP_ASSERT(__is_suspended(),
  "destroy() can only be called on suspended coroutines");
   __builtin_coro_destroy(__handle_);
 }
 
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 bool done() const {
   _LIBCPP_ASSERT(__is_suspended(),
  "done() can only be called on suspended coroutines");
@@ -138,7 +138,7 @@ public:
 }
 
 public:
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 static coroutine_handle from_address(void* __addr) _NOEXCEPT {
 coroutine_handle __tmp;
 __tmp.__handle_ = __addr;
@@ -146,7 +146,7 @@ public:
 }
 
 // FIXME: Should from_address(nullptr) be allowed?
-_LIBCPP_ALWAYS_INLINE
+_LIBCPP_INLINE_VISIBILITY
 static coroutine_handle from_address(nullptr_t) _NOEXCEPT {
   return coroutine_handle(nullptr);
 }
@@ -169,27 +169,27 @@ private:
 };
 
 // 18.11.2.7 comparison operators:
-inline _LIBCPP_ALWAYS_INLINE
+inline _LIBCPP_INLINE_VISIBILITY
 bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
 return __x.address() == __y.address();
 }
-inline _LIBCPP_ALWAYS_INLINE
+inline _LIBCPP_INLINE_VISIBILITY
 bool operator!=(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
 return !(__x == __y);
 }
-inline _LIBCPP_ALWAYS_INLINE
+inline _LIBCPP_INLINE_VISIBILITY
 bool operator<(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
 return less()(__x.address(), __y.address());
 }
-inline _LIBCPP_ALWAYS_INLINE
+inline _LIBCPP_INLINE_VISIBILITY
 bool operator>(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
 return __y < __x;
 }
-inline _LIBCPP_ALWAYS_INLINE
+inline _LIBCPP_INLINE_VISIBILITY
 bool operator<=(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
 return !(__x > __y);
 }
-inline _LIBCPP_ALWAYS_INLINE
+inline _LIBCPP_INLINE_VISIBILITY
 bool operator>=(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT {
 return !(__x < __y);
 }
@@ -202,8 +202,8 @@ public:
 // 18.11.2.1 construct/reset
 using coroutine_handle<>::coroutine_handle;
 #else
-_LIBCPP_ALWAYS_INLINE coroutine_handle() _NOEXCEPT : _Base() {}
-_LIBCPP_ALWAYS_INLINE coroutine_handle(nullptr_t) _NOEXCEPT : 
_Base(nullptr) {}
+_LIBCPP_INLINE_VISIBILITY coroutine_handle() _NOEXCEPT : _Base() {}
+_LIBCPP_INLINE_VISIBILITY coroutine_handle(nullptr_t) _NOEXCEPT : 
_Base(nullptr) {}
 #endif
 _LIBCPP_INLINE_VISIBILITY
 coroutine_handle& operator=(

[libcxx] r329239 - [coroutines] Allow compilation under c++03

2018-04-04 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed Apr  4 15:51:57 2018
New Revision: 329239

URL: http://llvm.org/viewvc/llvm-project?rev=329239&view=rev
Log:
[coroutines] Allow compilation under c++03

Modified:
libcxx/trunk/include/experimental/coroutine

Modified: libcxx/trunk/include/experimental/coroutine
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/experimental/coroutine?rev=329239&r1=329238&r2=329239&view=diff
==
--- libcxx/trunk/include/experimental/coroutine (original)
+++ libcxx/trunk/include/experimental/coroutine Wed Apr  4 15:51:57 2018
@@ -294,7 +294,7 @@ using noop_coroutine_handle = coroutine_
 
 inline _LIBCPP_INLINE_VISIBILITY
 noop_coroutine_handle noop_coroutine() _NOEXCEPT {
-  return {};
+  return noop_coroutine_handle();
 }
 #endif // __has_builtin(__builtin_coro_noop)
 


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


[libcxx] r329240 - [coroutines] libcxx noop_coroutine. Make bots happier

2018-04-04 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed Apr  4 16:43:50 2018
New Revision: 329240

URL: http://llvm.org/viewvc/llvm-project?rev=329240&view=rev
Log:
[coroutines] libcxx noop_coroutine. Make bots happier

Modified:

libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp

Modified: 
libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp?rev=329240&r1=329239&r2=329240&view=diff
==
--- 
libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp
 (original)
+++ 
libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp
 Wed Apr  4 16:43:50 2018
@@ -10,6 +10,8 @@
 
 // UNSUPPORTED: c++98, c++03, c++11
 // XFAIL: clang-5, clang-6
+// UNSUPPORTED: ubsan
+
 // 
 // struct noop_coroutine_promise;
 // using noop_coroutine_handle = coroutine_handle;
@@ -19,8 +21,11 @@
 #include 
 #include 
 
+#if __has_builtin(__builtin_coro_noop)
+
 namespace coro = std::experimental::coroutines_v1;
 
+
 
static_assert(std::is_same,
 coro::noop_coroutine_handle>::value, "");
 static_assert(std::is_same::value, "");
 
@@ -64,3 +69,8 @@ int main()
   assert(coro::coroutine_handle<>::from_address(h.address()) == base);
 }
 
+#else
+
+int main() {}
+
+#endif //  __has_builtin(__builtin_coro_noop)


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


[libcxx] r329245 - [coroutines] libcxx, noop_coroutine, make bots even more happy

2018-04-04 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed Apr  4 17:18:37 2018
New Revision: 329245

URL: http://llvm.org/viewvc/llvm-project?rev=329245&view=rev
Log:
[coroutines] libcxx, noop_coroutine, make bots even more happy

Modified:
libcxx/trunk/include/experimental/coroutine

libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp

Modified: libcxx/trunk/include/experimental/coroutine
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/experimental/coroutine?rev=329245&r1=329244&r2=329245&view=diff
==
--- libcxx/trunk/include/experimental/coroutine (original)
+++ libcxx/trunk/include/experimental/coroutine Wed Apr  4 17:18:37 2018
@@ -278,9 +278,9 @@ public:
   _LIBCPP_CONSTEXPR explicit operator bool() const _NOEXCEPT { return true; }
   _LIBCPP_CONSTEXPR bool done() const _NOEXCEPT { return false; }
 
-  _LIBCPP_CONSTEXPR void operator()() const _NOEXCEPT {}
-  _LIBCPP_CONSTEXPR void resume() const _NOEXCEPT {}
-  _LIBCPP_CONSTEXPR void destroy() const _NOEXCEPT {}
+  _LIBCPP_CONSTEXPR_AFTER_CXX17 void operator()() const _NOEXCEPT {}
+  _LIBCPP_CONSTEXPR_AFTER_CXX17 void resume() const _NOEXCEPT {}
+  _LIBCPP_CONSTEXPR_AFTER_CXX17 void destroy() const _NOEXCEPT {}
 
 private:
   friend coroutine_handle noop_coroutine() _NOEXCEPT;

Modified: 
libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp?rev=329245&r1=329244&r2=329245&view=diff
==
--- 
libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp
 (original)
+++ 
libcxx/trunk/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.noop/noop_coroutine.pass.cpp
 Wed Apr  4 17:18:37 2018
@@ -9,7 +9,6 @@
 
//===--===//
 
 // UNSUPPORTED: c++98, c++03, c++11
-// XFAIL: clang-5, clang-6
 // UNSUPPORTED: ubsan
 
 // 


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


r317981 - [coroutines] Promote cleanup.dest.slot allocas to registers to avoid storing it in the coroutine frame

2017-11-11 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Sat Nov 11 09:00:43 2017
New Revision: 317981

URL: http://llvm.org/viewvc/llvm-project?rev=317981&view=rev
Log:
[coroutines] Promote cleanup.dest.slot allocas to registers to avoid storing it 
in the coroutine frame

Summary:
We don't want to store cleanup dest slot saved into the coroutine frame (as 
some of the cleanup code may
access them after coroutine frame destroyed).

This is an alternative to https://reviews.llvm.org/D37093

It is possible to do this for all functions, but, cursory check showed that in 
-O0, we get slightly longer function (by 1-3 instructions), thus, we are only 
limiting cleanup.dest.slot elimination to coroutines.

Reviewers: rjmccall, hfinkel, eric_niebler

Reviewed By: eric_niebler

Subscribers: EricWF, cfe-commits

Differential Revision: https://reviews.llvm.org/D39768

Added:
cfe/trunk/test/CodeGenCoroutines/coro-dest-slot.cpp
Modified:
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=317981&r1=317980&r2=317981&view=diff
==
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Sat Nov 11 09:00:43 2017
@@ -33,9 +33,11 @@
 #include "clang/Frontend/CodeGenOptions.h"
 #include "clang/Sema/SemaDiagnostic.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Dominators.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Operator.h"
+#include "llvm/Transforms/Utils/PromoteMemToReg.h"
 using namespace clang;
 using namespace CodeGen;
 
@@ -419,6 +421,18 @@ void CodeGenFunction::FinishFunction(Sou
 I->first->replaceAllUsesWith(I->second);
 I->first->eraseFromParent();
   }
+
+  // Eliminate CleanupDestSlot alloca by replacing it with SSA values and
+  // PHIs if the current function is a coroutine. We don't do it for all
+  // functions as it may result in slight increase in numbers of instructions
+  // if compiled with no optimizations. We do it for coroutine as the lifetime
+  // of CleanupDestSlot alloca make correct coroutine frame building very
+  // difficult.
+  if (NormalCleanupDest && isCoroutine()) {
+llvm::DominatorTree DT(*CurFn);
+llvm::PromoteMemToReg(NormalCleanupDest, DT);
+NormalCleanupDest = nullptr;
+  }
 }
 
 /// ShouldInstrumentFunction - Return true if the current function should be

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=317981&r1=317980&r2=317981&view=diff
==
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sat Nov 11 09:00:43 2017
@@ -225,6 +225,10 @@ public:
   };
   CGCoroInfo CurCoro;
 
+  bool isCoroutine() const {
+return CurCoro.Data != nullptr;
+  }
+
   /// CurGD - The GlobalDecl for the current function being compiled.
   GlobalDecl CurGD;
 
@@ -764,7 +768,7 @@ public:
 ForceCleanup();
 }
 
-/// Checks if the global variable is captured in current function. 
+/// Checks if the global variable is captured in current function.
 bool isGlobalVarCaptured(const VarDecl *VD) const {
   VD = VD->getCanonicalDecl();
   return !VD->isLocalVarDeclOrParm() && CGF.LocalDeclMap.count(VD) > 0;
@@ -826,7 +830,7 @@ public:
   /// block through the normal cleanup handling code (if any) and then
   /// on to \arg Dest.
   void EmitBranchThroughCleanup(JumpDest Dest);
-  
+
   /// isObviouslyBranchWithoutCleanups - Return true if a branch to the
   /// specified destination obviously has no cleanups to run.  'false' is 
always
   /// a conservatively correct answer for this method.
@@ -1045,7 +1049,7 @@ public:
   if (Data.isValid()) Data.unbind(CGF);
 }
   };
-  
+
 private:
   CGDebugInfo *DebugInfo;
   bool DisableDebugInfo;
@@ -1434,7 +1438,7 @@ private:
 
   /// Add OpenCL kernel arg metadata and the kernel attribute meatadata to
   /// the function metadata.
-  void EmitOpenCLKernelMetadata(const FunctionDecl *FD, 
+  void EmitOpenCLKernelMetadata(const FunctionDecl *FD,
 llvm::Function *Fn);
 
 public:
@@ -1443,10 +1447,10 @@ public:
 
   CodeGenTypes &getTypes() const { return CGM.getTypes(); }
   ASTContext &getContext() const { return CGM.getContext(); }
-  CGDebugInfo *getDebugInfo() { 
-if (DisableDebugInfo) 
+  CGDebugInfo *getDebugInfo() {
+if (DisableDebugInfo)
   return nullptr;
-return DebugInfo; 
+return DebugInfo;
   }
   void disableDebugInfo() { DisableDebugInfo = true; }
   void enableDebugInfo() { DisableDebugInfo = false; }
@@ -2509,7 +2513,7 @@ public:
   };
   AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);
   void EmitAutoVarInit(cons

r291513 - [coroutines] Sema: Allow co_return all by itself.

2017-01-09 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon Jan  9 18:08:31 2017
New Revision: 291513

URL: http://llvm.org/viewvc/llvm-project?rev=291513&view=rev
Log:
[coroutines] Sema: Allow co_return all by itself.

Reviewers: rsmith, EricWF

Subscribers: mehdi_amini, llvm-commits, EricWF

Differential Revision: https://reviews.llvm.org/D26038

Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=291513&r1=291512&r2=291513&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jan  9 18:08:31 
2017
@@ -8720,10 +8720,6 @@ def err_coroutine_invalid_func_context :
   "|a copy assignment operator|a move assignment operator|the 'main' function"
   "|a constexpr function|a function with a deduced return type"
   "|a varargs function}0">;
-def ext_coroutine_without_co_await_co_yield : ExtWarn<
-  "'co_return' used in a function "
-  "that uses neither 'co_await' nor 'co_yield'">,
-  InGroup>;
 def err_implied_std_coroutine_traits_not_found : Error<
   "you need to include  before defining a coroutine">;
 def err_malformed_std_coroutine_traits : Error<

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=291513&r1=291512&r2=291513&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Mon Jan  9 18:08:31 2017
@@ -578,17 +578,6 @@ void Sema::CheckCompletedCoroutineBody(F
 isa(First) ? 1 : 2);
   }
 
-  bool AnyCoawaits = false;
-  bool AnyCoyields = false;
-  for (auto *CoroutineStmt : Fn->CoroutineStmts) {
-AnyCoawaits |= isa(CoroutineStmt);
-AnyCoyields |= isa(CoroutineStmt);
-  }
-
-  if (!AnyCoawaits && !AnyCoyields)
-Diag(Fn->CoroutineStmts.front()->getLocStart(),
- diag::ext_coroutine_without_co_await_co_yield);
-
   SourceLocation Loc = FD->getLocation();
 
   // Form a declaration statement for the promise declaration, so that AST

Modified: cfe/trunk/test/SemaCXX/coroutines.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/coroutines.cpp?rev=291513&r1=291512&r2=291513&view=diff
==
--- cfe/trunk/test/SemaCXX/coroutines.cpp (original)
+++ cfe/trunk/test/SemaCXX/coroutines.cpp Mon Jan  9 18:08:31 2017
@@ -154,12 +154,11 @@ void mixed_await() {
 }
 
 void only_coreturn(void_tag) {
-  co_return; // expected-warning {{'co_return' used in a function that uses 
neither 'co_await' nor 'co_yield'}}
+  co_return; // OK
 }
 
 void mixed_coreturn(void_tag, bool b) {
   if (b)
-// expected-warning@+1 {{'co_return' used in a function that uses neither}}
 co_return; // expected-note {{use of 'co_return'}}
   else
 return; // expected-error {{not allowed in coroutine}}


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


[PATCH] D24373: [Coroutines] Adding builtins for coroutine intrinsics and backendutil support.

2016-09-09 Thread Gor Nishanov via cfe-commits
GorNishanov created this revision.
GorNishanov added reviewers: rsmith, majnemer.
GorNishanov added a subscriber: cfe-commits.
Herald added subscribers: beanz, mehdi_amini.

With this commit simple coroutines can be created in plain C using coroutine 
builtins (see coro.c and coro.h for an example):


https://reviews.llvm.org/D24373

Files:
  include/clang/Basic/Builtins.def
  lib/CodeGen/BackendUtil.cpp
  lib/CodeGen/CGBuiltin.cpp
  lib/CodeGen/CMakeLists.txt
  test/Coroutines/Inputs/coro.h
  test/Coroutines/coro.c

Index: test/Coroutines/coro.c
===
--- /dev/null
+++ test/Coroutines/coro.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines -emit-llvm %s -o - -O3 | FileCheck %s
+#include "Inputs/coro.h"
+void print(int);
+
+void* f() {
+  CORO_BEGIN(malloc);
+
+  for (int i = 0;; ++i) {
+print(i);
+CORO_SUSPEND();
+  }
+
+  CORO_END(free);
+}
+
+// CHECK-LABEL: @main
+int main() {
+  void* coro = f();
+  CORO_RESUME(coro);
+  CORO_RESUME(coro);
+  CORO_DESTROY(coro);
+// CHECK: call void @print(i32 0)
+// CHECK: call void @print(i32 1)
+// CHECK: call void @print(i32 2)
+}
Index: test/Coroutines/Inputs/coro.h
===
--- /dev/null
+++ test/Coroutines/Inputs/coro.h
@@ -0,0 +1,36 @@
+void free(void *ptr);
+void *malloc(unsigned int);
+
+#define CORO_SUSPEND_IMPL(IsFinal) \
+  switch (__builtin_coro_suspend(__builtin_coro_save(0), IsFinal)) {   \
+  case 0:  \
+if (IsFinal)   \
+  __builtin_trap();\
+break; \
+  case 1:  \
+goto coro_Cleanup; \
+  default: \
+goto coro_Suspend; \
+  }
+
+#define CORO_SUSPEND() CORO_SUSPEND_IMPL(0)
+#define CORO_FINAL_SUSPEND() CORO_SUSPEND_IMPL(1)
+
+#define CORO_BEGIN(AllocFunc)  \
+  void *coro_hdl = __builtin_coro_begin(__builtin_coro_id(0, 0, 0, 0), \
+AllocFunc(__builtin_coro_size()));
+
+#define CORO_END(FreeFunc) \
+  coro_Cleanup : { \
+void *coro_mem = __builtin_coro_free(coro_hdl);\
+if (coro_mem)  \
+  FreeFunc(coro_mem);  \
+  }\
+  coro_Suspend:\
+  __builtin_coro_end(0, 0);\
+  return coro_hdl;
+
+#define CORO_RESUME(hdl) __builtin_coro_resume(hdl)
+#define CORO_DESTROY(hdl) __builtin_coro_destroy(hdl)
+
+
Index: lib/CodeGen/CMakeLists.txt
===
--- lib/CodeGen/CMakeLists.txt
+++ lib/CodeGen/CMakeLists.txt
@@ -3,6 +3,7 @@
   BitReader
   BitWriter
   Core
+  Coroutines
   Coverage
   IPO
   IRReader
Index: lib/CodeGen/CGBuiltin.cpp
===
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -462,6 +462,25 @@
   return Builder.CreateCall(F, {EmitScalarExpr(E), CI});
 }
 
+// Emit intrinsic with all of the parameters as specified in the builtin.
+// We special case llvm.coro.free, as it takes a token parameter that has no
+// representation in the __builtin type system.
+static RValue emitSimpleIntrinsic(CodeGenFunction &CGF, const CallExpr *E,
+  Intrinsic::ID ID) {
+  SmallVector Args;
+  switch (ID) {
+  default:
+break;
+  case Intrinsic::coro_free:
+Args.push_back(llvm::ConstantTokenNone::get(CGF.getLLVMContext()));
+break;
+  }
+  for (auto &Arg : E->arguments())
+Args.push_back(CGF.EmitScalarExpr(Arg));
+  Value *F = CGF.CGM.getIntrinsic(ID);
+  return RValue::get(CGF.Builder.CreateCall(F, Args));
+}
+
 RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
 unsigned BuiltinID, const CallExpr *E,
 ReturnValueSlot ReturnValue) {
@@ -2057,6 +2076,41 @@
 break;
   }
 
+  case Builtin::BI__builtin_coro_size: {
+ASTContext &Context = getContext();
+auto SizeTy = Context.getSizeType();
+IntegerType *T = Builder.getIntNT

r298784 - [coroutines] Add codegen for await and yield expressions

2017-03-25 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Sat Mar 25 21:18:05 2017
New Revision: 298784

URL: http://llvm.org/viewvc/llvm-project?rev=298784&view=rev
Log:
[coroutines] Add codegen for await and yield expressions

Details:

Emit suspend expression which roughly looks like:

auto && x = CommonExpr();
if (!x.await_ready()) {
   llvm_coro_save();
   x.await_suspend(...); (*)
   llvm_coro_suspend(); (**)
}
x.await_resume();
where the result of the entire expression is the result of x.await_resume()

(*) If x.await_suspend return type is bool, it allows to veto a suspend:
if (x.await_suspend(...))
   llvm_coro_suspend();
(**) llvm_coro_suspend() encodes three possible continuations as a switch 
instruction:

%where-to = call i8 @llvm.coro.suspend(...)
switch i8 %where-to, label %coro.ret [ ; jump to epilogue to suspend
  i8 0, label %yield.ready   ; go here when resumed
  i8 1, label %yield.cleanup ; go here when destroyed
]

Added:
cfe/trunk/test/CodeGenCoroutines/coro-await.cpp
Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/lib/CodeGen/CGExprAgg.cpp
cfe/trunk/lib/CodeGen/CGExprComplex.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=298784&r1=298783&r2=298784&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Sat Mar 25 21:18:05 2017
@@ -12,35 +12,58 @@
 
//===--===//
 
 #include "CodeGenFunction.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "clang/AST/StmtCXX.h"
 
 using namespace clang;
 using namespace CodeGen;
 
-namespace clang {
-namespace CodeGen {
+using llvm::Value;
+using llvm::BasicBlock;
 
-struct CGCoroData {
+namespace {
+enum class AwaitKind { Init, Normal, Yield, Final };
+static constexpr llvm::StringLiteral AwaitKindStr[] = {"init", "await", 
"yield",
+   "final"};
+}
 
-  // Stores the jump destination just before the final suspend. Coreturn
-  // statements jumps to this point after calling return_xxx promise member.
-  CodeGenFunction::JumpDest FinalJD;
+struct clang::CodeGen::CGCoroData {
+  // What is the current await expression kind and how many
+  // await/yield expressions were encountered so far.
+  // These are used to generate pretty labels for await expressions in LLVM IR.
+  AwaitKind CurrentAwaitKind = AwaitKind::Init;
+  unsigned AwaitNum = 0;
+  unsigned YieldNum = 0;
 
+  // How many co_return statements are in the coroutine. Used to decide whether
+  // we need to add co_return; equivalent at the end of the user authored body.
   unsigned CoreturnCount = 0;
 
+  // A branch to this block is emitted when coroutine needs to suspend.
+  llvm::BasicBlock *SuspendBB = nullptr;
+
+  // Stores the jump destination just before the coroutine memory is freed.
+  // This is the destination that every suspend point jumps to for the cleanup
+  // branch.
+  CodeGenFunction::JumpDest CleanupJD;
+
+  // Stores the jump destination just before the final suspend. The co_return
+  // statements jumps to this point after calling return_xxx promise member.
+  CodeGenFunction::JumpDest FinalJD;
+
   // Stores the llvm.coro.id emitted in the function so that we can supply it
   // as the first argument to coro.begin, coro.alloc and coro.free intrinsics.
   // Note: llvm.coro.id returns a token that cannot be directly expressed in a
   // builtin.
   llvm::CallInst *CoroId = nullptr;
+
   // If coro.id came from the builtin, remember the expression to give better
   // diagnostic. If CoroIdExpr is nullptr, the coro.id was created by
   // EmitCoroutineBody.
   CallExpr const *CoroIdExpr = nullptr;
 };
-}
-}
 
+// Defining these here allows to keep CGCoroData private to this file.
 clang::CodeGen::CodeGenFunction::CGCoroInfo::CGCoroInfo() {}
 CodeGenFunction::CGCoroInfo::~CGCoroInfo() {}
 
@@ -66,6 +89,126 @@ static void createCoroData(CodeGenFuncti
   CurCoro.Data->CoroIdExpr = CoroIdExpr;
 }
 
+// Synthesize a pretty name for a suspend point.
+static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) 
{
+  unsigned No = 0;
+  switch (Kind) {
+  case AwaitKind::Init:
+  case AwaitKind::Final:
+break;
+  case AwaitKind::Normal:
+No = ++Coro.AwaitNum;
+break;
+  case AwaitKind::Yield:
+No = ++Coro.YieldNum;
+break;
+  }
+  SmallString<32> Prefix(AwaitKindStr[static_cast(Kind)]);
+  if (No > 1) {
+Twine(No).toVector(Prefix);
+  }
+  return Prefix;
+}
+
+// Emit suspend expression which roughly looks like:
+//
+//   auto && x = CommonExpr();
+//   if (!x.await_ready()) {
+//  llvm_coro_save();
+//  x.await_suspend(...); (*)
+//  llvm_coro_suspend(); (**)
+//   }
+//   x.await_resume();
+//
+// where the re

r298891 - [coroutines] Handle get_return_object_on_allocation_failure

2017-03-27 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon Mar 27 18:36:59 2017
New Revision: 298891

URL: http://llvm.org/viewvc/llvm-project?rev=298891&view=rev
Log:
[coroutines] Handle get_return_object_on_allocation_failure

Summary:
If promise_type has get_return_object_on_allocation_failure defined,
check if an allocation function returns nullptr, and if so,
return the result of get_return_object_on_allocation_failure().

Reviewers: rsmith, EricWF

Reviewed By: EricWF

Subscribers: mehdi_amini, cfe-commits

Differential Revision: https://reviews.llvm.org/D31399

Modified:
cfe/trunk/include/clang/AST/StmtCXX.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/StmtCXX.cpp
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/include/clang/AST/StmtCXX.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtCXX.h?rev=298891&r1=298890&r2=298891&view=diff
==
--- cfe/trunk/include/clang/AST/StmtCXX.h (original)
+++ cfe/trunk/include/clang/AST/StmtCXX.h Mon Mar 27 18:36:59 2017
@@ -309,6 +309,7 @@ class CoroutineBodyStmt final
 Allocate,  ///< Coroutine frame memory allocation.
 Deallocate,///< Coroutine frame memory deallocation.
 ReturnValue,   ///< Return value for thunk function.
+ReturnStmtOnAllocFailure, ///< Return statement if allocation failed.
 FirstParamMove ///< First offset for move construction of parameter copies.
   };
   unsigned NumParams;
@@ -332,6 +333,7 @@ public:
 Expr *Allocate = nullptr;
 Expr *Deallocate = nullptr;
 Stmt *ReturnValue = nullptr;
+Stmt *ReturnStmtOnAllocFailure = nullptr;
 ArrayRef ParamMoves;
   };
 
@@ -379,6 +381,9 @@ public:
   Expr *getReturnValueInit() const {
 return cast_or_null(getStoredStmts()[SubStmt::ReturnValue]);
   }
+  Stmt *getReturnStmtOnAllocFailure() const {
+return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure];
+  }
   ArrayRef getParamMoves() const {
 return {getStoredStmts() + SubStmt::FirstParamMove, NumParams};
   }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=298891&r1=298890&r2=298891&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Mar 27 18:36:59 
2017
@@ -8878,6 +8878,8 @@ def err_coroutine_promise_unhandled_exce
 def warn_coroutine_promise_unhandled_exception_required_with_exceptions : 
Warning<
   "%0 is required to declare the member 'unhandled_exception()' when 
exceptions are enabled">,
   InGroup;
+def err_coroutine_promise_get_return_object_on_allocation_failure : Error<
+  "%0: 'get_return_object_on_allocation_failure()' must be a static member 
function">;
 }
 
 let CategoryName = "Documentation Issue" in {

Modified: cfe/trunk/lib/AST/StmtCXX.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtCXX.cpp?rev=298891&r1=298890&r2=298891&view=diff
==
--- cfe/trunk/lib/AST/StmtCXX.cpp (original)
+++ cfe/trunk/lib/AST/StmtCXX.cpp Mon Mar 27 18:36:59 2017
@@ -108,6 +108,8 @@ CoroutineBodyStmt::CoroutineBodyStmt(Cor
   SubStmts[CoroutineBodyStmt::Allocate] = Args.Allocate;
   SubStmts[CoroutineBodyStmt::Deallocate] = Args.Deallocate;
   SubStmts[CoroutineBodyStmt::ReturnValue] = Args.ReturnValue;
+  SubStmts[CoroutineBodyStmt::ReturnStmtOnAllocFailure] =
+  Args.ReturnStmtOnAllocFailure;
   std::copy(Args.ParamMoves.begin(), Args.ParamMoves.end(),
 const_cast(getParamMoves().data()));
 }
\ No newline at end of file

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=298891&r1=298890&r2=298891&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Mon Mar 27 18:36:59 2017
@@ -229,7 +229,24 @@ void CodeGenFunction::EmitCoroutineBody(
   createCoroData(*this, CurCoro, CoroId);
   CurCoro.Data->SuspendBB = RetBB;
 
-  EmitScalarExpr(S.getAllocate());
+  auto *AllocateCall = EmitScalarExpr(S.getAllocate());
+
+  // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
+  if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) {
+auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure");
+auto *InitBB = createBasicBlock("coro.init");
+
+// See if allocation was successful.
+auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy);
+auto *Cond = Builder.CreateICmpNE(AllocateCall, NullPtr);
+Builde

r298893 - Use BuildReturnStmt in SemaCoroutine to unbreak sanitizer tests.

2017-03-27 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon Mar 27 21:51:45 2017
New Revision: 298893

URL: http://llvm.org/viewvc/llvm-project?rev=298893&view=rev
Log:
Use BuildReturnStmt in SemaCoroutine to unbreak sanitizer tests.

FIXME: ActOnReturnStmt expects a scope that is inside of the function, due
  to CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent());
  S.getCurScope()->getFnParent() == nullptr at ActOnFinishFunctionBody when
  CoroutineBodyStmt is built. Figure it out and fix it.

Modified:
cfe/trunk/lib/Sema/SemaCoroutine.cpp

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=298893&r1=298892&r2=298893&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Mon Mar 27 21:51:45 2017
@@ -830,8 +830,13 @@ bool SubStmtBuilder::makeReturnOnAllocFa
   S.ActOnCallExpr(nullptr, DeclNameExpr.get(), Loc, {}, Loc);
   if (ReturnObjectOnAllocationFailure.isInvalid()) return false;
 
-  StmtResult ReturnStmt = S.ActOnReturnStmt(
-  Loc, ReturnObjectOnAllocationFailure.get(), S.getCurScope());
+  // FIXME: ActOnReturnStmt expects a scope that is inside of the function, due
+  //   to CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent());
+  //   S.getCurScope()->getFnParent() == nullptr at ActOnFinishFunctionBody 
when
+  //   CoroutineBodyStmt is built. Figure it out and fix it.
+  //   Use BuildReturnStmt here to unbreak sanitized tests. (Gor:3/27/2017)
+  StmtResult ReturnStmt =
+  S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get());
   if (ReturnStmt.isInvalid()) return false;
 
   this->ReturnStmtOnAllocFailure = ReturnStmt.get();


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


r299281 - [coroutines] Add cleanup for compiler injected objects/allocations in coroutine body

2017-03-31 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Fri Mar 31 19:22:47 2017
New Revision: 299281

URL: http://llvm.org/viewvc/llvm-project?rev=299281&view=rev
Log:
[coroutines] Add cleanup for compiler injected objects/allocations in coroutine 
body

Summary:
* Use pushCleanup to emit freeing coroutine memory on normal and EH exits.
* Surround emitted code with CodeGenFunction::RunCleanupsScope.

Reviewers: rsmith, rnk, EricWF

Reviewed By: rnk

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D31460

Added:
cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp
Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-return.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=299281&r1=299280&r2=299281&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Fri Mar 31 19:22:47 2017
@@ -215,6 +215,24 @@ void CodeGenFunction::EmitCoreturnStmt(C
   EmitBranchThroughCleanup(CurCoro.Data->FinalJD);
 }
 
+namespace {
+// Make sure to call coro.delete on scope exit.
+struct CallCoroDelete final : public EHScopeStack::Cleanup {
+  Stmt *Deallocate;
+
+  // TODO: Wrap deallocate in if(coro.free(...)) Deallocate.
+  void Emit(CodeGenFunction &CGF, Flags) override {
+// Note: That deallocation will be emitted twice: once for a normal exit 
and
+// once for exceptional exit. This usage is safe because Deallocate does 
not
+// contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
+// builds a single call to a deallocation function which is safe to emit
+// multiple times.
+CGF.EmitStmt(Deallocate);
+  }
+  explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
+};
+}
+
 void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
   auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
   auto &TI = CGM.getContext().getTargetInfo();
@@ -248,26 +266,28 @@ void CodeGenFunction::EmitCoroutineBody(
 EmitBlock(InitBB);
   }
 
-  // FIXME: Setup cleanup scopes.
-
-  EmitStmt(S.getPromiseDeclStmt());
-
   CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB);
-  CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
-
-  // FIXME: Emit initial suspend and more before the body.
-
-  CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
-  EmitStmt(S.getBody());
-
-  // See if we need to generate final suspend.
-  const bool CanFallthrough = Builder.GetInsertBlock();
-  const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
-  if (CanFallthrough || HasCoreturns) {
-EmitBlock(FinalBB);
-// FIXME: Emit final suspend.
+  {
+CodeGenFunction::RunCleanupsScope ResumeScope(*this);
+EHStack.pushCleanup(NormalAndEHCleanup, S.getDeallocate());
+
+EmitStmt(S.getPromiseDeclStmt());
+
+CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
+
+// FIXME: Emit initial suspend and more before the body.
+
+CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
+EmitStmt(S.getBody());
+
+// See if we need to generate final suspend.
+const bool CanFallthrough = Builder.GetInsertBlock();
+const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
+if (CanFallthrough || HasCoreturns) {
+  EmitBlock(FinalBB);
+  // FIXME: Emit final suspend.
+}
   }
-  EmitStmt(S.getDeallocate());
 
   EmitBlock(RetBB);
 

Added: cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp?rev=299281&view=auto
==
--- cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp (added)
+++ cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp Fri Mar 31 19:22:47 2017
@@ -0,0 +1,74 @@
+// Verify that coroutine promise and allocated memory are freed up on 
exception.
+// RUN: %clang_cc1 -std=c++1z -fcoroutines-ts -triple=x86_64-unknown-linux-gnu 
-emit-llvm -o - %s -fexceptions -fcxx-exceptions -disable-llvm-passes | 
FileCheck %s
+
+namespace std::experimental {
+template  struct coroutine_traits;
+
+template  struct coroutine_handle {
+  coroutine_handle() = default;
+  static coroutine_handle from_address(void *) { return {}; }
+};
+template <> struct coroutine_handle {
+  static coroutine_handle from_address(void *) { return {}; }
+  coroutine_handle() = default;
+  template 
+  coroutine_handle(coroutine_handle) {}
+};
+}
+
+struct suspend_always {
+  bool await_ready();
+  void await_suspend(std::experimental::coroutine_handle<>);
+  void await_resume();
+};
+
+template <> struct std::experimental::coroutine_traits {
+  struct promise_type {
+void get_return_object();
+suspend_always initial_suspend();
+suspend_always final_suspend();
+void return_void();
+promise_type();
+~promise_type();
+

r299510 - [coroutines] Add coro.end handling

2017-04-04 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Tue Apr  4 23:55:03 2017
New Revision: 299510

URL: http://llvm.org/viewvc/llvm-project?rev=299510&view=rev
Log:
[coroutines] Add coro.end handling

Summary:
For WinEH, We add a funclet bundle to a coro.end call, so that CoroSplit in 
LLVM can replace it with cleanup ret and cut the rest out.
For landing pad, we add a branch to resume block if coro.end returns true.

LLVM Part: https://reviews.llvm.org/D25445

Reviewers: majnemer

Reviewed By: majnemer

Subscribers: EricWF, cfe-commits, rsmith, mehdi_amini

Differential Revision: https://reviews.llvm.org/D25444

Added:
cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp
Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=299510&r1=299509&r2=299510&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Tue Apr  4 23:55:03 2017
@@ -215,6 +215,43 @@ void CodeGenFunction::EmitCoreturnStmt(C
   EmitBranchThroughCleanup(CurCoro.Data->FinalJD);
 }
 
+// For WinEH exception representation backend need to know what funclet 
coro.end
+// belongs to. That information is passed in a funclet bundle.
+static SmallVector
+getBundlesForCoroEnd(CodeGenFunction &CGF) {
+  SmallVector BundleList;
+
+  if (llvm::Instruction *EHPad = CGF.CurrentFuncletPad)
+BundleList.emplace_back("funclet", EHPad);
+
+  return BundleList;
+}
+
+namespace {
+// We will insert coro.end to cut any of the destructors for objects that
+// do not need to be destroyed once the coroutine is resumed.
+// See llvm/docs/Coroutines.rst for more details about coro.end.
+struct CallCoroEnd final : public EHScopeStack::Cleanup {
+  void Emit(CodeGenFunction &CGF, Flags flags) override {
+auto &CGM = CGF.CGM;
+auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy);
+llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
+// See if we have a funclet bundle to associate coro.end with. (WinEH)
+auto Bundles = getBundlesForCoroEnd(CGF);
+auto *CoroEnd = CGF.Builder.CreateCall(
+CoroEndFn, {NullPtr, CGF.Builder.getTrue()}, Bundles);
+if (Bundles.empty()) {
+  // Otherwise, (landingpad model), create a conditional branch that leads
+  // either to a cleanup block or a block with EH resume instruction.
+  auto *ResumeBB = CGF.getEHResumeBlock(/*cleanup=*/true);
+  auto *CleanupContBB = CGF.createBasicBlock("cleanup.cont");
+  CGF.Builder.CreateCondBr(CoroEnd, ResumeBB, CleanupContBB);
+  CGF.EmitBlock(CleanupContBB);
+}
+  }
+};
+}
+
 namespace {
 // Make sure to call coro.delete on scope exit.
 struct CallCoroDelete final : public EHScopeStack::Cleanup {
@@ -273,6 +310,8 @@ void CodeGenFunction::EmitCoroutineBody(
 
 EmitStmt(S.getPromiseDeclStmt());
 
+EHStack.pushCleanup(EHCleanup);
+
 CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
 
 // FIXME: Emit initial suspend and more before the body.
@@ -290,6 +329,8 @@ void CodeGenFunction::EmitCoroutineBody(
   }
 
   EmitBlock(RetBB);
+  llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
+  Builder.CreateCall(CoroEnd, {NullPtr, Builder.getFalse()});
 
   // FIXME: Emit return for the coroutine return object.
 }

Added: cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp?rev=299510&view=auto
==
--- cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp (added)
+++ cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp Tue Apr  4 23:55:03 
2017
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -std=c++1z -fcoroutines-ts 
-triple=x86_64-pc-windows-msvc18.0.0 -emit-llvm %s -o - -fexceptions 
-fcxx-exceptions -disable-llvm-passes | FileCheck %s
+// RUN: %clang_cc1 -std=c++1z -fcoroutines-ts -triple=x86_64-unknown-linux-gnu 
-emit-llvm -o - %s -fexceptions -fcxx-exceptions -disable-llvm-passes | 
FileCheck --check-prefix=CHECK-LPAD %s
+
+namespace std::experimental {
+template  struct coroutine_traits {
+  using promise_type = typename R::promise_type;
+};
+
+template  struct coroutine_handle;
+
+template <> struct coroutine_handle {
+  static coroutine_handle from_address(void *) noexcept;
+  coroutine_handle() = default;
+  template 
+  coroutine_handle(coroutine_handle) noexcept;
+};
+template  struct coroutine_handle: coroutine_handle {
+  coroutine_handle() = default;
+  static coroutine_handle from_address(void *) noexcept;
+};
+}
+
+struct suspend_always {
+  bool await_ready() noexcept;
+  void await_suspend(std::experimental::coroutine_handle<>) noexcept;
+  void await_resume() noexcept;
+};
+
+struct coro_t {
+  struct promise_type {
+coro_t get_return_object() noexcept;
+suspen

r308996 - [coroutines] Add serialization/deserialization of coroutines

2017-07-25 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Tue Jul 25 11:01:49 2017
New Revision: 308996

URL: http://llvm.org/viewvc/llvm-project?rev=308996&view=rev
Log:
[coroutines] Add serialization/deserialization of coroutines

Reviewers: rsmith

Reviewed By: rsmith

Subscribers: EricWF, cfe-commits

Differential Revision: https://reviews.llvm.org/D35383

Added:
cfe/trunk/test/PCH/coroutines.cpp
Modified:
cfe/trunk/include/clang/AST/StmtCXX.h
cfe/trunk/include/clang/Serialization/ASTBitCodes.h
cfe/trunk/lib/AST/StmtCXX.cpp
cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
cfe/trunk/lib/Serialization/ASTWriterStmt.cpp

Modified: cfe/trunk/include/clang/AST/StmtCXX.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtCXX.h?rev=308996&r1=308995&r2=308996&view=diff
==
--- cfe/trunk/include/clang/AST/StmtCXX.h (original)
+++ cfe/trunk/include/clang/AST/StmtCXX.h Tue Jul 25 11:01:49 2017
@@ -317,6 +317,7 @@ class CoroutineBodyStmt final
   unsigned NumParams;
 
   friend class ASTStmtReader;
+  friend class ASTReader;
   friend TrailingObjects;
 
   Stmt **getStoredStmts() { return getTrailingObjects(); }
@@ -347,6 +348,8 @@ private:
 
 public:
   static CoroutineBodyStmt *Create(const ASTContext &C, CtorArgs const &Args);
+  static CoroutineBodyStmt *Create(const ASTContext &C, EmptyShell,
+   unsigned NumParams);
 
   bool hasDependentPromiseType() const {
 return getPromiseDecl()->getType()->isDependentType();
@@ -444,6 +447,8 @@ public:
 SubStmts[SubStmt::PromiseCall] = PromiseCall;
   }
 
+  CoreturnStmt(EmptyShell) : CoreturnStmt({}, {}, {}) {}
+
   SourceLocation getKeywordLoc() const { return CoreturnLoc; }
 
   /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=308996&r1=308995&r2=308996&view=diff
==
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Jul 25 11:01:49 2017
@@ -1545,9 +1545,14 @@ namespace clang {
 
   // ARC
   EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
-  
+
   STMT_MS_DEPENDENT_EXISTS,   // MSDependentExistsStmt
-  EXPR_LAMBDA // LambdaExpr
+  EXPR_LAMBDA,// LambdaExpr
+  STMT_COROUTINE_BODY,
+  STMT_CORETURN,
+  EXPR_COAWAIT,
+  EXPR_COYIELD,
+  EXPR_DEPENDENT_COAWAIT,
 };
 
 /// \brief The kinds of designators that can occur in a

Modified: cfe/trunk/lib/AST/StmtCXX.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtCXX.cpp?rev=308996&r1=308995&r2=308996&view=diff
==
--- cfe/trunk/lib/AST/StmtCXX.cpp (original)
+++ cfe/trunk/lib/AST/StmtCXX.cpp Tue Jul 25 11:01:49 2017
@@ -96,6 +96,20 @@ CoroutineBodyStmt *CoroutineBodyStmt::Cr
   return new (Mem) CoroutineBodyStmt(Args);
 }
 
+CoroutineBodyStmt *CoroutineBodyStmt::Create(const ASTContext &C, EmptyShell,
+ unsigned NumParams) {
+  std::size_t Size = totalSizeToAlloc(
+  CoroutineBodyStmt::FirstParamMove + NumParams);
+
+  void *Mem = C.Allocate(Size, alignof(CoroutineBodyStmt));
+  auto *Result = new (Mem) CoroutineBodyStmt(CtorArgs());
+  Result->NumParams = NumParams;
+  auto *ParamBegin = Result->getStoredStmts() + SubStmt::FirstParamMove;
+  std::uninitialized_fill(ParamBegin, ParamBegin + NumParams,
+  static_cast(nullptr));
+  return Result;
+}
+
 CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args)
 : Stmt(CoroutineBodyStmtClass), NumParams(Args.ParamMoves.size()) {
   Stmt **SubStmts = getStoredStmts();

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=308996&r1=308995&r2=308996&view=diff
==
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Jul 25 11:01:49 2017
@@ -367,28 +367,45 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsm
 }
 
 void ASTStmtReader::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
-  // FIXME: Implement coroutine serialization.
-  llvm_unreachable("unimplemented");
+  VisitStmt(S);
+  assert(Record.peekInt() == S->NumParams);
+  Record.skipInts(1);
+  auto *StoredStmts = S->getStoredStmts();
+  for (unsigned i = 0;
+   i < CoroutineBodyStmt::SubStmt::FirstParamMove + S->NumParams; ++i)
+StoredStmts[i] = Record.readSubStmt();
 }
 
 void ASTStmtReader::VisitCoreturnStmt(CoreturnStmt *S) {
-  // FIXME: Implement coroutine seriali

r294933 - [coroutines] NFC: Refactor Sema::CoroutineBodyStmt construction.

2017-02-12 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Sun Feb 12 23:05:02 2017
New Revision: 294933

URL: http://llvm.org/viewvc/llvm-project?rev=294933&view=rev
Log:
[coroutines] NFC: Refactor Sema::CoroutineBodyStmt construction.

Summary:
Sema::CheckCompletedCoroutineBody was growing unwieldy with building all of the 
substatements. Also, constructors for CoroutineBodyStmt had way too many 
parameters.

Instead,  CoroutineBodyStmt now defines CtorArgs structure with all of the 
required construction parameters.
CheckCompleteCoroutineBody delegates construction of individual substatements 
to short functions one per each substatement.

Also, added a drive-by fix of initializing CoroutinePromise to nullptr in 
ScopeInfo.h.
And addressed the FIXME that wanted to tail allocate extra room at the end of 
the CoroutineBodyStmt to hold parameter move expressions. (The comment was 
longer that the code that implemented tail allocation).

Reviewers: rsmith, EricWF

Subscribers: mehdi_amini, cfe-commits

Differential Revision: https://reviews.llvm.org/D28835

Modified:
cfe/trunk/include/clang/AST/StmtCXX.h
cfe/trunk/include/clang/Sema/ScopeInfo.h
cfe/trunk/lib/AST/StmtCXX.cpp
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/include/clang/AST/StmtCXX.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtCXX.h?rev=294933&r1=294932&r2=294933&view=diff
==
--- cfe/trunk/include/clang/AST/StmtCXX.h (original)
+++ cfe/trunk/include/clang/AST/StmtCXX.h Sun Feb 12 23:05:02 2017
@@ -296,7 +296,9 @@ public:
 /// \brief Represents the body of a coroutine. This wraps the normal function
 /// body and holds the additional semantic context required to set up and tear
 /// down the coroutine frame.
-class CoroutineBodyStmt : public Stmt {
+class CoroutineBodyStmt final
+: public Stmt,
+  private llvm::TrailingObjects {
   enum SubStmt {
 Body,  ///< The body of the coroutine.
 Promise,   ///< The promise statement.
@@ -309,52 +311,76 @@ class CoroutineBodyStmt : public Stmt {
 ReturnValue,   ///< Return value for thunk function.
 FirstParamMove ///< First offset for move construction of parameter copies.
   };
-  Stmt *SubStmts[SubStmt::FirstParamMove];
+  unsigned NumParams;
 
   friend class ASTStmtReader;
+  friend TrailingObjects;
+
+  Stmt **getStoredStmts() { return getTrailingObjects(); }
+
+  Stmt *const *getStoredStmts() const { return getTrailingObjects(); }
+
 public:
-  CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend,
-Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough,
-Expr *Allocate, Stmt *Deallocate,
-Expr *ReturnValue, ArrayRef ParamMoves)
-  : Stmt(CoroutineBodyStmtClass) {
-SubStmts[CoroutineBodyStmt::Body] = Body;
-SubStmts[CoroutineBodyStmt::Promise] = Promise;
-SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend;
-SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend;
-SubStmts[CoroutineBodyStmt::OnException] = OnException;
-SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough;
-SubStmts[CoroutineBodyStmt::Allocate] = Allocate;
-SubStmts[CoroutineBodyStmt::Deallocate] = Deallocate;
-SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue;
-// FIXME: Tail-allocate space for parameter move expressions and store 
them.
-assert(ParamMoves.empty() && "not implemented yet");
-  }
+
+  struct CtorArgs {
+Stmt *Body = nullptr;
+Stmt *Promise = nullptr;
+Expr *InitialSuspend = nullptr;
+Expr *FinalSuspend = nullptr;
+Stmt *OnException = nullptr;
+Stmt *OnFallthrough = nullptr;
+Expr *Allocate = nullptr;
+Expr *Deallocate = nullptr;
+Stmt *ReturnValue = nullptr;
+ArrayRef ParamMoves;
+  };
+
+private:
+
+  CoroutineBodyStmt(CtorArgs const& Args);
+
+public:
+  static CoroutineBodyStmt *Create(const ASTContext &C, CtorArgs const &Args);
 
   /// \brief Retrieve the body of the coroutine as written. This will be either
   /// a CompoundStmt or a TryStmt.
   Stmt *getBody() const {
-return SubStmts[SubStmt::Body];
+return getStoredStmts()[SubStmt::Body];
   }
 
-  Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; }
+  Stmt *getPromiseDeclStmt() const {
+return getStoredStmts()[SubStmt::Promise];
+  }
   VarDecl *getPromiseDecl() const {
 return 
cast(cast(getPromiseDeclStmt())->getSingleDecl());
   }
 
-  Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; }
-  Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; }
+  Stmt *getInitSuspendStmt() const {
+return getStoredStmts()[SubStmt::InitSuspend];
+  }
+  Stmt *getFinalSuspendStmt() const {
+return getStoredStmts()[SubStmt::FinalSuspend];
+  }
 
-  Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; }
+  Stmt *

r297076 - [coroutines] Add co_return statement emission

2017-03-06 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon Mar  6 15:12:54 2017
New Revision: 297076

URL: http://llvm.org/viewvc/llvm-project?rev=297076&view=rev
Log:
[coroutines] Add co_return statement emission

Summary:
Added co_return statement emission.

Tweaked coro-alloc.cpp test to use co_return to trigger coroutine processing 
instead of co_await, since this change starts emitting the body of the 
coroutine and await expression handling has not been upstreamed yet.

Reviewers: rsmith, majnemer, EricWF, aaron.ballman

Reviewed By: rsmith

Subscribers: majnemer, llvm-commits, mehdi_amini

Differential Revision: https://reviews.llvm.org/D29979

Added:
cfe/trunk/test/CodeGenCoroutines/coro-return.cpp
Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/lib/CodeGen/CGStmt.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=297076&r1=297075&r2=297076&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Mon Mar  6 15:12:54 2017
@@ -21,6 +21,13 @@ namespace clang {
 namespace CodeGen {
 
 struct CGCoroData {
+
+  // Stores the jump destination just before the final suspend. Coreturn
+  // statements jumps to this point after calling return_xxx promise member.
+  CodeGenFunction::JumpDest FinalJD;
+
+  unsigned CoreturnCount = 0;
+
   // Stores the llvm.coro.id emitted in the function so that we can supply it
   // as the first argument to coro.begin, coro.alloc and coro.free intrinsics.
   // Note: llvm.coro.id returns a token that cannot be directly expressed in a
@@ -59,19 +66,46 @@ static void createCoroData(CodeGenFuncti
   CurCoro.Data->CoroIdExpr = CoroIdExpr;
 }
 
+void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) {
+  ++CurCoro.Data->CoreturnCount;
+  EmitStmt(S.getPromiseCall());
+  EmitBranchThroughCleanup(CurCoro.Data->FinalJD);
+}
+
 void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
   auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
   auto &TI = CGM.getContext().getTargetInfo();
   unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();
 
+  auto *FinalBB = createBasicBlock("coro.final");
+
   auto *CoroId = Builder.CreateCall(
   CGM.getIntrinsic(llvm::Intrinsic::coro_id),
   {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});
   createCoroData(*this, CurCoro, CoroId);
 
   EmitScalarExpr(S.getAllocate());
-  // FIXME: Emit the rest of the coroutine.
+
+  // FIXME: Setup cleanup scopes.
+
+  EmitStmt(S.getPromiseDeclStmt());
+
+  CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
+
+  // FIXME: Emit initial suspend and more before the body.
+
+  EmitStmt(S.getBody());
+
+  // See if we need to generate final suspend.
+  const bool CanFallthrough = Builder.GetInsertBlock();
+  const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
+  if (CanFallthrough || HasCoreturns) {
+EmitBlock(FinalBB);
+// FIXME: Emit final suspend.
+  }
   EmitStmt(S.getDeallocate());
+
+  // FIXME: Emit return for the coroutine return object.
 }
 
 // Emit coroutine intrinsic and patch up arguments of the token type.

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=297076&r1=297075&r2=297076&view=diff
==
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Mon Mar  6 15:12:54 2017
@@ -145,7 +145,7 @@ void CodeGenFunction::EmitStmt(const Stm
 EmitCoroutineBody(cast(*S));
 break;
   case Stmt::CoreturnStmtClass:
-CGM.ErrorUnsupported(S, "coroutine");
+EmitCoreturnStmt(cast(*S));
 break;
   case Stmt::CapturedStmtClass: {
 const CapturedStmt *CS = cast(S);

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=297076&r1=297075&r2=297076&view=diff
==
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Mar  6 15:12:54 2017
@@ -2506,6 +2506,7 @@ public:
   void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S);
 
   void EmitCoroutineBody(const CoroutineBodyStmt &S);
+  void EmitCoreturnStmt(const CoreturnStmt &S);
   RValue EmitCoroutineIntrinsic(const CallExpr *E, unsigned int IID);
 
   void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);

Modified: cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp?rev=297076&r1=297075&r2=297076&view=diff
===

r297224 - [coroutines] update coro_end builtin to match llvm

2017-03-07 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Tue Mar  7 15:01:08 2017
New Revision: 297224

URL: http://llvm.org/viewvc/llvm-project?rev=297224&view=rev
Log:
[coroutines] update coro_end builtin to match llvm

Summary: llvm.coro.end intrinsic now returns bool. Updating clang to match it.

Reviewers: GorNishanov, rsmith

Reviewed By: rsmith

Subscribers: mehdi_amini, cfe-commits, EricWF

Differential Revision: https://reviews.llvm.org/D30711

Modified:
cfe/trunk/include/clang/Basic/Builtins.def
cfe/trunk/test/CodeGenCoroutines/coro-builtins.c

Modified: cfe/trunk/include/clang/Basic/Builtins.def
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=297224&r1=297223&r2=297224&view=diff
==
--- cfe/trunk/include/clang/Basic/Builtins.def (original)
+++ cfe/trunk/include/clang/Basic/Builtins.def Tue Mar  7 15:01:08 2017
@@ -1365,7 +1365,7 @@ BUILTIN(__builtin_coro_free, "v*v*", "n"
 BUILTIN(__builtin_coro_id, "v*Iiv*v*v*", "n")
 BUILTIN(__builtin_coro_alloc, "b", "n")
 BUILTIN(__builtin_coro_begin, "v*v*", "n")
-BUILTIN(__builtin_coro_end, "vv*Ib", "n")
+BUILTIN(__builtin_coro_end, "bv*Ib", "n")
 BUILTIN(__builtin_coro_suspend, "cIb", "n")
 BUILTIN(__builtin_coro_param, "bv*v*", "n")
 // OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions.

Modified: cfe/trunk/test/CodeGenCoroutines/coro-builtins.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-builtins.c?rev=297224&r1=297223&r2=297224&view=diff
==
--- cfe/trunk/test/CodeGenCoroutines/coro-builtins.c (original)
+++ cfe/trunk/test/CodeGenCoroutines/coro-builtins.c Tue Mar  7 15:01:08 2017
@@ -43,7 +43,7 @@ void f(int n) {
   __builtin_coro_free(__builtin_coro_frame());
 
   // CHECK-NEXT: %[[FRAME6:.+]] = call i8* @llvm.coro.frame() 
-  // CHECK-NEXT: call void @llvm.coro.end(i8* %[[FRAME6]], i1 false)
+  // CHECK-NEXT: call i1 @llvm.coro.end(i8* %[[FRAME6]], i1 false)
   __builtin_coro_end(__builtin_coro_frame(), 0);
 
   // CHECK-NEXT: call i8 @llvm.coro.suspend(token none, i1 true)


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


r297356 - [coroutines] Build and pass coroutine_handle to await_suspend

2017-03-08 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Wed Mar  8 21:09:43 2017
New Revision: 297356

URL: http://llvm.org/viewvc/llvm-project?rev=297356&view=rev
Log:
[coroutines] Build and pass coroutine_handle to await_suspend

Summary:
This patch adds passing a coroutine_handle object to await_suspend calls.
It builds the coroutine_handle using 
coroutine_handle::from_address(__builtin_coro_frame()).

(a revision of https://reviews.llvm.org/D26316 that for some reason refuses to 
apply via arc patch)

Reviewers: GorNishanov

Subscribers: mehdi_amini, cfe-commits, EricWF

Differential Revision: https://reviews.llvm.org/D30769

Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/lib/Sema/SemaExprMember.cpp
cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
cfe/trunk/test/CodeGenCoroutines/coro-return.cpp
cfe/trunk/test/SemaCXX/coreturn.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=297356&r1=297355&r2=297356&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Mar  8 21:09:43 
2017
@@ -8828,8 +8828,13 @@ def err_coroutine_invalid_func_context :
   "|a copy assignment operator|a move assignment operator|the 'main' function"
   "|a constexpr function|a function with a deduced return type"
   "|a varargs function}0">;
-def err_implied_std_coroutine_traits_not_found : Error<
-  "you need to include  before defining a coroutine">;
+def err_implied_coroutine_type_not_found : Error<
+  "%0 type was not found; include  before defining "
+  "a coroutine">;
+def err_malformed_std_coroutine_handle : Error<
+  "std::experimental::coroutine_handle must be a class template">;
+def err_coroutine_handle_missing_member : Error<
+  "std::experimental::coroutine_handle missing a member named '%0'">;
 def err_malformed_std_coroutine_traits : Error<
   "'std::experimental::coroutine_traits' must be a class template">;
 def err_implied_std_coroutine_traits_promise_type_not_found : Error<
@@ -8838,7 +8843,7 @@ def err_implied_std_coroutine_traits_pro
   "this function cannot be a coroutine: %0 is not a class">;
 def err_coroutine_promise_type_incomplete : Error<
   "this function cannot be a coroutine: %0 is an incomplete type">;
-def err_coroutine_traits_missing_specialization : Error<
+def err_coroutine_type_missing_specialization : Error<
   "this function cannot be a coroutine: missing definition of "
   "specialization %q0">;
 def err_implied_std_current_exception_not_found : Error<

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=297356&r1=297355&r2=297356&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Wed Mar  8 21:09:43 2017
@@ -39,14 +39,16 @@ static QualType lookupPromiseType(Sema &
   // FIXME: Cache std::coroutine_traits once we've found it.
   NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace();
   if (!StdExp) {
-S.Diag(KwLoc, diag::err_implied_std_coroutine_traits_not_found);
+S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
+<< "std::experimental::coroutine_traits";
 return QualType();
   }
 
   LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
   FuncLoc, Sema::LookupOrdinaryName);
   if (!S.LookupQualifiedName(Result, StdExp)) {
-S.Diag(KwLoc, diag::err_implied_std_coroutine_traits_not_found);
+S.Diag(KwLoc, diag::err_implied_coroutine_type_not_found)
+<< "std::experimental::coroutine_traits";
 return QualType();
   }
 
@@ -76,7 +78,7 @@ static QualType lookupPromiseType(Sema &
   if (CoroTrait.isNull())
 return QualType();
   if (S.RequireCompleteType(KwLoc, CoroTrait,
-diag::err_coroutine_traits_missing_specialization))
+diag::err_coroutine_type_missing_specialization))
 return QualType();
 
   auto *RD = CoroTrait->getAsCXXRecordDecl();
@@ -116,6 +118,51 @@ static QualType lookupPromiseType(Sema &
   return PromiseType;
 }
 
+/// Look up the std::coroutine_traits<...>::promise_type for the given
+/// function type.
+static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
+  SourceLocation Loc) {
+  if (PromiseType.isNull())
+return QualType();
+
+  NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace();
+  assert(StdExp && "Should already be diagnosed");
+
+  LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_handle"),
+  Loc, Sema::LookupOrdinaryName);
+  if (!S.L

r297541 - [coroutines] Refactor SuspendExpr to create just one OpaqueValue (almost NFC)

2017-03-10 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Fri Mar 10 19:30:17 2017
New Revision: 297541

URL: http://llvm.org/viewvc/llvm-project?rev=297541&view=rev
Log:
[coroutines] Refactor SuspendExpr to create just one OpaqueValue (almost NFC)

Summary:
Create only one OpaqueValue for await_ready/await_suspend/await_resume.
Store OpaqueValue used in the CoroutineSuspendExpr node, so that CodeGen does 
not have to hunt looking for it.

Reviewers: rsmith, EricWF, aaron.ballman

Reviewed By: EricWF

Subscribers: mehdi_amini, cfe-commits

Differential Revision: https://reviews.llvm.org/D30775

Modified:
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/lib/Sema/SemaCoroutine.cpp

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=297541&r1=297540&r2=297541&view=diff
==
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Fri Mar 10 19:30:17 2017
@@ -4123,16 +4123,18 @@ class CoroutineSuspendExpr : public Expr
 
   enum SubExpr { Common, Ready, Suspend, Resume, Count };
   Stmt *SubExprs[SubExpr::Count];
+  OpaqueValueExpr *OpaqueValue = nullptr;
 
   friend class ASTStmtReader;
 public:
   CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common,
-   Expr *Ready, Expr *Suspend, Expr *Resume)
+   Expr *Ready, Expr *Suspend, Expr *Resume,
+   OpaqueValueExpr *OpaqueValue)
   : Expr(SC, Resume->getType(), Resume->getValueKind(),
  Resume->getObjectKind(), Resume->isTypeDependent(),
  Resume->isValueDependent(), Common->isInstantiationDependent(),
  Common->containsUnexpandedParameterPack()),
-KeywordLoc(KeywordLoc) {
+KeywordLoc(KeywordLoc), OpaqueValue(OpaqueValue) {
 SubExprs[SubExpr::Common] = Common;
 SubExprs[SubExpr::Ready] = Ready;
 SubExprs[SubExpr::Suspend] = Suspend;
@@ -4161,6 +4163,8 @@ public:
   Expr *getCommonExpr() const {
 return static_cast(SubExprs[SubExpr::Common]);
   }
+  /// \brief getOpaqueValue - Return the opaque value placeholder.
+  OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
 
   Expr *getReadyExpr() const {
 return static_cast(SubExprs[SubExpr::Ready]);
@@ -4194,10 +4198,11 @@ class CoawaitExpr : public CoroutineSusp
   friend class ASTStmtReader;
 public:
   CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready,
-  Expr *Suspend, Expr *Resume, bool IsImplicit = false)
+  Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue,
+  bool IsImplicit = false)
   : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready,
- Suspend, Resume) {
-  CoawaitBits.IsImplicit = IsImplicit;
+ Suspend, Resume, OpaqueValue) {
+CoawaitBits.IsImplicit = IsImplicit;
   }
   CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand,
   bool IsImplicit = false)
@@ -4270,9 +4275,9 @@ class CoyieldExpr : public CoroutineSusp
   friend class ASTStmtReader;
 public:
   CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready,
-  Expr *Suspend, Expr *Resume)
+  Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue)
   : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready,
- Suspend, Resume) {}
+ Suspend, Resume, OpaqueValue) {}
   CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand)
   : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {}
   CoyieldExpr(EmptyShell Empty)

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=297541&r1=297540&r2=297541&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Fri Mar 10 19:30:17 2017
@@ -312,8 +312,9 @@ static ExprResult buildCoroutineHandle(S
 }
 
 struct ReadySuspendResumeResult {
-  bool IsInvalid;
   Expr *Results[3];
+  OpaqueValueExpr *OpaqueValue;
+  bool IsInvalid;
 };
 
 static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
@@ -336,8 +337,11 @@ static ExprResult buildMemberCall(Sema &
 /// expression.
 static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl 
*CoroPromise,
   SourceLocation Loc, Expr *E) 
{
+  OpaqueValueExpr *Operand = new (S.Context)
+  OpaqueValueExpr(Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
+
   // Assume invalid until we see otherwise.
-  ReadySuspendResumeResult Calls = {true, {}};
+  ReadySuspendResumeResult Calls = {{}, Operand, /*IsInvalid=*/true};
 
   ExprResult CoroHandleRes = buildCoroutineHandle(S, C

r303573 - [coroutines] Build GRO declaration and return GRO statement

2017-05-22 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon May 22 15:22:23 2017
New Revision: 303573

URL: http://llvm.org/viewvc/llvm-project?rev=303573&view=rev
Log:
[coroutines] Build GRO declaration and return GRO statement

Summary:
1. build declaration of the gro local variable that keeps the result of 
get_return_object.
2. build return statement returning the gro variable
3. emit them during CodeGen
4. sema and CodeGen tests updated

Reviewers: EricWF, rsmith

Reviewed By: rsmith

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D31646

Modified:
cfe/trunk/include/clang/AST/StmtCXX.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/StmtCXX.cpp
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
cfe/trunk/lib/Sema/CoroutineStmtBuilder.h
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
cfe/trunk/test/SemaCXX/coroutines.cpp

Modified: cfe/trunk/include/clang/AST/StmtCXX.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtCXX.h?rev=303573&r1=303572&r2=303573&view=diff
==
--- cfe/trunk/include/clang/AST/StmtCXX.h (original)
+++ cfe/trunk/include/clang/AST/StmtCXX.h Mon May 22 15:22:23 2017
@@ -308,7 +308,9 @@ class CoroutineBodyStmt final
 OnFallthrough, ///< Handler for control flow falling off the body.
 Allocate,  ///< Coroutine frame memory allocation.
 Deallocate,///< Coroutine frame memory deallocation.
-ReturnValue,   ///< Return value for thunk function.
+ReturnValue,   ///< Return value for thunk function: p.get_return_object().
+ResultDecl,///< Declaration holding the result of get_return_object.
+ReturnStmt,///< Return statement for the thunk function.
 ReturnStmtOnAllocFailure, ///< Return statement if allocation failed.
 FirstParamMove ///< First offset for move construction of parameter copies.
   };
@@ -332,7 +334,9 @@ public:
 Stmt *OnFallthrough = nullptr;
 Expr *Allocate = nullptr;
 Expr *Deallocate = nullptr;
-Stmt *ReturnValue = nullptr;
+Expr *ReturnValue = nullptr;
+Stmt *ResultDecl = nullptr;
+Stmt *ReturnStmt = nullptr;
 Stmt *ReturnStmtOnAllocFailure = nullptr;
 ArrayRef ParamMoves;
   };
@@ -381,10 +385,11 @@ public:
   Expr *getDeallocate() const {
 return cast_or_null(getStoredStmts()[SubStmt::Deallocate]);
   }
-
   Expr *getReturnValueInit() const {
-return cast_or_null(getStoredStmts()[SubStmt::ReturnValue]);
+return cast(getStoredStmts()[SubStmt::ReturnValue]);
   }
+  Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; }
+  Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; }
   Stmt *getReturnStmtOnAllocFailure() const {
 return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure];
   }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=303573&r1=303572&r2=303573&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon May 22 15:22:23 
2017
@@ -8910,6 +8910,8 @@ def err_return_in_coroutine : Error<
   "return statement not allowed in coroutine; did you mean 'co_return'?">;
 def note_declared_coroutine_here : Note<
   "function is a coroutine due to use of '%0' here">;
+def note_promise_member_declared_here : Note<
+  "'%0' is declared here">;
 def err_coroutine_objc_method : Error<
   "Objective-C methods as coroutines are not yet supported">;
 def err_coroutine_unevaluated_context : Error<

Modified: cfe/trunk/lib/AST/StmtCXX.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtCXX.cpp?rev=303573&r1=303572&r2=303573&view=diff
==
--- cfe/trunk/lib/AST/StmtCXX.cpp (original)
+++ cfe/trunk/lib/AST/StmtCXX.cpp Mon May 22 15:22:23 2017
@@ -88,7 +88,7 @@ const VarDecl *CXXForRangeStmt::getLoopV
 }
 
 CoroutineBodyStmt *CoroutineBodyStmt::Create(
-const ASTContext &C, CoroutineBodyStmt::CtorArgs const& Args) {
+const ASTContext &C, CoroutineBodyStmt::CtorArgs const &Args) {
   std::size_t Size = totalSizeToAlloc(
   CoroutineBodyStmt::FirstParamMove + Args.ParamMoves.size());
 
@@ -108,6 +108,8 @@ CoroutineBodyStmt::CoroutineBodyStmt(Cor
   SubStmts[CoroutineBodyStmt::Allocate] = Args.Allocate;
   SubStmts[CoroutineBodyStmt::Deallocate] = Args.Deallocate;
   SubStmts[CoroutineBodyStmt::ReturnValue] = Args.ReturnValue;
+  SubStmts[CoroutineBodyStmt::ResultDecl] = Args.ResultDecl;
+  SubStmts[CoroutineBodyStmt::ReturnStmt] = Args.ReturnStmt;
   SubStmts[CoroutineBodyStmt::ReturnStmtOnAllocFailure] =
   Args.ReturnStmtOnAllocFailure;
   std

r303583 - [coroutines] Wrap the body of the coroutine in try-catch

2017-05-22 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon May 22 17:33:17 2017
New Revision: 303583

URL: http://llvm.org/viewvc/llvm-project?rev=303583&view=rev
Log:
[coroutines] Wrap the body of the coroutine in try-catch

Summary:
If unhandled_exception member function is present in the coroutine promise,
wrap the body of the coroutine in:

```
try {
  body
} catch(...) { promise.unhandled_exception(); }
```

Reviewers: EricWF, rnk, rsmith

Reviewed By: rsmith

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D31692

Added:
cfe/trunk/test/SemaCXX/coroutine-seh.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/lib/Sema/SemaCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp
cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=303583&r1=303582&r2=303583&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon May 22 17:33:17 
2017
@@ -8960,6 +8960,8 @@ def warn_coroutine_promise_unhandled_exc
   InGroup;
 def err_coroutine_promise_get_return_object_on_allocation_failure : Error<
   "%0: 'get_return_object_on_allocation_failure()' must be a static member 
function">;
+def err_seh_in_a_coroutine_with_cxx_exceptions : Error<
+  "cannot use SEH '__try' in a coroutine when C++ exceptions are enabled">;
 def err_coroutine_promise_new_requires_nothrow : Error<
   "%0 is required to have a non-throwing noexcept specification when the 
promise "
"type declares 'get_return_object_on_allocation_failure()'">;

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=303583&r1=303582&r2=303583&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Mon May 22 17:33:17 2017
@@ -270,6 +270,15 @@ struct CallCoroDelete final : public EHS
 };
 }
 
+static void emitBodyAndFallthrough(CodeGenFunction &CGF,
+   const CoroutineBodyStmt &S, Stmt *Body) {
+  CGF.EmitStmt(Body);
+  const bool CanFallthrough = CGF.Builder.GetInsertBlock();
+  if (CanFallthrough)
+if (Stmt *OnFallthrough = S.getFallthroughHandler())
+  CGF.EmitStmt(OnFallthrough);
+}
+
 void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
   auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
   auto &TI = CGM.getContext().getTargetInfo();
@@ -318,7 +327,19 @@ void CodeGenFunction::EmitCoroutineBody(
 // FIXME: Emit initial suspend and more before the body.
 
 CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
-EmitStmt(S.getBody());
+
+if (auto *OnException = S.getExceptionHandler()) {
+  auto Loc = S.getLocStart();
+  CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr, OnException);
+  auto *TryStmt = CXXTryStmt::Create(getContext(), Loc, S.getBody(), 
&Catch);
+
+  EnterCXXTryStmt(*TryStmt);
+  emitBodyAndFallthrough(*this, S, TryStmt->getTryBlock());
+  ExitCXXTryStmt(*TryStmt);
+}
+else {
+  emitBodyAndFallthrough(*this, S, S.getBody());
+}
 
 // See if we need to generate final suspend.
 const bool CanFallthrough = Builder.GetInsertBlock();

Modified: cfe/trunk/lib/Sema/SemaCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCoroutine.cpp?rev=303583&r1=303582&r2=303583&view=diff
==
--- cfe/trunk/lib/Sema/SemaCoroutine.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCoroutine.cpp Mon May 22 17:33:17 2017
@@ -1043,6 +1043,15 @@ bool CoroutineStmtBuilder::makeOnExcepti
   if (UnhandledException.isInvalid())
 return false;
 
+  // Since the body of the coroutine will be wrapped in try-catch, it will
+  // be incompatible with SEH __try if present in a function.
+  if (!S.getLangOpts().Borland && Fn.FirstSEHTryLoc.isValid()) {
+S.Diag(Fn.FirstSEHTryLoc, 
diag::err_seh_in_a_coroutine_with_cxx_exceptions);
+S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)
+<< Fn.getFirstCoroutineStmtKeyword();
+return false;
+  }
+
   this->OnException = UnhandledException.get();
   return true;
 }

Modified: cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp?rev=303583&r1=303582&r2=303583&view=diff
==
--- cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp (original)
+++ cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp Mon May 22 17

r303584 - [coroutines] Fix coro-eh-cleanup.cpp test

2017-05-22 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon May 22 17:41:28 2017
New Revision: 303584

URL: http://llvm.org/viewvc/llvm-project?rev=303584&view=rev
Log:
[coroutines] Fix coro-eh-cleanup.cpp test

Modified:
cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp

Modified: cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp?rev=303584&r1=303583&r2=303584&view=diff
==
--- cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp (original)
+++ cfe/trunk/test/CodeGenCoroutines/coro-eh-cleanup.cpp Mon May 22 17:41:28 
2017
@@ -51,7 +51,7 @@ coro_t f() {
 // CHECK: [[EHCLEANUP]]:
 // CHECK:   %[[INNERPAD:.+]] = cleanuppad within none []
 // CHECK:   call void @"\01??_DCleanup@@QEAAXXZ"(
-// CHECK:   cleanupret from %4 unwind label %[[CATCHDISPATCH:.+]]
+// CHECK:   cleanupret from %{{.+}} unwind label %[[CATCHDISPATCH:.+]]
 
 // CHECK: [[CATCHDISPATCH]]:
 // CHECK:   catchswitch within none [label %[[CATCHPAD:.+]]] unwind label 
%[[COROENDBB:.+]]


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


r303596 - [coroutines] Add support for allocation elision

2017-05-22 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon May 22 20:13:17 2017
New Revision: 303596

URL: http://llvm.org/viewvc/llvm-project?rev=303596&view=rev
Log:
[coroutines] Add support for allocation elision

Summary:
We wrap allocation code so that backend can elide it if necessary.
llvm.coro.alloc intrinsic returns true, when allocation is needed and false 
otherwise.

```
  %NeedAlloc = call i1 @llvm.coro.alloc(token %2)
  br i1 %NeedAlloc, label %AllocBB, label %InitBB

AllocBB:
  %5 = call i64 @llvm.coro.size.i64()
  %call = call i8* @_Znwm(i64 %5) ; operator new
  br label %InitBB

InitBB:
  %Phi = phi i8* [ null, %0 ], [ %call, %4 ]
  call i8* @llvm.coro.begin(token %2, i8* %Phi)
```

Reviewers: majnemer, EricWF

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D31584

Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=303596&r1=303595&r2=303596&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Mon May 22 20:13:17 2017
@@ -284,6 +284,9 @@ void CodeGenFunction::EmitCoroutineBody(
   auto &TI = CGM.getContext().getTargetInfo();
   unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();
 
+  auto *EntryBB = Builder.GetInsertBlock();
+  auto *AllocBB = createBasicBlock("coro.alloc");
+  auto *InitBB = createBasicBlock("coro.init");
   auto *FinalBB = createBasicBlock("coro.final");
   auto *RetBB = createBasicBlock("coro.ret");
 
@@ -293,12 +296,20 @@ void CodeGenFunction::EmitCoroutineBody(
   createCoroData(*this, CurCoro, CoroId);
   CurCoro.Data->SuspendBB = RetBB;
 
+  // Backend is allowed to elide memory allocations, to help it, emit
+  // auto mem = coro.alloc() ? 0 : ... allocation code ...;
+  auto *CoroAlloc = Builder.CreateCall(
+  CGM.getIntrinsic(llvm::Intrinsic::coro_alloc), {CoroId});
+
+  Builder.CreateCondBr(CoroAlloc, AllocBB, InitBB);
+
+  EmitBlock(AllocBB);
   auto *AllocateCall = EmitScalarExpr(S.getAllocate());
+  auto *AllocOrInvokeContBB = Builder.GetInsertBlock();
 
   // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
   if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) {
 auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure");
-auto *InitBB = createBasicBlock("coro.init");
 
 // See if allocation was successful.
 auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy);
@@ -308,9 +319,19 @@ void CodeGenFunction::EmitCoroutineBody(
 // If not, return OnAllocFailure object.
 EmitBlock(RetOnFailureBB);
 EmitStmt(RetOnAllocFailure);
-
-EmitBlock(InitBB);
   }
+  else {
+Builder.CreateBr(InitBB);
+  }
+
+  EmitBlock(InitBB);
+
+  // Pass the result of the allocation to coro.begin.
+  auto *Phi = Builder.CreatePHI(VoidPtrTy, 2);
+  Phi->addIncoming(NullPtr, EntryBB);
+  Phi->addIncoming(AllocateCall, AllocOrInvokeContBB);
+  Builder.CreateCall(
+  CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi});
 
   CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB);
   {

Modified: cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp?rev=303596&r1=303595&r2=303596&view=diff
==
--- cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp (original)
+++ cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp Mon May 22 20:13:17 2017
@@ -56,8 +56,17 @@ struct std::experimental::coroutine_trai
 // CHECK-LABEL: f0(
 extern "C" void f0(global_new_delete_tag) {
   // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
+  // CHECK: %[[NeedAlloc:.+]] = call i1 @llvm.coro.alloc(token %[[ID]])
+  // CHECK: br i1 %[[NeedAlloc]], label %[[AllocBB:.+]], label %[[InitBB:.+]]
+
+  // CHECK: [[AllocBB]]:
   // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
-  // CHECK: call i8* @_Znwm(i64 %[[SIZE]])
+  // CHECK: %[[MEM:.+]] = call i8* @_Znwm(i64 %[[SIZE]])
+  // CHECK: br label %[[InitBB]]
+
+  // CHECK: [[InitBB]]:
+  // CHECK: %[[PHI:.+]] = phi i8* [ null, %{{.+}} ], [ %call, %[[AllocBB]] ]
+  // CHECK: call i8* @llvm.coro.begin(token %[[ID]], i8* %[[PHI]])
 
   // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
   // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* 
%[[FRAME]])


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


r303598 - [coroutines] Replace all coro.frame builtins with an SSA value of coro.begin

2017-05-22 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon May 22 22:46:59 2017
New Revision: 303598

URL: http://llvm.org/viewvc/llvm-project?rev=303598&view=rev
Log:
[coroutines] Replace all coro.frame builtins with an SSA value of coro.begin

SemaCoroutine forms expressions referring to the coroutine frame of the 
enclosing coroutine using coro.frame builtin.
During codegen, we emit llvm.coro.begin intrinsic that returns the address of 
the coroutine frame.
When coro.frame is emitted, we replace it with SSA value of coro.begin.

Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
cfe/trunk/test/CodeGenCoroutines/coro-await.cpp
cfe/trunk/test/CodeGenCoroutines/coro-builtins.c

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=303598&r1=303597&r2=303598&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Mon May 22 22:46:59 2017
@@ -57,6 +57,11 @@ struct clang::CodeGen::CGCoroData {
   // builtin.
   llvm::CallInst *CoroId = nullptr;
 
+  // Stores the llvm.coro.begin emitted in the function so that we can replace
+  // all coro.frame intrinsics with direct SSA value of coro.begin that returns
+  // the address of the coroutine frame of the current coroutine.
+  llvm::CallInst *CoroBegin = nullptr;
+
   // If coro.id came from the builtin, remember the expression to give better
   // diagnostic. If CoroIdExpr is nullptr, the coro.id was created by
   // EmitCoroutineBody.
@@ -330,8 +335,9 @@ void CodeGenFunction::EmitCoroutineBody(
   auto *Phi = Builder.CreatePHI(VoidPtrTy, 2);
   Phi->addIncoming(NullPtr, EntryBB);
   Phi->addIncoming(AllocateCall, AllocOrInvokeContBB);
-  Builder.CreateCall(
+  auto *CoroBegin = Builder.CreateCall(
   CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi});
+  CurCoro.Data->CoroBegin = CoroBegin;
 
   CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB);
   {
@@ -388,6 +394,17 @@ RValue CodeGenFunction::EmitCoroutineInt
   switch (IID) {
   default:
 break;
+  // The coro.frame builtin is replaced with an SSA value of the coro.begin
+  // intrinsic.
+  case llvm::Intrinsic::coro_frame: {
+if (CurCoro.Data && CurCoro.Data->CoroBegin) {
+  return RValue::get(CurCoro.Data->CoroBegin);
+}
+CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_begin 
"
+  "has been used earlier in this function");
+auto NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
+return RValue::get(NullPtr);
+  }
   // The following three intrinsics take a token parameter referring to a token
   // returned by earlier call to @llvm.coro.id. Since we cannot represent it in
   // builtins, we patch it up here.
@@ -414,10 +431,16 @@ RValue CodeGenFunction::EmitCoroutineInt
   llvm::Value *F = CGM.getIntrinsic(IID);
   llvm::CallInst *Call = Builder.CreateCall(F, Args);
 
+  // Note: The following code is to enable to emit coroutine intrinsics by
+  // hand to experiment with coroutines in C.
   // If we see @llvm.coro.id remember it in the CoroData. We will update
   // coro.alloc, coro.begin and coro.free intrinsics to refer to it.
   if (IID == llvm::Intrinsic::coro_id) {
 createCoroData(*this, CurCoro, Call, E);
   }
+  else if (IID == llvm::Intrinsic::coro_begin) {
+if (CurCoro.Data)
+  CurCoro.Data->CoroBegin = Call;
+  }
   return RValue::get(Call);
 }

Modified: cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp?rev=303598&r1=303597&r2=303598&view=diff
==
--- cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp (original)
+++ cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp Mon May 22 22:46:59 2017
@@ -66,9 +66,8 @@ extern "C" void f0(global_new_delete_tag
 
   // CHECK: [[InitBB]]:
   // CHECK: %[[PHI:.+]] = phi i8* [ null, %{{.+}} ], [ %call, %[[AllocBB]] ]
-  // CHECK: call i8* @llvm.coro.begin(token %[[ID]], i8* %[[PHI]])
+  // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(token %[[ID]], i8* 
%[[PHI]])
 
-  // 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;
@@ -93,7 +92,7 @@ extern "C" void f1(promise_new_tag ) {
   // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
   // CHECK: call i8* 
@_ZNSt12experimental16coroutine_traitsIJv15promise_new_tagEE12promise_typenwEm(i64
 %[[SIZE]])
 
-  // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
+  // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
   // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* 
%[[FRAME]])
   // CHECK: call void @_ZdlPv(i8* %[[MEM]])
   co_return;
@@ -118,7 +117,7 @@ ext

r303599 - [coroutines] Add support for deallocation elision

2017-05-22 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Mon May 22 23:21:27 2017
New Revision: 303599

URL: http://llvm.org/viewvc/llvm-project?rev=303599&view=rev
Log:
[coroutines] Add support for deallocation elision

Wrap deallocation code with:

  if (auto *mem = coro.free()) Deallocate

When backend decides to elide allocations it will replace coro.free with 
nullptr to suppress deallocation code.

Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=303599&r1=303598&r2=303599&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Mon May 22 23:21:27 2017
@@ -62,6 +62,10 @@ struct clang::CodeGen::CGCoroData {
   // the address of the coroutine frame of the current coroutine.
   llvm::CallInst *CoroBegin = nullptr;
 
+  // Stores the last emitted coro.free for the deallocate expressions, we use 
it
+  // to wrap dealloc code with if(auto mem = coro.free) dealloc(mem).
+  llvm::CallInst *LastCoroFree = nullptr;
+
   // If coro.id came from the builtin, remember the expression to give better
   // diagnostic. If CoroIdExpr is nullptr, the coro.id was created by
   // EmitCoroutineBody.
@@ -262,14 +266,47 @@ namespace {
 struct CallCoroDelete final : public EHScopeStack::Cleanup {
   Stmt *Deallocate;
 
-  // TODO: Wrap deallocate in if(coro.free(...)) Deallocate.
+  // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;"
+
+  // Note: That deallocation will be emitted twice: once for a normal exit and
+  // once for exceptional exit. This usage is safe because Deallocate does not
+  // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
+  // builds a single call to a deallocation function which is safe to emit
+  // multiple times.
   void Emit(CodeGenFunction &CGF, Flags) override {
-// Note: That deallocation will be emitted twice: once for a normal exit 
and
-// once for exceptional exit. This usage is safe because Deallocate does 
not
-// contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
-// builds a single call to a deallocation function which is safe to emit
-// multiple times.
+// Remember the current point, as we are going to emit deallocation code
+// first to get to coro.free instruction that is an argument to a delete
+// call.
+BasicBlock *SaveInsertBlock = CGF.Builder.GetInsertBlock();
+
+auto *FreeBB = CGF.createBasicBlock("coro.free");
+CGF.EmitBlock(FreeBB);
 CGF.EmitStmt(Deallocate);
+
+auto *AfterFreeBB = CGF.createBasicBlock("after.coro.free");
+CGF.EmitBlock(AfterFreeBB);
+
+// We should have captured coro.free from the emission of deallocate.
+auto *CoroFree = CGF.CurCoro.Data->LastCoroFree;
+if (!CoroFree) {
+  CGF.CGM.Error(Deallocate->getLocStart(),
+"Deallocation expressoin does not refer to coro.free");
+  return;
+}
+
+// Get back to the block we were originally and move coro.free there.
+auto *InsertPt = SaveInsertBlock->getTerminator();
+CoroFree->moveBefore(InsertPt);
+CGF.Builder.SetInsertPoint(InsertPt);
+
+// Add if (auto *mem = coro.free) Deallocate;
+auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy);
+auto *Cond = CGF.Builder.CreateICmpNE(CoroFree, NullPtr);
+CGF.Builder.CreateCondBr(Cond, FreeBB, AfterFreeBB);
+
+// No longer need old terminator.
+InsertPt->eraseFromParent();
+CGF.Builder.SetInsertPoint(AfterFreeBB);
   }
   explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
 };
@@ -431,7 +468,7 @@ RValue CodeGenFunction::EmitCoroutineInt
   llvm::Value *F = CGM.getIntrinsic(IID);
   llvm::CallInst *Call = Builder.CreateCall(F, Args);
 
-  // Note: The following code is to enable to emit coroutine intrinsics by
+  // Note: The following code is to enable to emit coro.id and coro.begin by
   // hand to experiment with coroutines in C.
   // If we see @llvm.coro.id remember it in the CoroData. We will update
   // coro.alloc, coro.begin and coro.free intrinsics to refer to it.
@@ -442,5 +479,10 @@ RValue CodeGenFunction::EmitCoroutineInt
 if (CurCoro.Data)
   CurCoro.Data->CoroBegin = Call;
   }
-  return RValue::get(Call);
+  else if (IID == llvm::Intrinsic::coro_free) {
+// Remember the last coro_free as we need it to build the conditional
+// deletion of the coroutine frame.
+if (CurCoro.Data)
+  CurCoro.Data->LastCoroFree = Call;
+  }  return RValue::get(Call);
 }

Modified: cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp?rev=303599&r1=303598&r2=303599&view=diff
==
--- cfe/trunk/test/CodeGenCo

r303603 - [coroutines] Add emission of initial and final suspends

2017-05-22 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Tue May 23 00:04:01 2017
New Revision: 303603

URL: http://llvm.org/viewvc/llvm-project?rev=303603&view=rev
Log:
[coroutines] Add emission of initial and final suspends

https://reviews.llvm.org/D31608

Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-await.cpp
cfe/trunk/test/CodeGenCoroutines/coro-cleanup.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=303603&r1=303602&r2=303603&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Tue May 23 00:04:01 2017
@@ -388,7 +388,10 @@ void CodeGenFunction::EmitCoroutineBody(
 
 CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
 
-// FIXME: Emit initial suspend and more before the body.
+// FIXME: Emit param moves.
+
+CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
+EmitStmt(S.getInitSuspendStmt());
 
 CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
 
@@ -410,7 +413,8 @@ void CodeGenFunction::EmitCoroutineBody(
 const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
 if (CanFallthrough || HasCoreturns) {
   EmitBlock(FinalBB);
-  // FIXME: Emit final suspend.
+  CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
+  EmitStmt(S.getFinalSuspendStmt());
 }
   }
 

Modified: cfe/trunk/test/CodeGenCoroutines/coro-await.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-await.cpp?rev=303603&r1=303602&r2=303603&view=diff
==
--- cfe/trunk/test/CodeGenCoroutines/coro-await.cpp (original)
+++ cfe/trunk/test/CodeGenCoroutines/coro-await.cpp Tue May 23 00:04:01 2017
@@ -21,6 +21,17 @@ struct coroutine_handle : coroutine_hand
 }
 }
 
+struct init_susp {
+  bool await_ready();
+  void await_suspend(std::experimental::coroutine_handle<>);
+  void await_resume();
+};
+struct final_susp {
+  bool await_ready();
+  void await_suspend(std::experimental::coroutine_handle<>);
+  void await_resume();
+};
+
 struct suspend_always {
   int stuff;
   bool await_ready();
@@ -32,8 +43,8 @@ template<>
 struct std::experimental::coroutine_traits {
   struct promise_type {
 void get_return_object();
-suspend_always initial_suspend();
-suspend_always final_suspend();
+init_susp initial_suspend();
+final_susp final_suspend();
 void return_void();
   };
 };
@@ -42,6 +53,13 @@ struct std::experimental::coroutine_trai
 extern "C" void f0() {
   // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
 
+  // See if initial_suspend was issued:
+  // --
+  // CHECK: call void 
@_ZNSt12experimental16coroutine_traitsIJvEE12promise_type15initial_suspendEv(
+  // CHECK-NEXT: call zeroext i1 
@_ZN9init_susp11await_readyEv(%struct.init_susp*
+  // CHECK: %[[INITSP_ID:.+]] = call token @llvm.coro.save(
+  // CHECK: call i8 @llvm.coro.suspend(token %[[INITSP_ID]], i1 false)
+
   co_await suspend_always{};
   // See if we need to suspend:
   // --
@@ -76,6 +94,13 @@ extern "C" void f0() {
   // --
   // CHECK: [[READY_BB]]:
   // CHECK:  call void 
@_ZN14suspend_always12await_resumeEv(%struct.suspend_always* %[[AWAITABLE]])
+
+  // See if final_suspend was issued:
+  // --
+  // CHECK: call void 
@_ZNSt12experimental16coroutine_traitsIJvEE12promise_type13final_suspendEv(
+  // CHECK-NEXT: call zeroext i1 
@_ZN10final_susp11await_readyEv(%struct.final_susp*
+  // CHECK: %[[FINALSP_ID:.+]] = call token @llvm.coro.save(
+  // CHECK: call i8 @llvm.coro.suspend(token %[[FINALSP_ID]], i1 true)
 }
 
 struct suspend_maybe {
@@ -91,8 +116,8 @@ template<>
 struct std::experimental::coroutine_traits {
   struct promise_type {
 void get_return_object();
-suspend_always initial_suspend();
-suspend_always final_suspend();
+init_susp initial_suspend();
+final_susp final_suspend();
 void return_void();
 suspend_maybe yield_value(int);
   };
@@ -228,3 +253,21 @@ extern "C" void TestOpAwait() {
   // CHECK: call void @_ZN5MyAggawEv(%struct.MyAgg* %
   // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret %
 }
+
+// CHECK-LABEL: EndlessLoop(
+extern "C" void EndlessLoop() {
+  // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
+
+  // See if initial_suspend was issued:
+  // --
+  // CHECK: call void 
@_ZNSt12experimental16coroutine_traitsIJvEE12promise_type15initial_suspendEv(
+  // CHECK-NEXT: call zeroext i1 
@_ZN9init_susp11await_readyEv(%struct.init_susp*
+
+  for (;;)
+co_await suspend_always{};
+
+  // Verify that final_suspend was NOT issued:
+  // --
+  // CHECK-NOT: call void 
@_ZNSt12experimental16coroutine_

r303605 - [coroutines] Skip over passthrough operator co_await

2017-05-22 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Tue May 23 00:25:31 2017
New Revision: 303605

URL: http://llvm.org/viewvc/llvm-project?rev=303605&view=rev
Log:
[coroutines] Skip over passthrough operator co_await

https://reviews.llvm.org/D31627

Modified:
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/test/CodeGenCoroutines/coro-await.cpp

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=303605&r1=303604&r2=303605&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Tue May 23 00:25:31 2017
@@ -151,6 +151,20 @@ static RValue emitSuspendExpression(Code
 AwaitKind Kind, AggValueSlot aggSlot,
 bool ignoreResult) {
   auto *E = S.getCommonExpr();
+
+  // FIXME: rsmith 5/22/2017. Does it still make sense for us to have a 
+  // UO_Coawait at all? As I recall, the only purpose it ever had was to
+  // represent a dependent co_await expression that couldn't yet be resolved to
+  // a CoawaitExpr. But now we have (and need!) a separate DependentCoawaitExpr
+  // node to store unqualified lookup results, it seems that the UnaryOperator
+  // portion of the representation serves no purpose (and as seen in this 
patch,
+  // it's getting in the way). Can we remove it?
+
+  // Skip passthrough operator co_await (present when awaiting on an LValue).
+  if (auto *UO = dyn_cast(E))
+if (UO->getOpcode() == UO_Coawait)
+  E = UO->getSubExpr();
+
   auto Binder =
   CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), 
E);
   auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); });

Modified: cfe/trunk/test/CodeGenCoroutines/coro-await.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCoroutines/coro-await.cpp?rev=303605&r1=303604&r2=303605&view=diff
==
--- cfe/trunk/test/CodeGenCoroutines/coro-await.cpp (original)
+++ cfe/trunk/test/CodeGenCoroutines/coro-await.cpp Tue May 23 00:25:31 2017
@@ -271,3 +271,10 @@ extern "C" void EndlessLoop() {
   // CHECK-NOT: call void 
@_ZNSt12experimental16coroutine_traitsIJvEE12promise_type13final_suspendEv(
   // CHECK-NOT: call zeroext i1 
@_ZN10final_susp11await_readyEv(%struct.final_susp*
 }
+
+// Verifies that we don't crash when awaiting on an lvalue.
+// CHECK-LABEL: @_Z11AwaitLValuev(
+void AwaitLValue() {
+  suspend_always lval;
+  co_await lval;
+}


___
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.

2016-10-17 Thread Gor Nishanov via cfe-commits
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] D25349: [coroutines] Build fallthrough and set_exception statements.

2016-10-17 Thread Gor Nishanov via cfe-commits
GorNishanov added a comment.

@rsmith, I am wondering what were your thoughts on where to generate try { body 
} catch (...) { p.set_exception(std::exception()); }

Would it be in SemaCoroutine.cpp? Essentially, add something like this:

  `
bool makeBody() {
  if (!OnException)
return true;
  
  StmtResult CatchBlock = S.ActOnCXXCatchBlock(Loc, nullptr, OnException);
  if (CatchBlock.isInvalid())
return false;
  
  StmtResult TryBlock = S.ActOnCXXTryBlock(Loc, Body, {CatchBlock.get()});
  if (TryBlock.isInvalid())
return false;
  
  Body = TryBlock.get();
  
  return true;
}
  `


https://reviews.llvm.org/D25349



___
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.

2016-10-17 Thread Gor Nishanov via cfe-commits
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.

2016-10-20 Thread Gor Nishanov via cfe-commits
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


r285306 - [coroutines] Add allocation and deallocation substatements.

2016-10-27 Thread Gor Nishanov via cfe-commits
Author: gornishanov
Date: Thu Oct 27 11:28:31 2016
New Revision: 285306

URL: http://llvm.org/viewvc/llvm-project?rev=285306&view=rev
Log:
[coroutines] Add allocation and deallocation substatements.

Summary:
SemaCoroutine: Add allocation / deallocation substatements.
CGCoroutine/Test: Emit allocation and deallocation + test.

Reviewers: rsmith

Subscribers: ABataev, EricWF, llvm-commits, mehdi_amini

Differential Revision: https://reviews.llvm.org/D25879

Added:
cfe/trunk/test/CodeGenCoroutines/coro-alloc.cpp
Modified:
cfe/trunk/include/clang/AST/StmtCXX.h
cfe/trunk/lib/CodeGen/CGCoroutine.cpp
cfe/trunk/lib/CodeGen/CGStmt.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/lib/Sema/SemaCoroutine.cpp

Modified: cfe/trunk/include/clang/AST/StmtCXX.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtCXX.h?rev=285306&r1=285305&r2=285306&view=diff
==
--- cfe/trunk/include/clang/AST/StmtCXX.h (original)
+++ cfe/trunk/include/clang/AST/StmtCXX.h Thu Oct 27 11:28:31 2016
@@ -304,6 +304,8 @@ class CoroutineBodyStmt : public Stmt {
 FinalSuspend,  ///< The final suspend statement, run after the body.
 OnException,   ///< Handler for exceptions thrown in the body.
 OnFallthrough, ///< Handler for control flow falling off the body.
+Allocate,  ///< Coroutine frame memory allocation.
+Deallocate,///< Coroutine frame memory deallocation.
 ReturnValue,   ///< Return value for thunk function.
 FirstParamMove ///< First offset for move construction of parameter copies.
   };
@@ -313,6 +315,7 @@ class CoroutineBodyStmt : public Stmt {
 public:
   CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend,
 Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough,
+Expr *Allocate, Stmt *Deallocate,
 Expr *ReturnValue, ArrayRef ParamMoves)
   : Stmt(CoroutineBodyStmtClass) {
 SubStmts[CoroutineBodyStmt::Body] = Body;
@@ -321,6 +324,8 @@ public:
 SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend;
 SubStmts[CoroutineBodyStmt::OnException] = OnException;
 SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough;
+SubStmts[CoroutineBodyStmt::Allocate] = Allocate;
+SubStmts[CoroutineBodyStmt::Deallocate] = Deallocate;
 SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue;
 // FIXME: Tail-allocate space for parameter move expressions and store 
them.
 assert(ParamMoves.empty() && "not implemented yet");
@@ -345,6 +350,9 @@ public:
 return SubStmts[SubStmt::OnFallthrough];
   }
 
+  Expr *getAllocate() const { return cast(SubStmts[SubStmt::Allocate]); }
+  Stmt *getDeallocate() const { return SubStmts[SubStmt::Deallocate]; }
+
   Expr *getReturnValueInit() const {
 return cast(SubStmts[SubStmt::ReturnValue]);
   }

Modified: cfe/trunk/lib/CodeGen/CGCoroutine.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCoroutine.cpp?rev=285306&r1=285305&r2=285306&view=diff
==
--- cfe/trunk/lib/CodeGen/CGCoroutine.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCoroutine.cpp Thu Oct 27 11:28:31 2016
@@ -12,6 +12,7 @@
 
//===--===//
 
 #include "CodeGenFunction.h"
+#include "clang/AST/StmtCXX.h"
 
 using namespace clang;
 using namespace CodeGen;
@@ -36,9 +37,10 @@ struct CGCoroData {
 clang::CodeGen::CodeGenFunction::CGCoroInfo::CGCoroInfo() {}
 CodeGenFunction::CGCoroInfo::~CGCoroInfo() {}
 
-static bool createCoroData(CodeGenFunction &CGF,
+static void createCoroData(CodeGenFunction &CGF,
CodeGenFunction::CGCoroInfo &CurCoro,
-   llvm::CallInst *CoroId, CallExpr const *CoroIdExpr) 
{
+   llvm::CallInst *CoroId,
+   CallExpr const *CoroIdExpr = nullptr) {
   if (CurCoro.Data) {
 if (CurCoro.Data->CoroIdExpr)
   CGF.CGM.Error(CoroIdExpr->getLocStart(),
@@ -49,13 +51,27 @@ static bool createCoroData(CodeGenFuncti
 else
   llvm_unreachable("EmitCoroutineBodyStatement called twice?");
 
-return false;
+return;
   }
 
   CurCoro.Data = std::unique_ptr(new CGCoroData);
   CurCoro.Data->CoroId = CoroId;
   CurCoro.Data->CoroIdExpr = CoroIdExpr;
-  return true;
+}
+
+void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
+  auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
+  auto &TI = CGM.getContext().getTargetInfo();
+  unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();
+
+  auto *CoroId = Builder.CreateCall(
+  CGM.getIntrinsic(llvm::Intrinsic::coro_id),
+  {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});
+  createCoroData(*this, CurCoro, CoroId);
+
+  EmitScalarExpr(S.getAllocate());
+  // FIXME: Emit the rest of the coroutine.