[HLSL] Add an lvalue to rvalue cast when appropriate for HLSLElementwiseCast and HLSLAggregateSplatCast (#163828)

When the Sub expression of an HLSLAggregateSplatCast is an LValue insert
an LValue to RValue cast; done using DefaultLvalueConversion.
When the Sub expression of an HLSLElementwiseCast is an LValue and not a
record or an array insert an LValue to RValue cast.
Arrays were already handled correctly using an HLSLArrayRValue cast.

DefaultLvalueConversion is used to add the LValue to RValue cast when
appropriate and does not emit one when the expression is a record.

Update existing test which was broken by this change. Add two new tests
for HLSLElementwiseCast showing the lack of lvalue to rvalue cast for a
struct and showing the lvalue to rvalue cast for a vector.

Closes #163593
This commit is contained in:
Sarah Spall
2025-10-16 11:28:13 -07:00
committed by GitHub
parent a0b66b56c1
commit 8ebbb20dff
3 changed files with 31 additions and 3 deletions

View File

@@ -2927,6 +2927,8 @@ bool CastOperation::CheckHLSLCStyleCast(CheckedConversionKind CCK) {
SrcExpr = Self.ImpCastExprToType(
SrcExpr.get(), Self.Context.getArrayParameterType(SrcTy),
CK_HLSLArrayRValue, VK_PRValue, nullptr, CCK);
else
SrcExpr = Self.DefaultLvalueConversion(SrcExpr.get());
Kind = CK_HLSLElementwiseCast;
return true;
}
@@ -2935,6 +2937,7 @@ bool CastOperation::CheckHLSLCStyleCast(CheckedConversionKind CCK) {
// If the relative order of this and the HLSLElementWise cast checks
// are changed, it might change which cast handles what in a few cases
if (Self.HLSL().CanPerformAggregateSplatCast(SrcExpr.get(), DestType)) {
SrcExpr = Self.DefaultLvalueConversion(SrcExpr.get());
const VectorType *VT = SrcTy->getAs<VectorType>();
// change splat from vec1 case to splat from scalar
if (VT && VT->getNumElements() == 1)

View File

@@ -3,8 +3,9 @@
// splat from vec1 to vec
// CHECK-LABEL: call1
// CHECK: CStyleCastExpr {{.*}} 'int3':'vector<int, 3>' <HLSLAggregateSplatCast>
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' lvalue <FloatingToIntegral> part_of_explicit_cast
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' lvalue <HLSLVectorTruncation> part_of_explicit_cast
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <FloatingToIntegral> part_of_explicit_cast
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <HLSLVectorTruncation> part_of_explicit_cast
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float1':'vector<float, 1>' <LValueToRValue> part_of_explicit_cast
// CHECK-NEXT: DeclRefExpr {{.*}} 'float1':'vector<float, 1>' lvalue Var {{.*}} 'A' 'float1':'vector<float, 1>'
export void call1() {
float1 A = {1.0};
@@ -21,7 +22,7 @@ struct S {
// splat from scalar to aggregate
// CHECK-LABEL: call2
// CHECK: CStyleCastExpr {{.*}} 'S' <HLSLAggregateSplatCast>
// CHECK-NEXt: IntegerLiteral {{.*}} 'int' 5
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 5
export void call2() {
S s = (S)5;
}

View File

@@ -21,3 +21,27 @@ export void call2() {
float B[1] = {1.0};
B = (float[1])A;
}
struct S {
int A;
float F;
};
// cast from a struct
// CHECK-LABEL: call3
// CHECK: CStyleCastExpr {{.*}} 'int[2]' <HLSLElementwiseCast>
// CHECK-NEXT: DeclRefExpr {{.*}} 'S' lvalue Var {{.*}} 'SS' 'S'
export void call3() {
S SS = {1,1.0};
int A[2] = (int[2])SS;
}
// cast from a vector
// CHECK-LABEL: call4
// CHECK: CStyleCastExpr {{.*}} 'float[3]' <HLSLElementwiseCast>
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int3':'vector<int, 3>' <LValueToRValue> part_of_explicit_cast
// CHECK-NEXT: DeclRefExpr {{.*}} 'int3':'vector<int, 3>' lvalue Var {{.*}} 'A' 'int3'
export void call4() {
int3 A = {1,2,3};
float B[3] = (float[3])A;
}