1*4407cf95SChris B// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -fnative-half-type %s -DERRORS -Wconversion -Wdouble-promotion -verify 2*4407cf95SChris B// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl2018 -finclude-default-header -fnative-half-type %s -DERRORS -Wconversion -Wdouble-promotion -verify 3*4407cf95SChris B// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -fnative-half-type %s -ast-dump | FileCheck %s 4*4407cf95SChris B 5*4407cf95SChris B#if __HLSL_VERSION <= 2021 6*4407cf95SChris B// expected-warning@*{{support for HLSL language version hlsl2018 is incomplete, recommend using hlsl202x instead}} 7*4407cf95SChris B#endif 8*4407cf95SChris B 9*4407cf95SChris B//----------------------------------------------------------------------------// 10*4407cf95SChris B// Case 1: float4 * int4 and inverse. 11*4407cf95SChris B// 12*4407cf95SChris B// In both cases here the int is converted to a float and the computation 13*4407cf95SChris B// produces a float value. 14*4407cf95SChris B//----------------------------------------------------------------------------// 15*4407cf95SChris B 16*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used f4f4i4 'float4 (float4, int4)' 17*4407cf95SChris B// CHECK: BinaryOperator {{.*}} 'float4':'vector<float, 4>' '*' 18*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <LValueToRValue> 19*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>' 20*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <IntegralToFloating> 21*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue> 22*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>' 23*4407cf95SChris Bexport float4 f4f4i4(float4 A, int4 B) { 24*4407cf95SChris B return A * B; // expected-warning{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float4' (aka 'vector<float, 4>') may lose precision}} 25*4407cf95SChris B} 26*4407cf95SChris B 27*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used f4i4f4 'float4 (float4, int4)' 28*4407cf95SChris B// CHECK: BinaryOperator {{.*}} 'float4':'vector<float, 4>' '*' 29*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <IntegralToFloating> 30*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue> 31*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>' 32*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <LValueToRValue> 33*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>' 34*4407cf95SChris Bexport float4 f4i4f4(float4 A, int4 B) { 35*4407cf95SChris B return B * A; // expected-warning{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float4' (aka 'vector<float, 4>') may lose precision}} 36*4407cf95SChris B} 37*4407cf95SChris B 38*4407cf95SChris B//----------------------------------------------------------------------------// 39*4407cf95SChris B// Case 2: float4 * int2 and inverse. 40*4407cf95SChris B// 41*4407cf95SChris B// In both cases the float vector is trunctated to a float2 and the integer 42*4407cf95SChris B// vector is converted to a float2. 43*4407cf95SChris B//----------------------------------------------------------------------------// 44*4407cf95SChris B 45*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used f2f4i2 'float2 (float4, int2)' 46*4407cf95SChris B// CHECK: BinaryOperator {{.*}} 'vector<float, 2>' '*' 47*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>' <HLSLVectorTruncation> 48*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}}'float4':'vector<float, 4>' <LValueToRValue> 49*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>' 50*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>' <IntegralToFloating> 51*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int2':'vector<int, 2>' <LValueToRValue> 52*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'B' 'int2':'vector<int, 2>' 53*4407cf95SChris Bexport float2 f2f4i2(float4 A, int2 B) { 54*4407cf95SChris B // expected-warning@#f2f4i2 {{implicit conversion from 'int2' (aka 'vector<int, 2>') to 'vector<float, 2>' (vector of 2 'float' values) may lose precision}} 55*4407cf95SChris B // expected-warning@#f2f4i2 {{implicit conversion truncates vector: 'float4' (aka 'vector<float, 4>') to 'vector<float, 2>' (vector of 2 'float' values)}} 56*4407cf95SChris B return A * B; // #f2f4i2 57*4407cf95SChris B} 58*4407cf95SChris B 59*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used f2i2f4 'float2 (float4, int2)' 60*4407cf95SChris B// CHECK: BinaryOperator {{.*}} 'vector<float, 2>' '*' 61*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>' <IntegralToFloating> 62*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int2':'vector<int, 2>' <LValueToRValue> 63*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'B' 'int2':'vector<int, 2>' 64*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>' <HLSLVectorTruncation> 65*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}}'float4':'vector<float, 4>' <LValueToRValue> 66*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>' 67*4407cf95SChris Bexport float2 f2i2f4(float4 A, int2 B) { 68*4407cf95SChris B // expected-warning@#f2i2f4 {{implicit conversion from 'int2' (aka 'vector<int, 2>') to 'vector<float, 2>' (vector of 2 'float' values) may lose precision}} 69*4407cf95SChris B // expected-warning@#f2i2f4 {{implicit conversion truncates vector: 'float4' (aka 'vector<float, 4>') to 'vector<float, 2>' (vector of 2 'float' values)}} 70*4407cf95SChris B return B * A; // #f2i2f4 71*4407cf95SChris B} 72*4407cf95SChris B 73*4407cf95SChris B//----------------------------------------------------------------------------// 74*4407cf95SChris B// Case 3: Integers of mismatched sign, equivalent size, but the unsigned type 75*4407cf95SChris B// has lower conversion rank. 76*4407cf95SChris B// 77*4407cf95SChris B// This is the odd-ball case for HLSL that isn't really in spec, but we should 78*4407cf95SChris B// handle gracefully. The lower-ranked unsigned type is converted to the 79*4407cf95SChris B// equivalent unsigned type of higher rank, and the signed type is also 80*4407cf95SChris B// converted to that unsigned type (meaning `unsigned long` becomes `unsinged 81*4407cf95SChris B// long long`, and `long long` becomes `unsigned long long`). 82*4407cf95SChris B//----------------------------------------------------------------------------// 83*4407cf95SChris B 84*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used wierdo 'int4 (vector<unsigned long, 4>, vector<long long, 4>)' 85*4407cf95SChris B// CHECK: BinaryOperator {{.*}} 'vector<unsigned long long, 4>' '*' 86*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<unsigned long long, 4>' <IntegralCast> 87*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<unsigned long, 4>' <LValueToRValue> 88*4407cf95SChris B// CHECK-NEXT: DeclRefExpr{{.*}} 'vector<unsigned long, 4>' lvalue ParmVar {{.*}} 'A' 'vector<unsigned long, 4>' 89*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<unsigned long long, 4>' <IntegralCast> 90*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr{{.*}}> 'vector<long long, 4>' <LValueToRValue> 91*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}}'vector<long long, 4>' lvalue ParmVar {{.*}} 'B' 'vector<long long, 4>' 92*4407cf95SChris Bexport int4 wierdo(vector<unsigned long, 4> A, vector<long long, 4> B) { 93*4407cf95SChris B // expected-warning@#wierdo {{implicit conversion loses integer precision: 'vector<unsigned long long, 4>' (vector of 4 'unsigned long long' values) to 'vector<int, 4>' (vector of 4 'int' values)}} 94*4407cf95SChris B // expected-warning@#wierdo {{implicit conversion changes signedness: 'vector<long long, 4>' (vector of 4 'long long' values) to 'vector<unsigned long long, 4>' (vector of 4 'unsigned long long' values)}} 95*4407cf95SChris B return A * B; // #wierdo 96*4407cf95SChris B} 97*4407cf95SChris B 98*4407cf95SChris B//----------------------------------------------------------------------------// 99*4407cf95SChris B// Case 4: Compound assignment of float4 with an int4. 100*4407cf95SChris B// 101*4407cf95SChris B// In compound assignment the RHS is converted to match the LHS. 102*4407cf95SChris B//----------------------------------------------------------------------------// 103*4407cf95SChris B 104*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used f4f4i4compound 'float4 (float4, int4)' 105*4407cf95SChris B// CHECK: CompoundAssignOperator {{.*}} 'float4':'vector<float, 4>' lvalue '+=' ComputeLHSTy='float4':'vector<float, 4>' ComputeResultTy='float4':'vector<float, 4>' 106*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>' 107*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <IntegralToFloating> 108*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue> 109*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>' 110*4407cf95SChris Bexport float4 f4f4i4compound(float4 A, int4 B) { 111*4407cf95SChris B A += B; // expected-warning{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float4' (aka 'vector<float, 4>') may lose precision}} 112*4407cf95SChris B return A; 113*4407cf95SChris B} 114*4407cf95SChris B 115*4407cf95SChris B 116*4407cf95SChris B//----------------------------------------------------------------------------// 117*4407cf95SChris B// Case 5: Compound assignment of float2 with an int4. 118*4407cf95SChris B// 119*4407cf95SChris B// In compound assignment the RHS is converted to match the LHS. 120*4407cf95SChris B//----------------------------------------------------------------------------// 121*4407cf95SChris B 122*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used f4f2i4compound 'float4 (float2, int4)' 123*4407cf95SChris B// CHECK: CompoundAssignOperator {{.*}} 'float2':'vector<float, 2>' lvalue '+=' ComputeLHSTy='float2':'vector<float, 2>' ComputeResultTy='float2':'vector<float, 2>' 124*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue ParmVar {{.*}} 'A' 'float2':'vector<float, 2>' 125*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <IntegralToFloating> 126*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>' <HLSLVectorTruncation> 127*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue> 128*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>' 129*4407cf95SChris Bexport float4 f4f2i4compound(float2 A, int4 B) { 130*4407cf95SChris B // expected-warning@#f4f2i4compound{{implicit conversion truncates vector: 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>')}} 131*4407cf95SChris B // expected-warning@#f4f2i4compound{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>') may lose precision}} 132*4407cf95SChris B A += B; // #f4f2i4compound 133*4407cf95SChris B return A.xyxy; 134*4407cf95SChris B} 135*4407cf95SChris B 136*4407cf95SChris B//----------------------------------------------------------------------------// 137*4407cf95SChris B// Case 6: float2 * int4 138*4407cf95SChris B// 139*4407cf95SChris B// The int4 vector is trunctated to int2 then converted to float2. 140*4407cf95SChris B//----------------------------------------------------------------------------// 141*4407cf95SChris B 142*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used f4f2i4 'float2 (float2, int4)' 143*4407cf95SChris B// CHECK: BinaryOperator {{.*}} 'float2':'vector<float, 2>' '*' 144*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <LValueToRValue> 145*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue ParmVar {{.*}} 'A' 'float2':'vector<float, 2>' 146*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <IntegralToFloating> 147*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>' <HLSLVectorTruncation> 148*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue> 149*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>' 150*4407cf95SChris Bexport float2 f4f2i4(float2 A, int4 B) { 151*4407cf95SChris B // expected-warning@#f4f2i4{{implicit conversion truncates vector: 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>')}} 152*4407cf95SChris B // expected-warning@#f4f2i4{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>') may lose precision}} 153*4407cf95SChris B return A * B; // #f4f2i4 154*4407cf95SChris B} 155*4407cf95SChris B 156*4407cf95SChris B//----------------------------------------------------------------------------// 157*4407cf95SChris B// Case 7: Compound assignment of half4 with float4, and inverse. 158*4407cf95SChris B// 159*4407cf95SChris B// In compound assignment the RHS is converted to match the LHS. 160*4407cf95SChris B//----------------------------------------------------------------------------// 161*4407cf95SChris B 162*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used f4h4f4compound 'float4 (half4, float4)' 163*4407cf95SChris B// CHECK: CompoundAssignOperator {{.*}} 'half4':'vector<half, 4>' lvalue '+=' ComputeLHSTy='half4':'vector<half, 4>' ComputeResultTy='half4':'vector<half, 4>' 164*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'half4':'vector<half, 4>' lvalue ParmVar {{.*}} 'A' 'half4':'vector<half, 4>' 165*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' <FloatingCast> 166*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <LValueToRValue> 167*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'B' 'float4':'vector<float, 4>' 168*4407cf95SChris Bexport float4 f4h4f4compound(half4 A, float4 B) { 169*4407cf95SChris B A += B; // expected-warning{{implicit conversion loses floating-point precision: 'float4' (aka 'vector<float, 4>') to 'half4' (aka 'vector<half, 4>')}} 170*4407cf95SChris B return B; 171*4407cf95SChris B} 172*4407cf95SChris B 173*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used f4f4h4compound 'float4 (float4, half4)' 174*4407cf95SChris B// CHECK: CompoundAssignOperator {{.*}} 'float4':'vector<float, 4>' lvalue '+=' ComputeLHSTy='float4':'vector<float, 4>' ComputeResultTy='float4':'vector<float, 4>' 175*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>' 176*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <FloatingCast> 177*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' <LValueToRValue> 178*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'half4':'vector<half, 4>' lvalue ParmVar {{.*}} 'B' 'half4':'vector<half, 4>' 179*4407cf95SChris Bexport float4 f4f4h4compound(float4 A, half4 B) { 180*4407cf95SChris B A += B; // expected-warning{{implicit conversion increases floating-point precision: 'half4' (aka 'vector<half, 4>') to 'float4' (aka 'vector<float, 4>')}} 181*4407cf95SChris B return A; 182*4407cf95SChris B} 183*4407cf95SChris B 184*4407cf95SChris B//----------------------------------------------------------------------------// 185*4407cf95SChris B// Case 8: int64_t4 * uint4 186*4407cf95SChris B// 187*4407cf95SChris B// The unsigned argument is promoted to the higher ranked signed type since it 188*4407cf95SChris B// can express all values of the unsgined argument. 189*4407cf95SChris B//----------------------------------------------------------------------------// 190*4407cf95SChris B 191*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used l4l4i4 'int64_t4 (int64_t4, uint4)' 192*4407cf95SChris B// CHECK: BinaryOperator {{.*}} 'int64_t4':'vector<int64_t, 4>' '*' 193*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t4':'vector<int64_t, 4>' <LValueToRValue> 194*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int64_t4':'vector<int64_t, 4>' lvalue ParmVar {{.*}} 'A' 'int64_t4':'vector<int64_t, 4>' 195*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t4':'vector<int64_t, 4>' <IntegralCast> 196*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'uint4':'vector<uint, 4>' <LValueToRValue> 197*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'uint4':'vector<uint, 4>' lvalue ParmVar {{.*}} 'B' 'uint4':'vector<uint, 4>' 198*4407cf95SChris Bexport int64_t4 l4l4i4(int64_t4 A, uint4 B) { 199*4407cf95SChris B return A * B; 200*4407cf95SChris B} 201*4407cf95SChris B 202*4407cf95SChris B//----------------------------------------------------------------------------// 203*4407cf95SChris B// Case 9: Compound assignment of int4 from int64_t4 204*4407cf95SChris B// 205*4407cf95SChris B// In compound assignment the RHS is converted to match the LHS. 206*4407cf95SChris B//----------------------------------------------------------------------------// 207*4407cf95SChris B 208*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used i4i4l4compound 'int4 (int4, int64_t4)' 209*4407cf95SChris B// CHECK: CompoundAssignOperator {{.*}} 'int4':'vector<int, 4>' lvalue '+=' ComputeLHSTy='int4':'vector<int, 4>' ComputeResultTy='int4':'vector<int, 4>' 210*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'A' 'int4':'vector<int, 4>' 211*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <IntegralCast> 212*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t4':'vector<int64_t, 4>' <LValueToRValue> 213*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int64_t4':'vector<int64_t, 4>' lvalue ParmVar {{.*}} 'B' 'int64_t4':'vector<int64_t, 4>' 214*4407cf95SChris Bexport int4 i4i4l4compound(int4 A, int64_t4 B) { 215*4407cf95SChris B A += B; // expected-warning{{implicit conversion loses integer precision: 'int64_t4' (aka 'vector<int64_t, 4>') to 'int4' (aka 'vector<int, 4>')}} 216*4407cf95SChris B return A; 217*4407cf95SChris B} 218*4407cf95SChris B 219*4407cf95SChris B//----------------------------------------------------------------------------// 220*4407cf95SChris B// Case 10: Compound assignment of vector<unsigned long, 4> with argument of 221*4407cf95SChris B// vector<long long, 4> 222*4407cf95SChris B// 223*4407cf95SChris B// In compound assignment the RHS is converted to match the LHS. This one is 224*4407cf95SChris B// also the weird case because it is out of spec, but we should handle it 225*4407cf95SChris B// gracefully. 226*4407cf95SChris B//----------------------------------------------------------------------------// 227*4407cf95SChris B 228*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used wierdocompound 'vector<unsigned long, 4> (vector<unsigned long, 4>, vector<long long, 4>)' 229*4407cf95SChris B// CHECK: CompoundAssignOperator {{.*}} 'vector<unsigned long, 4>' lvalue '+=' ComputeLHSTy='vector<unsigned long, 4>' ComputeResultTy='vector<unsigned long, 4>' 230*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<unsigned long, 4>' lvalue ParmVar {{.*}} 'A' 'vector<unsigned long, 4>' 231*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<unsigned long, 4>' <IntegralCast> 232*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<long long, 4>' <LValueToRValue> 233*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'vector<long long, 4>' lvalue ParmVar {{.*}} 'B' 'vector<long long, 4>' 234*4407cf95SChris Bexport vector<unsigned long, 4> wierdocompound(vector<unsigned long, 4> A, vector<long long, 4> B) { 235*4407cf95SChris B // expected-warning@#wierdocompound{{implicit conversion changes signedness: 'vector<long long, 4>' (vector of 4 'long long' values) to 'vector<unsigned long, 4>' (vector of 4 'unsigned long' values)}} 236*4407cf95SChris B A += B; // #wierdocompound 237*4407cf95SChris B return A; 238*4407cf95SChris B} 239*4407cf95SChris B 240*4407cf95SChris B//----------------------------------------------------------------------------// 241*4407cf95SChris B// Case 11: Compound assignment of scalar with vector argument. 242*4407cf95SChris B// 243*4407cf95SChris B// Because the LHS of a compound assignment cannot change type, the RHS must be 244*4407cf95SChris B// implicitly convertable to the LHS type. 245*4407cf95SChris B//----------------------------------------------------------------------------// 246*4407cf95SChris B 247*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used ffi2compound 'float (float, int2)' 248*4407cf95SChris B// CHECK: CompoundAssignOperator {{.*}} 'float' lvalue '+=' ComputeLHSTy='float' ComputeResultTy='float' 249*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'A' 'float' 250*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <IntegralToFloating> 251*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <HLSLVectorTruncation> 252*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int2':'vector<int, 2>' <LValueToRValue> 253*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'B' 'int2':'vector<int, 2>' 254*4407cf95SChris Bexport float ffi2compound(float A, int2 B) { 255*4407cf95SChris B A += B; // expected-warning {{implicit conversion turns vector to scalar: 'int2' (aka 'vector<int, 2>') to 'float'}} 256*4407cf95SChris B return A; 257*4407cf95SChris B} 258*4407cf95SChris B 259*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used iif2compound 'int (int, float2)' 260*4407cf95SChris B// CHECK: CompoundAssignOperator {{.*}} 'int' lvalue '+=' ComputeLHSTy='int' ComputeResultTy='int' 261*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'A' 'int' 262*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <FloatingToIntegral> 263*4407cf95SChris B// CHECK-NEXT: mplicitCastExpr {{.*}} 'float' <HLSLVectorTruncation> 264*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr{{.*}} 'float2':'vector<float, 2>' <LValueToRValue> 265*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue ParmVar {{.*}} 'B' 'float2':'vector<float, 2>' 266*4407cf95SChris Bexport int iif2compound(int A, float2 B) { 267*4407cf95SChris B A += B; // expected-warning{{implicit conversion turns vector to scalar: 'float2' (aka 'vector<float, 2>') to 'int'}} 268*4407cf95SChris B return A; 269*4407cf95SChris B} 270*4407cf95SChris B 271*4407cf95SChris B 272*4407cf95SChris B//----------------------------------------------------------------------------// 273*4407cf95SChris B// Case 12: Compound assignment of vector of larger size than the argument. 274*4407cf95SChris B// 275*4407cf95SChris B// Because the LHS of a compound assignment cannot change type, the RHS must be 276*4407cf95SChris B// implicitly convertable to the LHS type. This fails since the RHS type can't 277*4407cf95SChris B// be vector-extended implicitly. 278*4407cf95SChris B//----------------------------------------------------------------------------// 279*4407cf95SChris B 280*4407cf95SChris B#ifdef ERRORS 281*4407cf95SChris B// The only cases that are really illegal here are when the RHS is a vector that 282*4407cf95SChris B// is larger than the LHS or when the LHS is a scalar. 283*4407cf95SChris B 284*4407cf95SChris Bexport float2 f2f4i2compound(float4 A, int2 B) { 285*4407cf95SChris B A += B; // expected-error{{left hand operand of type 'float4' (aka 'vector<float, 4>') to compound assignment cannot be truncated when used with right hand operand of type 'int2' (aka 'vector<int, 2>')}} 286*4407cf95SChris B return A.xy; 287*4407cf95SChris B} 288*4407cf95SChris B 289*4407cf95SChris B#endif 290*4407cf95SChris B 291*4407cf95SChris B//----------------------------------------------------------------------------// 292*4407cf95SChris B// Case 13: Comparison operators for mismatched arguments follow the same rules. 293*4407cf95SChris B// 294*4407cf95SChris B// Compare operators convert each argument following the usual arithmetic 295*4407cf95SChris B// conversions. 296*4407cf95SChris B//----------------------------------------------------------------------------// 297*4407cf95SChris B 298*4407cf95SChris B// Note: these cases work and generate correct code, but the way they get there 299*4407cf95SChris B// may change with https://github.com/llvm/llvm-project/issues/91639, because 300*4407cf95SChris B// representing boolean vectors as 32-bit integer vectors will allow more 301*4407cf95SChris B// efficient code generation. 302*4407cf95SChris B 303*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used b4f4i4Compare 'bool4 (float4, int4)' 304*4407cf95SChris B// CHECK: ImplicitCastExpr {{.*}} 'vector<bool, 4>' <IntegralToBoolean> 305*4407cf95SChris B// CHECK-NEXT: BinaryOperator {{.*}} 'vector<int, 4>' '<' 306*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <LValueToRValue> 307*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar {{.*}} 'A' 'float4':'vector<float, 4>' 308*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' <IntegralToFloating> 309*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue> 310*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>' 311*4407cf95SChris Bexport bool4 b4f4i4Compare(float4 A, int4 B) { 312*4407cf95SChris B return A < B; // expected-warning{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float4' (aka 'vector<float, 4>') may lose precision}} 313*4407cf95SChris B} 314*4407cf95SChris B 315*4407cf95SChris B 316*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used b2f2i4Compare 'bool2 (float2, int4)' 317*4407cf95SChris B// CHECK: ImplicitCastExpr {{.*}} 'vector<bool, 2>' <IntegralToBoolean> 318*4407cf95SChris B// CHECK-NEXT: BinaryOperator {{.*}} 'vector<int, 2>' '<=' 319*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <LValueToRValue> 320*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue ParmVar {{.*}} 'A' 'float2':'vector<float, 2>' 321*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <IntegralToFloating> 322*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>' <HLSLVectorTruncation> 323*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue> 324*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>' 325*4407cf95SChris B 326*4407cf95SChris Bexport bool2 b2f2i4Compare(float2 A, int4 B) { 327*4407cf95SChris B // expected-warning@#b2f2i4Compare{{implicit conversion truncates vector: 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>')}} 328*4407cf95SChris B // expected-warning@#b2f2i4Compare{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>') may lose precision}} 329*4407cf95SChris B return A <= B; // #b2f2i4Compare 330*4407cf95SChris B} 331*4407cf95SChris B 332*4407cf95SChris B// CHECK-LABEL: FunctionDecl {{.*}} used b4fi4Compare 'bool4 (float, int4)' 333*4407cf95SChris B// CHECK: ImplicitCastExpr {{.*}} 'vector<bool, 4>' <IntegralToBoolean> 334*4407cf95SChris B// CHECK-NEXT: BinaryOperator {{.*}} 'vector<int, 4>' '>' 335*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 4>' <VectorSplat> 336*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue> 337*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'A' 'float' 338*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 4>' <IntegralToFloating> 339*4407cf95SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue> 340*4407cf95SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar {{.*}} 'B' 'int4':'vector<int, 4>' 341*4407cf95SChris Bexport bool4 b4fi4Compare(float A, int4 B) { 342*4407cf95SChris B return A > B; // expected-warning{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'vector<float, 4>' (vector of 4 'float' values) may lose precision}} 343*4407cf95SChris B} 344*4407cf95SChris B 345*4407cf95SChris B//----------------------------------------------------------------------------// 346*4407cf95SChris B// Case 14: Logical operators on vectors are disallowed in HLSL 2021+ 347*4407cf95SChris B//----------------------------------------------------------------------------// 348*4407cf95SChris B 349*4407cf95SChris B#ifdef ERRORS 350*4407cf95SChris B 351*4407cf95SChris B#if __HLSL_VERSION >= 2021 352*4407cf95SChris B// expected-error@#b4f4i4Logical{{invalid operands to binary expression ('float4' (aka 'vector<float, 4>') and 'int4' (aka 'vector<int, 4>'))}} 353*4407cf95SChris B// expected-note@#b4f4i4Logical{{did you mean or?}} 354*4407cf95SChris B#else 355*4407cf95SChris B// expected-warning@#b4f4i4Logical{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float4' (aka 'vector<float, 4>') may lose precision}} 356*4407cf95SChris B#endif 357*4407cf95SChris B 358*4407cf95SChris Bexport bool4 b4f4i4Logical(float4 A, int4 B) { 359*4407cf95SChris B return A || B; // #b4f4i4Logical 360*4407cf95SChris B} 361*4407cf95SChris B 362*4407cf95SChris B#if __HLSL_VERSION >= 2021 363*4407cf95SChris B// expected-error@#b2f2i4Logical{{invalid operands to binary expression ('float2' (aka 'vector<float, 2>') and 'int4' (aka 'vector<int, 4>'))}} 364*4407cf95SChris B// expected-note@#b2f2i4Logical{{did you mean and?}} 365*4407cf95SChris B#else 366*4407cf95SChris B// expected-warning@#b2f2i4Logical{{implicit conversion truncates vector: 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>')}} 367*4407cf95SChris B// expected-warning@#b2f2i4Logical{{implicit conversion from 'int4' (aka 'vector<int, 4>') to 'float2' (aka 'vector<float, 2>') may lose precision}} 368*4407cf95SChris B#endif 369*4407cf95SChris B 370*4407cf95SChris Bexport bool2 b2f2i4Logical(float2 A, int4 B) { 371*4407cf95SChris B return A && B; // #b2f2i4Logical 372*4407cf95SChris B} 373*4407cf95SChris B 374*4407cf95SChris B#if __HLSL_VERSION >= 2021 375*4407cf95SChris B// expected-error@#b2b2b2Logical{{invalid operands to binary expression ('bool2' (aka 'vector<bool, 2>') and 'bool2')}} 376*4407cf95SChris B// expected-note@#b2b2b2Logical{{did you mean and?}} 377*4407cf95SChris B#endif 378*4407cf95SChris B 379*4407cf95SChris Bexport bool2 b2b2b2Logical(bool2 A, bool2 B) { 380*4407cf95SChris B return A && B; // #b2b2b2Logical 381*4407cf95SChris B} 382*4407cf95SChris B 383*4407cf95SChris B#endif 384