Browse Source

[spirv] Forward declaration of function inside another. (#3310)

* [spirv] Forward declaration of function inside another.

Fixes #3214.

* Add struct to test shader.
Ehsan 4 năm trước cách đây
mục cha
commit
d99be810ad

+ 6 - 1
tools/clang/lib/SPIRV/SpirvEmitter.cpp

@@ -1028,7 +1028,12 @@ SpirvInstruction *SpirvEmitter::castToType(SpirvInstruction *value,
 }
 
 void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) {
-  assert(decl->isThisDeclarationADefinition());
+  // Forward declaration of a function inside another.
+  if(!decl->isThisDeclarationADefinition()) {
+    addFunctionToWorkQueue(spvContext.getCurrentShaderModelKind(), decl,
+                           /*isEntryFunction*/ false);
+    return;
+  }
 
   // A RAII class for maintaining the current function under traversal.
   class FnEnvRAII {

+ 36 - 0
tools/clang/test/CodeGenSPIRV/fn.forward-declaration.hlsl

@@ -0,0 +1,36 @@
+// Run: %dxc -T ps_6_0 -E main
+
+struct foo
+{
+  float memberFunction() {
+    float MulBy3(float f);
+    return MulBy3(.25);
+  }
+};
+
+float4 main() : SV_Target
+{
+  foo f;
+  float a = f.memberFunction();
+
+  float MulBy2(float f);
+
+  // CHECK: OpFunctionCall %float %MulBy2 %param_var_f
+  return float4(MulBy2(.25), 1, 0, 1);
+}
+
+// Definitions of foo::memberFunction
+// CHECK: %foo_memberFunction = OpFunction %float None
+// CHECK: OpFunctionCall %float %MulBy3 %param_var_f_0
+// CHECK: OpFunctionEnd
+
+// CHECK: %MulBy2 = OpFunction %float None
+float MulBy2(float f) {
+  return f*2;
+}
+
+// CHECK: %MulBy3 = OpFunction %float None
+float MulBy3(float f) {
+  return f*3;
+}
+

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

@@ -595,6 +595,9 @@ TEST_F(FileTest, FunctionInCTBuffer) {
 
 TEST_F(FileTest, FunctionNoInline) { runFileTest("fn.noinline.hlsl"); }
 TEST_F(FileTest, FunctionExport) { runFileTest("fn.export.hlsl"); }
+TEST_F(FileTest, FunctionForwardDecl) {
+  runFileTest("fn.forward-declaration.hlsl");
+}
 
 // For OO features
 TEST_F(FileTest, StructMethodCall) {