https://github.com/aobolensk created 
https://github.com/llvm/llvm-project/pull/233828

Casts between function and object pointers failed CIR verification on targets 
with a separate program address space, like spirv64-intel

>From c84d5fc921f22d26afd6febd5ba97a4f887b93db Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <[email protected]>
Date: Tue, 20 Oct 2026 14:56:08 +0200
Subject: [PATCH] [CIR] Cast address spaces in pointer bitcasts

Casts between function and object pointers failed CIR verification on targets 
with a separate program address space, like spirv64-intel
---
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    |  9 ++++-
 .../CIR/CodeGen/spirv-intel-fn-ptr-cast.c     | 34 +++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CIR/CodeGen/spirv-intel-fn-ptr-cast.c

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index b1c40d9840b7d..179e6202130bd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -2657,7 +2657,14 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr 
*ce) {
     mlir::Value src = Visit(const_cast<Expr *>(subExpr));
     mlir::Type dstTy = cgf.convertType(destTy);
 
-    assert(!cir::MissingFeatures::addressSpace());
+    // Function and object pointers may differ in address space.
+    auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(src.getType());
+    auto dstPtrTy = mlir::dyn_cast<cir::PointerType>(dstTy);
+    if (srcPtrTy && dstPtrTy &&
+        srcPtrTy.getAddrSpace() != dstPtrTy.getAddrSpace())
+      src = cgf.performAddrSpaceCast(
+          src,
+          builder.getPointerTo(srcPtrTy.getPointee(), 
dstPtrTy.getAddrSpace()));
 
     if (cgf.sanOpts.has(SanitizerKind::CFIUnrelatedCast))
       cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
diff --git a/clang/test/CIR/CodeGen/spirv-intel-fn-ptr-cast.c 
b/clang/test/CIR/CodeGen/spirv-intel-fn-ptr-cast.c
new file mode 100644
index 0000000000000..d5f6d3d863f80
--- /dev/null
+++ b/clang/test/CIR/CodeGen/spirv-intel-fn-ptr-cast.c
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple spirv64-intel -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple spirv64-intel -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple spirv64-intel -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+// CIR-LABEL: cir.func{{.*}} @fp_to_void_ptr
+// CIR: %[[FP:.*]] = cir.load{{.*}} : {{.*}}, !cir.ptr<!cir.func<()>, 
target_address_space(9)>
+// CIR: %[[AS:.*]] = cir.cast address_space %[[FP]] : !cir.ptr<!cir.func<()>, 
target_address_space(9)> -> !cir.ptr<!cir.func<()>, target_address_space(4)>
+// CIR: cir.cast bitcast %[[AS]] : !cir.ptr<!cir.func<()>, 
target_address_space(4)> -> !cir.ptr<!void, target_address_space(4)>
+
+// LLVM-LABEL: define{{.*}} ptr addrspace(4) @fp_to_void_ptr
+// LLVM: %[[FP:.*]] = load ptr addrspace(9), ptr addrspace(4)
+// LLVM: addrspacecast ptr addrspace(9) %[[FP]] to ptr addrspace(4)
+
+// OGCG-LABEL: define{{.*}} ptr addrspace(4) @fp_to_void_ptr
+// OGCG: %[[FP:.*]] = load ptr addrspace(9), ptr addrspace(4)
+// OGCG: addrspacecast ptr addrspace(9) %[[FP]] to ptr addrspace(4)
+void *fp_to_void_ptr(void (*fp)(void)) { return (void *)fp; }
+
+// CIR-LABEL: cir.func{{.*}} @void_ptr_to_fp
+// CIR: %[[P:.*]] = cir.load{{.*}} : {{.*}}, !cir.ptr<!void, 
target_address_space(4)>
+// CIR: %[[AS:.*]] = cir.cast address_space %[[P]] : !cir.ptr<!void, 
target_address_space(4)> -> !cir.ptr<!void, target_address_space(9)>
+// CIR: cir.cast bitcast %[[AS]] : !cir.ptr<!void, target_address_space(9)> -> 
!cir.ptr<!cir.func<()>, target_address_space(9)>
+
+// LLVM-LABEL: define{{.*}} ptr addrspace(9) @void_ptr_to_fp
+// LLVM: %[[P:.*]] = load ptr addrspace(4), ptr addrspace(4)
+// LLVM: addrspacecast ptr addrspace(4) %[[P]] to ptr addrspace(9)
+
+// OGCG-LABEL: define{{.*}} ptr addrspace(9) @void_ptr_to_fp
+// OGCG: %[[P:.*]] = load ptr addrspace(4), ptr addrspace(4)
+// OGCG: addrspacecast ptr addrspace(4) %[[P]] to ptr addrspace(9)
+void (*void_ptr_to_fp(void *p))(void) { return (void (*)(void))p; }

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

Reply via email to