[CIR] Emit promise declaration in coroutine#166683
Merged
Andres-Salamanca merged 3 commits intollvm:mainfrom Nov 12, 2025
Merged
[CIR] Emit promise declaration in coroutine#166683Andres-Salamanca merged 3 commits intollvm:mainfrom
Andres-Salamanca merged 3 commits intollvm:mainfrom
Conversation
Member
|
@llvm/pr-subscribers-clangir Author: None (Andres-Salamanca) ChangesThis PR adds support for emitting the promise declaration in coroutines and obtaining the Full diff: https://github.com/llvm/llvm-project/pull/166683.diff 4 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 930ae55405756..133628045c8fb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -13,6 +13,7 @@
#include "CIRGenFunction.h"
#include "mlir/Support/LLVM.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
@@ -33,6 +34,65 @@ struct clang::CIRGen::CGCoroData {
CIRGenFunction::CGCoroInfo::CGCoroInfo() {}
CIRGenFunction::CGCoroInfo::~CGCoroInfo() {}
+namespace {
+// FIXME: both GetParamRef and ParamReferenceReplacerRAII are good template
+// candidates to be shared among LLVM / CIR codegen.
+
+// Hunts for the parameter reference in the parameter copy/move declaration.
+struct GetParamRef : public StmtVisitor<GetParamRef> {
+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.
+struct ParamReferenceReplacerRAII {
+ CIRGenFunction::DeclMapTy savedLocals;
+ CIRGenFunction::DeclMapTy &localDeclMap;
+
+ ParamReferenceReplacerRAII(CIRGenFunction::DeclMapTy &localDeclMap)
+ : localDeclMap(localDeclMap) {}
+
+ void addCopy(DeclStmt const *pm) {
+ // Figure out what param it refers to.
+
+ assert(pm->isSingleDecl());
+ VarDecl const *vd = static_cast<VarDecl const *>(pm->getSingleDecl());
+ Expr const *initExpr = vd->getInit();
+ GetParamRef visitor;
+ visitor.Visit(const_cast<Expr *>(initExpr));
+ assert(visitor.expr);
+ DeclRefExpr *dreOrig = 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});
+ }
+ }
+};
+} // namespace
static void createCoroData(CIRGenFunction &cgf,
CIRGenFunction::CGCoroInfo &curCoro,
cir::CallOp coroId) {
@@ -149,7 +209,46 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
if (s.getReturnStmtOnAllocFailure())
cgm.errorNYI("handle coroutine return alloc failure");
- assert(!cir::MissingFeatures::generateDebugInfo());
- assert(!cir::MissingFeatures::emitBodyAndFallthrough());
+ {
+ assert(!cir::MissingFeatures::generateDebugInfo());
+ ParamReferenceReplacerRAII paramReplacer(localDeclMap);
+ // Create mapping between parameters and copy-params for coroutine
+ // function.
+ llvm::ArrayRef<const Stmt *> paramMoves = s.getParamMoves();
+ assert((paramMoves.size() == 0 || (paramMoves.size() == fnArgs.size())) &&
+ "ParamMoves and FnArgs should be the same size for coroutine "
+ "function");
+ // For zipping the arg map into debug info.
+ assert(!cir::MissingFeatures::generateDebugInfo());
+
+ // 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 : paramMoves) {
+ if (emitStmt(pm, /*useCurrentScope=*/true).failed())
+ return mlir::failure();
+ paramReplacer.addCopy(cast<DeclStmt>(pm));
+ }
+
+ if (emitStmt(s.getPromiseDeclStmt(), /*useCurrentScope=*/true).failed())
+ return mlir::failure();
+ // returnValue should be valid as long as the coroutine's return type
+ // is not void. The assertion could help us to reduce the check later.
+ assert(returnValue.isValid() == (bool)s.getReturnStmt());
+ // Now we have the promise, initialize the GRO.
+ // We need to emit `get_return_object` first. According to:
+ // [dcl.fct.def.coroutine]p7
+ // The call to get_return_object is sequenced before the call to
+ // initial_suspend and is invoked at most once.
+ //
+ // So we couldn't emit return value when we emit return statment,
+ // otherwise the call to get_return_object wouldn't be in front
+ // of initial_suspend.
+ if (returnValue.isValid())
+ emitAnyExprToMem(s.getReturnValue(), returnValue,
+ s.getReturnValue()->getType().getQualifiers(),
+ /*isInit*/ true);
+ assert(!cir::MissingFeatures::emitBodyAndFallthrough());
+ }
return mlir::success();
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 71ff20a3b0e43..9925ad0a9f6d9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -620,6 +620,10 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin());
+ // Save parameters for coroutine function.
+ if (body && isa_and_nonnull<CoroutineBodyStmt>(body))
+ llvm::append_range(fnArgs, funcDecl->parameters());
+
if (isa<CXXDestructorDecl>(funcDecl)) {
emitDestructorBody(args);
} else if (isa<CXXConstructorDecl>(funcDecl)) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index c3fcd1a69a88e..cb3c91bf2f0e5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -152,6 +152,9 @@ class CIRGenFunction : public CIRGenTypeCache {
/// global initializers.
mlir::Operation *curFn = nullptr;
+ /// Save Parameter Decl for coroutine.
+ llvm::SmallVector<const ParmVarDecl *, 4> fnArgs;
+
using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
/// This keeps track of the CIR allocas or globals for local C
/// declarations.
diff --git a/clang/test/CIR/CodeGen/coro-task.cpp b/clang/test/CIR/CodeGen/coro-task.cpp
index 265325f82d7f7..5738c815909ea 100644
--- a/clang/test/CIR/CodeGen/coro-task.cpp
+++ b/clang/test/CIR/CodeGen/coro-task.cpp
@@ -36,6 +36,12 @@ struct suspend_never {
void await_resume() noexcept {}
};
+struct string {
+ int size() const;
+ string();
+ string(char const *s);
+};
+
} // namespace std
namespace folly {
@@ -101,7 +107,10 @@ co_invoke_fn co_invoke;
}} // namespace folly::coro
// CIR-DAG: ![[VoidTask:.*]] = !cir.record<struct "folly::coro::Task<void>" padded {!u8i}>
-
+// CIR-DAG: ![[IntTask:.*]] = !cir.record<struct "folly::coro::Task<int>" padded {!u8i}>
+// CIR-DAG: ![[VoidPromisse:.*]] = !cir.record<struct "folly::coro::Task<void>::promise_type" padded {!u8i}>
+// CIR-DAG: ![[IntPromisse:.*]] = !cir.record<struct "folly::coro::Task<int>::promise_type" padded {!u8i}>
+// CIR-DAG: ![[StdString:.*]] = !cir.record<struct "std::string" padded {!u8i}>
// CIR: module {{.*}} {
// CIR-NEXT: cir.global external @_ZN5folly4coro9co_invokeE = #cir.zero : !rec_folly3A3Acoro3A3Aco_invoke_fn
@@ -119,6 +128,7 @@ VoidTask silly_task() {
// CIR: cir.func coroutine dso_local @_Z10silly_taskv() -> ![[VoidTask]]
// CIR: %[[VoidTaskAddr:.*]] = cir.alloca ![[VoidTask]], {{.*}}, ["__retval"]
// CIR: %[[SavedFrameAddr:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__coro_frame_addr"]
+// CIR: %[[VoidPromisseAddr:.*]] = cir.alloca ![[VoidPromisse]], {{.*}}, ["__promise"]
// Get coroutine id with __builtin_coro_id.
@@ -138,3 +148,27 @@ VoidTask silly_task() {
// CIR: }
// CIR: %[[Load0:.*]] = cir.load{{.*}} %[[SavedFrameAddr]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
// CIR: %[[CoroFrameAddr:.*]] = cir.call @__builtin_coro_begin(%[[CoroId]], %[[Load0]])
+
+// Call promise.get_return_object() to retrieve the task object.
+
+// CIR: %[[RetObj:.*]] = cir.call @_ZN5folly4coro4TaskIvE12promise_type17get_return_objectEv(%[[VoidPromisseAddr]]) nothrow : {{.*}} -> ![[VoidTask]]
+// CIR: cir.store{{.*}} %[[RetObj]], %[[VoidTaskAddr]] : ![[VoidTask]]
+
+folly::coro::Task<int> byRef(const std::string& s) {
+ co_return s.size();
+}
+
+// CIR: cir.func coroutine dso_local @_Z5byRefRKSt6string(%[[ARG:.*]]: !cir.ptr<![[StdString]]> {{.*}}) -> ![[IntTask]]
+// CIR: %[[AllocaParam:.*]] = cir.alloca !cir.ptr<![[StdString]]>, {{.*}}, ["s", init, const]
+// CIR: %[[IntTaskAddr:.*]] = cir.alloca ![[IntTask]], {{.*}}, ["__retval"]
+// CIR: %[[SavedFrameAddr:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__coro_frame_addr"]
+// CIR: %[[AllocaFnUse:.*]] = cir.alloca !cir.ptr<![[StdString]]>, {{.*}}, ["s", init, const]
+// CIR: %[[IntPromisseAddr:.*]] = cir.alloca ![[IntPromisse]], {{.*}}, ["__promise"]
+// CIR: cir.store %[[ARG]], %[[AllocaParam]] : !cir.ptr<![[StdString]]>, {{.*}}
+
+// Call promise.get_return_object() to retrieve the task object.
+
+// CIR: %[[LOAD:.*]] = cir.load %[[AllocaParam]] : !cir.ptr<!cir.ptr<![[StdString]]>>, !cir.ptr<![[StdString]]>
+// CIR: cir.store {{.*}} %[[LOAD]], %[[AllocaFnUse]] : !cir.ptr<![[StdString]]>, !cir.ptr<!cir.ptr<![[StdString]]>>
+// CIR: %[[RetObj:.*]] = cir.call @_ZN5folly4coro4TaskIiE12promise_type17get_return_objectEv(%4) nothrow : {{.*}} -> ![[IntTask]]
+// CIR: cir.store {{.*}} %[[RetObj]], %[[IntTaskAddr]] : ![[IntTask]]
|
Member
|
@llvm/pr-subscribers-clang Author: None (Andres-Salamanca) ChangesThis PR adds support for emitting the promise declaration in coroutines and obtaining the Full diff: https://github.com/llvm/llvm-project/pull/166683.diff 4 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 930ae55405756..133628045c8fb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -13,6 +13,7 @@
#include "CIRGenFunction.h"
#include "mlir/Support/LLVM.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
@@ -33,6 +34,65 @@ struct clang::CIRGen::CGCoroData {
CIRGenFunction::CGCoroInfo::CGCoroInfo() {}
CIRGenFunction::CGCoroInfo::~CGCoroInfo() {}
+namespace {
+// FIXME: both GetParamRef and ParamReferenceReplacerRAII are good template
+// candidates to be shared among LLVM / CIR codegen.
+
+// Hunts for the parameter reference in the parameter copy/move declaration.
+struct GetParamRef : public StmtVisitor<GetParamRef> {
+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.
+struct ParamReferenceReplacerRAII {
+ CIRGenFunction::DeclMapTy savedLocals;
+ CIRGenFunction::DeclMapTy &localDeclMap;
+
+ ParamReferenceReplacerRAII(CIRGenFunction::DeclMapTy &localDeclMap)
+ : localDeclMap(localDeclMap) {}
+
+ void addCopy(DeclStmt const *pm) {
+ // Figure out what param it refers to.
+
+ assert(pm->isSingleDecl());
+ VarDecl const *vd = static_cast<VarDecl const *>(pm->getSingleDecl());
+ Expr const *initExpr = vd->getInit();
+ GetParamRef visitor;
+ visitor.Visit(const_cast<Expr *>(initExpr));
+ assert(visitor.expr);
+ DeclRefExpr *dreOrig = 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});
+ }
+ }
+};
+} // namespace
static void createCoroData(CIRGenFunction &cgf,
CIRGenFunction::CGCoroInfo &curCoro,
cir::CallOp coroId) {
@@ -149,7 +209,46 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
if (s.getReturnStmtOnAllocFailure())
cgm.errorNYI("handle coroutine return alloc failure");
- assert(!cir::MissingFeatures::generateDebugInfo());
- assert(!cir::MissingFeatures::emitBodyAndFallthrough());
+ {
+ assert(!cir::MissingFeatures::generateDebugInfo());
+ ParamReferenceReplacerRAII paramReplacer(localDeclMap);
+ // Create mapping between parameters and copy-params for coroutine
+ // function.
+ llvm::ArrayRef<const Stmt *> paramMoves = s.getParamMoves();
+ assert((paramMoves.size() == 0 || (paramMoves.size() == fnArgs.size())) &&
+ "ParamMoves and FnArgs should be the same size for coroutine "
+ "function");
+ // For zipping the arg map into debug info.
+ assert(!cir::MissingFeatures::generateDebugInfo());
+
+ // 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 : paramMoves) {
+ if (emitStmt(pm, /*useCurrentScope=*/true).failed())
+ return mlir::failure();
+ paramReplacer.addCopy(cast<DeclStmt>(pm));
+ }
+
+ if (emitStmt(s.getPromiseDeclStmt(), /*useCurrentScope=*/true).failed())
+ return mlir::failure();
+ // returnValue should be valid as long as the coroutine's return type
+ // is not void. The assertion could help us to reduce the check later.
+ assert(returnValue.isValid() == (bool)s.getReturnStmt());
+ // Now we have the promise, initialize the GRO.
+ // We need to emit `get_return_object` first. According to:
+ // [dcl.fct.def.coroutine]p7
+ // The call to get_return_object is sequenced before the call to
+ // initial_suspend and is invoked at most once.
+ //
+ // So we couldn't emit return value when we emit return statment,
+ // otherwise the call to get_return_object wouldn't be in front
+ // of initial_suspend.
+ if (returnValue.isValid())
+ emitAnyExprToMem(s.getReturnValue(), returnValue,
+ s.getReturnValue()->getType().getQualifiers(),
+ /*isInit*/ true);
+ assert(!cir::MissingFeatures::emitBodyAndFallthrough());
+ }
return mlir::success();
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 71ff20a3b0e43..9925ad0a9f6d9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -620,6 +620,10 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin());
+ // Save parameters for coroutine function.
+ if (body && isa_and_nonnull<CoroutineBodyStmt>(body))
+ llvm::append_range(fnArgs, funcDecl->parameters());
+
if (isa<CXXDestructorDecl>(funcDecl)) {
emitDestructorBody(args);
} else if (isa<CXXConstructorDecl>(funcDecl)) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index c3fcd1a69a88e..cb3c91bf2f0e5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -152,6 +152,9 @@ class CIRGenFunction : public CIRGenTypeCache {
/// global initializers.
mlir::Operation *curFn = nullptr;
+ /// Save Parameter Decl for coroutine.
+ llvm::SmallVector<const ParmVarDecl *, 4> fnArgs;
+
using DeclMapTy = llvm::DenseMap<const clang::Decl *, Address>;
/// This keeps track of the CIR allocas or globals for local C
/// declarations.
diff --git a/clang/test/CIR/CodeGen/coro-task.cpp b/clang/test/CIR/CodeGen/coro-task.cpp
index 265325f82d7f7..5738c815909ea 100644
--- a/clang/test/CIR/CodeGen/coro-task.cpp
+++ b/clang/test/CIR/CodeGen/coro-task.cpp
@@ -36,6 +36,12 @@ struct suspend_never {
void await_resume() noexcept {}
};
+struct string {
+ int size() const;
+ string();
+ string(char const *s);
+};
+
} // namespace std
namespace folly {
@@ -101,7 +107,10 @@ co_invoke_fn co_invoke;
}} // namespace folly::coro
// CIR-DAG: ![[VoidTask:.*]] = !cir.record<struct "folly::coro::Task<void>" padded {!u8i}>
-
+// CIR-DAG: ![[IntTask:.*]] = !cir.record<struct "folly::coro::Task<int>" padded {!u8i}>
+// CIR-DAG: ![[VoidPromisse:.*]] = !cir.record<struct "folly::coro::Task<void>::promise_type" padded {!u8i}>
+// CIR-DAG: ![[IntPromisse:.*]] = !cir.record<struct "folly::coro::Task<int>::promise_type" padded {!u8i}>
+// CIR-DAG: ![[StdString:.*]] = !cir.record<struct "std::string" padded {!u8i}>
// CIR: module {{.*}} {
// CIR-NEXT: cir.global external @_ZN5folly4coro9co_invokeE = #cir.zero : !rec_folly3A3Acoro3A3Aco_invoke_fn
@@ -119,6 +128,7 @@ VoidTask silly_task() {
// CIR: cir.func coroutine dso_local @_Z10silly_taskv() -> ![[VoidTask]]
// CIR: %[[VoidTaskAddr:.*]] = cir.alloca ![[VoidTask]], {{.*}}, ["__retval"]
// CIR: %[[SavedFrameAddr:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__coro_frame_addr"]
+// CIR: %[[VoidPromisseAddr:.*]] = cir.alloca ![[VoidPromisse]], {{.*}}, ["__promise"]
// Get coroutine id with __builtin_coro_id.
@@ -138,3 +148,27 @@ VoidTask silly_task() {
// CIR: }
// CIR: %[[Load0:.*]] = cir.load{{.*}} %[[SavedFrameAddr]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
// CIR: %[[CoroFrameAddr:.*]] = cir.call @__builtin_coro_begin(%[[CoroId]], %[[Load0]])
+
+// Call promise.get_return_object() to retrieve the task object.
+
+// CIR: %[[RetObj:.*]] = cir.call @_ZN5folly4coro4TaskIvE12promise_type17get_return_objectEv(%[[VoidPromisseAddr]]) nothrow : {{.*}} -> ![[VoidTask]]
+// CIR: cir.store{{.*}} %[[RetObj]], %[[VoidTaskAddr]] : ![[VoidTask]]
+
+folly::coro::Task<int> byRef(const std::string& s) {
+ co_return s.size();
+}
+
+// CIR: cir.func coroutine dso_local @_Z5byRefRKSt6string(%[[ARG:.*]]: !cir.ptr<![[StdString]]> {{.*}}) -> ![[IntTask]]
+// CIR: %[[AllocaParam:.*]] = cir.alloca !cir.ptr<![[StdString]]>, {{.*}}, ["s", init, const]
+// CIR: %[[IntTaskAddr:.*]] = cir.alloca ![[IntTask]], {{.*}}, ["__retval"]
+// CIR: %[[SavedFrameAddr:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__coro_frame_addr"]
+// CIR: %[[AllocaFnUse:.*]] = cir.alloca !cir.ptr<![[StdString]]>, {{.*}}, ["s", init, const]
+// CIR: %[[IntPromisseAddr:.*]] = cir.alloca ![[IntPromisse]], {{.*}}, ["__promise"]
+// CIR: cir.store %[[ARG]], %[[AllocaParam]] : !cir.ptr<![[StdString]]>, {{.*}}
+
+// Call promise.get_return_object() to retrieve the task object.
+
+// CIR: %[[LOAD:.*]] = cir.load %[[AllocaParam]] : !cir.ptr<!cir.ptr<![[StdString]]>>, !cir.ptr<![[StdString]]>
+// CIR: cir.store {{.*}} %[[LOAD]], %[[AllocaFnUse]] : !cir.ptr<![[StdString]]>, !cir.ptr<!cir.ptr<![[StdString]]>>
+// CIR: %[[RetObj:.*]] = cir.call @_ZN5folly4coro4TaskIiE12promise_type17get_return_objectEv(%4) nothrow : {{.*}} -> ![[IntTask]]
+// CIR: cir.store {{.*}} %[[RetObj]], %[[IntTaskAddr]] : ![[IntTask]]
|
andykaylor
approved these changes
Nov 8, 2025
Contributor
andykaylor
left a comment
There was a problem hiding this comment.
This looks good. I just have some nits about style and possibly some unmarked missing code.
a99949a to
55a5aa5
Compare
git-crd
pushed a commit
to git-crd/crd-llvm-project
that referenced
this pull request
Nov 13, 2025
This PR adds support for emitting the promise declaration in coroutines and obtaining the `get_return_object()`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds support for emitting the promise declaration in coroutines and obtaining the
get_return_object().