Browse Source

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 years ago
parent
commit
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) {