[clang] [HLSL] Make it possible to assign an array from a cbuffer (PR #134174)
Sarah Spall via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 7 14:56:51 PDT 2025
https://github.com/spall updated https://github.com/llvm/llvm-project/pull/134174
>From 5d81a4b7b034dd5999feb6ab37537270d6bae2a8 Mon Sep 17 00:00:00 2001
From: Sarah Spall <sarahspall at microsoft.com>
Date: Wed, 2 Apr 2025 12:04:18 -0700
Subject: [PATCH] compare unqualified canonical types and add an hlsl array
rvalue cast
---
clang/lib/Sema/SemaExprCXX.cpp | 14 ++---
clang/lib/Sema/SemaOverload.cpp | 10 ++--
clang/test/CodeGenHLSL/ArrayAssignable.hlsl | 63 ++++++++++++++++++++-
3 files changed, 70 insertions(+), 17 deletions(-)
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index fa492bc124abd..dd4887c0b2878 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4418,19 +4418,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_HLSL_Array_RValue:
if (ToType->isArrayParameterType()) {
FromType = Context.getArrayParameterType(FromType);
- From = ImpCastExprToType(From, FromType, CK_HLSLArrayRValue, VK_PRValue,
- /*BasePath=*/nullptr, CCK)
- .get();
- } else { // FromType must be ArrayParameterType
- assert(FromType->isArrayParameterType() &&
- "FromType must be ArrayParameterType in ICK_HLSL_Array_RValue \
- if it is not ToType");
+ } else if (FromType->isArrayParameterType()) {
const ArrayParameterType *APT = cast<ArrayParameterType>(FromType);
FromType = APT->getConstantArrayType(Context);
- From = ImpCastExprToType(From, FromType, CK_HLSLArrayRValue, VK_PRValue,
- /*BasePath=*/nullptr, CCK)
- .get();
}
+ From = ImpCastExprToType(From, FromType, CK_HLSLArrayRValue, VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
break;
case ICK_Function_To_Pointer:
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 1802f8f4e1f91..d282fe50e49f1 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -2268,17 +2268,15 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// handling here.
if (ToType->isArrayParameterType()) {
FromType = S.Context.getArrayParameterType(FromType);
- SCS.First = ICK_HLSL_Array_RValue;
} else if (FromType->isArrayParameterType()) {
const ArrayParameterType *APT = cast<ArrayParameterType>(FromType);
FromType = APT->getConstantArrayType(S.Context);
- SCS.First = ICK_HLSL_Array_RValue;
- } else {
- SCS.First = ICK_Identity;
}
- if (S.Context.getCanonicalType(FromType) !=
- S.Context.getCanonicalType(ToType))
+ SCS.First = ICK_HLSL_Array_RValue;
+
+ if (FromType.getCanonicalType().getUnqualifiedType() !=
+ ToType.getCanonicalType().getUnqualifiedType())
return false;
SCS.setAllToTypes(ToType);
diff --git a/clang/test/CodeGenHLSL/ArrayAssignable.hlsl b/clang/test/CodeGenHLSL/ArrayAssignable.hlsl
index e2ff2de68ed99..723d521596baf 100644
--- a/clang/test/CodeGenHLSL/ArrayAssignable.hlsl
+++ b/clang/test/CodeGenHLSL/ArrayAssignable.hlsl
@@ -1,4 +1,23 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --enable-var-scope
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+
+struct S {
+ int x;
+ float f;
+};
+
+// CHECK: [[CBLayout:%.*]] = type <{ [2 x float], [2 x <4 x i32>], [2 x [2 x i32]], [1 x target("dx.Layout", %S, 8, 0, 4)] }>
+// CHECK: @CBArrays.cb = global target("dx.CBuffer", target("dx.Layout", [[CBLayout]], 136, 0, 32, 64, 128))
+// CHECK: @c1 = external addrspace(2) global [2 x float], align 4
+// CHECK: @c2 = external addrspace(2) global [2 x <4 x i32>], align 16
+// CHECK: @c3 = external addrspace(2) global [2 x [2 x i32]], align 4
+// CHECK: @c4 = external addrspace(2) global [1 x target("dx.Layout", %S, 8, 0, 4)], align 4
+
+cbuffer CBArrays {
+ float c1[2];
+ int4 c2[2];
+ int c3[2][2];
+ S c4[1];
+}
// CHECK-LABEL: define void {{.*}}arr_assign1
// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4
@@ -116,3 +135,45 @@ void arr_assign7() {
int Arr2[2][2] = {{0, 0}, {1, 1}};
(Arr = Arr2)[0] = {6, 6};
}
+
+// Verify you can assign from a cbuffer array
+
+// CHECK-LABEL: define void {{.*}}arr_assign8
+// CHECK: [[C:%.*]] = alloca [2 x float], align 4
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[C]], ptr align 4 {{.*}}, i32 8, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 4 [[C]], ptr addrspace(2) align 4 @c1, i32 8, i1 false)
+// CHECK-NEXT: ret void
+void arr_assign8() {
+ float C[2] = {1.0, 2.0};
+ C = c1;
+}
+
+// CHECK-LABEL: define void {{.*}}arr_assign9
+// CHECK: [[C:%.*]] = alloca [2 x <4 x i32>], align 16
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[C]], ptr align 16 {{.*}}, i32 32, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 16 [[C]], ptr addrspace(2) align 16 @c2, i32 32, i1 false)
+// CHECK-NEXT: ret void
+void arr_assign9() {
+ int4 C[2] = {1,2,3,4,5,6,7,8};
+ C = c2;
+}
+
+// CHECK-LABEL: define void {{.*}}arr_assign10
+// CHECK: [[C:%.*]] = alloca [2 x [2 x i32]], align 4
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[C]], ptr align 4 {{.*}}, i32 16, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 4 [[C]], ptr addrspace(2) align 4 @c3, i32 16, i1 false)
+// CHECK-NEXT: ret void
+void arr_assign10() {
+ int C[2][2] = {1,2,3,4};
+ C = c3;
+}
+
+// CHECK-LABEL: define void {{.*}}arr_assign11
+// CHECK: [[C:%.*]] = alloca [1 x %struct.S], align 4
+// CHECK: call void @llvm.memcpy.p0.p2.i32(ptr align 4 [[C]], ptr addrspace(2) align 4 @c4, i32 8, i1 false)
+// CHECK-NEXT: ret void
+void arr_assign11() {
+ S s = {1, 2.0};
+ S C[1] = {s};
+ C = c4;
+}
More information about the cfe-commits
mailing list