Skip to content

Commit e446b47

Browse files
committed
[CIR] Upstream AddressSpace casting support
1 parent 1d29065 commit e446b47

File tree

11 files changed

+195
-18
lines changed

11 files changed

+195
-18
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,15 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
424424
return createBitcast(src, getPointerTo(newPointeeTy));
425425
}
426426

427+
mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
428+
mlir::Type newTy) {
429+
return createCast(loc, cir::CastKind::address_space, src, newTy);
430+
}
431+
432+
mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
433+
return createAddrSpaceCast(src.getLoc(), src, newTy);
434+
}
435+
427436
//===--------------------------------------------------------------------===//
428437
// Binary Operators
429438
//===--------------------------------------------------------------------===//

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,24 @@ static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const CallExpr *e,
5858
return RValue::get(result);
5959
}
6060

61+
// Initialize the alloca with the given size and alignment according to the lang
62+
// opts. Supporting only the trivial non-initialization for now.
63+
static void initializeAlloca(CIRGenFunction &CGF,
64+
[[maybe_unused]] mlir::Value AllocaAddr,
65+
[[maybe_unused]] mlir::Value Size,
66+
[[maybe_unused]] CharUnits AlignmentInBytes) {
67+
68+
switch (CGF.getLangOpts().getTrivialAutoVarInit()) {
69+
case LangOptions::TrivialAutoVarInitKind::Uninitialized:
70+
// Nothing to initialize.
71+
return;
72+
case LangOptions::TrivialAutoVarInitKind::Zero:
73+
case LangOptions::TrivialAutoVarInitKind::Pattern:
74+
assert(false && "unexpected trivial auto var init kind NYI");
75+
return;
76+
}
77+
}
78+
6179
RValue CIRGenFunction::emitRotate(const CallExpr *e, bool isRotateLeft) {
6280
mlir::Value input = emitScalarExpr(e->getArg(0));
6381
mlir::Value amount = emitScalarExpr(e->getArg(1));
@@ -172,28 +190,21 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
172190
builder.getUInt8Ty(), "bi_alloca", suitableAlignmentInBytes, size);
173191

174192
// Initialize the allocated buffer if required.
175-
if (builtinID != Builtin::BI__builtin_alloca_uninitialized) {
176-
// Initialize the alloca with the given size and alignment according to
177-
// the lang opts. Only the trivial non-initialization is supported for
178-
// now.
179-
180-
switch (getLangOpts().getTrivialAutoVarInit()) {
181-
case LangOptions::TrivialAutoVarInitKind::Uninitialized:
182-
// Nothing to initialize.
183-
break;
184-
case LangOptions::TrivialAutoVarInitKind::Zero:
185-
case LangOptions::TrivialAutoVarInitKind::Pattern:
186-
cgm.errorNYI("trivial auto var init");
187-
break;
188-
}
189-
}
193+
if (builtinID != Builtin::BI__builtin_alloca_uninitialized)
194+
initializeAlloca(*this, allocaAddr, size, suitableAlignmentInBytes);
190195

191196
// An alloca will always return a pointer to the alloca (stack) address
192197
// space. This address space need not be the same as the AST / Language
193198
// default (e.g. in C / C++ auto vars are in the generic address space). At
194199
// the AST level this is handled within CreateTempAlloca et al., but for the
195200
// builtin / dynamic alloca we have to handle it here.
196201
assert(!cir::MissingFeatures::addressSpace());
202+
cir::AddressSpace aas = getCIRAllocaAddressSpace();
203+
cir::AddressSpace eas = cir::toCIRAddressSpace(
204+
e->getType()->getPointeeType().getAddressSpace());
205+
if (eas != aas) {
206+
assert(false && "Non-default address space for alloca NYI");
207+
}
197208

198209
// Bitcast the alloca to the expected type.
199210
return RValue::get(

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,19 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
11901190
case CK_Dynamic:
11911191
case CK_ToUnion:
11921192
case CK_BaseToDerived:
1193-
case CK_AddressSpaceConversion:
1193+
case CK_AddressSpaceConversion: {
1194+
LValue lv = emitLValue(e->getSubExpr());
1195+
QualType destTy = getContext().getPointerType(e->getType());
1196+
cir::AddressSpace srcAS =
1197+
cir::toCIRAddressSpace(e->getSubExpr()->getType().getAddressSpace());
1198+
cir::AddressSpace destAS =
1199+
cir::toCIRAddressSpace(e->getType().getAddressSpace());
1200+
mlir::Value V = getTargetHooks().performAddrSpaceCast(
1201+
*this, lv.getPointer(), srcAS, destAS, convertType(destTy));
1202+
return makeAddrLValue(Address(V, convertTypeForMem(e->getType()),
1203+
lv.getAddress().getAlignment()),
1204+
e->getType(), lv.getBaseInfo());
1205+
}
11941206
case CK_ObjCObjectLValueCast:
11951207
case CK_VectorSplat:
11961208
case CK_ConstructorConversion:
@@ -2283,7 +2295,10 @@ Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,
22832295
// be different from the type defined by the language. For example,
22842296
// in C++ the auto variables are in the default address space. Therefore
22852297
// cast alloca to the default address space when necessary.
2286-
assert(!cir::MissingFeatures::addressSpace());
2298+
if (auto astAS = cir::toCIRAddressSpace(cgm.getLangTempAllocaAddressSpace());
2299+
getCIRAllocaAddressSpace() != astAS) {
2300+
llvm_unreachable("Requires address space cast which is NYI");
2301+
}
22872302
return Address(v, ty, align);
22882303
}
22892304

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
8787
//===--------------------------------------------------------------------===//
8888
// Utilities
8989
//===--------------------------------------------------------------------===//
90+
mlir::Type convertType(QualType ty) { return cgf.convertType(ty); }
9091

9192
mlir::Value emitComplexToScalarConversion(mlir::Location loc,
9293
mlir::Value value, CastKind kind,
@@ -1862,6 +1863,27 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
18621863
return cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()),
18631864
src, dstTy);
18641865
}
1866+
case CK_AddressSpaceConversion: {
1867+
Expr::EvalResult result;
1868+
if (subExpr->EvaluateAsRValue(result, cgf.getContext()) &&
1869+
result.Val.isNullPointer()) {
1870+
// If E has side effect, it is emitted even if its final result is a
1871+
// null pointer. In that case, a DCE pass should be able to
1872+
// eliminate the useless instructions emitted during translating E.
1873+
if (result.HasSideEffects)
1874+
Visit(subExpr);
1875+
return cgf.cgm.emitNullConstant(destTy,
1876+
cgf.getLoc(subExpr->getExprLoc()));
1877+
}
1878+
// Since target may map different address spaces in AST to the same address
1879+
// space, an address space conversion may end up as a bitcast.
1880+
cir::AddressSpace srcAS = cir::toCIRAddressSpace(
1881+
subExpr->getType()->getPointeeType().getAddressSpace());
1882+
cir::AddressSpace destAS =
1883+
cir::toCIRAddressSpace(destTy->getPointeeType().getAddressSpace());
1884+
return cgf.cgm.getTargetCIRGenInfo().performAddrSpaceCast(
1885+
cgf, Visit(subExpr), srcAS, destAS, convertType(destTy));
1886+
}
18651887

18661888
case CK_AtomicToNonAtomic: {
18671889
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ class CIRGenFunction : public CIRGenTypeCache {
160160
const TargetInfo &getTarget() const { return cgm.getTarget(); }
161161
mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
162162

163+
const TargetCIRGenInfo &getTargetHooks() const {
164+
return cgm.getTargetCIRGenInfo();
165+
}
166+
163167
// ---------------------
164168
// Opaque value handling
165169
// ---------------------

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,23 @@ CIRGenModule::getAddrOfConstantStringFromLiteral(const StringLiteral *s,
13631363
return builder.getGlobalViewAttr(ptrTy, gv);
13641364
}
13651365

1366+
// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
1367+
LangAS CIRGenModule::getLangTempAllocaAddressSpace() const {
1368+
if (getLangOpts().OpenCL)
1369+
return LangAS::opencl_private;
1370+
1371+
// For temporaries inside functions, CUDA treats them as normal variables.
1372+
// LangAS::cuda_device, on the other hand, is reserved for those variables
1373+
// explicitly marked with __device__.
1374+
if (getLangOpts().CUDAIsDevice)
1375+
return LangAS::Default;
1376+
1377+
if (getLangOpts().SYCLIsDevice ||
1378+
(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice))
1379+
llvm_unreachable("NYI");
1380+
return LangAS::Default;
1381+
}
1382+
13661383
void CIRGenModule::emitExplicitCastExprType(const ExplicitCastExpr *e,
13671384
CIRGenFunction *cgf) {
13681385
if (cgf && e->getType()->isVariablyModifiedType())

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,12 @@ class CIRGenModule : public CIRGenTypeCache {
270270
getAddrOfConstantStringFromLiteral(const StringLiteral *s,
271271
llvm::StringRef name = ".str");
272272

273+
/// Returns the address space for temporary allocations in the language. This
274+
/// ensures that the allocated variable's address space matches the
275+
/// expectations of the AST, rather than using the target's allocation address
276+
/// space, which may lead to type mismatches in other parts of the IR.
277+
LangAS getLangTempAllocaAddressSpace() const;
278+
273279
/// Set attributes which are common to any form of a global definition (alias,
274280
/// Objective-C method, function, global variable).
275281
///

clang/lib/CIR/CodeGen/CIRGenTypes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
405405
const ReferenceType *refTy = cast<ReferenceType>(ty);
406406
QualType elemTy = refTy->getPointeeType();
407407
auto pointeeType = convertTypeForMem(elemTy);
408-
resultType = builder.getPointerTo(pointeeType);
408+
resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
409409
assert(resultType && "Cannot get pointer type?");
410410
break;
411411
}

clang/lib/CIR/CodeGen/TargetInfo.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "TargetInfo.h"
22
#include "ABIInfo.h"
3+
#include "CIRGenFunction.h"
4+
#include "clang/CIR/Dialect/IR/CIRDialect.h"
35

46
using namespace clang;
57
using namespace clang::CIRGen;
@@ -68,3 +70,14 @@ bool TargetCIRGenInfo::isNoProtoCallVariadic(
6870
// For everything else, we just prefer false unless we opt out.
6971
return false;
7072
}
73+
74+
mlir::Value TargetCIRGenInfo::performAddrSpaceCast(
75+
CIRGenFunction &cgf, mlir::Value src, cir::AddressSpace srcAS,
76+
cir::AddressSpace destAS, mlir::Type destTy, bool isNonNull) const {
77+
// Since target may map different address spaces in AST to the same address
78+
// space, an address space conversion may end up as a bitcast.
79+
if (cir::GlobalOp globalOp = src.getDefiningOp<cir::GlobalOp>())
80+
llvm_unreachable("Global ops addrspace cast NYI");
81+
// Try to preserve the source's name to make IR more readable.
82+
return cgf.getBuilder().createAddrSpaceCast(src, destTy);
83+
}

clang/lib/CIR/CodeGen/TargetInfo.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ class TargetCIRGenInfo {
4545
/// Returns ABI info helper for the target.
4646
const ABIInfo &getABIInfo() const { return *info; }
4747

48+
/// Perform address space cast of an expression of pointer type.
49+
/// \param V is the value to be casted to another address space.
50+
/// \param SrcAddr is the CIR address space of \p V.
51+
/// \param DestAddr is the targeted CIR address space.
52+
/// \param DestTy is the destination pointer type.
53+
/// \param IsNonNull is the flag indicating \p V is known to be non null.
54+
virtual mlir::Value performAddrSpaceCast(CIRGenFunction &cgf, mlir::Value v,
55+
cir::AddressSpace srcAS,
56+
cir::AddressSpace destAS,
57+
mlir::Type destTy,
58+
bool isNonNull = false) const;
59+
4860
/// Determine whether a call to an unprototyped functions under
4961
/// the given calling convention should use the variadic
5062
/// convention or the non-variadic convention.

0 commit comments

Comments
 (0)