Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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 @@ -465,6 +465,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
7 changes: 7 additions & 0 deletions clang/lib/CIR/CodeGen/Address.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@

#include "mlir/IR/Value.h"
#include "clang/AST/CharUnits.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Casting.h"

namespace clang::CIRGen {

Expand Down Expand Up @@ -114,6 +116,11 @@ class Address {
return elementType;
}

cir::TargetAddressSpaceAttr getAddressSpace() const {
auto ptrTy = llvm::dyn_cast<cir::PointerType>(getType());
return ptrTy.getAddrSpace();
}

clang::CharUnits getAlignment() const { return alignment; }

/// Get the operation which defines this address.
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
43 changes: 41 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,27 @@ 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);
else
cgm.errorNYI(
e->getSourceRange(),
"emitCastLValue: address space conversion from unknown address "
"space");

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 @@ -2298,6 +2321,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 @@ -2312,7 +2337,21 @@ 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 = alloca.getAddressSpace()
? clang::getLangASFromTargetAS(
alloca.getAddressSpace().getValue().getUInt())
: clang::LangAS::Default;
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
31 changes: 31 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 @@ -1874,6 +1876,35 @@ 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::QualType srcTy = subExpr->IgnoreImpCasts()->getType();
if (srcTy->isPointerType() || srcTy->isReferenceType())
srcTy = srcTy->getPointeeType();

clang::LangAS srcLangAS = srcTy.getAddressSpace();
cir::TargetAddressSpaceAttr subExprAS;
if (clang::isTargetAddressSpace(srcLangAS))
subExprAS = cir::toCIRTargetAddressSpace(cgf.getMLIRContext(), srcLangAS);
else
cgf.cgm.errorNYI(subExpr->getSourceRange(),
"non-target address space conversion");
// 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 @@ -217,6 +217,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
Loading