Skip to content

Commit 8f90716

Browse files
authored
[CIR] Upstream AddressSpace conversions support (#161212)
related: #160386 Add support for address space conversions in CIR. - Added `createAddrSpaceCast` methods to `CIRBaseBuilderTy` to handle address space conversions - Implemented address space conversion handling in `emitCastLValue` and `VisitCastExpr` - Added `performAddrSpaceCast` method to `TargetCIRGenInfo` for target-specific address space casting - Added `getLangTempAllocaAddressSpace` to `CIRGenModule` to get the language-specific address space for temporary allocations - Added a test file `address-space-conversion.cpp` to verify address space conversion functionality
1 parent 18f29a5 commit 8f90716

File tree

16 files changed

+290
-8
lines changed

16 files changed

+290
-8
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,15 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
465465
return createCompare(ptr.getLoc(), cir::CmpOpKind::eq, ptr, nullPtr);
466466
}
467467

468+
mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
469+
mlir::Type newTy) {
470+
return createCast(loc, cir::CastKind::address_space, src, newTy);
471+
}
472+
473+
mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
474+
return createAddrSpaceCast(src.getLoc(), src, newTy);
475+
}
476+
468477
//===--------------------------------------------------------------------===//
469478
// Binary Operators
470479
//===--------------------------------------------------------------------===//

clang/include/clang/CIR/Dialect/IR/CIRTypes.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#ifndef CLANG_CIR_DIALECT_IR_CIRTYPES_H
1414
#define CLANG_CIR_DIALECT_IR_CIRTYPES_H
1515

16+
#include "mlir/IR/Attributes.h"
1617
#include "mlir/IR/BuiltinAttributes.h"
18+
#include "mlir/IR/MLIRContext.h"
1719
#include "mlir/IR/Types.h"
1820
#include "mlir/Interfaces/DataLayoutInterfaces.h"
1921
#include "clang/Basic/AddressSpaces.h"
@@ -38,6 +40,15 @@ bool isValidFundamentalIntWidth(unsigned width);
3840
/// void, or abstract types.
3941
bool isSized(mlir::Type ty);
4042

43+
//===----------------------------------------------------------------------===//
44+
// AddressSpace helpers
45+
//===----------------------------------------------------------------------===//
46+
cir::TargetAddressSpaceAttr toCIRTargetAddressSpace(mlir::MLIRContext &context,
47+
clang::LangAS langAS);
48+
49+
bool isMatchingAddressSpace(cir::TargetAddressSpaceAttr cirAS,
50+
clang::LangAS as);
51+
4152
} // namespace cir
4253

4354
//===----------------------------------------------------------------------===//

clang/lib/CIR/CodeGen/Address.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616

1717
#include "mlir/IR/Value.h"
1818
#include "clang/AST/CharUnits.h"
19+
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
1920
#include "clang/CIR/Dialect/IR/CIRTypes.h"
2021
#include "clang/CIR/MissingFeatures.h"
2122
#include "llvm/ADT/PointerIntPair.h"
23+
#include "llvm/Support/Casting.h"
2224

2325
namespace clang::CIRGen {
2426

@@ -114,6 +116,11 @@ class Address {
114116
return elementType;
115117
}
116118

119+
cir::TargetAddressSpaceAttr getAddressSpace() const {
120+
auto ptrTy = mlir::dyn_cast<cir::PointerType>(getType());
121+
return ptrTy.getAddrSpace();
122+
}
123+
117124
clang::CharUnits getAlignment() const { return alignment; }
118125

119126
/// Get the operation which defines this address.

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "CIRGenCall.h"
15-
#include "CIRGenConstantEmitter.h"
1615
#include "CIRGenFunction.h"
1716
#include "CIRGenModule.h"
1817
#include "CIRGenValue.h"
@@ -22,6 +21,7 @@
2221
#include "clang/AST/Expr.h"
2322
#include "clang/AST/GlobalDecl.h"
2423
#include "clang/Basic/Builtins.h"
24+
#include "clang/CIR/Dialect/IR/CIRTypes.h"
2525
#include "clang/CIR/MissingFeatures.h"
2626
#include "llvm/Support/ErrorHandling.h"
2727

@@ -193,11 +193,16 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
193193
// default (e.g. in C / C++ auto vars are in the generic address space). At
194194
// the AST level this is handled within CreateTempAlloca et al., but for the
195195
// builtin / dynamic alloca we have to handle it here.
196-
assert(!cir::MissingFeatures::addressSpace());
196+
197+
if (!cir::isMatchingAddressSpace(
198+
getCIRAllocaAddressSpace(),
199+
e->getType()->getPointeeType().getAddressSpace())) {
200+
cgm.errorNYI(e->getSourceRange(), "Non-default address space for alloca");
201+
}
197202

198203
// Bitcast the alloca to the expected type.
199-
return RValue::get(
200-
builder.createBitcast(allocaAddr, builder.getVoidPtrTy()));
204+
return RValue::get(builder.createBitcast(
205+
allocaAddr, builder.getVoidPtrTy(getCIRAllocaAddressSpace())));
201206
}
202207

203208
case Builtin::BIcos:

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222
#include "clang/AST/Decl.h"
2323
#include "clang/AST/Expr.h"
2424
#include "clang/AST/ExprCXX.h"
25+
#include "clang/Basic/AddressSpaces.h"
26+
#include "clang/Basic/TargetInfo.h"
27+
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
2528
#include "clang/CIR/Dialect/IR/CIRDialect.h"
29+
#include "clang/CIR/Dialect/IR/CIRTypes.h"
2630
#include "clang/CIR/MissingFeatures.h"
2731
#include <optional>
2832

@@ -1205,7 +1209,6 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
12051209
case CK_AtomicToNonAtomic:
12061210
case CK_ToUnion:
12071211
case CK_BaseToDerived:
1208-
case CK_AddressSpaceConversion:
12091212
case CK_ObjCObjectLValueCast:
12101213
case CK_VectorSplat:
12111214
case CK_ConstructorConversion:
@@ -1219,7 +1222,27 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
12191222

12201223
return {};
12211224
}
1225+
case CK_AddressSpaceConversion: {
1226+
LValue lv = emitLValue(e->getSubExpr());
1227+
QualType destTy = getContext().getPointerType(e->getType());
1228+
1229+
clang::LangAS srcLangAS = e->getSubExpr()->getType().getAddressSpace();
1230+
cir::TargetAddressSpaceAttr srcAS;
1231+
if (clang::isTargetAddressSpace(srcLangAS))
1232+
srcAS = cir::toCIRTargetAddressSpace(getMLIRContext(), srcLangAS);
1233+
else
1234+
cgm.errorNYI(
1235+
e->getSourceRange(),
1236+
"emitCastLValue: address space conversion from unknown address "
1237+
"space");
12221238

1239+
mlir::Value v = getTargetHooks().performAddrSpaceCast(
1240+
*this, lv.getPointer(), srcAS, convertType(destTy));
1241+
1242+
return makeAddrLValue(Address(v, convertTypeForMem(e->getType()),
1243+
lv.getAddress().getAlignment()),
1244+
e->getType(), lv.getBaseInfo());
1245+
}
12231246
case CK_LValueBitCast: {
12241247
// This must be a reinterpret_cast (or c-style equivalent).
12251248
const auto *ce = cast<ExplicitCastExpr>(e);
@@ -2233,6 +2256,8 @@ Address CIRGenFunction::createTempAllocaWithoutCast(
22332256

22342257
/// This creates a alloca and inserts it into the entry block. The alloca is
22352258
/// casted to default address space if necessary.
2259+
// TODO(cir): Implement address space casting to match classic codegen's
2260+
// CreateTempAlloca behavior with DestLangAS parameter
22362261
Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,
22372262
mlir::Location loc, const Twine &name,
22382263
mlir::Value arraySize,
@@ -2247,7 +2272,21 @@ Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,
22472272
// be different from the type defined by the language. For example,
22482273
// in C++ the auto variables are in the default address space. Therefore
22492274
// cast alloca to the default address space when necessary.
2250-
assert(!cir::MissingFeatures::addressSpace());
2275+
2276+
LangAS allocaAS = alloca.getAddressSpace()
2277+
? clang::getLangASFromTargetAS(
2278+
alloca.getAddressSpace().getValue().getUInt())
2279+
: clang::LangAS::Default;
2280+
LangAS dstTyAS = clang::LangAS::Default;
2281+
if (getCIRAllocaAddressSpace()) {
2282+
dstTyAS = clang::getLangASFromTargetAS(
2283+
getCIRAllocaAddressSpace().getValue().getUInt());
2284+
}
2285+
2286+
if (dstTyAS != allocaAS) {
2287+
getTargetHooks().performAddrSpaceCast(*this, v, getCIRAllocaAddressSpace(),
2288+
builder.getPointerTo(ty, dstTyAS));
2289+
}
22512290
return Address(v, ty, align);
22522291
}
22532292

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "clang/AST/Expr.h"
1717
#include "clang/AST/StmtVisitor.h"
18+
#include "clang/CIR/Dialect/IR/CIRTypes.h"
1819
#include "clang/CIR/MissingFeatures.h"
1920

2021
#include "mlir/IR/Location.h"
@@ -91,6 +92,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
9192
//===--------------------------------------------------------------------===//
9293
// Utilities
9394
//===--------------------------------------------------------------------===//
95+
mlir::Type convertType(QualType ty) { return cgf.convertType(ty); }
9496

9597
mlir::Value emitComplexToScalarConversion(mlir::Location loc,
9698
mlir::Value value, CastKind kind,
@@ -1888,6 +1890,35 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
18881890
return cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()),
18891891
src, dstTy);
18901892
}
1893+
case CK_AddressSpaceConversion: {
1894+
Expr::EvalResult result;
1895+
if (subExpr->EvaluateAsRValue(result, cgf.getContext()) &&
1896+
result.Val.isNullPointer()) {
1897+
// If e has side effect, it is emitted even if its final result is a
1898+
// null pointer. In that case, a DCE pass should be able to
1899+
// eliminate the useless instructions emitted during translating E.
1900+
if (result.HasSideEffects)
1901+
Visit(subExpr);
1902+
return cgf.cgm.emitNullConstant(destTy,
1903+
cgf.getLoc(subExpr->getExprLoc()));
1904+
}
1905+
1906+
clang::QualType srcTy = subExpr->IgnoreImpCasts()->getType();
1907+
if (srcTy->isPointerType() || srcTy->isReferenceType())
1908+
srcTy = srcTy->getPointeeType();
1909+
1910+
clang::LangAS srcLangAS = srcTy.getAddressSpace();
1911+
cir::TargetAddressSpaceAttr subExprAS;
1912+
if (clang::isTargetAddressSpace(srcLangAS))
1913+
subExprAS = cir::toCIRTargetAddressSpace(cgf.getMLIRContext(), srcLangAS);
1914+
else
1915+
cgf.cgm.errorNYI(subExpr->getSourceRange(),
1916+
"non-target address space conversion");
1917+
// Since target may map different address spaces in AST to the same address
1918+
// space, an address space conversion may end up as a bitcast.
1919+
return cgf.cgm.getTargetCIRGenInfo().performAddrSpaceCast(
1920+
cgf, Visit(subExpr), subExprAS, convertType(destTy));
1921+
}
18911922

18921923
case CK_AtomicToNonAtomic: {
18931924
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
@@ -222,6 +222,10 @@ class CIRGenFunction : public CIRGenTypeCache {
222222
const TargetInfo &getTarget() const { return cgm.getTarget(); }
223223
mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }
224224

225+
const TargetCIRGenInfo &getTargetHooks() const {
226+
return cgm.getTargetCIRGenInfo();
227+
}
228+
225229
// ---------------------
226230
// Opaque value handling
227231
// ---------------------

clang/lib/CIR/CodeGen/CIRGenModule.cpp

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

1427+
// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
1428+
LangAS CIRGenModule::getLangTempAllocaAddressSpace() const {
1429+
if (getLangOpts().OpenCL)
1430+
return LangAS::opencl_private;
1431+
1432+
// For temporaries inside functions, CUDA treats them as normal variables.
1433+
// LangAS::cuda_device, on the other hand, is reserved for those variables
1434+
// explicitly marked with __device__.
1435+
if (getLangOpts().CUDAIsDevice)
1436+
return LangAS::Default;
1437+
1438+
if (getLangOpts().SYCLIsDevice ||
1439+
(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice))
1440+
errorNYI("SYCL or OpenMP temp address space");
1441+
return LangAS::Default;
1442+
}
1443+
14271444
void CIRGenModule::emitExplicitCastExprType(const ExplicitCastExpr *e,
14281445
CIRGenFunction *cgf) {
14291446
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
@@ -297,6 +297,12 @@ class CIRGenModule : public CIRGenTypeCache {
297297
getAddrOfConstantStringFromLiteral(const StringLiteral *s,
298298
llvm::StringRef name = ".str");
299299

300+
/// Returns the address space for temporary allocations in the language. This
301+
/// ensures that the allocated variable's address space matches the
302+
/// expectations of the AST, rather than using the target's allocation address
303+
/// space, which may lead to type mismatches in other parts of the IR.
304+
LangAS getLangTempAllocaAddressSpace() const;
305+
300306
/// Set attributes which are common to any form of a global definition (alias,
301307
/// Objective-C method, function, global variable).
302308
///

clang/lib/CIR/CodeGen/CIRGenTypes.cpp

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

0 commit comments

Comments
 (0)