Browse Source

[spirv] Support static member with inline initializer (#842)

Lei Zhang 7 years ago
parent
commit
1d671e843e

+ 1 - 0
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

@@ -235,6 +235,7 @@ SpirvEvalInfo DeclResultIdMapper::getDeclResultId(const NamedDecl *decl) {
     }
 
   assert(false && "found unregistered decl");
+  decl->dump();
   return 0;
 }
 

+ 16 - 0
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -310,6 +310,22 @@ void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
       }
     } else if (auto *varDecl = dyn_cast<VarDecl>(decl)) {
       doVarDecl(varDecl);
+    } else if (auto *recordDecl = dyn_cast<RecordDecl>(decl)) {
+      // Ignore implict records
+      // Somehow we'll have implicit records with:
+      //   static const int Length = count;
+      // that can mess up with the normal CodeGen.
+      if (recordDecl->isImplicit())
+        continue;
+
+      // Handle each static member with inline initializer.
+      // 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))
+          if (varDecl->isStaticDataMember() && varDecl->hasInit())
+            doVarDecl(varDecl);
     } else if (auto *bufferDecl = dyn_cast<HLSLBufferDecl>(decl)) {
       // This is a cbuffer/tbuffer decl.
 

+ 29 - 0
tools/clang/test/CodeGenSPIRV/oo.static.member.init.hlsl

@@ -0,0 +1,29 @@
+// Run: %dxc -T vs_6_0 -E main
+
+struct S {
+    static const int FIVE = 5;
+    static const int SIX;
+};
+
+const int S::SIX = 6;
+
+class T {
+    static const int FIVE = 5;
+    static const int SIX;
+};
+
+const int T::SIX = 6;
+
+int foo(int val) { return val; }
+
+// CHECK:   %FIVE = OpVariable %_ptr_Private_int Private %int_5
+// CHECK:    %SIX = OpVariable %_ptr_Private_int Private %int_6
+// CHECK: %FIVE_0 = OpVariable %_ptr_Private_int Private %int_5
+// CHECK:  %SIX_0 = OpVariable %_ptr_Private_int Private %int_6
+int main() : A {
+// CHECK: OpLoad %int %FIVE
+// CHECK: OpLoad %int %SIX
+// CHECK: OpLoad %int %FIVE_0
+// CHECK: OpLoad %int %SIX_0
+    return foo(S::FIVE) + foo(S::SIX) + foo(T::FIVE) + foo(T::SIX);
+}

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

@@ -366,6 +366,9 @@ TEST_F(FileTest, StructStaticMember) {
 TEST_F(FileTest, ClassStaticMember) {
   runFileTest("oo.struct.static.member.hlsl");
 }
+TEST_F(FileTest, StaticMemberInitializer) {
+  runFileTest("oo.static.member.init.hlsl");
+}
 
 // For semantics
 // SV_Position, SV_ClipDistance, and SV_CullDistance are covered in