[clang] [CIR] Infrastructure and MemorySpaceAttrInterface for Address Spaces (PR #179073)
David Rivera via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 4 13:51:51 PST 2026
https://github.com/RiverDave updated https://github.com/llvm/llvm-project/pull/179073
>From 8fee86d3d86a565db540246d1d7ce18c84012ce4 Mon Sep 17 00:00:00 2001
From: David Rivera <davidriverg at gmail.com>
Date: Sat, 31 Jan 2026 17:48:05 -0500
Subject: [PATCH 1/3] [CIR] Infrastructure and MemorySpaceAttrInterface for
Address Spaces
---
.../CIR/Dialect/Builder/CIRBaseBuilder.h | 20 +-
clang/include/clang/CIR/Dialect/IR/CIRAttrs.h | 1 +
.../include/clang/CIR/Dialect/IR/CIRAttrs.td | 55 +++++-
.../clang/CIR/Dialect/IR/CIREnumAttr.td | 19 ++
clang/include/clang/CIR/Dialect/IR/CIRTypes.h | 17 +-
.../include/clang/CIR/Dialect/IR/CIRTypes.td | 10 +-
clang/lib/CIR/CodeGen/Address.h | 3 +-
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 2 +-
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 16 +-
clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 5 +-
clang/lib/CIR/CodeGen/CIRGenTypeCache.h | 5 +-
clang/lib/CIR/CodeGen/TargetInfo.cpp | 6 +-
clang/lib/CIR/CodeGen/TargetInfo.h | 11 +-
clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 108 +++++++++-
clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 187 ++++++++++++++----
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 23 ++-
clang/test/CIR/IR/address-space.cir | 41 ++++
clang/test/CIR/IR/invalid-addrspace.cir | 32 ++-
18 files changed, 468 insertions(+), 93 deletions(-)
create mode 100644 clang/test/CIR/IR/address-space.cir
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 229bf1e205994..8fe2e85432a74 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -153,29 +153,27 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return cir::PointerType::get(ty);
}
- cir::PointerType getPointerTo(mlir::Type ty, cir::TargetAddressSpaceAttr as) {
+ cir::PointerType getPointerTo(mlir::Type ty,
+ mlir::ptr::MemorySpaceAttrInterface as) {
+ if (!as)
+ return cir::PointerType::get(ty);
return cir::PointerType::get(ty, as);
}
cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
- if (langAS == clang::LangAS::Default) // Default address space.
+ if (langAS == clang::LangAS::Default)
return getPointerTo(ty);
- if (clang::isTargetAddressSpace(langAS)) {
- unsigned addrSpace = clang::toTargetAddressSpace(langAS);
- auto asAttr = cir::TargetAddressSpaceAttr::get(
- getContext(), getUI32IntegerAttr(addrSpace));
- return getPointerTo(ty, asAttr);
- }
-
- llvm_unreachable("language-specific address spaces NYI");
+ mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr =
+ cir::toCIRAddressSpaceAttr(getContext(), langAS);
+ return getPointerTo(ty, addrSpaceAttr);
}
cir::PointerType getVoidPtrTy(clang::LangAS langAS = clang::LangAS::Default) {
return getPointerTo(cir::VoidType::get(getContext()), langAS);
}
- cir::PointerType getVoidPtrTy(cir::TargetAddressSpaceAttr as) {
+ cir::PointerType getVoidPtrTy(mlir::ptr::MemorySpaceAttrInterface as) {
return getPointerTo(cir::VoidType::get(getContext()), as);
}
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
index 858d4d6350bed..1d61bd998c216 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
@@ -13,6 +13,7 @@
#ifndef CLANG_CIR_DIALECT_IR_CIRATTRS_H
#define CLANG_CIR_DIALECT_IR_CIRATTRS_H
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributeInterfaces.h"
#include "clang/Basic/AddressSpaces.h"
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index d7938bc350925..bc6b1c61a4f6b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -14,6 +14,7 @@
#define CLANG_CIR_DIALECT_IR_CIRATTRS_TD
include "mlir/IR/BuiltinAttributeInterfaces.td"
+include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
include "clang/CIR/Dialect/IR/CIRAttrConstraints.td"
include "clang/CIR/Dialect/IR/CIRDialect.td"
@@ -781,16 +782,64 @@ def CIR_DynamicCastInfoAttr : CIR_Attr<"DynamicCastInfo", "dyn_cast_info"> {
}];
}
+//===----------------------------------------------------------------------===//
+// LangAddressSpaceAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_LangAddressSpaceAttr : CIR_EnumAttr<CIR_LangAddressSpace,
+ "lang_address_space", [
+ DeclareAttrInterfaceMethods<MemorySpaceAttrInterface>
+]> {
+ let summary = "Represents a language address space";
+ let description = [{
+ Encodes the semantic address spaces defined by the front-end language
+ (e.g. `__shared__`, `__constant__`, `__local__`). Values are stored using the
+ `cir::LangAddressSpace` enum, keeping the representation compact and
+ preserving the qualifier until it is mapped onto target/LLVM address-space
+ numbers.
+
+ Example:
+ ```mlir
+ !cir.ptr<!s32i, lang_address_space(offload_local)>
+ cir.global constant external lang_address_space(offload_constant)
+ ```
+ }];
+
+ let builders = [
+ AttrBuilder<(ins "clang::LangAS":$langAS), [{
+ return $_get($_ctxt, cir::toCIRLangAddressSpace(langAS));
+ }]>
+ ];
+
+ let assemblyFormat = [{
+ `(` custom<AddressSpaceValue>($value) `)`
+ }];
+
+ let defaultValue = "cir::LangAddressSpace::Default";
+
+ let extraClassDeclaration = [{
+ unsigned getAsUnsignedValue() const;
+ }];
+
+ let extraClassDefinition = [{
+ unsigned $cppClass::getAsUnsignedValue() const {
+ return static_cast<unsigned>(getValue());
+ }
+ }];
+}
+
//===----------------------------------------------------------------------===//
// TargetAddressSpaceAttr
//===----------------------------------------------------------------------===//
def CIR_TargetAddressSpaceAttr : CIR_Attr< "TargetAddressSpace",
- "target_address_space"> {
+ "target_address_space", [
+ DeclareAttrInterfaceMethods<MemorySpaceAttrInterface>
+ ]> {
let summary = "Represents a target-specific numeric address space";
let description = [{
The TargetAddressSpaceAttr represents a target-specific numeric address space,
- corresponding to the LLVM IR `addressspace` qualifier and the clang
+ corresponding to the LLVM IR `addrspace` qualifier and the clang
`address_space` attribute.
A value of zero represents the default address space. The semantics of non-zero
@@ -804,7 +853,7 @@ def CIR_TargetAddressSpaceAttr : CIR_Attr< "TargetAddressSpace",
```
}];
- let parameters = (ins "mlir::IntegerAttr":$value);
+ let parameters = (ins "unsigned":$value);
let assemblyFormat = "`<` `target` `<` $value `>` `>`";
}
diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
index 98b8a31d2a18a..1de6ffdc08d72 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
@@ -14,6 +14,7 @@
#define CLANG_CIR_DIALECT_IR_CIRENUMATTR_TD
include "mlir/IR/EnumAttr.td"
+include "clang/CIR/Dialect/IR/CIRDialect.td"
class CIR_I32EnumAttr<string name, string summary, list<I32EnumAttrCase> cases>
: I32EnumAttr<name, summary, cases> {
@@ -35,4 +36,22 @@ class CIR_DefaultValuedEnumParameter<EnumAttrInfo info, string value = "">
let defaultValue = value;
}
+def CIR_LangAddressSpace : CIR_I32EnumAttr<
+ "LangAddressSpace", "language address space kind", [
+ I32EnumAttrCase<"Default", 0, "default">,
+ I32EnumAttrCase<"OffloadPrivate", 1, "offload_private">,
+ I32EnumAttrCase<"OffloadLocal", 2, "offload_local">,
+ I32EnumAttrCase<"OffloadGlobal", 3, "offload_global">,
+ I32EnumAttrCase<"OffloadConstant", 4, "offload_constant">,
+ I32EnumAttrCase<"OffloadGeneric", 5, "offload_generic">
+]> {
+ let description = [{
+ Enumerates language-specific address spaces used by CIR. These represent
+ semantic qualifiers from source languages (e.g., CUDA `__shared__`,
+ OpenCL `__local`) before target lowering.
+ }];
+
+ let genSpecializedAttr = 0;
+}
+
#endif // CLANG_CIR_DIALECT_IR_CIRENUMATTR_TD
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
index 939e774a6ea67..eee4140ba2801 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
@@ -13,6 +13,7 @@
#ifndef CLANG_CIR_DIALECT_IR_CIRTYPES_H
#define CLANG_CIR_DIALECT_IR_CIRTYPES_H
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/MLIRContext.h"
@@ -43,12 +44,22 @@ bool isSized(mlir::Type ty);
//===----------------------------------------------------------------------===//
// AddressSpace helpers
//===----------------------------------------------------------------------===//
-cir::TargetAddressSpaceAttr toCIRTargetAddressSpace(mlir::MLIRContext &context,
- clang::LangAS langAS);
-bool isMatchingAddressSpace(cir::TargetAddressSpaceAttr cirAS,
+cir::LangAddressSpace toCIRLangAddressSpace(clang::LangAS langAS);
+
+// Compare a CIR memory space attribute with a Clang LangAS.
+bool isMatchingAddressSpace(mlir::MLIRContext &ctx,
+ mlir::ptr::MemorySpaceAttrInterface cirAS,
clang::LangAS as);
+/// Convert an AST LangAS to the appropriate CIR address space attribute
+/// interface.
+mlir::ptr::MemorySpaceAttrInterface
+toCIRAddressSpaceAttr(mlir::MLIRContext *ctx, clang::LangAS langAS);
+
+bool isSupportedCIRMemorySpaceAttr(
+ mlir::ptr::MemorySpaceAttrInterface memorySpace);
+
} // namespace cir
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index ea2113432d5b5..9b01ee54f8afe 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -252,19 +252,19 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
let parameters = (ins
"mlir::Type":$pointee,
OptionalParameter<
- "cir::TargetAddressSpaceAttr">:$addrSpace
+ "mlir::ptr::MemorySpaceAttrInterface">:$addrSpace
);
let skipDefaultBuilders = 1;
let builders = [
TypeBuilderWithInferredContext<(ins
"mlir::Type":$pointee,
- CArg<"cir::TargetAddressSpaceAttr", "nullptr">:$addrSpace), [{
+ CArg<"mlir::ptr::MemorySpaceAttrInterface", "{}">:$addrSpace), [{
return $_get(pointee.getContext(), pointee, addrSpace);
}]>,
TypeBuilder<(ins
"mlir::Type":$pointee,
- CArg<"cir::TargetAddressSpaceAttr", "nullptr">:$addrSpace), [{
+ CArg<"mlir::ptr::MemorySpaceAttrInterface", "{}">:$addrSpace), [{
return $_get($_ctxt, pointee, addrSpace);
}]>
];
@@ -272,7 +272,7 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
let assemblyFormat = [{
`<`
$pointee
- ( `,` ` ` custom<TargetAddressSpace>($addrSpace)^ )?
+ ( `,` ` ` custom<AddressSpaceValue>($addrSpace)^ )?
`>`
}];
@@ -303,6 +303,8 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
return false;
}
}];
+
+ let genVerifyDecl = 1;
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/Address.h b/clang/lib/CIR/CodeGen/Address.h
index f32cde957cd5c..b459ec948c2c4 100644
--- a/clang/lib/CIR/CodeGen/Address.h
+++ b/clang/lib/CIR/CodeGen/Address.h
@@ -14,6 +14,7 @@
#ifndef CLANG_LIB_CIR_ADDRESS_H
#define CLANG_LIB_CIR_ADDRESS_H
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "mlir/IR/Value.h"
#include "clang/AST/CharUnits.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
@@ -127,7 +128,7 @@ class Address {
return elementType;
}
- cir::TargetAddressSpaceAttr getAddressSpace() const {
+ mlir::ptr::MemorySpaceAttrInterface getAddressSpace() const {
auto ptrTy = mlir::dyn_cast<cir::PointerType>(getType());
return ptrTy.getAddrSpace();
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 580ada8901cbb..dd225a41ef7ae 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -338,7 +338,7 @@ static RValue emitBuiltinAlloca(CIRGenFunction &cgf, const CallExpr *e,
// builtin / dynamic alloca we have to handle it here.
if (!cir::isMatchingAddressSpace(
- cgf.getCIRAllocaAddressSpace(),
+ cgf.getMLIRContext(), cgf.getCIRAllocaAddressSpace(),
e->getType()->getPointeeType().getAddressSpace())) {
cgf.cgm.errorNYI(e->getSourceRange(),
"Non-default address space for alloca");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 8bdf075aab695..8b11f44ad0034 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -15,6 +15,7 @@
#include "CIRGenFunction.h"
#include "CIRGenModule.h"
#include "CIRGenValue.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Value.h"
#include "clang/AST/Attr.h"
@@ -1455,9 +1456,9 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
QualType destTy = getContext().getPointerType(e->getType());
clang::LangAS srcLangAS = e->getSubExpr()->getType().getAddressSpace();
- cir::TargetAddressSpaceAttr srcAS;
+ mlir::ptr::MemorySpaceAttrInterface srcAS;
if (clang::isTargetAddressSpace(srcLangAS))
- srcAS = cir::toCIRTargetAddressSpace(getMLIRContext(), srcLangAS);
+ srcAS = cir::toCIRAddressSpaceAttr(&getMLIRContext(), srcLangAS);
else
cgm.errorNYI(
e->getSourceRange(),
@@ -2504,15 +2505,8 @@ Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,
// in C++ the auto variables are in the default address space. Therefore
// cast alloca to the default address space when necessary.
- 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());
- }
+ mlir::ptr::MemorySpaceAttrInterface allocaAS = alloca.getAddressSpace();
+ mlir::ptr::MemorySpaceAttrInterface dstTyAS = getCIRAllocaAddressSpace();
if (dstTyAS != allocaAS) {
getTargetHooks().performAddrSpaceCast(*this, v, getCIRAllocaAddressSpace(),
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 940a0cb616b27..9c653665b9718 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -19,6 +19,7 @@
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "mlir/IR/Location.h"
#include "mlir/IR/Value.h"
@@ -2143,9 +2144,9 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
srcTy = srcTy->getPointeeType();
clang::LangAS srcLangAS = srcTy.getAddressSpace();
- cir::TargetAddressSpaceAttr subExprAS;
+ mlir::ptr::MemorySpaceAttrInterface subExprAS;
if (clang::isTargetAddressSpace(srcLangAS))
- subExprAS = cir::toCIRTargetAddressSpace(cgf.getMLIRContext(), srcLangAS);
+ subExprAS = cir::toCIRAddressSpaceAttr(&cgf.getMLIRContext(), srcLangAS);
else
cgf.cgm.errorNYI(subExpr->getSourceRange(),
"non-target address space conversion");
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
index 0f63e91f45564..4f3c319816e3a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
#define LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "clang/AST/CharUnits.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -80,7 +81,7 @@ struct CIRGenTypeCache {
unsigned char SizeAlignInBytes;
};
- cir::TargetAddressSpaceAttr cirAllocaAddressSpace;
+ mlir::ptr::MemorySpaceAttrInterface cirAllocaAddressSpace;
clang::CharUnits getSizeSize() const {
return clang::CharUnits::fromQuantity(SizeSizeInBytes);
@@ -93,7 +94,7 @@ struct CIRGenTypeCache {
return clang::CharUnits::fromQuantity(PointerAlignInBytes);
}
- cir::TargetAddressSpaceAttr getCIRAllocaAddressSpace() const {
+ mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const {
return cirAllocaAddressSpace;
}
};
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index dc29dc0204c19..131fe4c8076f3 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -1,6 +1,7 @@
#include "TargetInfo.h"
#include "ABIInfo.h"
#include "CIRGenFunction.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
@@ -92,8 +93,9 @@ bool TargetCIRGenInfo::isNoProtoCallVariadic(
}
mlir::Value TargetCIRGenInfo::performAddrSpaceCast(
- CIRGenFunction &cgf, mlir::Value v, cir::TargetAddressSpaceAttr srcAddr,
- mlir::Type destTy, bool isNonNull) const {
+ CIRGenFunction &cgf, mlir::Value v,
+ mlir::ptr::MemorySpaceAttrInterface srcAS, 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>())
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h
index bab838692e215..d93255119727f 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.h
+++ b/clang/lib/CIR/CodeGen/TargetInfo.h
@@ -16,6 +16,7 @@
#include "ABIInfo.h"
#include "CIRGenTypes.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
@@ -48,7 +49,7 @@ class TargetCIRGenInfo {
const ABIInfo &getABIInfo() const { return *info; }
/// Get the address space for alloca.
- virtual cir::TargetAddressSpaceAttr getCIRAllocaAddressSpace() const {
+ virtual mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const {
return {};
}
/// Perform address space cast of an expression of pointer type.
@@ -56,10 +57,10 @@ class TargetCIRGenInfo {
/// \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;
+ virtual mlir::Value
+ performAddrSpaceCast(CIRGenFunction &cgf, mlir::Value v,
+ mlir::ptr::MemorySpaceAttrInterface srcAS,
+ mlir::Type destTy, bool isNonNull = false) const;
/// Determine whether a call to an unprototyped functions under
/// the given calling convention should use the variadic
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 43bd33759fba9..67509f3cf452a 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "mlir/IR/DialectImplementation.h"
@@ -47,11 +48,21 @@ parseFloatLiteral(mlir::AsmParser &parser,
// AddressSpaceAttr
//===----------------------------------------------------------------------===//
-mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p,
- cir::TargetAddressSpaceAttr &attr);
+mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p,
+ cir::LangAddressSpace &addrSpace) {
+ llvm::SMLoc loc = p.getCurrentLocation();
+ mlir::FailureOr<cir::LangAddressSpace> result =
+ mlir::FieldParser<cir::LangAddressSpace>::parse(p);
+ if (mlir::failed(result))
+ return p.emitError(loc, "expected address space keyword");
+ addrSpace = result.value();
+ return mlir::success();
+}
-void printTargetAddressSpace(mlir::AsmPrinter &p,
- cir::TargetAddressSpaceAttr attr);
+void printAddressSpaceValue(mlir::AsmPrinter &p,
+ cir::LangAddressSpace addrSpace) {
+ p << cir::stringifyEnum(addrSpace);
+}
static mlir::ParseResult parseConstPtr(mlir::AsmParser &parser,
mlir::IntegerAttr &value);
@@ -64,6 +75,95 @@ static void printConstPtr(mlir::AsmPrinter &p, mlir::IntegerAttr value);
using namespace mlir;
using namespace cir;
+//===----------------------------------------------------------------------===//
+// MemorySpaceAttrInterface implementations for Lang and Target address space
+// attributes
+//===----------------------------------------------------------------------===//
+
+bool LangAddressSpaceAttr::isValidLoad(
+ mlir::Type type, mlir::ptr::AtomicOrdering ordering,
+ std::optional<int64_t> alignment, const mlir::DataLayout *dataLayout,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidLoad for LangAddressSpaceAttr NYI");
+}
+
+bool LangAddressSpaceAttr::isValidStore(
+ mlir::Type type, mlir::ptr::AtomicOrdering ordering,
+ std::optional<int64_t> alignment, const mlir::DataLayout *dataLayout,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidStore for LangAddressSpaceAttr NYI");
+}
+
+bool LangAddressSpaceAttr::isValidAtomicOp(
+ mlir::ptr::AtomicBinOp op, mlir::Type type,
+ mlir::ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
+ const mlir::DataLayout *dataLayout,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidAtomicOp for LangAddressSpaceAttr NYI");
+}
+
+bool LangAddressSpaceAttr::isValidAtomicXchg(
+ mlir::Type type, mlir::ptr::AtomicOrdering successOrdering,
+ mlir::ptr::AtomicOrdering failureOrdering, std::optional<int64_t> alignment,
+ const mlir::DataLayout *dataLayout,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidAtomicXchg for LangAddressSpaceAttr NYI");
+}
+
+bool LangAddressSpaceAttr::isValidAddrSpaceCast(
+ mlir::Type tgt, mlir::Type src,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidAddrSpaceCast for LangAddressSpaceAttr NYI");
+}
+
+bool LangAddressSpaceAttr::isValidPtrIntCast(
+ mlir::Type intLikeTy, mlir::Type ptrLikeTy,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidPtrIntCast for LangAddressSpaceAttr NYI");
+}
+
+bool TargetAddressSpaceAttr::isValidLoad(
+ mlir::Type type, mlir::ptr::AtomicOrdering ordering,
+ std::optional<int64_t> alignment, const mlir::DataLayout *dataLayout,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidLoad for TargetAddressSpaceAttr NYI");
+}
+
+bool TargetAddressSpaceAttr::isValidStore(
+ mlir::Type type, mlir::ptr::AtomicOrdering ordering,
+ std::optional<int64_t> alignment, const mlir::DataLayout *dataLayout,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidStore for TargetAddressSpaceAttr NYI");
+}
+
+bool TargetAddressSpaceAttr::isValidAtomicOp(
+ mlir::ptr::AtomicBinOp op, mlir::Type type,
+ mlir::ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
+ const mlir::DataLayout *dataLayout,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidAtomicOp for TargetAddressSpaceAttr NYI");
+}
+
+bool TargetAddressSpaceAttr::isValidAtomicXchg(
+ mlir::Type type, mlir::ptr::AtomicOrdering successOrdering,
+ mlir::ptr::AtomicOrdering failureOrdering, std::optional<int64_t> alignment,
+ const mlir::DataLayout *dataLayout,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidAtomicXchg for TargetAddressSpaceAttr NYI");
+}
+
+bool TargetAddressSpaceAttr::isValidAddrSpaceCast(
+ mlir::Type tgt, mlir::Type src,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidAddrSpaceCast for TargetAddressSpaceAttr NYI");
+}
+
+bool TargetAddressSpaceAttr::isValidPtrIntCast(
+ mlir::Type intLikeTy, mlir::Type ptrLikeTy,
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
+ llvm_unreachable("isValidPtrIntCast for TargetAddressSpaceAttr NYI");
+}
+
//===----------------------------------------------------------------------===//
// General CIR parsing / printing
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 43853b6696a94..42445a07864d8 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -12,12 +12,15 @@
#include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/DialectImplementation.h"
#include "mlir/IR/MLIRContext.h"
+#include "mlir/Support/LLVM.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/CIROpsEnums.h"
#include "clang/CIR/Dialect/IR/CIRTypesDetails.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/APInt.h"
@@ -60,6 +63,14 @@ static void printFuncTypeParams(mlir::AsmPrinter &p,
// AddressSpace
//===----------------------------------------------------------------------===//
+mlir::ParseResult
+parseAddressSpaceValue(mlir::AsmParser &p,
+ mlir::ptr::MemorySpaceAttrInterface &attr);
+
+void printAddressSpaceValue(mlir::AsmPrinter &printer,
+ mlir::ptr::MemorySpaceAttrInterface attr);
+
+// Custom parser/printer for the `addrSpace` parameter in `!cir.ptr`.
mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p,
cir::TargetAddressSpaceAttr &attr);
@@ -930,58 +941,158 @@ void cir::VectorType::print(mlir::AsmPrinter &odsPrinter) const {
}
//===----------------------------------------------------------------------===//
-// TargetAddressSpace definitions
+// AddressSpace 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::isSupportedCIRMemorySpaceAttr(
+ mlir::ptr::MemorySpaceAttrInterface memorySpace) {
+ return mlir::isa<cir::LangAddressSpaceAttr, cir::TargetAddressSpaceAttr>(
+ memorySpace);
+}
+
+cir::LangAddressSpace cir::toCIRLangAddressSpace(clang::LangAS langAS) {
+ using clang::LangAS;
+ switch (langAS) {
+ case LangAS::Default:
+ return LangAddressSpace::Default;
+ case LangAS::opencl_global:
+ return LangAddressSpace::OffloadGlobal;
+ case LangAS::opencl_local:
+ case LangAS::cuda_shared:
+ // Local means local among the work-group (OpenCL) or block (CUDA).
+ // All threads inside the kernel can access local memory.
+ return LangAddressSpace::OffloadLocal;
+ case LangAS::cuda_device:
+ return LangAddressSpace::OffloadGlobal;
+ case LangAS::opencl_constant:
+ case LangAS::cuda_constant:
+ return LangAddressSpace::OffloadConstant;
+ case LangAS::opencl_private:
+ return LangAddressSpace::OffloadPrivate;
+ case LangAS::opencl_generic:
+ return LangAddressSpace::OffloadGeneric;
+ case LangAS::opencl_global_device:
+ case LangAS::opencl_global_host:
+ case LangAS::sycl_global:
+ case LangAS::sycl_global_device:
+ case LangAS::sycl_global_host:
+ case LangAS::sycl_local:
+ case LangAS::sycl_private:
+ case LangAS::ptr32_sptr:
+ case LangAS::ptr32_uptr:
+ case LangAS::ptr64:
+ case LangAS::hlsl_groupshared:
+ case LangAS::wasm_funcref:
+ llvm_unreachable("NYI");
+ default:
+ llvm_unreachable("unknown/unsupported clang language address space");
+ }
}
-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;
+mlir::ParseResult
+parseAddressSpaceValue(mlir::AsmParser &p,
+ mlir::ptr::MemorySpaceAttrInterface &attr) {
- if (!isTargetAddressSpace(as))
- return false;
+ llvm::SMLoc loc = p.getCurrentLocation();
- return cirAS.getValue().getUInt() == toTargetAddressSpace(as);
-}
+ // Try to parse target address space first.
+ attr = nullptr;
+ if (p.parseOptionalKeyword("target_address_space").succeeded()) {
+ unsigned val;
+ if (p.parseLParen())
+ return p.emitError(loc, "expected '(' after 'target_address_space'");
-mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p,
- cir::TargetAddressSpaceAttr &attr) {
- if (failed(p.parseKeyword("target_address_space")))
- return mlir::failure();
+ if (p.parseInteger(val))
+ return p.emitError(loc, "expected target address space value");
+
+ if (p.parseRParen())
+ return p.emitError(loc, "expected ')'");
- if (failed(p.parseLParen()))
- return mlir::failure();
+ attr = cir::TargetAddressSpaceAttr::get(p.getContext(), val);
+ return mlir::success();
+ }
- int32_t targetValue;
- if (failed(p.parseInteger(targetValue)))
- return p.emitError(p.getCurrentLocation(),
- "expected integer address space value");
+ // Try to parse language specific address space.
+ if (p.parseOptionalKeyword("lang_address_space").succeeded()) {
+ if (p.parseLParen())
+ return p.emitError(loc, "expected '(' after 'lang_address_space'");
- if (failed(p.parseRParen()))
- return p.emitError(p.getCurrentLocation(),
- "expected ')' after address space value");
+ mlir::FailureOr<cir::LangAddressSpace> result =
+ mlir::FieldParser<cir::LangAddressSpace>::parse(p);
+ if (mlir::failed(result))
+ return mlir::failure();
+
+ if (p.parseRParen())
+ return p.emitError(loc, "expected ')'");
+
+ attr = cir::LangAddressSpaceAttr::get(p.getContext(), result.value());
+ return mlir::success();
+ }
+
+ llvm::StringRef keyword;
+ if (p.parseOptionalKeyword(&keyword).succeeded())
+ return p.emitError(loc, "unknown address space specifier '")
+ << keyword << "'; expected 'target_address_space' or "
+ << "'lang_address_space'";
- mlir::MLIRContext *context = p.getBuilder().getContext();
- attr = cir::TargetAddressSpaceAttr::get(
- context, p.getBuilder().getUI32IntegerAttr(targetValue));
return mlir::success();
}
-// The custom printer for the `addrspace` parameter in `!cir.ptr`.
-// in the format of `target_address_space(N)`.
-void printTargetAddressSpace(mlir::AsmPrinter &p,
- cir::TargetAddressSpaceAttr attr) {
- p << "target_address_space(" << attr.getValue().getUInt() << ")";
+void printAddressSpaceValue(mlir::AsmPrinter &p,
+ mlir::ptr::MemorySpaceAttrInterface attr) {
+ if (!attr)
+ return;
+
+ if (auto language = dyn_cast<cir::LangAddressSpaceAttr>(attr)) {
+ p << "lang_address_space("
+ << cir::stringifyLangAddressSpace(language.getValue()) << ')';
+ return;
+ }
+
+ if (auto target = dyn_cast<cir::TargetAddressSpaceAttr>(attr)) {
+ p << "target_address_space(" << target.getValue() << ')';
+ return;
+ }
+
+ llvm_unreachable("unexpected address-space attribute kind");
+}
+
+mlir::ptr::MemorySpaceAttrInterface
+cir::toCIRAddressSpaceAttr(mlir::MLIRContext *ctx, clang::LangAS langAS) {
+ using clang::LangAS;
+
+ if (langAS == LangAS::Default)
+ return {}; // Default address space is represented as an empty attribute.
+
+ if (clang::isTargetAddressSpace(langAS)) {
+ unsigned targetAS = clang::toTargetAddressSpace(langAS);
+ return cir::TargetAddressSpaceAttr::get(ctx, targetAS);
+ }
+
+ return cir::LangAddressSpaceAttr::get(ctx, toCIRLangAddressSpace(langAS));
+}
+
+bool cir::isMatchingAddressSpace(mlir::MLIRContext &ctx,
+ mlir::ptr::MemorySpaceAttrInterface cirAS,
+ clang::LangAS as) {
+ return cir::toCIRAddressSpaceAttr(&ctx, as) == cirAS;
+}
+
+//===----------------------------------------------------------------------===//
+// PointerType Definitions
+//===----------------------------------------------------------------------===//
+
+mlir::LogicalResult cir::PointerType::verify(
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
+ mlir::Type pointee, mlir::ptr::MemorySpaceAttrInterface addrSpace) {
+ if (addrSpace) {
+ if (!isSupportedCIRMemorySpaceAttr(addrSpace)) {
+ return emitError() << "unsupported address space attribute; expected "
+ "'target_address_space' or 'lang_address_space'";
+ }
+ }
+
+ return success();
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 5d2a1098799bb..229df9950b139 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -21,12 +21,14 @@
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinDialect.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Types.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
+#include "mlir/Support/LLVM.h"
#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Export.h"
@@ -40,6 +42,7 @@
#include "clang/CIR/Passes.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TimeProfiler.h"
@@ -3038,14 +3041,28 @@ std::unique_ptr<cir::LowerModule> prepareLowerModule(mlir::ModuleOp module) {
return {};
return cir::createLowerModule(module, rewriter);
}
+static unsigned
+getNumericASFromCIRAS(mlir::ptr::MemorySpaceAttrInterface asAttr,
+ [[maybe_unused]] cir::LowerModule *lowerModule) {
+ if (!asAttr)
+ return 0; // default AS
+ if (auto targetAddrSpaceAttr =
+ mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(asAttr))
+ return targetAddrSpaceAttr.getValue();
+
+ if (mlir::isa_and_present<cir::LangAddressSpaceAttr>(asAttr))
+ llvm_unreachable("lowering LangAddressSpaceAttr NYI");
+
+ llvm_unreachable("unexpected address Space attribute kindI");
+}
static void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
mlir::DataLayout &dataLayout,
cir::LowerModule *lowerModule) {
converter.addConversion([&](cir::PointerType type) -> mlir::Type {
- unsigned addrSpace =
- type.getAddrSpace() ? type.getAddrSpace().getValue().getUInt() : 0;
- return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
+ mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr = type.getAddrSpace();
+ unsigned numericAS = getNumericASFromCIRAS(addrSpaceAttr, lowerModule);
+ return mlir::LLVM::LLVMPointerType::get(type.getContext(), numericAS);
});
converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
assert(!cir::MissingFeatures::addressSpace());
diff --git a/clang/test/CIR/IR/address-space.cir b/clang/test/CIR/IR/address-space.cir
new file mode 100644
index 0000000000000..9a729c934bc11
--- /dev/null
+++ b/clang/test/CIR/IR/address-space.cir
@@ -0,0 +1,41 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+
+module {
+ cir.func @target_address_space_ptr(%p: !cir.ptr<!s32i, target_address_space(1)>) {
+ cir.return
+ }
+
+ cir.func @lang_address_space_offload_local(%p: !cir.ptr<!s32i, lang_address_space(offload_local)>) {
+ cir.return
+ }
+
+ cir.func @lang_address_space_offload_global(%p: !cir.ptr<!s32i, lang_address_space(offload_global)>) {
+ cir.return
+ }
+
+ cir.func @lang_address_space_offload_constant(%p: !cir.ptr<!s32i, lang_address_space(offload_constant)>) {
+ cir.return
+ }
+
+ cir.func @lang_address_space_offload_private(%p: !cir.ptr<!s32i, lang_address_space(offload_private)>) {
+ cir.return
+ }
+
+ cir.func @lang_address_space_offload_generic(%p: !cir.ptr<!s32i, lang_address_space(offload_generic)>) {
+ cir.return
+ }
+
+ cir.func @default_address_space(%p: !cir.ptr<!s32i>) {
+ cir.return
+ }
+}
+
+// CHECK: cir.func @target_address_space_ptr(%arg0: !cir.ptr<!s32i, target_address_space(1)>)
+// CHECK: cir.func @lang_address_space_offload_local(%arg0: !cir.ptr<!s32i, lang_address_space(offload_local)>)
+// CHECK: cir.func @lang_address_space_offload_global(%arg0: !cir.ptr<!s32i, lang_address_space(offload_global)>)
+// CHECK: cir.func @lang_address_space_offload_constant(%arg0: !cir.ptr<!s32i, lang_address_space(offload_constant)>)
+// CHECK: cir.func @lang_address_space_offload_private(%arg0: !cir.ptr<!s32i, lang_address_space(offload_private)>)
+// CHECK: cir.func @lang_address_space_offload_generic(%arg0: !cir.ptr<!s32i, lang_address_space(offload_generic)>)
+// CHECK: cir.func @default_address_space(%arg0: !cir.ptr<!s32i>)
diff --git a/clang/test/CIR/IR/invalid-addrspace.cir b/clang/test/CIR/IR/invalid-addrspace.cir
index 4b6a388b1e4a8..d38868f1febf0 100644
--- a/clang/test/CIR/IR/invalid-addrspace.cir
+++ b/clang/test/CIR/IR/invalid-addrspace.cir
@@ -3,7 +3,7 @@
// -----
!u64i = !cir.int<u, 64>
-// expected-error @below {{expected 'target_address_space'}}
+// expected-error @+1 {{unknown address space specifier 'foobar'; expected 'target_address_space' or 'lang_address_space'}}
cir.func @address_space1(%p : !cir.ptr<!u64i, foobar>) {
cir.return
}
@@ -11,6 +11,7 @@ cir.func @address_space1(%p : !cir.ptr<!u64i, foobar>) {
// -----
!u64i = !cir.int<u, 64>
+// expected-error at below {{expected '(' after 'target_address_space'}}
// expected-error at below {{expected '('}}
cir.func @address_space2(%p : !cir.ptr<!u64i, target_address_space>) {
cir.return
@@ -19,8 +20,33 @@ cir.func @address_space2(%p : !cir.ptr<!u64i, target_address_space>) {
// -----
!u64i = !cir.int<u, 64>
-// expected-error at +2 {{expected integer value}}
-// expected-error at below {{expected integer address space value}}
+// expected-error at below {{expected target address space value}}
+// expected-error at below {{expected integer value}}
cir.func @address_space3(%p : !cir.ptr<!u64i, target_address_space()>) {
cir.return
}
+
+// -----
+
+!u64i = !cir.int<u, 64>
+// expected-error at below {{expected '(' after 'lang_address_space'}}
+// expected-error at below {{expected '('}}
+cir.func @lang_address_space_no_parens(%p : !cir.ptr<!u64i, lang_address_space>) {
+ cir.return
+}
+
+// -----
+
+!u64i = !cir.int<u, 64>
+// expected-error at +1 {{expected keyword for language address space kind}}
+cir.func @lang_address_space_empty(%p : !cir.ptr<!u64i, lang_address_space()>) {
+ cir.return
+}
+
+// -----
+
+!u64i = !cir.int<u, 64>
+// expected-error at +1 {{expected one of [default, offload_private, offload_local, offload_global, offload_constant, offload_generic] for language address space kind}}
+cir.func @lang_address_space_invalid(%p : !cir.ptr<!u64i, lang_address_space(foobar)>) {
+ cir.return
+}
>From 0d5df25423bc513c027b7ac71109bc2158dcf119 Mon Sep 17 00:00:00 2001
From: David Rivera <davidriverg at gmail.com>
Date: Wed, 4 Feb 2026 16:26:53 -0500
Subject: [PATCH 2/3] Address first round of comments
---
.../clang/CIR/Dialect/Builder/CIRBaseBuilder.h | 2 +-
clang/include/clang/CIR/Dialect/IR/CIRTypes.h | 5 ++---
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 4 ++--
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 2 +-
clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 2 +-
clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 11 +++++------
6 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 8fe2e85432a74..dfae0a4592030 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -165,7 +165,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return getPointerTo(ty);
mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr =
- cir::toCIRAddressSpaceAttr(getContext(), langAS);
+ cir::toCIRAddressSpaceAttr(*getContext(), langAS);
return getPointerTo(ty, addrSpaceAttr);
}
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
index eee4140ba2801..02545ea412a52 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
@@ -48,14 +48,13 @@ bool isSized(mlir::Type ty);
cir::LangAddressSpace toCIRLangAddressSpace(clang::LangAS langAS);
// Compare a CIR memory space attribute with a Clang LangAS.
-bool isMatchingAddressSpace(mlir::MLIRContext &ctx,
- mlir::ptr::MemorySpaceAttrInterface cirAS,
+bool isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS,
clang::LangAS as);
/// Convert an AST LangAS to the appropriate CIR address space attribute
/// interface.
mlir::ptr::MemorySpaceAttrInterface
-toCIRAddressSpaceAttr(mlir::MLIRContext *ctx, clang::LangAS langAS);
+toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS);
bool isSupportedCIRMemorySpaceAttr(
mlir::ptr::MemorySpaceAttrInterface memorySpace);
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index dd225a41ef7ae..a36001975a0c9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -338,10 +338,10 @@ static RValue emitBuiltinAlloca(CIRGenFunction &cgf, const CallExpr *e,
// builtin / dynamic alloca we have to handle it here.
if (!cir::isMatchingAddressSpace(
- cgf.getMLIRContext(), cgf.getCIRAllocaAddressSpace(),
+ cgf.getCIRAllocaAddressSpace(),
e->getType()->getPointeeType().getAddressSpace())) {
cgf.cgm.errorNYI(e->getSourceRange(),
- "Non-default address space for alloca");
+ "Address Space Cast for builtin alloca");
}
// Bitcast the alloca to the expected type.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 8b11f44ad0034..381f48a00609a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1458,7 +1458,7 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
clang::LangAS srcLangAS = e->getSubExpr()->getType().getAddressSpace();
mlir::ptr::MemorySpaceAttrInterface srcAS;
if (clang::isTargetAddressSpace(srcLangAS))
- srcAS = cir::toCIRAddressSpaceAttr(&getMLIRContext(), srcLangAS);
+ srcAS = cir::toCIRAddressSpaceAttr(getMLIRContext(), srcLangAS);
else
cgm.errorNYI(
e->getSourceRange(),
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 9c653665b9718..e9090b5635b6d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -2146,7 +2146,7 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
clang::LangAS srcLangAS = srcTy.getAddressSpace();
mlir::ptr::MemorySpaceAttrInterface subExprAS;
if (clang::isTargetAddressSpace(srcLangAS))
- subExprAS = cir::toCIRAddressSpaceAttr(&cgf.getMLIRContext(), srcLangAS);
+ subExprAS = cir::toCIRAddressSpaceAttr(cgf.getMLIRContext(), srcLangAS);
else
cgf.cgm.errorNYI(subExpr->getSourceRange(),
"non-target address space conversion");
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 42445a07864d8..eb39207e5f081 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -1058,7 +1058,7 @@ void printAddressSpaceValue(mlir::AsmPrinter &p,
}
mlir::ptr::MemorySpaceAttrInterface
-cir::toCIRAddressSpaceAttr(mlir::MLIRContext *ctx, clang::LangAS langAS) {
+cir::toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS) {
using clang::LangAS;
if (langAS == LangAS::Default)
@@ -1066,16 +1066,15 @@ cir::toCIRAddressSpaceAttr(mlir::MLIRContext *ctx, clang::LangAS langAS) {
if (clang::isTargetAddressSpace(langAS)) {
unsigned targetAS = clang::toTargetAddressSpace(langAS);
- return cir::TargetAddressSpaceAttr::get(ctx, targetAS);
+ return cir::TargetAddressSpaceAttr::get(&ctx, targetAS);
}
- return cir::LangAddressSpaceAttr::get(ctx, toCIRLangAddressSpace(langAS));
+ return cir::LangAddressSpaceAttr::get(&ctx, toCIRLangAddressSpace(langAS));
}
-bool cir::isMatchingAddressSpace(mlir::MLIRContext &ctx,
- mlir::ptr::MemorySpaceAttrInterface cirAS,
+bool cir::isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS,
clang::LangAS as) {
- return cir::toCIRAddressSpaceAttr(&ctx, as) == cirAS;
+ return cir::toCIRAddressSpaceAttr(*cirAS.getContext(), as) == cirAS;
}
//===----------------------------------------------------------------------===//
>From f043eb6068e5dda790ee39a6e7264e5777f8003c Mon Sep 17 00:00:00 2001
From: David Rivera <davidriverg at gmail.com>
Date: Wed, 4 Feb 2026 16:51:19 -0500
Subject: [PATCH 3/3] test work now yo
---
clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index eb39207e5f081..659862ef208eb 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -1074,6 +1074,8 @@ cir::toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS) {
bool cir::isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS,
clang::LangAS as) {
+ if (!cirAS)
+ return as == clang::LangAS::Default;
return cir::toCIRAddressSpaceAttr(*cirAS.getContext(), as) == cirAS;
}
More information about the cfe-commits
mailing list