Skip to content

Commit

Permalink
Merging r308996:
Browse files Browse the repository at this point in the history
------------------------------------------------------------------------
r308996 | gornishanov | 2017-07-25 11:01:49 -0700 (Tue, 25 Jul 2017) | 9 lines

[coroutines] Add serialization/deserialization of coroutines

Reviewers: rsmith

Reviewed By: rsmith

Subscribers: EricWF, cfe-commits

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

llvm-svn: 309954
  • Loading branch information
zmodem committed Aug 3, 2017
1 parent 4a02632 commit db948f8
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 30 deletions.
5 changes: 5 additions & 0 deletions clang/include/clang/AST/StmtCXX.h
Expand Up @@ -317,6 +317,7 @@ class CoroutineBodyStmt final
unsigned NumParams;

friend class ASTStmtReader;
friend class ASTReader;
friend TrailingObjects;

Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); }
Expand Down Expand Up @@ -347,6 +348,8 @@ class CoroutineBodyStmt final

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();
Expand Down Expand Up @@ -444,6 +447,8 @@ class CoreturnStmt : public Stmt {
SubStmts[SubStmt::PromiseCall] = PromiseCall;
}

CoreturnStmt(EmptyShell) : CoreturnStmt({}, {}, {}) {}

SourceLocation getKeywordLoc() const { return CoreturnLoc; }

/// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr
Expand Down
9 changes: 7 additions & 2 deletions clang/include/clang/Serialization/ASTBitCodes.h
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/AST/StmtCXX.cpp
Expand Up @@ -96,6 +96,20 @@ CoroutineBodyStmt *CoroutineBodyStmt::Create(
return new (Mem) CoroutineBodyStmt(Args);
}

CoroutineBodyStmt *CoroutineBodyStmt::Create(const ASTContext &C, EmptyShell,
unsigned NumParams) {
std::size_t Size = totalSizeToAlloc<Stmt *>(
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<Stmt *>(nullptr));
return Result;
}

CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args)
: Stmt(CoroutineBodyStmtClass), NumParams(Args.ParamMoves.size()) {
Stmt **SubStmts = getStoredStmts();
Expand Down
66 changes: 53 additions & 13 deletions clang/lib/Serialization/ASTReaderStmt.cpp
Expand Up @@ -367,28 +367,45 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) {
}

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 serialization.
llvm_unreachable("unimplemented");
VisitStmt(S);
S->CoreturnLoc = Record.readSourceLocation();
for (auto &SubStmt: S->SubStmts)
SubStmt = Record.readSubStmt();
S->IsImplicit = Record.readInt() != 0;
}

void ASTStmtReader::VisitCoawaitExpr(CoawaitExpr *S) {
// FIXME: Implement coroutine serialization.
llvm_unreachable("unimplemented");
void ASTStmtReader::VisitCoawaitExpr(CoawaitExpr *E) {
VisitExpr(E);
E->KeywordLoc = ReadSourceLocation();
for (auto &SubExpr: E->SubExprs)
SubExpr = Record.readSubStmt();
E->OpaqueValue = cast_or_null<OpaqueValueExpr>(Record.readSubStmt());
E->setIsImplicit(Record.readInt() != 0);
}

void ASTStmtReader::VisitDependentCoawaitExpr(DependentCoawaitExpr *S) {
// FIXME: Implement coroutine serialization.
llvm_unreachable("unimplemented");
void ASTStmtReader::VisitCoyieldExpr(CoyieldExpr *E) {
VisitExpr(E);
E->KeywordLoc = ReadSourceLocation();
for (auto &SubExpr: E->SubExprs)
SubExpr = Record.readSubStmt();
E->OpaqueValue = cast_or_null<OpaqueValueExpr>(Record.readSubStmt());
}

void ASTStmtReader::VisitCoyieldExpr(CoyieldExpr *S) {
// FIXME: Implement coroutine serialization.
llvm_unreachable("unimplemented");
void ASTStmtReader::VisitDependentCoawaitExpr(DependentCoawaitExpr *E) {
VisitExpr(E);
E->KeywordLoc = ReadSourceLocation();
for (auto &SubExpr: E->SubExprs)
SubExpr = Record.readSubStmt();
}

void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) {
Expand Down Expand Up @@ -3947,6 +3964,29 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = LambdaExpr::CreateDeserialized(Context, NumCaptures);
break;
}

case STMT_COROUTINE_BODY: {
unsigned NumParams = Record[ASTStmtReader::NumStmtFields];
S = CoroutineBodyStmt::Create(Context, Empty, NumParams);
break;
}

case STMT_CORETURN:
S = new (Context) CoreturnStmt(Empty);
break;

case EXPR_COAWAIT:
S = new (Context) CoawaitExpr(Empty);
break;

case EXPR_COYIELD:
S = new (Context) CoyieldExpr(Empty);
break;

case EXPR_DEPENDENT_COAWAIT:
S = new (Context) DependentCoawaitExpr(Empty);
break;

}

// We hit a STMT_STOP, so we're done with this expression.
Expand Down
49 changes: 34 additions & 15 deletions clang/lib/Serialization/ASTWriterStmt.cpp
Expand Up @@ -286,7 +286,7 @@ void ASTStmtWriter::VisitMSAsmStmt(MSAsmStmt *S) {
}

// Outputs
for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {
for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) {
Record.AddStmt(S->getOutputExpr(I));
Record.AddString(S->getOutputConstraint(I));
}
Expand All @@ -300,29 +300,48 @@ void ASTStmtWriter::VisitMSAsmStmt(MSAsmStmt *S) {
Code = serialization::STMT_MSASM;
}

void ASTStmtWriter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
// FIXME: Implement coroutine serialization.
llvm_unreachable("unimplemented");
void ASTStmtWriter::VisitCoroutineBodyStmt(CoroutineBodyStmt *CoroStmt) {
VisitStmt(CoroStmt);
Record.push_back(CoroStmt->getParamMoves().size());
for (Stmt *S : CoroStmt->children())
Record.AddStmt(S);
Code = serialization::STMT_COROUTINE_BODY;
}

void ASTStmtWriter::VisitCoreturnStmt(CoreturnStmt *S) {
// FIXME: Implement coroutine serialization.
llvm_unreachable("unimplemented");
VisitStmt(S);
Record.AddSourceLocation(S->getKeywordLoc());
Record.AddStmt(S->getOperand());
Record.AddStmt(S->getPromiseCall());
Record.push_back(S->isImplicit());
Code = serialization::STMT_CORETURN;
}

void ASTStmtWriter::VisitCoawaitExpr(CoawaitExpr *S) {
// FIXME: Implement coroutine serialization.
llvm_unreachable("unimplemented");
void ASTStmtWriter::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E) {
VisitExpr(E);
Record.AddSourceLocation(E->getKeywordLoc());
for (Stmt *S : E->children())
Record.AddStmt(S);
Record.AddStmt(E->getOpaqueValue());
}

void ASTStmtWriter::VisitDependentCoawaitExpr(DependentCoawaitExpr *S) {
// FIXME: Implement coroutine serialization.
llvm_unreachable("unimplemented");
void ASTStmtWriter::VisitCoawaitExpr(CoawaitExpr *E) {
VisitCoroutineSuspendExpr(E);
Record.push_back(E->isImplicit());
Code = serialization::EXPR_COAWAIT;
}

void ASTStmtWriter::VisitCoyieldExpr(CoyieldExpr *E) {
VisitCoroutineSuspendExpr(E);
Code = serialization::EXPR_COYIELD;
}

void ASTStmtWriter::VisitCoyieldExpr(CoyieldExpr *S) {
// FIXME: Implement coroutine serialization.
llvm_unreachable("unimplemented");
void ASTStmtWriter::VisitDependentCoawaitExpr(DependentCoawaitExpr *E) {
VisitExpr(E);
Record.AddSourceLocation(E->getKeywordLoc());
for (Stmt *S : E->children())
Record.AddStmt(S);
Code = serialization::EXPR_DEPENDENT_COAWAIT;
}

void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) {
Expand Down
77 changes: 77 additions & 0 deletions clang/test/PCH/coroutines.cpp
@@ -0,0 +1,77 @@
// Test this without pch.
// RUN: %clang_cc1 -include %s -verify -std=c++1z -fcoroutines-ts %s

// Test with pch.
// RUN: %clang_cc1 -std=c++1z -fcoroutines-ts -emit-pch -o %t %s
// RUN: %clang_cc1 -include-pch %t -verify -std=c++1z -fcoroutines-ts %s

#ifndef HEADER
#define HEADER

namespace std::experimental {
template <typename... T> struct coroutine_traits;

template <class Promise = void> struct coroutine_handle {
coroutine_handle() = default;
static coroutine_handle from_address(void *) noexcept;
};
template <> struct coroutine_handle<void> {
static coroutine_handle from_address(void *) noexcept;
coroutine_handle() = default;
template <class PromiseType>
coroutine_handle(coroutine_handle<PromiseType>) noexcept;
};
}

struct suspend_always {
bool await_ready() noexcept;
void await_suspend(std::experimental::coroutine_handle<>) noexcept;
void await_resume() noexcept;
};

template <typename... Args> struct std::experimental::coroutine_traits<void, Args...> {
struct promise_type {
void get_return_object() noexcept;
suspend_always initial_suspend() noexcept;
suspend_always final_suspend() noexcept;
void return_void() noexcept;
suspend_always yield_value(int) noexcept;
promise_type();
~promise_type() noexcept;
void unhandled_exception() noexcept;
};
};

template <typename... Args> struct std::experimental::coroutine_traits<int, Args...> {
struct promise_type {
int get_return_object() noexcept;
suspend_always initial_suspend() noexcept;
suspend_always final_suspend() noexcept;
void return_value(int) noexcept;
promise_type();
~promise_type() noexcept;
void unhandled_exception() noexcept;
};
};

template <typename T>
void f(T x) { // checks coawait_expr and coroutine_body_stmt
co_yield 42; // checks coyield_expr
co_await x; // checks dependent_coawait
co_return; // checks coreturn_stmt
}

template <typename T>
int f2(T x) { // checks coawait_expr and coroutine_body_stmt
co_return x; // checks coreturn_stmt with expr
}

#else

// expected-no-diagnostics
void g() {
f(suspend_always{});
f2(42);
}

#endif

0 comments on commit db948f8

Please sign in to comment.