Skip to content

Commit 3715d6e

Browse files
author
git apple-llvm automerger
committed
Merge commit '16f5a85fb648' from llvm.org/main into next
2 parents 4943dcc + 16f5a85 commit 3715d6e

File tree

13 files changed

+318
-0
lines changed

13 files changed

+318
-0
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,6 +2341,12 @@ def CIR_FuncOp : CIR_Op<"func", [
23412341
The function linkage information is specified by `linkage`, as defined by
23422342
`GlobalLinkageKind` attribute.
23432343

2344+
A compiler builtin function must be marked as `builtin` for further
2345+
processing when lowering from CIR.
2346+
2347+
The `coroutine` keyword is used to mark a coroutine function, which requires
2348+
at least one `cir.await` instruction to be used in its body.
2349+
23442350
The `lambda` translates to a C++ `operator()` that implements a lambda, this
23452351
allow callsites to make certain assumptions about the real function nature
23462352
when writing analysis.
@@ -2362,11 +2368,22 @@ def CIR_FuncOp : CIR_Op<"func", [
23622368
// Linkage information
23632369
cir.func linkonce_odr @some_method(...)
23642370
```
2371+
// Builtin function
2372+
cir.func builtin @__builtin_coro_end(!cir.ptr<i8>, !cir.bool) -> !cir.bool
2373+
// Coroutine
2374+
cir.func coroutine @_Z10silly_taskv() -> !CoroTask {
2375+
...
2376+
cir.await(...)
2377+
...
2378+
}
2379+
```
23652380
}];
23662381

23672382
let arguments = (ins SymbolNameAttr:$sym_name,
23682383
CIR_VisibilityAttr:$global_visibility,
23692384
TypeAttrOf<CIR_FuncType>:$function_type,
2385+
UnitAttr:$builtin,
2386+
UnitAttr:$coroutine,
23702387
UnitAttr:$lambda,
23712388
UnitAttr:$no_proto,
23722389
UnitAttr:$dso_local,

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@ struct MissingFeatures {
136136
static bool recordZeroInitPadding() { return false; }
137137
static bool zeroSizeRecordMembers() { return false; }
138138

139+
// Coroutines
140+
static bool coroAllocBuiltinCall() { return false; }
141+
static bool coroBeginBuiltinCall() { return false; }
142+
static bool coroEndBuiltinCall() { return false; }
143+
static bool coroSizeBuiltinCall() { return false; }
144+
static bool coroutineFrame() { return false; }
145+
139146
// Various handling of deferred processing in CIRGenModule.
140147
static bool cgmRelease() { return false; }
141148
static bool deferredVtables() { return false; }

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,32 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
428428
return emitUnaryFPBuiltin<cir::ATanOp>(*this, *e);
429429
case Builtin::BI__builtin_elementwise_cos:
430430
return emitUnaryFPBuiltin<cir::CosOp>(*this, *e);
431+
case Builtin::BI__builtin_coro_id:
432+
case Builtin::BI__builtin_coro_promise:
433+
case Builtin::BI__builtin_coro_resume:
434+
case Builtin::BI__builtin_coro_noop:
435+
case Builtin::BI__builtin_coro_destroy:
436+
case Builtin::BI__builtin_coro_done:
437+
case Builtin::BI__builtin_coro_alloc:
438+
case Builtin::BI__builtin_coro_begin:
439+
case Builtin::BI__builtin_coro_end:
440+
case Builtin::BI__builtin_coro_suspend:
441+
case Builtin::BI__builtin_coro_align:
442+
cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_id like NYI");
443+
return getUndefRValue(e->getType());
444+
445+
case Builtin::BI__builtin_coro_frame: {
446+
cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_frame NYI");
447+
assert(!cir::MissingFeatures::coroutineFrame());
448+
return getUndefRValue(e->getType());
449+
}
450+
case Builtin::BI__builtin_coro_free:
451+
case Builtin::BI__builtin_coro_size: {
452+
cgm.errorNYI(e->getSourceRange(),
453+
"BI__builtin_coro_free, BI__builtin_coro_size NYI");
454+
assert(!cir::MissingFeatures::coroSizeBuiltinCall());
455+
return getUndefRValue(e->getType());
456+
}
431457
}
432458

433459
// If this is an alias for a lib function (e.g. __builtin_sin), emit
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//===----- CGCoroutine.cpp - Emit CIR Code for C++ coroutines -------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This contains code dealing with C++ code generation of coroutines.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "CIRGenFunction.h"
14+
#include "mlir/Support/LLVM.h"
15+
#include "clang/AST/StmtCXX.h"
16+
#include "clang/Basic/TargetInfo.h"
17+
#include "clang/CIR/Dialect/IR/CIRTypes.h"
18+
19+
using namespace clang;
20+
using namespace clang::CIRGen;
21+
22+
struct clang::CIRGen::CGCoroData {
23+
// Stores the __builtin_coro_id emitted in the function so that we can supply
24+
// it as the first argument to other builtins.
25+
cir::CallOp coroId = nullptr;
26+
};
27+
28+
// Defining these here allows to keep CGCoroData private to this file.
29+
CIRGenFunction::CGCoroInfo::CGCoroInfo() {}
30+
CIRGenFunction::CGCoroInfo::~CGCoroInfo() {}
31+
32+
static void createCoroData(CIRGenFunction &cgf,
33+
CIRGenFunction::CGCoroInfo &curCoro,
34+
cir::CallOp coroId) {
35+
assert(!curCoro.data && "EmitCoroutineBodyStatement called twice?");
36+
37+
curCoro.data = std::make_unique<CGCoroData>();
38+
curCoro.data->coroId = coroId;
39+
}
40+
41+
cir::CallOp CIRGenFunction::emitCoroIDBuiltinCall(mlir::Location loc,
42+
mlir::Value nullPtr) {
43+
cir::IntType int32Ty = builder.getUInt32Ty();
44+
45+
const TargetInfo &ti = cgm.getASTContext().getTargetInfo();
46+
unsigned newAlign = ti.getNewAlign() / ti.getCharWidth();
47+
48+
mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroId);
49+
50+
cir::FuncOp fnOp;
51+
if (!builtin) {
52+
fnOp = cgm.createCIRBuiltinFunction(
53+
loc, cgm.builtinCoroId,
54+
cir::FuncType::get({int32Ty, VoidPtrTy, VoidPtrTy, VoidPtrTy}, int32Ty),
55+
/*FD=*/nullptr);
56+
assert(fnOp && "should always succeed");
57+
} else {
58+
fnOp = cast<cir::FuncOp>(builtin);
59+
}
60+
61+
return builder.createCallOp(loc, fnOp,
62+
mlir::ValueRange{builder.getUInt32(newAlign, loc),
63+
nullPtr, nullPtr, nullPtr});
64+
}
65+
66+
mlir::LogicalResult
67+
CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
68+
mlir::Location openCurlyLoc = getLoc(s.getBeginLoc());
69+
cir::ConstantOp nullPtrCst = builder.getNullPtr(VoidPtrTy, openCurlyLoc);
70+
71+
auto fn = mlir::cast<cir::FuncOp>(curFn);
72+
fn.setCoroutine(true);
73+
cir::CallOp coroId = emitCoroIDBuiltinCall(openCurlyLoc, nullPtrCst);
74+
createCoroData(*this, curCoro, coroId);
75+
76+
assert(!cir::MissingFeatures::coroAllocBuiltinCall());
77+
78+
assert(!cir::MissingFeatures::coroBeginBuiltinCall());
79+
80+
assert(!cir::MissingFeatures::generateDebugInfo());
81+
return mlir::success();
82+
}

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ void CIRGenFunction::LexicalScope::cleanup() {
342342
cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
343343
CIRGenBuilderTy &builder = cgf.getBuilder();
344344

345+
// If we are on a coroutine, add the coro_end builtin call.
346+
assert(!cir::MissingFeatures::coroEndBuiltinCall());
347+
345348
auto fn = dyn_cast<cir::FuncOp>(cgf.curFn);
346349
assert(fn && "emitReturn from non-function");
347350
if (!fn.getFunctionType().hasVoidReturn()) {

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class LoopOp;
4747

4848
namespace clang::CIRGen {
4949

50+
struct CGCoroData;
51+
5052
class CIRGenFunction : public CIRGenTypeCache {
5153
public:
5254
CIRGenModule &cgm;
@@ -66,6 +68,18 @@ class CIRGenFunction : public CIRGenTypeCache {
6668
/// The compiler-generated variable that holds the return value.
6769
std::optional<mlir::Value> fnRetAlloca;
6870

71+
// Holds coroutine data if the current function is a coroutine. We use a
72+
// wrapper to manage its lifetime, so that we don't have to define CGCoroData
73+
// in this header.
74+
struct CGCoroInfo {
75+
std::unique_ptr<CGCoroData> data;
76+
CGCoroInfo();
77+
~CGCoroInfo();
78+
};
79+
CGCoroInfo curCoro;
80+
81+
bool isCoroutine() const { return curCoro.data != nullptr; }
82+
6983
/// The temporary alloca to hold the return value. This is
7084
/// invalid iff the function has no return value.
7185
Address returnValue = Address::invalid();
@@ -1174,6 +1188,10 @@ class CIRGenFunction : public CIRGenTypeCache {
11741188

11751189
void emitConstructorBody(FunctionArgList &args);
11761190

1191+
mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s);
1192+
cir::CallOp emitCoroEndBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
1193+
cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr);
1194+
11771195
void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
11781196

11791197
void emitDestructorBody(FunctionArgList &args);

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,15 @@ CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
20692069
return func;
20702070
}
20712071

2072+
cir::FuncOp
2073+
CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
2074+
cir::FuncType ty,
2075+
const clang::FunctionDecl *fd) {
2076+
cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
2077+
fnOp.setBuiltin(true);
2078+
return fnOp;
2079+
}
2080+
20722081
mlir::SymbolTable::Visibility
20732082
CIRGenModule::getMLIRVisibility(cir::GlobalOp op) {
20742083
// MLIR doesn't accept public symbols declarations (only

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,13 @@ class CIRGenModule : public CIRGenTypeCache {
475475
cir::FuncType funcType,
476476
const clang::FunctionDecl *funcDecl);
477477

478+
/// Create a CIR function with builtin attribute set.
479+
cir::FuncOp createCIRBuiltinFunction(mlir::Location loc, llvm::StringRef name,
480+
cir::FuncType ty,
481+
const clang::FunctionDecl *fd);
482+
483+
static constexpr const char *builtinCoroId = "__builtin_coro_id";
484+
478485
/// Given a builtin id for a function like "__builtin_fabsf", return a
479486
/// Function* for "fabsf".
480487
cir::FuncOp getBuiltinLibFunction(const FunctionDecl *fd, unsigned builtinID);

clang/lib/CIR/CodeGen/CIRGenStmt.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
197197
case Stmt::SEHLeaveStmtClass:
198198
case Stmt::SYCLKernelCallStmtClass:
199199
case Stmt::CoroutineBodyStmtClass:
200+
return emitCoroutineBody(cast<CoroutineBodyStmt>(*s));
200201
case Stmt::CoreturnStmtClass:
201202
case Stmt::CXXTryStmtClass:
202203
case Stmt::IndirectGotoStmtClass:

clang/lib/CIR/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_clang_library(clangCIR
1414
CIRGenCall.cpp
1515
CIRGenClass.cpp
1616
CIRGenCleanup.cpp
17+
CIRGenCoroutine.cpp
1718
CIRGenCXX.cpp
1819
CIRGenCXXABI.cpp
1920
CIRGenBuiltin.cpp

0 commit comments

Comments
 (0)