[clang] [CIR] Infrastructure for Language-specific Address Spaces (PR #179054)
David Rivera via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 31 09:48:41 PST 2026
https://github.com/RiverDave updated https://github.com/llvm/llvm-project/pull/179054
>From 84f35af0ae101d05405ea718f6e85e35168a7fce Mon Sep 17 00:00:00 2001
From: David Rivera <davidriverg at gmail.com>
Date: Sat, 31 Jan 2026 12:05:56 -0500
Subject: [PATCH 1/2] [CIR] Infrastructure for Language-specific Address Spaces
---
clang/include/clang/CIR/Dialect/IR/CIRAttrs.h | 1 +
.../include/clang/CIR/Dialect/IR/CIRAttrs.td | 53 ++++++++-
.../clang/CIR/Dialect/IR/CIREnumAttr.td | 19 +++
clang/include/clang/CIR/Dialect/IR/CIRTypes.h | 4 +
clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 108 ++++++++++++++++-
clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 112 +++++++++++++++++-
6 files changed, 290 insertions(+), 7 deletions(-)
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 2309811815f27..4fbab2e83663d 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"
@@ -766,16 +767,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
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..16c48ba4fb4e9 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,6 +44,9 @@ bool isSized(mlir::Type ty);
//===----------------------------------------------------------------------===//
// AddressSpace helpers
//===----------------------------------------------------------------------===//
+
+cir::LangAddressSpace toCIRLangAddressSpace(clang::LangAS langAS);
+
cir::TargetAddressSpaceAttr toCIRTargetAddressSpace(mlir::MLIRContext &context,
clang::LangAS langAS);
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 2f4240c385cab..8b5cbf45c8e97 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "mlir/IR/DialectImplementation.h"
#include "llvm/ADT/TypeSwitch.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..2ba4a3c5ff080 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -60,6 +60,14 @@ static void printFuncTypeParams(mlir::AsmPrinter &p,
// AddressSpace
//===----------------------------------------------------------------------===//
+static mlir::ParseResult
+parseAddressSpaceValue(mlir::AsmParser &p,
+ mlir::ptr::MemorySpaceAttrInterface &attr);
+
+static 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,9 +938,111 @@ void cir::VectorType::print(mlir::AsmPrinter &odsPrinter) const {
}
//===----------------------------------------------------------------------===//
-// TargetAddressSpace definitions
+// AddressSpace definitions
//===----------------------------------------------------------------------===//
+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");
+ }
+}
+
+static mlir::ParseResult
+parseAddressSpaceValue(mlir::AsmParser &p,
+ mlir::ptr::MemorySpaceAttrInterface &attr) {
+
+ llvm::SMLoc loc = p.getCurrentLocation();
+
+ // 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'");
+
+ if (p.parseInteger(val))
+ return p.emitError(loc, "expected target address space value");
+
+ if (p.parseRParen())
+ return p.emitError(loc, "expected ')'");
+
+ attr = cir::TargetAddressSpaceAttr::get(
+ p.getContext(), p.getBuilder().getUI32IntegerAttr(val));
+ return mlir::success();
+ }
+
+ // 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'");
+
+ mlir::FailureOr<cir::LangAddressSpace> result =
+ mlir::FieldParser<cir::LangAddressSpace>::parse(p);
+ if (mlir::failed(result))
+ return p.emitError(loc, "expected language address space keyword");
+
+ if (p.parseRParen())
+ return p.emitError(loc, "expected ')'");
+
+ attr = cir::LangAddressSpaceAttr::get(p.getContext(), result.value());
+ return mlir::success();
+ }
+
+ return mlir::success();
+}
+
+static 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");
+}
+
cir::TargetAddressSpaceAttr
cir::toCIRTargetAddressSpace(mlir::MLIRContext &context, clang::LangAS langAS) {
return cir::TargetAddressSpaceAttr::get(
>From c3df9636c1c5231c2418e342f2d605e1e731f6af Mon Sep 17 00:00:00 2001
From: David Rivera <davidriverg at gmail.com>
Date: Sat, 31 Jan 2026 12:09:57 -0500
Subject: [PATCH 2/2] like fix some format yo
---
clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 2 +-
clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 8b5cbf45c8e97..f528f54511a57 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -10,8 +10,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "mlir/IR/DialectImplementation.h"
#include "llvm/ADT/TypeSwitch.h"
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 2ba4a3c5ff080..8d97a8d5c88cd 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -60,12 +60,12 @@ static void printFuncTypeParams(mlir::AsmPrinter &p,
// AddressSpace
//===----------------------------------------------------------------------===//
-static mlir::ParseResult
+mlir::ParseResult
parseAddressSpaceValue(mlir::AsmParser &p,
mlir::ptr::MemorySpaceAttrInterface &attr);
-static void printAddressSpaceValue(mlir::AsmPrinter &printer,
- 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,
@@ -980,7 +980,7 @@ cir::LangAddressSpace cir::toCIRLangAddressSpace(clang::LangAS langAS) {
}
}
-static mlir::ParseResult
+mlir::ParseResult
parseAddressSpaceValue(mlir::AsmParser &p,
mlir::ptr::MemorySpaceAttrInterface &attr) {
@@ -1024,8 +1024,8 @@ parseAddressSpaceValue(mlir::AsmParser &p,
return mlir::success();
}
-static void printAddressSpaceValue(mlir::AsmPrinter &p,
- mlir::ptr::MemorySpaceAttrInterface attr) {
+void printAddressSpaceValue(mlir::AsmPrinter &p,
+ mlir::ptr::MemorySpaceAttrInterface attr) {
if (!attr)
return;
More information about the cfe-commits
mailing list