From 8d9daa25d42811b6e75d77713c62afa94af5144a Mon Sep 17 00:00:00 2001 From: Steven Perron Date: Fri, 30 Jun 2023 01:57:14 -0700 Subject: [PATCH] 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 --- tools/clang/lib/SPIRV/SpirvEmitter.cpp | 8 +++++-- tools/clang/test/CodeGenSPIRV/class.enum.hlsl | 24 +++++++++++++++++++ .../unittests/SPIRV/CodeGenSpirvTest.cpp | 1 + 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 tools/clang/test/CodeGenSPIRV/class.enum.hlsl diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index a617b09a56..74ebcc8871 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/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(subDecl)) + for (auto *subDecl : recordDecl->decls()) { + if (auto *varDecl = dyn_cast(subDecl)) { if (varDecl->isStaticDataMember() && varDecl->hasInit()) doVarDecl(varDecl); + } else if (auto *enumDecl = dyn_cast(subDecl)) { + doEnumDecl(enumDecl); + } + } } void SpirvEmitter::doEnumDecl(const EnumDecl *decl) { diff --git a/tools/clang/test/CodeGenSPIRV/class.enum.hlsl b/tools/clang/test/CodeGenSPIRV/class.enum.hlsl new file mode 100644 index 0000000000..856324fda4 --- /dev/null +++ b/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; +} diff --git a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp b/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp index 62366bcf48..4f671a0941 100644 --- a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp +++ b/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) {