Skip to content

Commit f02b285

Browse files
authored
[HLSL] Reland; Make it possible to assign an array from a cbuffer (#136580)
Reland #134174 Update Sema Checking to always do an HLSL Array RValue cast in the case we are dealing with hlsl constant array types Instead of comparing canonical types, compare canonical unqualified types Add a test to show it is possible to assign an array from a cbuffer. Closes #133767
1 parent c179847 commit f02b285

File tree

3 files changed

+71
-17
lines changed

3 files changed

+71
-17
lines changed

clang/lib/Sema/SemaExprCXX.cpp

+4-10
Original file line numberDiff line numberDiff line change
@@ -4745,19 +4745,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
47454745
case ICK_HLSL_Array_RValue:
47464746
if (ToType->isArrayParameterType()) {
47474747
FromType = Context.getArrayParameterType(FromType);
4748-
From = ImpCastExprToType(From, FromType, CK_HLSLArrayRValue, VK_PRValue,
4749-
/*BasePath=*/nullptr, CCK)
4750-
.get();
4751-
} else { // FromType must be ArrayParameterType
4752-
assert(FromType->isArrayParameterType() &&
4753-
"FromType must be ArrayParameterType in ICK_HLSL_Array_RValue \
4754-
if it is not ToType");
4748+
} else if (FromType->isArrayParameterType()) {
47554749
const ArrayParameterType *APT = cast<ArrayParameterType>(FromType);
47564750
FromType = APT->getConstantArrayType(Context);
4757-
From = ImpCastExprToType(From, FromType, CK_HLSLArrayRValue, VK_PRValue,
4758-
/*BasePath=*/nullptr, CCK)
4759-
.get();
47604751
}
4752+
From = ImpCastExprToType(From, FromType, CK_HLSLArrayRValue, VK_PRValue,
4753+
/*BasePath=*/nullptr, CCK)
4754+
.get();
47614755
break;
47624756

47634757
case ICK_Function_To_Pointer:

clang/lib/Sema/SemaOverload.cpp

+5-6
Original file line numberDiff line numberDiff line change
@@ -2275,17 +2275,16 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
22752275
// handling here.
22762276
if (ToType->isArrayParameterType()) {
22772277
FromType = S.Context.getArrayParameterType(FromType);
2278-
SCS.First = ICK_HLSL_Array_RValue;
22792278
} else if (FromType->isArrayParameterType()) {
22802279
const ArrayParameterType *APT = cast<ArrayParameterType>(FromType);
22812280
FromType = APT->getConstantArrayType(S.Context);
2282-
SCS.First = ICK_HLSL_Array_RValue;
2283-
} else {
2284-
SCS.First = ICK_Identity;
22852281
}
22862282

2287-
if (S.Context.getCanonicalType(FromType) !=
2288-
S.Context.getCanonicalType(ToType))
2283+
SCS.First = ICK_HLSL_Array_RValue;
2284+
2285+
// Don't consider qualifiers, which include things like address spaces
2286+
if (FromType.getCanonicalType().getUnqualifiedType() !=
2287+
ToType.getCanonicalType().getUnqualifiedType())
22892288
return false;
22902289

22912290
SCS.setAllToTypes(ToType);

clang/test/CodeGenHLSL/ArrayAssignable.hlsl

+62-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,23 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --enable-var-scope
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
2+
3+
struct S {
4+
int x;
5+
float f;
6+
};
7+
8+
// 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)] }>
9+
// CHECK: @CBArrays.cb = global target("dx.CBuffer", target("dx.Layout", [[CBLayout]], 136, 0, 32, 64, 128))
10+
// CHECK: @c1 = external addrspace(2) global [2 x float], align 4
11+
// CHECK: @c2 = external addrspace(2) global [2 x <4 x i32>], align 16
12+
// CHECK: @c3 = external addrspace(2) global [2 x [2 x i32]], align 4
13+
// CHECK: @c4 = external addrspace(2) global [1 x target("dx.Layout", %S, 8, 0, 4)], align 4
14+
15+
cbuffer CBArrays : register(b0) {
16+
float c1[2];
17+
int4 c2[2];
18+
int c3[2][2];
19+
S c4[1];
20+
}
221

322
// CHECK-LABEL: define void {{.*}}arr_assign1
423
// CHECK: [[Arr:%.*]] = alloca [2 x i32], align 4
@@ -116,3 +135,45 @@ void arr_assign7() {
116135
int Arr2[2][2] = {{0, 0}, {1, 1}};
117136
(Arr = Arr2)[0] = {6, 6};
118137
}
138+
139+
// Verify you can assign from a cbuffer array
140+
141+
// CHECK-LABEL: define void {{.*}}arr_assign8
142+
// CHECK: [[C:%.*]] = alloca [2 x float], align 4
143+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[C]], ptr align 4 {{.*}}, i32 8, i1 false)
144+
// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 4 [[C]], ptr addrspace(2) align 4 @c1, i32 8, i1 false)
145+
// CHECK-NEXT: ret void
146+
void arr_assign8() {
147+
float C[2] = {1.0, 2.0};
148+
C = c1;
149+
}
150+
151+
// CHECK-LABEL: define void {{.*}}arr_assign9
152+
// CHECK: [[C:%.*]] = alloca [2 x <4 x i32>], align 16
153+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[C]], ptr align 16 {{.*}}, i32 32, i1 false)
154+
// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 16 [[C]], ptr addrspace(2) align 16 @c2, i32 32, i1 false)
155+
// CHECK-NEXT: ret void
156+
void arr_assign9() {
157+
int4 C[2] = {1,2,3,4,5,6,7,8};
158+
C = c2;
159+
}
160+
161+
// CHECK-LABEL: define void {{.*}}arr_assign10
162+
// CHECK: [[C:%.*]] = alloca [2 x [2 x i32]], align 4
163+
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[C]], ptr align 4 {{.*}}, i32 16, i1 false)
164+
// CHECK-NEXT: call void @llvm.memcpy.p0.p2.i32(ptr align 4 [[C]], ptr addrspace(2) align 4 @c3, i32 16, i1 false)
165+
// CHECK-NEXT: ret void
166+
void arr_assign10() {
167+
int C[2][2] = {1,2,3,4};
168+
C = c3;
169+
}
170+
171+
// CHECK-LABEL: define void {{.*}}arr_assign11
172+
// CHECK: [[C:%.*]] = alloca [1 x %struct.S], align 4
173+
// CHECK: call void @llvm.memcpy.p0.p2.i32(ptr align 4 [[C]], ptr addrspace(2) align 4 @c4, i32 8, i1 false)
174+
// CHECK-NEXT: ret void
175+
void arr_assign11() {
176+
S s = {1, 2.0};
177+
S C[1] = {s};
178+
C = c4;
179+
}

0 commit comments

Comments
 (0)