Skip to content

Commit 43279b3

Browse files
authored
Fix crashes related to handling of constexpr cast involving vector types (#3524)
1 parent ae83452 commit 43279b3

5 files changed

Lines changed: 149 additions & 14 deletions

File tree

tools/clang/lib/AST/ExprConstant.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5732,6 +5732,58 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
57325732
}
57335733
return Success(Elts, E);
57345734
}
5735+
case CK_HLSLVectorTruncationCast: {
5736+
if (!Visit(SE))
5737+
return Error(E);
5738+
unsigned destSize = hlsl::IsHLSLVecType(E->getType()) ? hlsl::GetHLSLVecSize(E->getType()) : 1;
5739+
unsigned srcSize = Result.getVectorLength();
5740+
// Given that this is a vector truncation op, dest size must be
5741+
// less than the source size.
5742+
if (destSize >= srcSize)
5743+
return Error(E);
5744+
5745+
SmallVector<APValue, 4> Elts;
5746+
for (uint32_t i = 0; i < destSize; ++i) {
5747+
APValue Elem = Result.getVectorElt(i);
5748+
Elts.push_back(Elem);
5749+
}
5750+
return Success(Elts, E);
5751+
}
5752+
case CK_HLSLCC_IntegralCast: {
5753+
if (!Visit(SE))
5754+
return Error(E);
5755+
SmallVector<APValue, 4> Elts;
5756+
for (uint32_t i = 0; i < Result.getVectorLength(); ++i) {
5757+
APValue Elem = Result.getVectorElt(i);
5758+
APSInt NewElemInt = HandleIntToIntCast(
5759+
Info, E, hlsl::GetHLSLVecElementType(E->getType()),
5760+
hlsl::GetHLSLVecElementType(SE->getType()), Elem.getInt());
5761+
APValue NewElem(NewElemInt);
5762+
Elts.push_back(NewElem);
5763+
}
5764+
return Success(Elts, E);
5765+
}
5766+
case CK_HLSLCC_FloatingToBoolean:
5767+
case CK_HLSLCC_IntegralToBoolean: {
5768+
if (!Visit(SE))
5769+
return Error(E);
5770+
SmallVector<APValue, 4> Elts;
5771+
for (uint32_t i = 0; i < Result.getVectorLength(); ++i) {
5772+
APValue Elem = Result.getVectorElt(i);
5773+
bool ResultBool;
5774+
if (!HandleConversionToBool(Elem, ResultBool))
5775+
return Error(E);
5776+
// Construct an int with bitwidth 1 to represent a boolean
5777+
APSInt ElemBool(/*BitWidth*/ 1);
5778+
if (ResultBool) {
5779+
// If the conversion to bool is true then set the LSB
5780+
ElemBool.setBit(0);
5781+
}
5782+
APValue NewElem(ElemBool);
5783+
Elts.push_back(NewElem);
5784+
}
5785+
return Success(Elts, E);
5786+
}
57355787
case CK_HLSLCC_IntegralToFloating: {
57365788
if (!Visit(SE))
57375789
return Error(E);

tools/clang/lib/CodeGen/CGExprConstant.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -744,8 +744,11 @@ class ConstExprEmitter :
744744
return nullptr;
745745
// HLSL Change Begins.
746746
case CK_HLSLCC_FloatingCast:
747+
case CK_HLSLCC_IntegralCast:
748+
case CK_HLSLCC_IntegralToBoolean:
747749
case CK_HLSLCC_IntegralToFloating:
748750
case CK_HLSLCC_FloatingToIntegral:
751+
case CK_HLSLCC_FloatingToBoolean:
749752
// Since these cast kinds have already been handled in ExprConstant.cpp,
750753
// we can reuse the logic there.
751754
return CGM.EmitConstantExpr(E, E->getType(), CGF);
@@ -773,18 +776,26 @@ class ConstExprEmitter :
773776
if (llvm::ConstantDataVector *CDV = dyn_cast<llvm::ConstantDataVector>(C)) {
774777
for (unsigned i = 0; i < vecSize; i++)
775778
Elts[i] = CDV->getElementAsConstant(i);
776-
} else {
777-
llvm::ConstantVector *CV = dyn_cast<llvm::ConstantVector>(C);
779+
} else if (llvm::ConstantVector* CV = dyn_cast<llvm::ConstantVector>(C)) {
778780
for (unsigned i = 0; i < vecSize; i++)
779781
Elts[i] = CV->getOperand(i);
782+
} else {
783+
llvm::ConstantAggregateZero* CAZ = cast<llvm::ConstantAggregateZero>(C);
784+
for (unsigned i = 0; i < vecSize; i++)
785+
Elts[i] = CAZ->getElementValue(i);
780786
}
781787
return llvm::ConstantVector::get(Elts);
782788
}
783789
case CK_HLSLVectorToScalarCast: {
784-
if (llvm::ConstantDataVector *CDV = cast<llvm::ConstantDataVector>(C))
790+
if (llvm::ConstantDataVector* CDV = dyn_cast<llvm::ConstantDataVector>(C)) {
785791
return CDV->getElementAsConstant(0);
786-
llvm::ConstantVector *CV = cast<llvm::ConstantVector>(C);
787-
return CV->getOperand(0);
792+
}
793+
else if (llvm::ConstantVector* CV = dyn_cast<llvm::ConstantVector>(C)) {
794+
return CV->getOperand(0);
795+
} else {
796+
llvm::ConstantAggregateZero* CAZ = cast<llvm::ConstantAggregateZero>(C);
797+
return CAZ->getElementValue((unsigned)0);
798+
}
788799
}
789800
case CK_HLSLMatrixTruncationCast: {
790801
llvm::StructType *ST =

tools/clang/test/CodeGenSPIRV/cast.vector.trunc.hlsl

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11
// Run: %dxc -T vs_6_0 -E main
22

3-
// CHECK: [[v4f32c:%\d+]] = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
4-
// CHECK: [[v3f32c:%\d+]] = OpConstantComposite %v3float %float_5 %float_6 %float_7
5-
// CHECK: [[v2f32c:%\d+]] = OpConstantComposite %v2float %float_8 %float_9
3+
// CHECK: [[v3f32c0:%\d+]] = OpConstantComposite %v3float %float_1 %float_2 %float_3
4+
// CHECK: [[v3f32c1:%\d+]] = OpConstantComposite %v3float %float_5 %float_6 %float_7
5+
// CHECK: [[v2f32c:%\d+]] = OpConstantComposite %v2float %float_8 %float_9
66

77
void main() {
88
// CHECK-LABEL: %bb_entry = OpLabel
99

1010
// From constant
11-
// CHECK: [[c1:%\d+]] = OpCompositeExtract %float [[v4f32c]] 0
12-
// CHECK-NEXT: [[c2:%\d+]] = OpCompositeExtract %float [[v4f32c]] 1
13-
// CHECK-NEXT: [[c3:%\d+]] = OpCompositeExtract %float [[v4f32c]] 2
14-
// CHECK-NEXT: [[vf3:%\d+]] = OpCompositeConstruct %v3float [[c1]] [[c2]] [[c3]]
15-
// CHECK-NEXT: OpStore %vf3 [[vf3]]
11+
// CHECK: OpStore %vf3 [[v3f32c0]]
1612
float3 vf3 = float4(1, 2, 3, 4);
17-
// CHECK-NEXT: [[c5:%\d+]] = OpCompositeExtract %float [[v3f32c]] 0
13+
// CHECK-NEXT: [[c5:%\d+]] = OpCompositeExtract %float [[v3f32c1]] 0
1814
// CHECK-NEXT: OpStore %vf1 [[c5]]
1915
float1 vf1;
2016
vf1 = float3(5, 6, 7);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DLHS_TY=uint -DRHS_TY=uint %s | FileCheck %s
2+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DLHS_TY=float16_t -DRHS_TY=float16_t %s | FileCheck %s
3+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DLHS_TY=bool -DRHS_TY=float16_t %s | FileCheck %s
4+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DLHS_TY=uint16_t -DRHS_TY=float %s | FileCheck %s
5+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DLHS_TY=uint -DRHS_TY=bool %s | FileCheck %s
6+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DLHS_TY=bool -DRHS_TY=uint %s | FileCheck %s
7+
8+
// This file tests truncation cast between two constexpr-vectors with different component count and/or types.
9+
10+
// CHECK: define void @main()
11+
12+
13+
RWByteAddressBuffer rwbab;
14+
15+
void main() : OUT {
16+
17+
// Case 1: all zero constant
18+
const LHS_TY s0 = vector<RHS_TY, 4>(0, 0, 0, 0);
19+
rwbab.Store(100, s0);
20+
21+
const vector<LHS_TY, 1> v1 = vector<RHS_TY, 4>(0, 0, 0, 0);
22+
rwbab.Store(200, v1);
23+
24+
const vector<LHS_TY, 2> v2 = vector<RHS_TY, 4>(0, 0, 0, 0);
25+
rwbab.Store(300, v2);
26+
27+
const vector<LHS_TY, 3> v3 = vector<RHS_TY, 4>(0, 0, 0, 0);
28+
rwbab.Store(400, v3);
29+
30+
const vector<LHS_TY, 4> v4 = vector<RHS_TY, 4>(0, 0, 0, 0);
31+
rwbab.Store(500, v4);
32+
33+
// Case 2: Non-zero constant
34+
const LHS_TY s1 = vector<RHS_TY, 4>(1, 2, 3, 4);
35+
rwbab.Store(600, s1);
36+
37+
const vector<LHS_TY, 1> v5 = vector<RHS_TY, 4>(1, 2, 3, 4);
38+
rwbab.Store(700, v5);
39+
40+
const vector<LHS_TY, 2> v6 = vector<RHS_TY, 4>(1, 2, 3, 4);
41+
rwbab.Store(800, v6);
42+
43+
const vector<LHS_TY, 3> v7 = vector<RHS_TY, 4>(1, 2, 3, 4);
44+
rwbab.Store(900, v7);
45+
46+
const vector<LHS_TY, 4> v8 = vector<RHS_TY, 4>(1, 2, 3, 4);
47+
rwbab.Store(1000, v8);
48+
49+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DVEC1 -DLHS_TY=uint16_t -DRHS_TY=uint %s | FileCheck %s
2+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DVEC1 -DLHS_TY=uint -DRHS_TY=uint16_t %s | FileCheck %s
3+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DVEC1 -DLHS_TY=bool -DRHS_TY=int %s | FileCheck %s
4+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DVEC1 -DLHS_TY=float -DRHS_TY=bool %s | FileCheck %s
5+
// RUN: %dxc -E main -T vs_6_2 -enable-16bit-types -DVEC1 -DLHS_TY=float -DRHS_TY=float16_t %s | FileCheck %s
6+
7+
8+
// This file tests cast between two constexpr-vectors having same component count, but different component types.
9+
10+
// CHECK: define void @main()
11+
12+
13+
RWByteAddressBuffer rwbab;
14+
15+
void main() : OUT {
16+
const vector<LHS_TY, 1> v1 = vector<RHS_TY, 1>(0);
17+
rwbab.Store(256, v1);
18+
19+
const vector<LHS_TY, 2> v2 = vector<RHS_TY, 2>(1, 2);
20+
rwbab.Store(512, v2);
21+
22+
const vector<LHS_TY, 3> v3 = vector<RHS_TY, 3>(4, 5, 6);
23+
rwbab.Store(1024, v3);
24+
25+
const vector<LHS_TY, 4> v4 = vector<RHS_TY, 4>(7, 8, 9, 10);
26+
rwbab.Store(2048, v4);
27+
}

0 commit comments

Comments
 (0)