瀏覽代碼

[spirv] Non-literal 'literal float' as initializer (#1122)

Handle FlatConversion for cases such as:
```
S myS = (S)(1.0/0.0);
```
These cases result in an initializer of type 'literal float', even
though the initializer is *not* a FloatingLiteral!
Ehsan 7 年之前
父節點
當前提交
fc771d1046

+ 16 - 4
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -2175,13 +2175,22 @@ SpirvEvalInfo SPIRVEmitter::doCastExpr(const CastExpr *expr) {
       return SpirvEvalInfo(subExprId).setRValue().setConstant();
       return SpirvEvalInfo(subExprId).setRValue().setConstant();
     }
     }
 
 
-    // Try to evaluate 'literal float' as float rather than double.
+    TypeTranslator::LiteralTypeHint hint(typeTranslator);
+    // Try to evaluate float literals as float rather than double.
     if (const auto *floatLiteral = dyn_cast<FloatingLiteral>(subExpr)) {
     if (const auto *floatLiteral = dyn_cast<FloatingLiteral>(subExpr)) {
       subExprId = tryToEvaluateAsFloat32(floatLiteral->getValue());
       subExprId = tryToEvaluateAsFloat32(floatLiteral->getValue());
       if (subExprId)
       if (subExprId)
         evalType = astContext.FloatTy;
         evalType = astContext.FloatTy;
     }
     }
-    // Try to evaluate 'literal int' as 32-bit int rather than 64-bit int.
+    // Evaluate 'literal float' initializer type as float rather than double.
+    // TODO: This could result in rounding error if the initializer is a
+    // non-literal expression that requires larger than 32 bits and has the
+    // 'literal float' type.
+    else if (subExprType->isSpecificBuiltinType(BuiltinType::LitFloat)) {
+      evalType = astContext.FloatTy;
+      hint.setHint(astContext.FloatTy);
+    }
+    // Try to evaluate integer literals as 32-bit int rather than 64-bit int.
     else if (const auto *intLiteral = dyn_cast<IntegerLiteral>(subExpr)) {
     else if (const auto *intLiteral = dyn_cast<IntegerLiteral>(subExpr)) {
       const bool isSigned = subExprType->isSignedIntegerType();
       const bool isSigned = subExprType->isSignedIntegerType();
       subExprId = tryToEvaluateAsInt32(intLiteral->getValue(), isSigned);
       subExprId = tryToEvaluateAsInt32(intLiteral->getValue(), isSigned);
@@ -2250,15 +2259,18 @@ uint32_t SPIRVEmitter::processFlatConversion(const QualType type,
         case BuiltinType::Bool:
         case BuiltinType::Bool:
           return castToBool(initId, initType, ty);
           return castToBool(initId, initType, ty);
         // Target type is an integer variant.
         // Target type is an integer variant.
-        // TODO: Add long and ulong.
         case BuiltinType::Int:
         case BuiltinType::Int:
         case BuiltinType::Short:
         case BuiltinType::Short:
         case BuiltinType::Min12Int:
         case BuiltinType::Min12Int:
         case BuiltinType::UShort:
         case BuiltinType::UShort:
         case BuiltinType::UInt:
         case BuiltinType::UInt:
+        case BuiltinType::Long:
+        case BuiltinType::LongLong:
+        case BuiltinType::ULong:
+        case BuiltinType::ULongLong:
           return castToInt(initId, initType, ty, srcLoc);
           return castToInt(initId, initType, ty, srcLoc);
         // Target type is a float variant.
         // Target type is a float variant.
-        // TODO: Add double.
+        case BuiltinType::Double:
         case BuiltinType::Float:
         case BuiltinType::Float:
         case BuiltinType::Half:
         case BuiltinType::Half:
         case BuiltinType::Min10Float:
         case BuiltinType::Min10Float:

+ 50 - 0
tools/clang/test/CodeGenSPIRV/cast.flat-conversion.literal-initializer.hlsl

@@ -0,0 +1,50 @@
+// Run: %dxc -T ps_6_0 -E main
+
+struct S {
+  float2   a;
+  float    b;
+  double2  c;
+  double   d;
+  int64_t  e;
+  uint64_t f;
+};
+
+void main() {
+
+// CHECK:              [[inf:%\d+]] = OpFDiv %float %float_1 %float_0
+// CHECK-NEXT:        [[inf2:%\d+]] = OpCompositeConstruct %v2float [[inf]] [[inf]]
+// CHECK-NEXT:  [[inf_double:%\d+]] = OpFConvert %double [[inf]]
+// CHECK-NEXT: [[inf2_double:%\d+]] = OpCompositeConstruct %v2double [[inf_double]] [[inf_double]] 
+// CHECK-NEXT:  [[inf_double:%\d+]] = OpFConvert %double [[inf]]
+// CHECK-NEXT: [[inf_double_:%\d+]] = OpFConvert %double [[inf]]
+// CHECK-NEXT:   [[inf_int64:%\d+]] = OpConvertFToS %long [[inf_double_]]
+// CHECK-NEXT: [[inf_double_:%\d+]] = OpFConvert %double [[inf]]
+// CHECK-NEXT:  [[inf_uint64:%\d+]] = OpConvertFToU %ulong [[inf_double_]]
+// CHECK-NEXT:             {{%\d+}} = OpCompositeConstruct %S [[inf2]] [[inf]] [[inf2_double]] [[inf_double]] [[inf_int64]] [[inf_uint64]]
+  S s3 = (S)(1.0 / 0.0);
+
+// CHECK:              [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT:  [[b2_float:%\d+]] = OpCompositeConstruct %v2float [[b]] [[b]]
+// CHECK-NEXT:  [[b_double:%\d+]] = OpFConvert %double [[b]]
+// CHECK-NEXT: [[b2_double:%\d+]] = OpCompositeConstruct %v2double [[b_double]] [[b_double]]
+// CHECK-NEXT:  [[b_double:%\d+]] = OpFConvert %double [[b]]
+// CHECK-NEXT: [[b_double_:%\d+]] = OpFConvert %double [[b]]
+// CHECK-NEXT:   [[b_int64:%\d+]] = OpConvertFToS %long [[b_double_]]
+// CHECK-NEXT: [[b_double_:%\d+]] = OpFConvert %double [[b]]
+// CHECK-NEXT:  [[b_uint64:%\d+]] = OpConvertFToU %ulong [[b_double_]]
+// CHECK-NEXT:           {{%\d+}} = OpCompositeConstruct %S [[b2_float]] [[b]] [[b2_double]] [[b_double]] [[b_int64]] [[b_uint64]]
+  float b;
+  S s2 = (S)(b);
+
+
+// CHECK:              [[a:%\d+]] = OpLoad %double %a
+// CHECK-NEXT:   [[a_float:%\d+]] = OpFConvert %float [[a]]
+// CHECK-NEXT:  [[a2_float:%\d+]] = OpCompositeConstruct %v2float [[a_float]] [[a_float]]
+// CHECK-NEXT:   [[a_float:%\d+]] = OpFConvert %float [[a]]
+// CHECK-NEXT: [[a2_double:%\d+]] = OpCompositeConstruct %v2double [[a]] [[a]]
+// CHECK-NEXT:   [[a_int64:%\d+]] = OpConvertFToS %long [[a]]
+// CHECK-NEXT:  [[a_uint64:%\d+]] = OpConvertFToU %ulong [[a]]
+// CHECK-NEXT:           {{%\d+}} = OpCompositeConstruct %S [[a2_float]] [[a_float]] [[a2_double]] [[a]] [[a_int64]] [[a_uint64]]
+  double a;
+  S s1 = (S)(a);
+}

+ 3 - 0
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -336,6 +336,9 @@ TEST_F(FileTest, CastFlatConversionStruct) {
 TEST_F(FileTest, CastFlatConversionNoOp) {
 TEST_F(FileTest, CastFlatConversionNoOp) {
   runFileTest("cast.flat-conversion.no-op.hlsl");
   runFileTest("cast.flat-conversion.no-op.hlsl");
 }
 }
+TEST_F(FileTest, CastFlatConversionLiteralInitializer) {
+  runFileTest("cast.flat-conversion.literal-initializer.hlsl");
+}
 TEST_F(FileTest, CastExplicitVecToMat) {
 TEST_F(FileTest, CastExplicitVecToMat) {
   runFileTest("cast.vec-to-mat.explicit.hlsl");
   runFileTest("cast.vec-to-mat.explicit.hlsl");
 }
 }