Skip to content

Commit f9bf059

Browse files
author
z1.cciauto
committed
merge main into amd-staging
2 parents 5c6c17c + 8ae30a3 commit f9bf059

File tree

125 files changed

+3276
-1131
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+3276
-1131
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/CIRGenExpr.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,8 +1108,9 @@ CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) {
11081108
return lv;
11091109
}
11101110

1111-
LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *e) {
1112-
cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e);
1111+
LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *e,
1112+
llvm::StringRef name) {
1113+
cir::GlobalOp globalOp = cgm.getGlobalForStringLiteral(e, name);
11131114
assert(globalOp.getAlignment() && "expected alignment for string literal");
11141115
unsigned align = *(globalOp.getAlignment());
11151116
mlir::Value addr =
@@ -2372,6 +2373,21 @@ mlir::Value CIRGenFunction::emitScalarConstant(
23722373
return builder.getConstant(getLoc(e->getSourceRange()), constant.getValue());
23732374
}
23742375

2376+
LValue CIRGenFunction::emitPredefinedLValue(const PredefinedExpr *e) {
2377+
const StringLiteral *sl = e->getFunctionName();
2378+
assert(sl != nullptr && "No StringLiteral name in PredefinedExpr");
2379+
auto fn = cast<cir::FuncOp>(curFn);
2380+
StringRef fnName = fn.getName();
2381+
fnName.consume_front("\01");
2382+
std::array<StringRef, 2> nameItems = {
2383+
PredefinedExpr::getIdentKindName(e->getIdentKind()), fnName};
2384+
std::string gvName = llvm::join(nameItems, ".");
2385+
if (isa_and_nonnull<BlockDecl>(curCodeDecl))
2386+
cgm.errorNYI(e->getSourceRange(), "predefined lvalue in block");
2387+
2388+
return emitStringLiteralLValue(sl, gvName);
2389+
}
2390+
23752391
/// An LValue is a candidate for having its loads and stores be made atomic if
23762392
/// we are operating under /volatile:ms *and* the LValue itself is volatile and
23772393
/// performing such an operation can be performed without a libcall.

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 5 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()) {
@@ -815,6 +818,8 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
815818
return emitMemberExpr(cast<MemberExpr>(e));
816819
case Expr::CompoundLiteralExprClass:
817820
return emitCompoundLiteralLValue(cast<CompoundLiteralExpr>(e));
821+
case Expr::PredefinedExprClass:
822+
return emitPredefinedLValue(cast<PredefinedExpr>(e));
818823
case Expr::BinaryOperatorClass:
819824
return emitBinaryOperatorLValue(cast<BinaryOperator>(e));
820825
case Expr::CompoundAssignOperatorClass: {

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 22 additions & 1 deletion
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);
@@ -1279,6 +1297,8 @@ class CIRGenFunction : public CIRGenTypeCache {
12791297
void emitInitializerForField(clang::FieldDecl *field, LValue lhs,
12801298
clang::Expr *init);
12811299

1300+
LValue emitPredefinedLValue(const PredefinedExpr *e);
1301+
12821302
mlir::Value emitPromotedComplexExpr(const Expr *e, QualType promotionType);
12831303

12841304
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType);
@@ -1473,7 +1493,8 @@ class CIRGenFunction : public CIRGenTypeCache {
14731493

14741494
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult);
14751495

1476-
LValue emitStringLiteralLValue(const StringLiteral *e);
1496+
LValue emitStringLiteralLValue(const StringLiteral *e,
1497+
llvm::StringRef name = ".str");
14771498

14781499
mlir::LogicalResult emitSwitchBody(const clang::Stmt *s);
14791500
mlir::LogicalResult emitSwitchCase(const clang::SwitchCase &s,

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,32 +1343,36 @@ cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
13431343

13441344
mlir::Attribute c = getConstantArrayFromStringLiteral(s);
13451345

1346-
if (getLangOpts().WritableStrings) {
1347-
errorNYI(s->getSourceRange(),
1348-
"getGlobalForStringLiteral: Writable strings");
1349-
}
1350-
1351-
// Mangle the string literal if that's how the ABI merges duplicate strings.
1352-
// Don't do it if they are writable, since we don't want writes in one TU to
1353-
// affect strings in another.
1354-
if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
1355-
!getLangOpts().WritableStrings) {
1356-
errorNYI(s->getSourceRange(),
1357-
"getGlobalForStringLiteral: mangle string literals");
1358-
}
1359-
1360-
// Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
1361-
// we need to do that explicitly.
1362-
std::string uniqueName = getUniqueGlobalName(name.str());
1363-
mlir::Location loc = getLoc(s->getSourceRange());
1364-
auto typedC = llvm::cast<mlir::TypedAttr>(c);
1365-
cir::GlobalOp gv =
1366-
generateStringLiteral(loc, typedC, cir::GlobalLinkageKind::PrivateLinkage,
1367-
*this, uniqueName, alignment);
1368-
setDSOLocal(static_cast<mlir::Operation *>(gv));
1346+
cir::GlobalOp gv;
1347+
if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {
1348+
gv = constantStringMap[c];
1349+
// The bigger alignment always wins.
1350+
if (!gv.getAlignment() ||
1351+
uint64_t(alignment.getQuantity()) > *gv.getAlignment())
1352+
gv.setAlignmentAttr(getSize(alignment));
1353+
} else {
1354+
// Mangle the string literal if that's how the ABI merges duplicate strings.
1355+
// Don't do it if they are writable, since we don't want writes in one TU to
1356+
// affect strings in another.
1357+
if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
1358+
!getLangOpts().WritableStrings) {
1359+
errorNYI(s->getSourceRange(),
1360+
"getGlobalForStringLiteral: mangle string literals");
1361+
}
13691362

1370-
assert(!cir::MissingFeatures::sanitizers());
1363+
// Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
1364+
// we need to do that explicitly.
1365+
std::string uniqueName = getUniqueGlobalName(name.str());
1366+
mlir::Location loc = getLoc(s->getSourceRange());
1367+
auto typedC = llvm::cast<mlir::TypedAttr>(c);
1368+
gv = generateStringLiteral(loc, typedC,
1369+
cir::GlobalLinkageKind::PrivateLinkage, *this,
1370+
uniqueName, alignment);
1371+
setDSOLocal(static_cast<mlir::Operation *>(gv));
1372+
constantStringMap[c] = gv;
13711373

1374+
assert(!cir::MissingFeatures::sanitizers());
1375+
}
13721376
return gv;
13731377
}
13741378

@@ -2065,6 +2069,15 @@ CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
20652069
return func;
20662070
}
20672071

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+
20682081
mlir::SymbolTable::Visibility
20692082
CIRGenModule::getMLIRVisibility(cir::GlobalOp op) {
20702083
// MLIR doesn't accept public symbols declarations (only

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ class CIRGenModule : public CIRGenTypeCache {
274274
llvm_unreachable("unknown visibility!");
275275
}
276276

277+
llvm::DenseMap<mlir::Attribute, cir::GlobalOp> constantStringMap;
278+
277279
/// Return a constant array for the given string.
278280
mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e);
279281

@@ -473,6 +475,13 @@ class CIRGenModule : public CIRGenTypeCache {
473475
cir::FuncType funcType,
474476
const clang::FunctionDecl *funcDecl);
475477

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+
476485
/// Given a builtin id for a function like "__builtin_fabsf", return a
477486
/// Function* for "fabsf".
478487
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:

0 commit comments

Comments
 (0)