https://github.com/RiverDave updated 
https://github.com/llvm/llvm-project/pull/161028

>From 42940a5ebddba0ed3030d8b63285f79d21bcfdc1 Mon Sep 17 00:00:00 2001
From: David Rivera <davidriv...@gmail.com>
Date: Sat, 27 Sep 2025 19:14:52 -0400
Subject: [PATCH] [CIR] Upstream `AddressSpace` support for `PointerType`

---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h      |  16 ++-
 clang/include/clang/CIR/Dialect/IR/CIRAttrs.h |   1 +
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  |  41 ++++++
 .../clang/CIR/Dialect/IR/CIREnumAttr.td       |  24 ++++
 clang/include/clang/CIR/Dialect/IR/CIRTypes.h |  38 +++++
 .../include/clang/CIR/Dialect/IR/CIRTypes.td  |  62 +++++---
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp          |   3 +-
 clang/lib/CIR/CodeGen/CIRGenTypeCache.h       |   6 +
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp         |   2 +-
 clang/lib/CIR/CodeGen/TargetInfo.h            |   2 +
 clang/lib/CIR/Dialect/IR/CIRAttrs.cpp         |   9 ++
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp         | 133 +++++++++++++++---
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  19 ++-
 clang/test/CIR/IR/invalid-addrspace.cir       |  36 +++++
 clang/test/CIR/address-space.c                |  22 +++
 15 files changed, 370 insertions(+), 44 deletions(-)
 create mode 100644 clang/test/CIR/IR/invalid-addrspace.cir
 create mode 100644 clang/test/CIR/address-space.c

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index a3f167e3cde2c..cef8624e65d57 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -129,8 +129,20 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return cir::PointerType::get(ty);
   }
 
-  cir::PointerType getVoidPtrTy() {
-    return getPointerTo(cir::VoidType::get(getContext()));
+  cir::PointerType getPointerTo(mlir::Type ty, cir::AddressSpace as) {
+    return cir::PointerType::get(ty, as);
+  }
+
+  cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
+    return getPointerTo(ty, cir::toCIRAddressSpace(langAS));
+  }
+
+  cir::PointerType getVoidPtrTy(clang::LangAS langAS = clang::LangAS::Default) 
{
+    return getPointerTo(cir::VoidType::get(getContext()), langAS);
+  }
+
+  cir::PointerType getVoidPtrTy(cir::AddressSpace as) {
+    return getPointerTo(cir::VoidType::get(getContext()), as);
   }
 
   cir::BoolAttr getCIRBoolAttr(bool state) {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
index 925a9a87e267f..03a6a97dc8c2e 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
@@ -15,6 +15,7 @@
 
 #include "mlir/IR/Attributes.h"
 #include "mlir/IR/BuiltinAttributeInterfaces.h"
+#include "clang/Basic/AddressSpaces.h"
 
 #include "clang/CIR/Dialect/IR/CIROpsEnums.h"
 
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index f8358de9a1eb9..01dd2106136ab 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -601,6 +601,47 @@ def CIR_VTableAttr : CIR_Attr<"VTable", "vtable", 
[TypedAttrInterface]> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// AddressSpaceAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_AddressSpaceAttr : CIR_EnumAttr<CIR_AddressSpace, "address_space"> {
+  let builders = [AttrBuilder<(ins "clang::LangAS":$langAS), [{
+      return $_get($_ctxt, cir::toCIRAddressSpace(langAS));
+    }]>];
+
+  let assemblyFormat = [{
+    `` custom<AddressSpaceValue>($value)
+  }];
+
+  let defaultValue = "cir::AddressSpace::Default";
+
+  let extraClassDeclaration = [{
+    bool isLang() const;
+    bool isTarget() const;
+    unsigned getTargetValue() const;
+    unsigned getAsUnsignedValue() const;
+  }];
+
+  let extraClassDefinition = [{
+    unsigned $cppClass::getAsUnsignedValue() const {
+      return static_cast<unsigned>(getValue());
+    }
+
+    bool $cppClass::isLang() const {
+      return cir::isLangAddressSpace(getValue());
+    }
+
+    bool $cppClass::isTarget() const {
+      return cir::isTargetAddressSpace(getValue());
+    }
+
+    unsigned $cppClass::getTargetValue() const {
+      return cir::getTargetAddressSpaceValue(getValue());
+    }
+  }];
+}
+
 
//===----------------------------------------------------------------------===//
 // ConstComplexAttr
 
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td 
b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
index 98b8a31d2a18a..6566b8e771a75 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
@@ -35,4 +35,28 @@ class CIR_DefaultValuedEnumParameter<EnumAttrInfo info, 
string value = "">
   let defaultValue = value;
 }
 
+def CIR_AddressSpace
+    : CIR_I32EnumAttr<
+          "AddressSpace", "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">,
+           I32EnumAttrCase<"Target", 6, "target">]> {
+  let description = [{
+    The `address_space` attribute is used to represent address spaces for
+    pointer types in CIR. It provides a unified model on top of `clang::LangAS`
+    and simplifies the representation of address spaces.
+
+    The `value` parameter is an extensible enum, which encodes target address
+    space as an offset to the last language address space. For that reason, the
+    attribute is implemented as custom AddressSpaceAttr, which provides custom
+    printer and parser for the `value` parameter.
+  }];
+
+  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 bfa165cdd945e..6a2b02ce46cd6 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
@@ -16,6 +16,8 @@
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/Types.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
 #include "clang/CIR/Interfaces/CIRTypeInterfaces.h"
 
 namespace cir {
@@ -35,6 +37,42 @@ bool isValidFundamentalIntWidth(unsigned width);
 /// void, or abstract types.
 bool isSized(mlir::Type ty);
 
+//===----------------------------------------------------------------------===//
+// AddressSpace helpers
+//===----------------------------------------------------------------------===//
+
+cir::AddressSpace toCIRAddressSpace(clang::LangAS langAS);
+
+constexpr unsigned getAsUnsignedValue(cir::AddressSpace as) {
+  return static_cast<unsigned>(as);
+}
+
+inline constexpr unsigned targetAddressSpaceOffset =
+    cir::getMaxEnumValForAddressSpace();
+
+// Target address space is used for target-specific address spaces that are not
+// part of the enum. Its value is represented as an offset from the maximum
+// value of the enum. Make sure that it is always the last enum value.
+static_assert(getAsUnsignedValue(cir::AddressSpace::Target) ==
+                  cir::getMaxEnumValForAddressSpace(),
+              "Target address space must be the last enum value");
+
+constexpr bool isTargetAddressSpace(cir::AddressSpace as) {
+  return getAsUnsignedValue(as) >= cir::getMaxEnumValForAddressSpace();
+}
+
+constexpr bool isLangAddressSpace(cir::AddressSpace as) {
+  return !isTargetAddressSpace(as);
+}
+
+constexpr unsigned getTargetAddressSpaceValue(cir::AddressSpace as) {
+  assert(isTargetAddressSpace(as) && "expected target address space");
+  return getAsUnsignedValue(as) - targetAddressSpaceOffset;
+}
+
+constexpr cir::AddressSpace computeTargetAddressSpace(unsigned v) {
+  return static_cast<cir::AddressSpace>(v + targetAddressSpaceOffset);
+}
 } // namespace cir
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 4eec34cb299ab..13edfc5143650 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -14,10 +14,12 @@
 #define CLANG_CIR_DIALECT_IR_CIRTYPES_TD
 
 include "clang/CIR/Dialect/IR/CIRDialect.td"
+include "clang/CIR/Dialect/IR/CIREnumAttr.td"
 include "clang/CIR/Dialect/IR/CIRTypeConstraints.td"
 include "clang/CIR/Interfaces/CIRTypeInterfaces.td"
 include "mlir/Interfaces/DataLayoutInterfaces.td"
 include "mlir/IR/AttrTypeBase.td"
+include "mlir/IR/EnumAttr.td"
 
 
//===----------------------------------------------------------------------===//
 // CIR Types
@@ -226,31 +228,57 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
 ]> {
   let summary = "CIR pointer type";
   let description = [{
-    The `!cir.ptr` type represents C and C++ pointer types and C++ reference
-    types, other than pointers-to-members.  The `pointee` type is the type
-    pointed to.
+    The `!cir.ptr` type is a typed pointer type. It is used to represent
+    pointers to objects in C/C++. The type of the pointed-to object is given by
+    the `pointee` parameter. The `addrSpace` parameter is an optional address
+    space attribute that specifies the address space of the pointer. If not
+    specified, the pointer is assumed to be in the default address space.
 
-    TODO(CIR): The address space attribute is not yet implemented.
-  }];
+    The `!cir.ptr` type can point to any type, including fundamental types,
+    records, arrays, vectors, functions, and other pointers. It can also point
+    to incomplete types, such as incomplete records.
 
-  let parameters = (ins "mlir::Type":$pointee);
+    Note: Data-member pointers and method pointers are represented by
+    `!cir.data_member` and `!cir.method` types, respectively not by
+    `!cir.ptr` type.
 
-  let builders = [
-    TypeBuilderWithInferredContext<(ins "mlir::Type":$pointee), [{
-      return $_get(pointee.getContext(), pointee);
-    }]>,
-    TypeBuilder<(ins "mlir::Type":$pointee), [{
-      return $_get($_ctxt, pointee);
-    }]>
-  ];
+    Examples:
 
-  let assemblyFormat = [{
-    `<` $pointee  `>`
+    ```mlir
+    !cir.ptr<!cir.int<u, 8>>
+    !cir.ptr<!cir.float>
+    !cir.ptr<!cir.record<struct "MyStruct">>
+    !cir.ptr<!cir.record<struct "MyStruct">, addrspace(offload_private)>
+    !cir.ptr<!cir.int<u, 8>, addrspace(target<1>)>
+    ```
   }];
 
-  let genVerifyDecl = 1;
+  let parameters = (ins "mlir::Type":$pointee,
+      CIR_DefaultValuedEnumParameter<CIR_AddressSpace,
+                                     "cir::AddressSpace::Default">:$addrSpace);
 
   let skipDefaultBuilders = 1;
+  let builders = [TypeBuilderWithInferredContext<
+                      (ins "mlir::Type":$pointee,
+                          CArg<"cir::AddressSpace",
+                               "cir::AddressSpace::Default">:$addrSpace),
+                      [{
+        return $_get(pointee.getContext(), pointee, addrSpace);
+    }]>,
+                  TypeBuilder<
+                      (ins "mlir::Type":$pointee,
+                          CArg<"cir::AddressSpace",
+                               "cir::AddressSpace::Default">:$addrSpace),
+                      [{
+        return $_get($_ctxt, pointee, addrSpace);
+    }]>];
+
+  let assemblyFormat = [{
+    `<`
+      $pointee
+      ( `,` `addrspace` `(` custom<AddressSpaceValue>($addrSpace)^ `)` )?
+    `>`
+  }];
 
   let extraClassDeclaration = [{
     template <typename ...Types>
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index fa68ad931ba74..44626bbdd1dfa 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -2053,7 +2053,8 @@ mlir::Value CIRGenFunction::emitAlloca(StringRef name, 
mlir::Type ty,
   // layout like original CodeGen. The data layout awareness should be done in
   // the lowering pass instead.
   assert(!cir::MissingFeatures::addressSpace());
-  cir::PointerType localVarPtrTy = builder.getPointerTo(ty);
+  cir::PointerType localVarPtrTy =
+      builder.getPointerTo(ty, getCIRAllocaAddressSpace());
   mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);
 
   mlir::Value addr;
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h 
b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
index cc3ce09be4f95..b95f0404eb8d9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
@@ -73,6 +73,8 @@ struct CIRGenTypeCache {
   /// The alignment of size_t.
   unsigned char SizeAlignInBytes;
 
+  cir::AddressSpace cirAllocaAddressSpace;
+
   clang::CharUnits getSizeAlign() const {
     return clang::CharUnits::fromQuantity(SizeAlignInBytes);
   }
@@ -80,6 +82,10 @@ struct CIRGenTypeCache {
   clang::CharUnits getPointerAlign() const {
     return clang::CharUnits::fromQuantity(PointerAlignInBytes);
   }
+
+  cir::AddressSpace getCIRAllocaAddressSpace() const {
+    return cirAllocaAddressSpace;
+  }
 };
 
 } // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index bb24933a22ed7..e65896a9ff109 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -417,7 +417,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
 
     mlir::Type pointeeType = convertType(elemTy);
 
-    resultType = builder.getPointerTo(pointeeType);
+    resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
     break;
   }
 
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h 
b/clang/lib/CIR/CodeGen/TargetInfo.h
index a5c548aa2c7c4..1c3ba0b9971b3 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.h
+++ b/clang/lib/CIR/CodeGen/TargetInfo.h
@@ -32,6 +32,8 @@ bool isEmptyFieldForLayout(const ASTContext &context, const 
FieldDecl *fd);
 /// if the [[no_unique_address]] attribute would have made them empty.
 bool isEmptyRecordForLayout(const ASTContext &context, QualType t);
 
+class CIRGenFunction;
+
 class TargetCIRGenInfo {
   std::unique_ptr<ABIInfo> info;
 
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp 
b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 95faad6746955..ac3e08c880614 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -43,6 +43,15 @@ parseFloatLiteral(mlir::AsmParser &parser,
                   mlir::FailureOr<llvm::APFloat> &value,
                   cir::FPTypeInterface fpType);
 
+//===----------------------------------------------------------------------===//
+// AddressSpaceAttr
+//===----------------------------------------------------------------------===//
+
+mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p,
+                                         cir::AddressSpace &addrSpace);
+
+void printAddressSpaceValue(mlir::AsmPrinter &p, cir::AddressSpace addrSpace);
+
 static mlir::ParseResult parseConstPtr(mlir::AsmParser &parser,
                                        mlir::IntegerAttr &value);
 
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp 
b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 35b4513c5789f..32254fb1e21c1 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -38,6 +38,26 @@ parseFuncTypeParams(mlir::AsmParser &p, 
llvm::SmallVector<mlir::Type> &params,
 static void printFuncTypeParams(mlir::AsmPrinter &p,
                                 mlir::ArrayRef<mlir::Type> params,
                                 bool isVarArg);
+//===----------------------------------------------------------------------===//
+// CIR Custom Parser/Printer Signatures
+//===----------------------------------------------------------------------===//
+
+static mlir::ParseResult
+parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector<mlir::Type> &params,
+                    bool &isVarArg);
+
+static void printFuncTypeParams(mlir::AsmPrinter &p,
+                                mlir::ArrayRef<mlir::Type> params,
+                                bool isVarArg);
+
+//===----------------------------------------------------------------------===//
+// AddressSpace
+//===----------------------------------------------------------------------===//
+
+mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p,
+                                         cir::AddressSpace &addrSpace);
+
+void printAddressSpaceValue(mlir::AsmPrinter &p, cir::AddressSpace addrSpace);
 
 
//===----------------------------------------------------------------------===//
 // Get autogenerated stuff
@@ -297,6 +317,20 @@ bool RecordType::isLayoutIdentical(const RecordType 
&other) {
 // Data Layout information for types
 
//===----------------------------------------------------------------------===//
 
+llvm::TypeSize
+PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
+                               ::mlir::DataLayoutEntryListRef params) const {
+  // FIXME: improve this in face of address spaces
+  return llvm::TypeSize::getFixed(64);
+}
+
+uint64_t
+PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
+                             ::mlir::DataLayoutEntryListRef params) const {
+  // FIXME: improve this in face of address spaces
+  return 8;
+}
+
 llvm::TypeSize
 RecordType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
                               mlir::DataLayoutEntryListRef params) const {
@@ -766,30 +800,93 @@ mlir::LogicalResult cir::VectorType::verify(
 }
 
 
//===----------------------------------------------------------------------===//
-// PointerType Definitions
-//===----------------------------------------------------------------------===//
-
-llvm::TypeSize
-PointerType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
-                               ::mlir::DataLayoutEntryListRef params) const {
-  // FIXME: improve this in face of address spaces
-  return llvm::TypeSize::getFixed(64);
+// AddressSpace definitions
+//===----------------------------------------------------------------------===//
+
+cir::AddressSpace cir::toCIRAddressSpace(clang::LangAS langAS) {
+  using clang::LangAS;
+  switch (langAS) {
+  case LangAS::Default:
+    return AddressSpace::Default;
+  case LangAS::opencl_global:
+    return AddressSpace::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 AddressSpace::OffloadLocal;
+  case LangAS::cuda_device:
+    return AddressSpace::OffloadGlobal;
+  case LangAS::opencl_constant:
+  case LangAS::cuda_constant:
+    return AddressSpace::OffloadConstant;
+  case LangAS::opencl_private:
+    return AddressSpace::OffloadPrivate;
+  case LangAS::opencl_generic:
+    return AddressSpace::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:
+    // Target address space offset arithmetics
+    return static_cast<cir::AddressSpace>(clang::toTargetAddressSpace(langAS) +
+                                          cir::getMaxEnumValForAddressSpace());
+  }
 }
 
-uint64_t
-PointerType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
-                             ::mlir::DataLayoutEntryListRef params) const {
-  // FIXME: improve this in face of address spaces
-  return 8;
-}
+mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p,
+                                         cir::AddressSpace &addrSpace) {
+  llvm::SMLoc loc = p.getCurrentLocation();
+  mlir::FailureOr<cir::AddressSpace> result =
+      mlir::FieldParser<cir::AddressSpace>::parse(p);
+  if (mlir::failed(result))
+    return p.emitError(loc, "expected address space keyword");
+
+  // Address space is either a target address space or a regular one.
+  // - If it is a target address space, we expect a value to follow in the form
+  // of `<value>`, where value is an integer that represents the target address
+  // space value. This value is kept in the address space enum as an offset
+  // from the maximum address space value, which is defined in
+  // `cir::getMaxEnumValForAddressSpace()`. This allows us to use
+  // the same enum for both regular and target address spaces.
+  // - Otherwise, we just use the parsed value.
+  if (cir::isTargetAddressSpace(result.value())) {
+    if (p.parseLess())
+      return p.emitError(loc, "expected '<' after target address space");
+
+    int64_t targetValue;
+    if (p.parseInteger(targetValue) || p.parseGreater())
+      return p.emitError(loc, "expected target address space value");
+
+    addrSpace = cir::computeTargetAddressSpace(targetValue);
+  } else {
+    addrSpace = result.value();
+  }
 
-mlir::LogicalResult
-PointerType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
-                    mlir::Type pointee) {
-  // TODO(CIR): Verification of the address space goes here.
   return mlir::success();
 }
 
+// Prints the address space value in the form of:
+// - `target<value>` for target address spaces
+// - or just the address space name for regular address spaces.
+void printAddressSpaceValue(mlir::AsmPrinter &p, cir::AddressSpace addrSpace) {
+  if (cir::isTargetAddressSpace(addrSpace))
+    p << cir::stringifyEnum(cir::AddressSpace::Target) << '<'
+      << cir::getTargetAddressSpaceValue(addrSpace) << '>';
+  else
+    p << cir::stringifyEnum(addrSpace);
+}
+
 
//===----------------------------------------------------------------------===//
 // CIR Dialect
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 876948d53010b..5c674a71d1569 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2298,14 +2298,23 @@ mlir::LogicalResult 
CIRToLLVMSelectOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+static unsigned
+getTargetAddrSpaceFromCIRAddrSpace(cir::AddressSpace addrSpace) {
+  if (addrSpace == cir::AddressSpace::Default)
+    return 0; // Default address space is always 0 in LLVM.
+
+  if (cir::isTargetAddressSpace(addrSpace))
+    return cir::getTargetAddressSpaceValue(addrSpace);
+
+  llvm_unreachable("CIR AS map is not available");
+}
+
 static void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
                                  mlir::DataLayout &dataLayout) {
   converter.addConversion([&](cir::PointerType type) -> mlir::Type {
-    // Drop pointee type since LLVM dialect only allows opaque pointers.
-    assert(!cir::MissingFeatures::addressSpace());
-    unsigned targetAS = 0;
-
-    return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS);
+    unsigned addrSpace =
+        getTargetAddrSpaceFromCIRAddrSpace(type.getAddrSpace());
+    return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace);
   });
   converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
     assert(!cir::MissingFeatures::addressSpace());
diff --git a/clang/test/CIR/IR/invalid-addrspace.cir 
b/clang/test/CIR/IR/invalid-addrspace.cir
new file mode 100644
index 0000000000000..d65599a770bb7
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-addrspace.cir
@@ -0,0 +1,36 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+// -----
+
+!u64i = !cir.int<u, 64>
+// expected-error@below {{expected address space keyword}}
+// expected-error@below {{expected keyword for address space kind}}
+cir.func @address_space1(%p : !cir.ptr<!u64i, addrspace()>) {
+  cir.return
+}
+
+// -----
+
+!u64i = !cir.int<u, 64>
+// expected-error@below {{expected target address space value}}
+// expected-error@below {{expected integer value}}
+cir.func @address_space2(%p : !cir.ptr<!u64i, addrspace(target<>)>) {
+  cir.return
+}
+
+// -----
+
+!u64i = !cir.int<u, 64>
+// expected-error@below {{expected '<'}}
+cir.func @address_space3(%p : !cir.ptr<!u64i, addrspace(target)>) {
+  cir.return
+}
+
+// -----
+
+!u64i = !cir.int<u, 64>
+// expected-error@below {{expected one of [default, offload_private, 
offload_local, offload_global, offload_constant, offload_generic, target] for 
address space kind, got: foobar}}
+// expected-error@below {{expected address space keyword}}
+cir.func @address_space4(%p : !cir.ptr<!u64i, addrspace(foobar)>) {
+  cir.return
+}
\ No newline at end of file
diff --git a/clang/test/CIR/address-space.c b/clang/test/CIR/address-space.c
new file mode 100644
index 0000000000000..d131fb84d98dc
--- /dev/null
+++ b/clang/test/CIR/address-space.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+
+// CIR: cir.func dso_local {{@.*foo.*}}(%arg0: !cir.ptr<!s32i, 
addrspace(target<1>)>
+// LLVM: define dso_local void @foo(ptr addrspace(1) %0)
+void foo(int __attribute__((address_space(1))) *arg) {
+  return;
+}
+
+// CIR: cir.func dso_local {{@.*bar.*}}(%arg0: !cir.ptr<!s32i, 
addrspace(target<0>)>
+// LLVM: define dso_local void @bar(ptr %0)
+void bar(int __attribute__((address_space(0))) *arg) {
+  return;
+}
+
+// CIR: cir.func dso_local {{@.*baz.*}}(%arg0: !cir.ptr<!s32i>
+// LLVM: define dso_local void @baz(ptr %0)
+void baz(int *arg) {
+  return;
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to