Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,15 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return createCompare(ptr.getLoc(), cir::CmpOpKind::eq, ptr, nullPtr);
}

mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
mlir::Type newTy) {
return createCast(loc, cir::CastKind::address_space, src, newTy);
}

mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
return createAddrSpaceCast(src.getLoc(), src, newTy);
}

//===--------------------------------------------------------------------===//
// Binary Operators
//===--------------------------------------------------------------------===//
Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#ifndef CLANG_CIR_DIALECT_IR_CIRTYPES_H
#define CLANG_CIR_DIALECT_IR_CIRTYPES_H

#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/Types.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include "clang/Basic/AddressSpaces.h"
Expand All @@ -38,6 +40,15 @@ bool isValidFundamentalIntWidth(unsigned width);
/// void, or abstract types.
bool isSized(mlir::Type ty);

//===----------------------------------------------------------------------===//
// AddressSpace helpers
//===----------------------------------------------------------------------===//
cir::TargetAddressSpaceAttr toCIRTargetAddressSpace(mlir::MLIRContext &context,
clang::LangAS langAS);

bool isMatchingAddressSpace(cir::TargetAddressSpaceAttr cirAS,
clang::LangAS as);

} // namespace cir

//===----------------------------------------------------------------------===//
Expand Down
16 changes: 9 additions & 7 deletions clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//

#include "CIRGenCall.h"
#include "CIRGenConstantEmitter.h"
#include "CIRGenFunction.h"
#include "CIRGenModule.h"
#include "CIRGenValue.h"
Expand All @@ -22,6 +21,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/Basic/Builtins.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/Support/ErrorHandling.h"

Expand Down Expand Up @@ -173,9 +173,6 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,

// Initialize the allocated buffer if required.
if (builtinID != Builtin::BI__builtin_alloca_uninitialized) {
// Initialize the alloca with the given size and alignment according to
// the lang opts. Only the trivial non-initialization is supported for
// now.

switch (getLangOpts().getTrivialAutoVarInit()) {
case LangOptions::TrivialAutoVarInitKind::Uninitialized:
Expand All @@ -193,11 +190,16 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
// default (e.g. in C / C++ auto vars are in the generic address space). At
// the AST level this is handled within CreateTempAlloca et al., but for the
// builtin / dynamic alloca we have to handle it here.
assert(!cir::MissingFeatures::addressSpace());

if (!cir::isMatchingAddressSpace(
getCIRAllocaAddressSpace(),
e->getType()->getPointeeType().getAddressSpace())) {
cgm.errorNYI(e->getSourceRange(), "Non-default address space for alloca");
}

// Bitcast the alloca to the expected type.
return RValue::get(
builder.createBitcast(allocaAddr, builder.getVoidPtrTy()));
return RValue::get(builder.createBitcast(
allocaAddr, builder.getVoidPtrTy(getCIRAllocaAddressSpace())));
}

case Builtin::BIcos:
Expand Down
36 changes: 34 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include <optional>

Expand Down Expand Up @@ -1197,7 +1201,6 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
case CK_AtomicToNonAtomic:
case CK_ToUnion:
case CK_BaseToDerived:
case CK_AddressSpaceConversion:
case CK_ObjCObjectLValueCast:
case CK_VectorSplat:
case CK_ConstructorConversion:
Expand All @@ -1211,7 +1214,23 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {

return {};
}
case CK_AddressSpaceConversion: {
LValue lv = emitLValue(e->getSubExpr());
QualType destTy = getContext().getPointerType(e->getType());

clang::LangAS srcLangAS = e->getSubExpr()->getType().getAddressSpace();
cir::TargetAddressSpaceAttr srcAS;
if (clang::isTargetAddressSpace(srcLangAS)) {
srcAS = cir::toCIRTargetAddressSpace(getMLIRContext(), srcLangAS);
}

mlir::Value v = getTargetHooks().performAddrSpaceCast(
*this, lv.getPointer(), srcAS, convertType(destTy));

return makeAddrLValue(Address(v, convertTypeForMem(e->getType()),
lv.getAddress().getAlignment()),
e->getType(), lv.getBaseInfo());
}
case CK_LValueBitCast: {
// This must be a reinterpret_cast (or c-style equivalent).
const auto *ce = cast<ExplicitCastExpr>(e);
Expand Down Expand Up @@ -2275,6 +2294,8 @@ Address CIRGenFunction::createTempAllocaWithoutCast(

/// This creates a alloca and inserts it into the entry block. The alloca is
/// casted to default address space if necessary.
// TODO(cir): Implement address space casting to match classic codegen's
// CreateTempAlloca behavior with DestLangAS parameter
Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,
mlir::Location loc, const Twine &name,
mlir::Value arraySize,
Expand All @@ -2289,7 +2310,18 @@ Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,
// be different from the type defined by the language. For example,
// in C++ the auto variables are in the default address space. Therefore
// cast alloca to the default address space when necessary.
assert(!cir::MissingFeatures::addressSpace());

LangAS allocaAS = cgm.getLangTempAllocaAddressSpace();
LangAS dstTyAS = clang::LangAS::Default;
if (getCIRAllocaAddressSpace()) {
dstTyAS = clang::getLangASFromTargetAS(
getCIRAllocaAddressSpace().getValue().getUInt());
}

if (dstTyAS != allocaAS) {
getTargetHooks().performAddrSpaceCast(*this, v, getCIRAllocaAddressSpace(),
builder.getPointerTo(ty, dstTyAS));
}
return Address(v, ty, align);
}

Expand Down
25 changes: 25 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "clang/AST/Expr.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"

#include "mlir/IR/Location.h"
Expand Down Expand Up @@ -87,6 +88,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
//===--------------------------------------------------------------------===//
// Utilities
//===--------------------------------------------------------------------===//
mlir::Type convertType(QualType ty) { return cgf.convertType(ty); }

mlir::Value emitComplexToScalarConversion(mlir::Location loc,
mlir::Value value, CastKind kind,
Expand Down Expand Up @@ -1871,6 +1873,29 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
return cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()),
src, dstTy);
}
case CK_AddressSpaceConversion: {
Expr::EvalResult result;
if (subExpr->EvaluateAsRValue(result, cgf.getContext()) &&
result.Val.isNullPointer()) {
// If e has side effect, it is emitted even if its final result is a
// null pointer. In that case, a DCE pass should be able to
// eliminate the useless instructions emitted during translating E.
if (result.HasSideEffects)
Visit(subExpr);
return cgf.cgm.emitNullConstant(destTy,
cgf.getLoc(subExpr->getExprLoc()));
}

clang::LangAS srcLangAS = subExpr->getType().getAddressSpace();
cir::TargetAddressSpaceAttr subExprAS;
if (clang::isTargetAddressSpace(srcLangAS)) {
subExprAS = cir::toCIRTargetAddressSpace(cgf.getMLIRContext(), srcLangAS);
}
// Since target may map different address spaces in AST to the same address
// space, an address space conversion may end up as a bitcast.
return cgf.cgm.getTargetCIRGenInfo().performAddrSpaceCast(
cgf, Visit(subExpr), subExprAS, convertType(destTy));
}

case CK_AtomicToNonAtomic: {
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ class CIRGenFunction : public CIRGenTypeCache {
const TargetInfo &getTarget() const { return cgm.getTarget(); }
mlir::MLIRContext &getMLIRContext() { return cgm.getMLIRContext(); }

const TargetCIRGenInfo &getTargetHooks() const {
return cgm.getTargetCIRGenInfo();
}

// ---------------------
// Opaque value handling
// ---------------------
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1424,6 +1424,23 @@ CIRGenModule::getAddrOfConstantStringFromLiteral(const StringLiteral *s,
return builder.getGlobalViewAttr(ptrTy, gv);
}

// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
LangAS CIRGenModule::getLangTempAllocaAddressSpace() const {
if (getLangOpts().OpenCL)
return LangAS::opencl_private;

// For temporaries inside functions, CUDA treats them as normal variables.
// LangAS::cuda_device, on the other hand, is reserved for those variables
// explicitly marked with __device__.
if (getLangOpts().CUDAIsDevice)
return LangAS::Default;

if (getLangOpts().SYCLIsDevice ||
(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice))
errorNYI("SYCL or OpenMP temp address space");
return LangAS::Default;
}

void CIRGenModule::emitExplicitCastExprType(const ExplicitCastExpr *e,
CIRGenFunction *cgf) {
if (cgf && e->getType()->isVariablyModifiedType())
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,12 @@ class CIRGenModule : public CIRGenTypeCache {
getAddrOfConstantStringFromLiteral(const StringLiteral *s,
llvm::StringRef name = ".str");

/// Returns the address space for temporary allocations in the language. This
/// ensures that the allocated variable's address space matches the
/// expectations of the AST, rather than using the target's allocation address
/// space, which may lead to type mismatches in other parts of the IR.
LangAS getLangTempAllocaAddressSpace() const;

/// Set attributes which are common to any form of a global definition (alias,
/// Objective-C method, function, global variable).
///
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
const ReferenceType *refTy = cast<ReferenceType>(ty);
QualType elemTy = refTy->getPointeeType();
auto pointeeType = convertTypeForMem(elemTy);
resultType = builder.getPointerTo(pointeeType);
resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
assert(resultType && "Cannot get pointer type?");
break;
}
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/CIR/CodeGen/TargetInfo.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "TargetInfo.h"
#include "ABIInfo.h"
#include "CIRGenFunction.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"

using namespace clang;
using namespace clang::CIRGen;
Expand Down Expand Up @@ -68,3 +71,14 @@ bool TargetCIRGenInfo::isNoProtoCallVariadic(
// For everything else, we just prefer false unless we opt out.
return false;
}

mlir::Value TargetCIRGenInfo::performAddrSpaceCast(
CIRGenFunction &cgf, mlir::Value v, cir::TargetAddressSpaceAttr srcAddr,
mlir::Type destTy, bool isNonNull) const {
// Since target may map different address spaces in AST to the same address
// space, an address space conversion may end up as a bitcast.
if (cir::GlobalOp globalOp = v.getDefiningOp<cir::GlobalOp>())
cgf.cgm.errorNYI("Global op addrspace cast");
// Try to preserve the source's name to make IR more readable.
return cgf.getBuilder().createAddrSpaceCast(v, destTy);
}
12 changes: 12 additions & 0 deletions clang/lib/CIR/CodeGen/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "ABIInfo.h"
#include "CIRGenTypes.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"

#include <memory>
#include <utility>
Expand All @@ -33,6 +34,8 @@ bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd);
/// if the [[no_unique_address]] attribute would have made them empty.
bool isEmptyRecordForLayout(const ASTContext &context, QualType t);

class CIRGenFunction;

class TargetCIRGenInfo {
std::unique_ptr<ABIInfo> info;

Expand All @@ -48,6 +51,15 @@ class TargetCIRGenInfo {
virtual cir::TargetAddressSpaceAttr getCIRAllocaAddressSpace() const {
return {};
}
/// Perform address space cast of an expression of pointer type.
/// \param V is the value to be casted to another address space.
/// \param DestTy is the destination pointer type.
/// \param srcAS is theaddress space of \p V.
/// \param IsNonNull is the flag indicating \p V is known to be non null.
virtual mlir::Value performAddrSpaceCast(CIRGenFunction &cgf, mlir::Value v,
cir::TargetAddressSpaceAttr srcAddr,
mlir::Type destTy,
bool isNonNull = false) const;

/// Determine whether a call to an unprototyped functions under
/// the given calling convention should use the variadic
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,16 @@ LogicalResult cir::CastOp::verify() {
mlir::Type resType = getType();
mlir::Type srcType = getSrc().getType();

// Verify address space casts for pointer types. given that
// casts for within a different address space are illegal.
auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(srcType);
auto resPtrTy = mlir::dyn_cast<cir::PointerType>(resType);
if (srcPtrTy && resPtrTy && (getKind() != cir::CastKind::address_space))
if (srcPtrTy.getAddrSpace() != resPtrTy.getAddrSpace()) {
return emitOpError() << "result type address space does not match the "
"address space of the operand";
}

if (mlir::isa<cir::VectorType>(srcType) &&
mlir::isa<cir::VectorType>(resType)) {
// Use the element type of the vector to verify the cast kind. (Except for
Expand Down
26 changes: 26 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@

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

#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/DialectImplementation.h"
#include "mlir/IR/MLIRContext.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIRTypesDetails.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/TypeSwitch.h"

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -807,6 +812,27 @@ mlir::LogicalResult cir::VectorType::verify(
// TargetAddressSpace definitions
//===----------------------------------------------------------------------===//

cir::TargetAddressSpaceAttr
cir::toCIRTargetAddressSpace(mlir::MLIRContext &context, clang::LangAS langAS) {
return cir::TargetAddressSpaceAttr::get(
&context,
IntegerAttr::get(&context,
llvm::APSInt(clang::toTargetAddressSpace(langAS))));
}

bool cir::isMatchingAddressSpace(cir::TargetAddressSpaceAttr cirAS,
clang::LangAS as) {
// If there is no CIR target attr, consider it "default" and only match
// when the AST address space is LangAS::Default.
if (!cirAS)
return as == clang::LangAS::Default;

if (!isTargetAddressSpace(as))
return false;

return cirAS.getValue().getUInt() == toTargetAddressSpace(as);
}

mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p,
cir::TargetAddressSpaceAttr &attr) {
if (failed(p.parseKeyword("target_address_space")))
Expand Down
Loading