소스 검색

[spirv] Temporary struct/class object method call. (#912)

Ehsan 7 년 전
부모
커밋
4561cb9ea1

+ 17 - 1
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -1518,7 +1518,23 @@ SpirvEvalInfo SPIRVEmitter::processCall(const CallExpr *callExpr) {
         // For non-static member calls, evaluate the object and pass it as the
         // first argument.
         const auto *object = memberCall->getImplicitObjectArgument();
-        args.push_back(doExpr(object));
+        const auto objectEvalInfo = doExpr(object);
+        uint32_t objectId = objectEvalInfo;
+
+        // If not already a variable, we need to create a temporary variable and
+        // pass the object pointer to the function. Example:
+        // getObject().objectMethod();
+        if (objectEvalInfo.isRValue()) {
+          const auto objType = object->getType();
+          const uint32_t varType = typeTranslator.translateType(objType);
+          const std::string varName =
+              "temp.var." + TypeTranslator::getName(objType);
+          const uint32_t tempVarId = theBuilder.addFnVar(varType, varName);
+          theBuilder.createStore(tempVarId, objectEvalInfo);
+          objectId = tempVarId;
+        }
+
+        args.push_back(objectId);
         // We do not need to create a new temporary variable for the this
         // object. Use the evaluated argument.
         params.push_back(args.back());

+ 3 - 3
tools/clang/lib/SPIRV/TypeTranslator.h

@@ -156,6 +156,9 @@ public:
   /// (in a recursive away).
   static bool isOpaqueStructType(QualType tye);
 
+  /// \brief Returns a string name for the given type.
+  static std::string getName(QualType type);
+
   /// \brief Returns the the element type for the given scalar/vector/matrix
   /// type. Returns empty QualType for other cases.
   QualType getElementType(QualType type);
@@ -198,9 +201,6 @@ private:
   /// that can be used to create an image object.
   spv::ImageFormat translateSampledTypeToImageFormat(QualType type);
 
-  /// \brief Returns a string name for the given type.
-  static std::string getName(QualType type);
-
 public:
   /// \brief Returns the alignment and size in bytes for the given type
   /// according to the given LayoutRule.

+ 63 - 28
tools/clang/test/CodeGenSPIRV/oo.class.method.hlsl

@@ -3,62 +3,83 @@
 class S {
   float    a;
   float3   b;
-  
+
   // Not referencing members
   float fn_no_ref() {
-      return 4.2;
+    return 4.2;
   }
-  
+
   // Referencing members
   float fn_ref() {
-      return a + this.b[0];
+    return a + this.b[0];
   }
-  
+
   // Calling a method defined later
   float fn_call(float c) {
-      return fn_param(c);
+    return fn_param(c);
   }
-  
+
   // Passing in parameters
   float fn_param(float c) {
-      return a + c;
+    return a + c;
   }
-  
+
   // Unused method
   float fn_unused() {
-      return 2.4;
+    return 2.4;
   }
-  
+
   // Static method
   static float fn_static() {
-      return 3.5;
+    return 3.5;
   }
 };
 
 class T {
   S s;
-  
+
   // Calling method in nested class
   float fn_nested() {
-      return s.fn_ref();
+    return s.fn_ref();
   }
-  
+
   // Static method with the same name as S
   static float fn_static() {
-      return 6.7;
+    return 6.7;
+  }
+
+  // Get inner object
+  S get_S() {
+    return s;
   }
 };
 
-// CHECK:   [[ft_f32:%\d+]] = OpTypeFunction %float
-// CHECK:     [[ft_S:%\d+]] = OpTypeFunction %float %_ptr_Function_S
-// CHECK: [[ft_S_f32:%\d+]] = OpTypeFunction %float %_ptr_Function_S %_ptr_Function_float
-// CHECK:     [[ft_T:%\d+]] = OpTypeFunction %float %_ptr_Function_T
+T foo() {
+  T t;
+  return t;
+}
+
+// CHECK:     [[ft_f32:%\d+]] = OpTypeFunction %float
+// CHECK:       [[ft_S:%\d+]] = OpTypeFunction %float %_ptr_Function_S
+// CHECK:   [[ft_S_f32:%\d+]] = OpTypeFunction %float %_ptr_Function_S %_ptr_Function_float
+// CHECK:       [[ft_T:%\d+]] = OpTypeFunction %float %_ptr_Function_T
+// CHECK:  [[fooFnType:%\d+]] = OpTypeFunction %T
+// CHECK: [[getSFntype:%\d+]] = OpTypeFunction %S %_ptr_Function_T
+
+float main() : A {
 
 // CHECK-LABEL:   %src_main = OpFunction
 // CHECK-NEXT:    %bb_entry = OpLabel
 // CHECK-NEXT:           %s = OpVariable %_ptr_Function_S Function
 // CHECK-NEXT:           %t = OpVariable %_ptr_Function_T Function
+// CHECK-NEXT:          %f1 = OpVariable %_ptr_Function_float Function
 // CHECK-NEXT: %param_var_c = OpVariable %_ptr_Function_float Function
+// CHECK-NEXT:          %f2 = OpVariable %_ptr_Function_float Function
+// CHECK-NEXT:  %temp_var_T = OpVariable %_ptr_Function_T Function
+// CHECK-NEXT:  %temp_var_S = OpVariable %_ptr_Function_S Function
+    S s;
+    T t;
+
 // CHECK:          {{%\d+}} = OpFunctionCall %float %S_fn_no_ref %s
 // CHECK:          {{%\d+}} = OpFunctionCall %float %S_fn_ref %s
 // CHECK:          {{%\d+}} = OpFunctionCall %float %S_fn_call %s %param_var_c
@@ -67,12 +88,18 @@ class T {
 // CHECK:          {{%\d+}} = OpFunctionCall %float %T_fn_static
 // CHECK:          {{%\d+}} = OpFunctionCall %float %S_fn_static
 // CHECK:          {{%\d+}} = OpFunctionCall %float %T_fn_static
+  float f1 = s.fn_no_ref() + s.fn_ref() + s.fn_call(5.0) + t.fn_nested() +
+             s.fn_static() + t.fn_static() + S::fn_static() + T::fn_static();
+
+// CHECK:      [[temp_T:%\d+]] = OpFunctionCall %T %foo
+// CHECK-NEXT:                   OpStore %temp_var_T [[temp_T]]
+// CHECK-NEXT: [[temp_S:%\d+]] = OpFunctionCall %S %T_get_S %temp_var_T
+// CHECK-NEXT:                   OpStore %temp_var_S [[temp_S]]
+// CHECK-NEXT:        {{%\d+}} = OpFunctionCall %float %S_fn_ref %temp_var_S
+  float f2 = foo().get_S().fn_ref();
+
+  return f1;
 // CHECK:                     OpFunctionEnd
-float main() : A {
-    S s;
-    T t;
-    return s.fn_no_ref() + s.fn_ref() + s.fn_call(5.0) + t.fn_nested() +
-           s.fn_static() + t.fn_static() + S::fn_static() + T::fn_static();
 }
 
 // CHECK:       %S_fn_no_ref = OpFunction %float None [[ft_S]]
@@ -114,10 +141,18 @@ float main() : A {
 // CHECK-NEXT:    %bb_entry_5 = OpLabel
 // CHECK:                       OpFunctionEnd
 
+// CHECK:               %foo = OpFunction %T None [[fooFnType]]
+// CHECK-NEXT:   %bb_entry_6 = OpLabel
+// CHECK:                      OpFunctionEnd
+
+// CHECK:           %T_get_S = OpFunction %S None [[getSFntype]]
+// CHECK-NEXT: %param_this_3 = OpFunctionParameter %_ptr_Function_T
+// CHECK-NEXT:   %bb_entry_7 = OpLabel
+// CHECK:                      OpFunctionEnd
 
 // CHECK:        %S_fn_param = OpFunction %float None [[ft_S_f32]]
-// CHECK-NEXT: %param_this_3 = OpFunctionParameter %_ptr_Function_S
+// CHECK-NEXT: %param_this_4 = OpFunctionParameter %_ptr_Function_S
 // CHECK-NEXT:          %c_0 = OpFunctionParameter %_ptr_Function_float
-// CHECK-NEXT:   %bb_entry_6 = OpLabel
-// CHECK:           {{%\d+}} = OpAccessChain %_ptr_Function_float %param_this_3 %int_0
+// CHECK-NEXT:   %bb_entry_8 = OpLabel
+// CHECK:           {{%\d+}} = OpAccessChain %_ptr_Function_float %param_this_4 %int_0
 // CHECK:                      OpFunctionEnd

+ 89 - 54
tools/clang/test/CodeGenSPIRV/oo.struct.method.hlsl

@@ -1,64 +1,85 @@
 // Run: %dxc -T vs_6_0 -E main
 
 struct S {
-    float    a;
-    float3   b;
-
-    // Not referencing members
-    float fn_no_ref() {
-        return 4.2;
-    }
-
-    // Referencing members
-    float fn_ref() {
-        return a + this.b[0];
-    }
-
-    // Calling a method defined later
-    float fn_call(float c) {
-        return fn_param(c);
-    }
-
-    // Passing in parameters
-    float fn_param(float c) {
-        return a + c;
-    }
-
-    // Unused method
-    float fn_unused() {
-        return 2.4;
-    }
-
-    // Static method
-    static float fn_static() {
-        return 3.5;
-    }
+  float    a;
+  float3   b;
+
+  // Not referencing members
+  float fn_no_ref() {
+    return 4.2;
+  }
+
+  // Referencing members
+  float fn_ref() {
+    return a + this.b[0];
+  }
+
+  // Calling a method defined later
+  float fn_call(float c) {
+    return fn_param(c);
+  }
+
+  // Passing in parameters
+  float fn_param(float c) {
+    return a + c;
+  }
+
+  // Unused method
+  float fn_unused() {
+    return 2.4;
+  }
+
+  // Static method
+  static float fn_static() {
+    return 3.5;
+  }
 };
 
 struct T {
-    S s;
+  S s;
+
+  // Calling method in nested struct
+  float fn_nested() {
+    return s.fn_ref();
+  }
+
+  // Static method with the same name as S
+  static float fn_static() {
+    return 6.7;
+  }
+
+  // Get inner object
+  S get_S() {
+    return s;
+  }
+};
 
-    // Calling method in nested struct
-    float fn_nested() {
-        return s.fn_ref();
-    }
+T foo() {
+  T t;
+  return t;
+}
 
-    // Static method with the same name as S
-    static float fn_static() {
-        return 6.7;
-    }
-};
+// CHECK:     [[ft_f32:%\d+]] = OpTypeFunction %float
+// CHECK:       [[ft_S:%\d+]] = OpTypeFunction %float %_ptr_Function_S
+// CHECK:   [[ft_S_f32:%\d+]] = OpTypeFunction %float %_ptr_Function_S %_ptr_Function_float
+// CHECK:       [[ft_T:%\d+]] = OpTypeFunction %float %_ptr_Function_T
+// CHECK:  [[fooFnType:%\d+]] = OpTypeFunction %T
+// CHECK: [[getSFntype:%\d+]] = OpTypeFunction %S %_ptr_Function_T
 
-// CHECK:   [[ft_f32:%\d+]] = OpTypeFunction %float
-// CHECK:     [[ft_S:%\d+]] = OpTypeFunction %float %_ptr_Function_S
-// CHECK: [[ft_S_f32:%\d+]] = OpTypeFunction %float %_ptr_Function_S %_ptr_Function_float
-// CHECK:     [[ft_T:%\d+]] = OpTypeFunction %float %_ptr_Function_T
+float main() : A {
 
 // CHECK-LABEL:   %src_main = OpFunction
 // CHECK-NEXT:    %bb_entry = OpLabel
 // CHECK-NEXT:           %s = OpVariable %_ptr_Function_S Function
 // CHECK-NEXT:           %t = OpVariable %_ptr_Function_T Function
+// CHECK-NEXT:          %f1 = OpVariable %_ptr_Function_float Function
 // CHECK-NEXT: %param_var_c = OpVariable %_ptr_Function_float Function
+// CHECK-NEXT:          %f2 = OpVariable %_ptr_Function_float Function
+// CHECK-NEXT:  %temp_var_T = OpVariable %_ptr_Function_T Function
+// CHECK-NEXT:  %temp_var_S = OpVariable %_ptr_Function_S Function
+    S s;
+    T t;
+
 // CHECK:          {{%\d+}} = OpFunctionCall %float %S_fn_no_ref %s
 // CHECK:          {{%\d+}} = OpFunctionCall %float %S_fn_ref %s
 // CHECK:          {{%\d+}} = OpFunctionCall %float %S_fn_call %s %param_var_c
@@ -67,12 +88,18 @@ struct T {
 // CHECK:          {{%\d+}} = OpFunctionCall %float %T_fn_static
 // CHECK:          {{%\d+}} = OpFunctionCall %float %S_fn_static
 // CHECK:          {{%\d+}} = OpFunctionCall %float %T_fn_static
+  float f1 = s.fn_no_ref() + s.fn_ref() + s.fn_call(5.0) + t.fn_nested() +
+             s.fn_static() + t.fn_static() + S::fn_static() + T::fn_static();
+
+// CHECK:      [[temp_T:%\d+]] = OpFunctionCall %T %foo
+// CHECK-NEXT:                   OpStore %temp_var_T [[temp_T]]
+// CHECK-NEXT: [[temp_S:%\d+]] = OpFunctionCall %S %T_get_S %temp_var_T
+// CHECK-NEXT:                   OpStore %temp_var_S [[temp_S]]
+// CHECK-NEXT:        {{%\d+}} = OpFunctionCall %float %S_fn_ref %temp_var_S
+  float f2 = foo().get_S().fn_ref();
+
+  return f1;
 // CHECK:                     OpFunctionEnd
-float main() : A {
-    S s;
-    T t;
-    return s.fn_no_ref() + s.fn_ref() + s.fn_call(5.0) + t.fn_nested() +
-           s.fn_static() + t.fn_static() + S::fn_static() + T::fn_static();
 }
 
 // CHECK:       %S_fn_no_ref = OpFunction %float None [[ft_S]]
@@ -114,10 +141,18 @@ float main() : A {
 // CHECK-NEXT:    %bb_entry_5 = OpLabel
 // CHECK:                       OpFunctionEnd
 
+// CHECK:               %foo = OpFunction %T None [[fooFnType]]
+// CHECK-NEXT:   %bb_entry_6 = OpLabel
+// CHECK:                      OpFunctionEnd
+
+// CHECK:           %T_get_S = OpFunction %S None [[getSFntype]]
+// CHECK-NEXT: %param_this_3 = OpFunctionParameter %_ptr_Function_T
+// CHECK-NEXT:   %bb_entry_7 = OpLabel
+// CHECK:                      OpFunctionEnd
 
 // CHECK:        %S_fn_param = OpFunction %float None [[ft_S_f32]]
-// CHECK-NEXT: %param_this_3 = OpFunctionParameter %_ptr_Function_S
+// CHECK-NEXT: %param_this_4 = OpFunctionParameter %_ptr_Function_S
 // CHECK-NEXT:          %c_0 = OpFunctionParameter %_ptr_Function_float
-// CHECK-NEXT:   %bb_entry_6 = OpLabel
-// CHECK:           {{%\d+}} = OpAccessChain %_ptr_Function_float %param_this_3 %int_0
+// CHECK-NEXT:   %bb_entry_8 = OpLabel
+// CHECK:           {{%\d+}} = OpAccessChain %_ptr_Function_float %param_this_4 %int_0
 // CHECK:                      OpFunctionEnd