Author: Konstantinos Parasyris
Date: 2026-09-15T16:52:30-07:00
New Revision: 99f7a3ee4b76e0b77552f57a7cc9a4262ceddbd9

URL: 
https://github.com/llvm/llvm-project/commit/99f7a3ee4b76e0b77552f57a7cc9a4262ceddbd9
DIFF: 
https://github.com/llvm/llvm-project/commit/99f7a3ee4b76e0b77552f57a7cc9a4262ceddbd9.diff

LOG: [CIR][SYCL] Emit generic address space for default pointers in device code 
(#223464)

Added: 
    clang/test/CIR/CodeGenSYCL/kernel-caller-address-space.cpp

Modified: 
    clang/lib/CIR/CodeGen/CIRGenModule.cpp
    clang/lib/CIR/CodeGen/CIRGenTypes.cpp
    clang/lib/CIR/CodeGen/CIRGenTypes.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index bdc2707723283..3af6ce4ce6e94 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -2344,8 +2344,9 @@ LangAS CIRGenModule::getLangTempAllocaAddressSpace() 
const {
 
   if (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice)
     assert(!cir::MissingFeatures::openMP());
+
   if (getLangOpts().SYCLIsDevice)
-    errorNYI("SYCL temp address space");
+    return LangAS::Default;
 
   return LangAS::Default;
 }

diff  --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index f2cb875e908a7..9e5b8bbb82cb1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -544,7 +544,8 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
     const ReferenceType *refTy = cast<ReferenceType>(ty);
     QualType elemTy = refTy->getPointeeType();
     auto pointeeType = convertTypeForMem(elemTy);
-    resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
+    resultType =
+        builder.getPointerTo(pointeeType, getPointerAddressSpace(elemTy));
     assert(resultType && "Cannot get pointer type?");
     break;
   }
@@ -556,7 +557,8 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
 
     mlir::Type pointeeType = convertType(elemTy);
 
-    resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
+    resultType =
+        builder.getPointerTo(pointeeType, getPointerAddressSpace(elemTy));
     break;
   }
 
@@ -871,6 +873,23 @@ void CIRGenTypes::updateCompletedType(const TagDecl *td) {
   assert(!cir::MissingFeatures::generateDebugInfo());
 }
 
+mlir::ptr::MemorySpaceAttrInterface
+CIRGenTypes::getPointerAddressSpace(clang::QualType pointeeTy) const {
+  // An explicit source address space is carried directly.
+  if (pointeeTy.getAddressSpace() != LangAS::Default)
+    return cir::toCIRAddressSpaceAttr(getMLIRContext(),
+                                      pointeeTy.getAddressSpace());
+
+  // Resolve a default-address-space pointee through getTargetAddressSpace, as
+  // classic CodeGen does. This is only non-zero for languages that default to
+  // a non-default address space (e.g. generic for SYCL device data), and uses
+  // the program address space for functions.
+  unsigned targetAS = getTargetAddressSpace(pointeeTy);
+  if (targetAS == 0)
+    return {};
+  return cir::TargetAddressSpaceAttr::get(&getMLIRContext(), targetAS);
+}
+
 unsigned CIRGenTypes::getTargetAddressSpace(QualType ty) const {
   // Return the address space for the type. If the type is a
   // function type without an address space qualifier, the

diff  --git a/clang/lib/CIR/CodeGen/CIRGenTypes.h 
b/clang/lib/CIR/CodeGen/CIRGenTypes.h
index e2045f9e58d04..852e1f4ab6699 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.h
@@ -240,6 +240,14 @@ class CIRGenTypes {
   arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt);
 
   unsigned getTargetAddressSpace(QualType ty) const;
+
+  /// Returns the CIR address space for a pointer/reference to \p pointeeTy, or
+  /// a null attribute for the default address space. A default-address-space
+  /// pointee is resolved through getTargetAddressSpace (e.g. generic for SYCL
+  /// device data, program address space for functions), matching classic
+  /// CodeGen.
+  mlir::ptr::MemorySpaceAttrInterface
+  getPointerAddressSpace(clang::QualType pointeeTy) const;
 };
 
 } // namespace clang::CIRGen

diff  --git a/clang/test/CIR/CodeGenSYCL/kernel-caller-address-space.cpp 
b/clang/test/CIR/CodeGenSYCL/kernel-caller-address-space.cpp
new file mode 100644
index 0000000000000..306917a46502b
--- /dev/null
+++ b/clang/test/CIR/CodeGenSYCL/kernel-caller-address-space.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++20 -fsycl-is-device -triple spirv64-unknown-unknown 
-fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -std=c++20 -fsycl-is-device -triple spirv64-unknown-unknown 
-fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -std=c++20 -fsycl-is-device -triple spirv64-unknown-unknown 
-emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+
+// SYCL uses the "generic as default address space" deduction mode: unlike
+// OpenCL, the address space is not deduced in Sema, so an unqualified pointer
+// reaches CodeGen as LangAS::Default and must be given the generic address
+// space during device compilation. This verifies that a pointer captured by a
+// SYCL kernel is emitted in the generic address space (address space 4 on the
+// SPIR-V target), matching classic CodeGen.
+
+// Required by sycl_kernel_entry_point semantics.
+template <typename KernelName, typename... Ts>
+void sycl_kernel_launch(const char *, Ts...) {}
+
+template <typename KernelName, typename KernelType>
+[[clang::sycl_kernel_entry_point(KernelName)]]
+void kernel_single_task(KernelType kf) { kf(); }
+
+struct KN;
+
+void test(int *p) {
+  kernel_single_task<KN>([p]() { *p = 42; });
+}
+
+// The captured pointer lives in the closure object. Its default address space
+// is resolved to the generic address space.
+// CIR: !cir.ptr<!s32i, target_address_space(4)>
+
+// The kernel caller entry point receives the closure and casts it to the
+// generic address space before invoking the kernel functor.
+// CIR-LABEL: cir.func {{.*}}@_ZTS2KN
+// CIR:         cir.cast address_space {{.*}} -> !cir.ptr<{{.*}}, 
target_address_space(4)>
+
+// The kernel functor's operator() reads the captured pointer, which is a
+// generic-address-space pointer, and stores through it.
+// CIR-LABEL: cir.func {{.*}}@_ZZ4testPiENKUlvE_clEv
+// CIR:         cir.get_member {{.*}} -> !cir.ptr<!cir.ptr<!s32i, 
target_address_space(4)>>
+// CIR:         cir.store {{.*}} : !s32i, !cir.ptr<!s32i, 
target_address_space(4)>
+
+// The captured pointer field and the store through it use address space 4,
+// matching classic CodeGen.
+// LLVM: %class.anon{{.*}} = type { ptr addrspace(4) }
+// LLVM-LABEL: define {{.*}}@_ZZ4testPiENKUlvE_clEv(ptr addrspace(4)
+// LLVM:         store i32 42, ptr addrspace(4)
+
+struct FPKN;
+void callee();
+
+void test_fp() {
+  kernel_single_task<FPKN>([]() { void (*fp)() = callee; fp(); });
+}
+
+// Unlike data pointers, function pointers use the program address space (0),
+// not the generic address space: the pointee is a function type.
+// CIR-LABEL: cir.func {{.*}}@_ZZ7test_fpvENKUlvE_clEv
+// CIR:         cir.alloca {{.*}}"fp"{{.*}}: !cir.ptr<!cir.ptr<!cir.func<()>>>
+// LLVM-LABEL: define {{.*}}@_ZZ7test_fpvENKUlvE_clEv
+// LLVM:         store ptr @_Z6calleev, ptr


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

Reply via email to