Skip to content

Commit 507bc17

Browse files
committed
Review fixes
1 parent 1b6e5a5 commit 507bc17

File tree

8 files changed

+49
-278
lines changed

8 files changed

+49
-278
lines changed

clang/include/clang/AST/ExprCXX.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5038,7 +5038,8 @@ class CoroutineSuspendExpr : public Expr {
50385038
OpaqueValueExpr *OpaqueValue = nullptr;
50395039

50405040
public:
5041-
enum SuspendReturnType { SuspendVoid, SuspendBool, SuspendHandle };
5041+
// These types correspond to the three C++ 'await_suspend' return variants
5042+
enum class SuspendReturnType { SuspendVoid, SuspendBool, SuspendHandle };
50425043

50435044
CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Operand,
50445045
Expr *Common, Expr *Ready, Expr *Suspend, Expr *Resume,
@@ -5109,10 +5110,12 @@ class CoroutineSuspendExpr : public Expr {
51095110
return SuspendReturnType::SuspendVoid;
51105111
if (SuspendType->isBooleanType())
51115112
return SuspendReturnType::SuspendBool;
5112-
if (SuspendType->isVoidPointerType())
5113-
return SuspendReturnType::SuspendHandle;
51145113

5115-
llvm_unreachable("Unexpected await_suspend expression return type");
5114+
// Void pointer is the type of handle.address(), which is returned
5115+
// from the await suspend wrapper so that the temporary coroutine handle
5116+
// value won't go to the frame by mistake
5117+
assert(SuspendType->isVoidPointerType());
5118+
return SuspendReturnType::SuspendHandle;
51165119
}
51175120

51185121
SourceLocation getKeywordLoc() const { return KeywordLoc; }

clang/lib/CodeGen/CGCoroutine.cpp

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ static bool AwaitSuspendStmtCanThrow(const Stmt *S) {
182182
// auto && x = CommonExpr();
183183
// if (!x.await_ready()) {
184184
// llvm_coro_save();
185-
// llvm_coro_await_suspend(&x, frame, wrapper) (*)
186-
// llvm_coro_suspend(); (**)
185+
// llvm_coro_await_suspend(&x, frame, wrapper) (*) (**)
186+
// llvm_coro_suspend(); (***)
187187
// }
188188
// x.await_resume();
189189
//
@@ -202,11 +202,11 @@ static bool AwaitSuspendStmtCanThrow(const Stmt *S) {
202202
// return awaiter.await_suspend(handle);
203203
// }
204204
//
205-
// If x.await_suspend return type is bool, it allows to veto a suspend:
205+
// (**) If x.await_suspend return type is bool, it allows to veto a suspend:
206206
// if (x.await_suspend(...))
207207
// llvm_coro_suspend();
208208
//
209-
// (**) llvm_coro_suspend() encodes three possible continuations as
209+
// (***) llvm_coro_suspend() encodes three possible continuations as
210210
// a switch instruction:
211211
//
212212
// %where-to = call i8 @llvm.coro.suspend(...)
@@ -250,14 +250,9 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
250250
auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy);
251251
auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
252252

253-
const auto AwaitSuspendCanThrow =
254-
AwaitSuspendStmtCanThrow(S.getSuspendExpr());
255-
256253
auto SuspendWrapper = CodeGenFunction(CGF.CGM).generateAwaitSuspendWrapper(
257254
CGF.CurFn->getName(), Prefix, S);
258255

259-
llvm::CallBase *SuspendRet = nullptr;
260-
261256
CGF.CurCoro.InSuspendBlock = true;
262257

263258
assert(CGF.CurCoro.Data && CGF.CurCoro.Data->CoroBegin &&
@@ -271,21 +266,26 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
271266
SuspendIntrinsicCallArgs.push_back(SuspendWrapper);
272267

273268
const auto SuspendReturnType = S.getSuspendReturnType();
274-
llvm::Intrinsic::ID IID;
269+
llvm::Intrinsic::ID AwaitSuspendIID;
275270

276271
switch (SuspendReturnType) {
277-
case CoroutineSuspendExpr::SuspendVoid:
278-
IID = llvm::Intrinsic::coro_await_suspend_void;
272+
case CoroutineSuspendExpr::SuspendReturnType::SuspendVoid:
273+
AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_void;
279274
break;
280-
case CoroutineSuspendExpr::SuspendBool:
281-
IID = llvm::Intrinsic::coro_await_suspend_bool;
275+
case CoroutineSuspendExpr::SuspendReturnType::SuspendBool:
276+
AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_bool;
282277
break;
283-
case CoroutineSuspendExpr::SuspendHandle:
284-
IID = llvm::Intrinsic::coro_await_suspend_handle;
278+
case CoroutineSuspendExpr::SuspendReturnType::SuspendHandle:
279+
AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_handle;
285280
break;
286281
}
287282

288-
llvm::Function *AwaitSuspendIntrinsic = CGF.CGM.getIntrinsic(IID);
283+
llvm::Function *AwaitSuspendIntrinsic = CGF.CGM.getIntrinsic(AwaitSuspendIID);
284+
285+
const auto AwaitSuspendCanThrow =
286+
AwaitSuspendStmtCanThrow(S.getSuspendExpr());
287+
288+
llvm::CallBase *SuspendRet = nullptr;
289289
// FIXME: add call attributes?
290290
if (AwaitSuspendCanThrow)
291291
SuspendRet =
@@ -298,10 +298,10 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
298298
CGF.CurCoro.InSuspendBlock = false;
299299

300300
switch (SuspendReturnType) {
301-
case CoroutineSuspendExpr::SuspendVoid:
301+
case CoroutineSuspendExpr::SuspendReturnType::SuspendVoid:
302302
assert(SuspendRet->getType()->isVoidTy());
303303
break;
304-
case CoroutineSuspendExpr::SuspendBool: {
304+
case CoroutineSuspendExpr::SuspendReturnType::SuspendBool: {
305305
assert(SuspendRet->getType()->isIntegerTy());
306306

307307
// Veto suspension if requested by bool returning await_suspend.
@@ -311,7 +311,7 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
311311
CGF.EmitBlock(RealSuspendBlock);
312312
break;
313313
}
314-
case CoroutineSuspendExpr::SuspendHandle: {
314+
case CoroutineSuspendExpr::SuspendReturnType::SuspendHandle: {
315315
assert(SuspendRet->getType()->isPointerTy());
316316

317317
auto ResumeIntrinsic = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_resume);

clang/lib/Sema/SemaCoroutine.cpp

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -347,39 +347,14 @@ static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
347347

348348
Expr *JustAddress = AddressExpr.get();
349349

350-
// FIXME: Without optimizations, the temporary result from `await_suspend()`
351-
// may be put on the coroutine frame since the coroutine frame constructor
352-
// will think the temporary variable will escape from the
353-
// `coroutine_handle<>::address()` call. This is problematic since the
354-
// coroutine should be considered to be suspended after it enters
355-
// `await_suspend` so it shouldn't access/update the coroutine frame after
356-
// that.
357-
//
358-
// See https://github.com/llvm/llvm-project/issues/65054 for the report.
359-
//
360-
// The long term solution may wrap the whole logic about `await-suspend`
361-
// into a standalone function. This is similar to the proposed solution
362-
// in tryMarkAwaitSuspendNoInline. See the comments there for details.
363-
//
364-
// The short term solution here is to mark `coroutine_handle<>::address()`
365-
// function as always-inline so that the coroutine frame constructor won't
366-
// think the temporary result is escaped incorrectly.
367-
if (auto *FD = cast<CallExpr>(JustAddress)->getDirectCallee())
368-
if (!FD->hasAttr<AlwaysInlineAttr>() && !FD->hasAttr<NoInlineAttr>())
369-
FD->addAttr(AlwaysInlineAttr::CreateImplicit(S.getASTContext(),
370-
FD->getLocation()));
371-
372350
// Check that the type of AddressExpr is void*
373351
if (!JustAddress->getType().getTypePtr()->isVoidPointerType())
374352
S.Diag(cast<CallExpr>(JustAddress)->getCalleeDecl()->getLocation(),
375353
diag::warn_coroutine_handle_address_invalid_return_type)
376354
<< JustAddress->getType();
377355

378-
// Clean up temporary objects so that they don't live across suspension points
379-
// unnecessarily. We choose to clean up before the call to
380-
// __builtin_coro_resume so that the cleanup code are not inserted in-between
381-
// the resume call and return instruction, which would interfere with the
382-
// musttail call contract.
356+
// Clean up temporary objects, because the resulting expression
357+
// will become the body of await_suspend wrapper.
383358
return S.MaybeCreateExprWithCleanups(JustAddress);
384359
}
385360

clang/test/CodeGenCoroutines/coro-simplify-suspend-point.cpp

Lines changed: 0 additions & 66 deletions
This file was deleted.

clang/test/CodeGenCoroutines/pr56329.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,9 @@ Task Outer() {
115115
// CHECK-NOT: _exit
116116
// CHECK: musttail call
117117
// CHECK: musttail call
118+
// CHECK: musttail call
118119
// CHECK-NEXT: ret void
120+
// CHECK-EMPTY:
121+
// CHECK-NEXT: unreachable:
122+
// CHECK-NEXT: unreachable
119123
// CHECK-NEXT: }

clang/test/CodeGenCoroutines/pr65054.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \
2-
// RUN: -O0 -disable-llvm-passes -emit-llvm %s -o - \
3-
// RUN: | FileCheck %s --check-prefix=FRONTEND
4-
51
// The output of O0 is highly redundant and hard to test. Also it is not good
62
// limit the output of O0. So we test the optimized output from O0. The idea
73
// is the optimizations shouldn't change the semantics of the program.
@@ -51,9 +47,6 @@ MyTask FooBar() {
5147
}
5248
}
5349

54-
// FRONTEND: define{{.*}}@_ZNKSt16coroutine_handleIvE7addressEv{{.*}}#[[address_attr:[0-9]+]]
55-
// FRONTEND: attributes #[[address_attr]] = {{.*}}alwaysinline
56-
5750
// CHECK-O0: define{{.*}}@_Z6FooBarv.resume
5851
// CHECK-O0: call{{.*}}@__await_suspend_wrapper__Z6FooBarv_await(
5952
// CHECK-O0-NOT: store

0 commit comments

Comments
 (0)