ソースを参照

Process enums in class (#5330)

The SPIR-V emitter does not process enum that are declared in class.
This leads to errors in some places it will be used. The fix is to
process the enum in the same place that static variables for an enum are
processed. They are essentially treated like a static variable.

Fixes #5325
Steven Perron 2 年 前
コミット
8d9daa25d4

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

@@ -1689,10 +1689,14 @@ void SpirvEmitter::doRecordDecl(const RecordDecl *recordDecl) {
   // Each static member has a corresponding VarDecl inside the
   // RecordDecl. For those defined in the translation unit,
   // their VarDecls do not have initializer.
-  for (auto *subDecl : recordDecl->decls())
-    if (auto *varDecl = dyn_cast<VarDecl>(subDecl))
+  for (auto *subDecl : recordDecl->decls()) {
+    if (auto *varDecl = dyn_cast<VarDecl>(subDecl)) {
       if (varDecl->isStaticDataMember() && varDecl->hasInit())
         doVarDecl(varDecl);
+    } else if (auto *enumDecl = dyn_cast<EnumDecl>(subDecl)) {
+      doEnumDecl(enumDecl);
+    }
+  }
 }
 
 void SpirvEmitter::doEnumDecl(const EnumDecl *decl) {

+ 24 - 0
tools/clang/test/CodeGenSPIRV/class.enum.hlsl

@@ -0,0 +1,24 @@
+// RUN: %dxc -T ps_6_2 -E PSMain
+
+// The value for the enum is stored in a variable, which will be optimized
+// away when optimizations are enabled.
+// CHECK: [[enum_var:%\w+]] = OpVariable %_ptr_Private_int Private %int_1
+struct TestStruct {
+    enum EnumInTestStruct {
+        A = 1,
+    };
+};
+
+// CHECK: %testFunc = OpFunction %int
+// CHECK-NEXT: OpLabel
+// CHECK-NEXT: [[ld:%\w+]] = OpLoad %int [[enum_var]]
+// CHECK-NEXT: OpReturnValue [[ld]]
+TestStruct::EnumInTestStruct testFunc() {
+    return TestStruct::A;
+}
+
+uint PSMain() : SV_TARGET
+{
+    TestStruct::EnumInTestStruct i = testFunc();
+    return i;
+}

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

@@ -109,6 +109,7 @@ TEST_F(FileTest, BindlessConstantBufferArrayType) {
               /*legalization*/ false);
 }
 TEST_F(FileTest, EnumType) { runFileTest("type.enum.hlsl"); }
+TEST_F(FileTest, ClassEnumType) { runFileTest("class.enum.hlsl"); }
 TEST_F(FileTest, TBufferType) { runFileTest("type.tbuffer.hlsl"); }
 TEST_F(FileTest, TextureBufferType) { runFileTest("type.texture-buffer.hlsl"); }
 TEST_F(FileTest, RasterizerOrderedTexture2DType) {