https://github.com/RiverDave created 
https://github.com/llvm/llvm-project/pull/179073

None

>From 9ddd795e75b8e4ca6fa1559eab17d8e8c9f3a542 Mon Sep 17 00:00:00 2001
From: David Rivera <[email protected]>
Date: Sat, 31 Jan 2026 17:32:31 -0500
Subject: [PATCH] [CIR] Implement MemorySpaceAttrInterface for lang and target
 specific AS attributes

---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h      |  20 ++--
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  |   2 +-
 clang/include/clang/CIR/Dialect/IR/CIRTypes.h |  14 ++-
 .../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/CIRTypes.cpp         | 104 +++++++++---------
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  23 +++-
 clang/test/CIR/IR/address-space.cir           |  41 +++++++
 clang/test/CIR/IR/invalid-addrspace.cir       |  32 +++++-
 15 files changed, 192 insertions(+), 102 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 2aaae86240cf2..de32aa227174d 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.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 4fbab2e83663d..0ab45f776f822 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -838,7 +838,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/CIRTypes.h 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
index 16c48ba4fb4e9..ff0abfd01caba 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
@@ -47,12 +47,18 @@ bool isSized(mlir::Type ty);
 
 cir::LangAddressSpace toCIRLangAddressSpace(clang::LangAS langAS);
 
-cir::TargetAddressSpaceAttr toCIRTargetAddressSpace(mlir::MLIRContext &context,
-                                                    clang::LangAS langAS);
-
-bool isMatchingAddressSpace(cir::TargetAddressSpaceAttr cirAS,
+// 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 5ba7726e9b1a6..a940047f38acf 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 0e5a5b531df78..474d2c0d00c8f 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 504f18e1a9f31..ce0e62164029a 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"
@@ -1437,9 +1438,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(),
@@ -2486,15 +2487,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 2af210bed98ff..62d9117562e8b 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 377c532e492d9..275ad03cfd61f 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"
 
@@ -73,8 +74,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 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>())
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h 
b/clang/lib/CIR/CodeGen/TargetInfo.h
index 9535ba94fb08b..25bde654810ad 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/CIRTypes.cpp 
b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 8d97a8d5c88cd..8a8ada3d9ec20 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"
@@ -313,14 +316,13 @@ Type RecordType::getLargestMember(const 
::mlir::DataLayout &dataLayout) const {
   auto endIt = getPadded() ? std::prev(members.end()) : members.end();
   if (endIt == members.begin())
     return {};
-  return *std::max_element(
-      members.begin(), endIt, [&](Type lhs, Type rhs) {
-        return dataLayout.getTypeABIAlignment(lhs) <
-                   dataLayout.getTypeABIAlignment(rhs) ||
-               (dataLayout.getTypeABIAlignment(lhs) ==
-                    dataLayout.getTypeABIAlignment(rhs) &&
-                dataLayout.getTypeSize(lhs) < dataLayout.getTypeSize(rhs));
-      });
+  return *std::max_element(members.begin(), endIt, [&](Type lhs, Type rhs) {
+    return dataLayout.getTypeABIAlignment(lhs) <
+               dataLayout.getTypeABIAlignment(rhs) ||
+           (dataLayout.getTypeABIAlignment(lhs) ==
+                dataLayout.getTypeABIAlignment(rhs) &&
+            dataLayout.getTypeSize(lhs) < dataLayout.getTypeSize(rhs));
+  });
 }
 
 bool RecordType::isLayoutIdentical(const RecordType &other) {
@@ -941,6 +943,12 @@ void cir::VectorType::print(mlir::AsmPrinter &odsPrinter) 
const {
 // AddressSpace definitions
 
//===----------------------------------------------------------------------===//
 
+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) {
@@ -999,8 +1007,7 @@ parseAddressSpaceValue(mlir::AsmParser &p,
     if (p.parseRParen())
       return p.emitError(loc, "expected ')'");
 
-    attr = cir::TargetAddressSpaceAttr::get(
-        p.getContext(), p.getBuilder().getUI32IntegerAttr(val));
+    attr = cir::TargetAddressSpaceAttr::get(p.getContext(), val);
     return mlir::success();
   }
 
@@ -1012,7 +1019,7 @@ parseAddressSpaceValue(mlir::AsmParser &p,
     mlir::FailureOr<cir::LangAddressSpace> result =
         mlir::FieldParser<cir::LangAddressSpace>::parse(p);
     if (mlir::failed(result))
-      return p.emitError(loc, "expected language address space keyword");
+      return mlir::failure();
 
     if (p.parseRParen())
       return p.emitError(loc, "expected ')'");
@@ -1021,6 +1028,12 @@ parseAddressSpaceValue(mlir::AsmParser &p,
     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'";
+
   return mlir::success();
 }
 
@@ -1043,55 +1056,42 @@ void printAddressSpaceValue(mlir::AsmPrinter &p,
   llvm_unreachable("unexpected address-space attribute kind");
 }
 
-cir::TargetAddressSpaceAttr
-cir::toCIRTargetAddressSpace(mlir::MLIRContext &context, clang::LangAS langAS) 
{
-  return cir::TargetAddressSpaceAttr::get(
-      &context,
-      IntegerAttr::get(&context,
-                       llvm::APSInt(clang::toTargetAddressSpace(langAS))));
-}
+mlir::ptr::MemorySpaceAttrInterface
+cir::toCIRAddressSpaceAttr(mlir::MLIRContext *ctx, clang::LangAS langAS) {
+  using clang::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 (langAS == LangAS::Default)
+    return {}; // Default address space is represented as an empty attribute.
 
-  if (!isTargetAddressSpace(as))
-    return false;
+  if (clang::isTargetAddressSpace(langAS)) {
+    unsigned targetAS = clang::toTargetAddressSpace(langAS);
+    return cir::TargetAddressSpaceAttr::get(ctx, targetAS);
+  }
 
-  return cirAS.getValue().getUInt() == toTargetAddressSpace(as);
+  return cir::LangAddressSpaceAttr::get(ctx, toCIRLangAddressSpace(langAS));
 }
 
-mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p,
-                                          cir::TargetAddressSpaceAttr &attr) {
-  if (failed(p.parseKeyword("target_address_space")))
-    return mlir::failure();
-
-  if (failed(p.parseLParen()))
-    return mlir::failure();
-
-  int32_t targetValue;
-  if (failed(p.parseInteger(targetValue)))
-    return p.emitError(p.getCurrentLocation(),
-                       "expected integer address space value");
+bool cir::isMatchingAddressSpace(mlir::MLIRContext &ctx,
+                                 mlir::ptr::MemorySpaceAttrInterface cirAS,
+                                 clang::LangAS as) {
+  return cir::toCIRAddressSpaceAttr(&ctx, as) == cirAS;
+}
 
-  if (failed(p.parseRParen()))
-    return p.emitError(p.getCurrentLocation(),
-                       "expected ')' after address space value");
+//===----------------------------------------------------------------------===//
+// PointerType Definitions
+//===----------------------------------------------------------------------===//
 
-  mlir::MLIRContext *context = p.getBuilder().getContext();
-  attr = cir::TargetAddressSpaceAttr::get(
-      context, p.getBuilder().getUI32IntegerAttr(targetValue));
-  return mlir::success();
-}
+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'";
+    }
+  }
 
-// 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() << ")";
+  return success();
 }
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index a774b0dcc6ba8..584d163e15073 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"
 
@@ -2953,14 +2956,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@below {{expected '(' after 'target_address_space'}}
 // expected-error@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@+2 {{expected integer value}}
-// expected-error@below {{expected integer address space value}}
+// expected-error@below {{expected target address space value}}
+// expected-error@below {{expected integer value}}
 cir.func @address_space3(%p : !cir.ptr<!u64i, target_address_space()>) {
   cir.return
 }
+
+// -----
+
+!u64i = !cir.int<u, 64>
+// expected-error@below {{expected '(' after 'lang_address_space'}}
+// expected-error@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@+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@+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
+}

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to