[llvm] [HLSL] Leave out entryname from string table for PSV versions < 3 (PR #191528)

Joshua Batista via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 29 13:53:21 PDT 2026


https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/191528

>From ca8554d899c24383d95e34e8caeb765c40f7a4f9 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 10 Apr 2026 14:20:52 -0700
Subject: [PATCH 1/7] first attempt

---
 llvm/include/llvm/MC/DXContainerPSVInfo.h     |  2 +-
 llvm/lib/MC/DXContainerPSVInfo.cpp            | 11 ++-
 llvm/lib/ObjectYAML/DXContainerEmitter.cpp    |  3 +-
 llvm/lib/ObjectYAML/DXContainerYAML.cpp       |  5 +-
 .../lib/Target/DirectX/DXContainerGlobals.cpp |  4 +-
 .../DXContainer/PSVv2-entry-name.yaml         | 74 +++++++++++++++++++
 6 files changed, 91 insertions(+), 8 deletions(-)
 create mode 100644 llvm/test/ObjectYAML/DXContainer/PSVv2-entry-name.yaml

diff --git a/llvm/include/llvm/MC/DXContainerPSVInfo.h b/llvm/include/llvm/MC/DXContainerPSVInfo.h
index eb6d9e14d92c3..056e2d0f8ff65 100644
--- a/llvm/include/llvm/MC/DXContainerPSVInfo.h
+++ b/llvm/include/llvm/MC/DXContainerPSVInfo.h
@@ -76,7 +76,7 @@ struct PSVRuntimeInfo {
   void write(raw_ostream &OS,
              uint32_t Version = std::numeric_limits<uint32_t>::max()) const;
 
-  void finalize(Triple::EnvironmentType Stage);
+  void finalize(Triple::EnvironmentType Stage, uint32_t Version);
 
 private:
   SmallVector<uint32_t, 64> IndexBuffer;
diff --git a/llvm/lib/MC/DXContainerPSVInfo.cpp b/llvm/lib/MC/DXContainerPSVInfo.cpp
index f70c8b1af01b3..896143f239c11 100644
--- a/llvm/lib/MC/DXContainerPSVInfo.cpp
+++ b/llvm/lib/MC/DXContainerPSVInfo.cpp
@@ -146,7 +146,7 @@ void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
                                llvm::endianness::little);
 }
 
-void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {
+void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage, uint32_t Version) {
   IsFinalized = true;
   BaseData.SigInputElements = static_cast<uint32_t>(InputElements.size());
   BaseData.SigOutputElements = static_cast<uint32_t>(OutputElements.size());
@@ -164,7 +164,9 @@ void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {
   ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
                      SemanticNames, PatchOrPrimElements);
 
-  DXConStrTabBuilder.add(EntryName);
+  // only add the entry name to the string table for versions 3 and above
+  if (Version >= 3)
+    DXConStrTabBuilder.add(EntryName);
 
   DXConStrTabBuilder.finalize();
   for (auto ElAndName : zip(SignatureElements, SemanticNames)) {
@@ -175,8 +177,9 @@ void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {
       El.swapBytes();
   }
 
-  BaseData.EntryNameOffset =
-      static_cast<uint32_t>(DXConStrTabBuilder.getOffset(EntryName));
+  if (Version >= 3)
+    BaseData.EntryNameOffset =
+        static_cast<uint32_t>(DXConStrTabBuilder.getOffset(EntryName));
 
   if (!sys::IsBigEndianHost)
     return;
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index b00e45d912be1..312c74befd752 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -242,7 +242,8 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
                                 P.Info->PatchOutputMap.end());
 
       PSV.finalize(static_cast<Triple::EnvironmentType>(
-          Triple::Pixel + P.Info->Info.ShaderStage));
+                       Triple::Pixel + P.Info->Info.ShaderStage),
+                   P.Info->Version);
       PSV.write(OS, P.Info->Version);
       break;
     }
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 15f614871f57e..20220e3fbfbd5 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -770,8 +770,11 @@ void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
   IO.mapRequired("NumThreadsY", Info.NumThreadsY);
   IO.mapRequired("NumThreadsZ", Info.NumThreadsZ);
 
-  if (Version == 2)
+  if (Version == 2) {
+    if (!IO.outputting())
+      IO.mapOptional("EntryName", EntryName);
     return;
+  }
 
   IO.mapRequired("EntryName", EntryName);
 }
diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 5fdc498db57e1..df8965feb90e7 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -300,7 +300,9 @@ void DXContainerGlobals::addPipelineStateValidationInfo(
       MMI.ShaderProfile != Triple::RootSignature)
     PSV.EntryName = MMI.EntryPropertyVec[0].Entry->getName();
 
-  PSV.finalize(MMI.ShaderProfile);
+  // use the latest version
+  uint32_t Version = std::numeric_limits<uint32_t>::max();
+  PSV.finalize(MMI.ShaderProfile, Version);
   PSV.write(OS);
   Constant *Constant =
       ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-entry-name.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-entry-name.yaml
new file mode 100644
index 0000000000000..c3f944e035024
--- /dev/null
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-entry-name.yaml
@@ -0,0 +1,74 @@
+# Verify that setting EntryName for PSV v2 does not place it in the string
+# table. The entry name is only used starting at PSV v3.
+
+# Produce the binary and round-trip it to YAML.
+# RUN: yaml2obj %s -o %t
+# RUN: obj2yaml %t | FileCheck %s --check-prefix=ROUNDTRIP
+
+# Verify the entry name string does not appear anywhere in the binary.
+# RUN: %python -c "data = open(r'%t', 'rb').read(); assert b'CSMain' not in data, 'Entry name should not be in binary for PSV v2'"
+
+--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  PartCount:       2
+Parts:
+  - Name:            PSV0
+    Size:            144
+    PSVInfo:
+      Version:         2
+      ShaderStage:     5
+      MinimumWaveLaneCount: 0
+      MaximumWaveLaneCount: 4294967295
+      UsesViewID:      0
+      SigInputVectors: 0
+      SigOutputVectors: [ 8, 16, 32, 64 ]
+      NumThreadsX:     512
+      NumThreadsY:     1024
+      NumThreadsZ:     2048
+      EntryName:       CSMain
+      ResourceStride:       24
+      Resources:
+        - Type:            Sampler
+          Space:           2
+          LowerBound:      3
+          UpperBound:      4
+          Kind:            TextureCube
+          Flags:
+            UsedByAtomic64:  false
+        - Type:            Invalid
+          Space:           32768
+          LowerBound:      8388608
+          UpperBound:      2147483648
+          Kind:            Invalid
+          Flags:
+            UsedByAtomic64:  false
+      SigInputElements: []
+      SigOutputElements: []
+      SigPatchOrPrimElements: []
+      InputOutputMap:
+        - [  ]
+        - [  ]
+        - [  ]
+        - [  ]
+  - Name:            DXIL
+    Size:            24
+    Program:
+      MajorVersion:    6
+      MinorVersion:    0
+      ShaderKind:      5
+      Size:            6
+      DXILMajorVersion: 0
+      DXILMinorVersion: 1
+      DXILSize:        0
+...
+
+# The round-tripped YAML should not contain EntryName for PSV v2.
+# ROUNDTRIP:     Version:         2
+# ROUNDTRIP:     NumThreadsZ:     2048
+# ROUNDTRIP-NOT: EntryName
+# ROUNDTRIP:     ResourceStride:  24

>From a16c322f4ca685a28ad00e61dd1a7f85e94ddba0 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 17 Apr 2026 14:22:19 -0700
Subject: [PATCH 2/7] address comments

---
 llvm/include/llvm/MC/DXContainerPSVInfo.h      |  4 ++--
 llvm/lib/MC/DXContainerPSVInfo.cpp             | 11 +++++------
 llvm/lib/ObjectYAML/DXContainerEmitter.cpp     |  6 +++---
 llvm/lib/ObjectYAML/DXContainerYAML.cpp        |  2 +-
 llvm/lib/Target/DirectX/DXContainerGlobals.cpp |  5 ++---
 5 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/MC/DXContainerPSVInfo.h b/llvm/include/llvm/MC/DXContainerPSVInfo.h
index 056e2d0f8ff65..d3fcb1cfa207b 100644
--- a/llvm/include/llvm/MC/DXContainerPSVInfo.h
+++ b/llvm/include/llvm/MC/DXContainerPSVInfo.h
@@ -68,7 +68,7 @@ struct PSVRuntimeInfo {
   std::array<SmallVector<uint32_t>, 4> InputOutputMap;
   SmallVector<uint32_t> InputPatchMap;
   SmallVector<uint32_t> PatchOutputMap;
-  llvm::StringRef EntryName;
+  std::optional<llvm::StringRef> EntryName;
 
   // Serialize PSVInfo into the provided raw_ostream. The version field
   // specifies the data version to encode, the default value specifies encoding
@@ -76,7 +76,7 @@ struct PSVRuntimeInfo {
   void write(raw_ostream &OS,
              uint32_t Version = std::numeric_limits<uint32_t>::max()) const;
 
-  void finalize(Triple::EnvironmentType Stage, uint32_t Version);
+  void finalize(Triple::EnvironmentType Stage);
 
 private:
   SmallVector<uint32_t, 64> IndexBuffer;
diff --git a/llvm/lib/MC/DXContainerPSVInfo.cpp b/llvm/lib/MC/DXContainerPSVInfo.cpp
index 896143f239c11..18b0a1c762b7d 100644
--- a/llvm/lib/MC/DXContainerPSVInfo.cpp
+++ b/llvm/lib/MC/DXContainerPSVInfo.cpp
@@ -146,7 +146,7 @@ void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
                                llvm::endianness::little);
 }
 
-void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage, uint32_t Version) {
+void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {
   IsFinalized = true;
   BaseData.SigInputElements = static_cast<uint32_t>(InputElements.size());
   BaseData.SigOutputElements = static_cast<uint32_t>(OutputElements.size());
@@ -164,9 +164,8 @@ void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage, uint32_t Version) {
   ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
                      SemanticNames, PatchOrPrimElements);
 
-  // only add the entry name to the string table for versions 3 and above
-  if (Version >= 3)
-    DXConStrTabBuilder.add(EntryName);
+  if (EntryName)
+    DXConStrTabBuilder.add(*EntryName);
 
   DXConStrTabBuilder.finalize();
   for (auto ElAndName : zip(SignatureElements, SemanticNames)) {
@@ -177,9 +176,9 @@ void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage, uint32_t Version) {
       El.swapBytes();
   }
 
-  if (Version >= 3)
+  if (EntryName)
     BaseData.EntryNameOffset =
-        static_cast<uint32_t>(DXConStrTabBuilder.getOffset(EntryName));
+        static_cast<uint32_t>(DXConStrTabBuilder.getOffset(*EntryName));
 
   if (!sys::IsBigEndianHost)
     return;
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index 312c74befd752..9c1f8387cdda7 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -201,7 +201,8 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
       mcdxbc::PSVRuntimeInfo PSV;
       memcpy(&PSV.BaseData, &P.Info->Info, sizeof(dxbc::PSV::v3::RuntimeInfo));
       PSV.Resources = P.Info->Resources;
-      PSV.EntryName = P.Info->EntryName;
+      if (P.Info->Version >= 3)
+        PSV.EntryName = P.Info->EntryName;
 
       for (auto El : P.Info->SigInputElements)
         PSV.InputElements.push_back(mcdxbc::PSVSignatureElement{
@@ -242,8 +243,7 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
                                 P.Info->PatchOutputMap.end());
 
       PSV.finalize(static_cast<Triple::EnvironmentType>(
-                       Triple::Pixel + P.Info->Info.ShaderStage),
-                   P.Info->Version);
+          Triple::Pixel + P.Info->Info.ShaderStage));
       PSV.write(OS, P.Info->Version);
       break;
     }
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 20220e3fbfbd5..8695c71bf7639 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -776,7 +776,7 @@ void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
     return;
   }
 
-  IO.mapRequired("EntryName", EntryName);
+  IO.mapOptional("EntryName", EntryName);
 }
 
 } // namespace llvm
diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index df8965feb90e7..e329e4b38d8a3 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -300,9 +300,8 @@ void DXContainerGlobals::addPipelineStateValidationInfo(
       MMI.ShaderProfile != Triple::RootSignature)
     PSV.EntryName = MMI.EntryPropertyVec[0].Entry->getName();
 
-  // use the latest version
-  uint32_t Version = std::numeric_limits<uint32_t>::max();
-  PSV.finalize(MMI.ShaderProfile, Version);
+  // Use the latest version.
+  PSV.finalize(MMI.ShaderProfile);
   PSV.write(OS);
   Constant *Constant =
       ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);

>From e01f323facf5d267780666a7d0a5a19cec08ff32 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 17 Apr 2026 15:05:01 -0700
Subject: [PATCH 3/7] update to required

---
 llvm/lib/ObjectYAML/DXContainerYAML.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 8695c71bf7639..20220e3fbfbd5 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -776,7 +776,7 @@ void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
     return;
   }
 
-  IO.mapOptional("EntryName", EntryName);
+  IO.mapRequired("EntryName", EntryName);
 }
 
 } // namespace llvm

>From dfc3eb7413f0fb956e8d6ae48945bb237e6295da Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 23 Apr 2026 15:21:14 -0700
Subject: [PATCH 4/7] address Tex

---
 llvm/lib/ObjectYAML/DXContainerYAML.cpp       | 26 +++++---
 .../DXContainer/PSVv1-numthreads.yaml         | 66 +++++++++++++++++++
 2 files changed, 83 insertions(+), 9 deletions(-)
 create mode 100644 llvm/test/ObjectYAML/DXContainer/PSVv1-numthreads.yaml

diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 20220e3fbfbd5..824e29dc5cbde 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -685,6 +685,17 @@ void ScalarEnumerationTraits<dxbc::ComparisonFunc>::enumeration(
 
 } // namespace yaml
 
+// Map a version-dependent field as required when the version includes it,
+// or as optional when reading YAML for an older version.
+template <typename T>
+static void mapRequiredOrOptional(yaml::IO &IO, bool Required, const char *Key,
+                                  T &Val) {
+  if (Required)
+    IO.mapRequired(Key, Val);
+  else
+    IO.mapOptional(Key, Val);
+}
+
 void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
   dxbc::PipelinePSVInfo &StageInfo = Info.StageInfo;
   Triple::EnvironmentType Stage = dxbc::getShaderStage(Info.ShaderStage);
@@ -763,20 +774,17 @@ void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
   MutableArrayRef<uint8_t> Vec(Info.SigOutputVectors);
   IO.mapRequired("SigOutputVectors", Vec);
 
-  if (Version == 1)
+  if (IO.outputting() && Version == 1)
     return;
 
-  IO.mapRequired("NumThreadsX", Info.NumThreadsX);
-  IO.mapRequired("NumThreadsY", Info.NumThreadsY);
-  IO.mapRequired("NumThreadsZ", Info.NumThreadsZ);
+  mapRequiredOrOptional(IO, Version > 1, "NumThreadsX", Info.NumThreadsX);
+  mapRequiredOrOptional(IO, Version > 1, "NumThreadsY", Info.NumThreadsY);
+  mapRequiredOrOptional(IO, Version > 1, "NumThreadsZ", Info.NumThreadsZ);
 
-  if (Version == 2) {
-    if (!IO.outputting())
-      IO.mapOptional("EntryName", EntryName);
+  if (IO.outputting() && Version == 2)
     return;
-  }
 
-  IO.mapRequired("EntryName", EntryName);
+  mapRequiredOrOptional(IO, Version > 2, "EntryName", EntryName);
 }
 
 } // namespace llvm
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-numthreads.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-numthreads.yaml
new file mode 100644
index 0000000000000..44b413fb3a278
--- /dev/null
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-numthreads.yaml
@@ -0,0 +1,66 @@
+# Verify that specifying NumThreads fields for PSV v1 does not write them to
+# the binary. NumThreads fields are only used starting at PSV v2.
+
+# Produce the binary and round-trip it to YAML.
+# RUN: yaml2obj %s -o %t
+# RUN: obj2yaml %t | FileCheck %s --check-prefix=ROUNDTRIP
+
+--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  PartCount:       2
+Parts:
+  - Name:            PSV0
+    Size:            144
+    PSVInfo:
+      Version:         1
+      ShaderStage:     5
+      MinimumWaveLaneCount: 0
+      MaximumWaveLaneCount: 4294967295
+      UsesViewID:      0
+      SigInputVectors: 0
+      SigOutputVectors: [ 8, 16, 32, 64 ]
+      NumThreadsX:     512
+      NumThreadsY:     1024
+      NumThreadsZ:     2048
+      ResourceStride:       16
+      Resources:
+        - Type:            Sampler
+          Space:           2
+          LowerBound:      3
+          UpperBound:      4
+        - Type:            Invalid
+          Space:           32768
+          LowerBound:      8388608
+          UpperBound:      2147483648
+      SigInputElements: []
+      SigOutputElements: []
+      SigPatchOrPrimElements: []
+      InputOutputMap:
+        - [  ]
+        - [  ]
+        - [  ]
+        - [  ]
+  - Name:            DXIL
+    Size:            24
+    Program:
+      MajorVersion:    6
+      MinorVersion:    0
+      ShaderKind:      5
+      Size:            6
+      DXILMajorVersion: 0
+      DXILMinorVersion: 1
+      DXILSize:        0
+...
+
+# The round-tripped YAML should not contain NumThreads fields for PSV v1.
+# ROUNDTRIP:     Version:         1
+# ROUNDTRIP:     SigOutputVectors:
+# ROUNDTRIP-NOT: NumThreadsX
+# ROUNDTRIP-NOT: NumThreadsY
+# ROUNDTRIP-NOT: NumThreadsZ
+# ROUNDTRIP:     ResourceStride:  16

>From a8607a34377b68547efa632dca4fa8ee3b4e67ca Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Thu, 23 Apr 2026 16:22:48 -0700
Subject: [PATCH 5/7] remove unneeded comment

---
 llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index e329e4b38d8a3..5fdc498db57e1 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -300,7 +300,6 @@ void DXContainerGlobals::addPipelineStateValidationInfo(
       MMI.ShaderProfile != Triple::RootSignature)
     PSV.EntryName = MMI.EntryPropertyVec[0].Entry->getName();
 
-  // Use the latest version.
   PSV.finalize(MMI.ShaderProfile);
   PSV.write(OS);
   Constant *Constant =

>From 73c1acf0ba6c195e2bde13f95f50931c5223abd5 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Tue, 28 Apr 2026 13:17:31 -0700
Subject: [PATCH 6/7] add string table and runtimeinfosize fields to yaml, and
 check them.

---
 llvm/include/llvm/BinaryFormat/DXContainer.h       |  2 ++
 llvm/include/llvm/ObjectYAML/DXContainerYAML.h     | 14 ++++++++++++++
 llvm/lib/ObjectYAML/DXContainerYAML.cpp            | 10 ++++++++++
 .../DXContainer/PSVv1-amplification.yaml           |  1 +
 .../test/ObjectYAML/DXContainer/PSVv1-compute.yaml |  1 +
 llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml |  1 +
 .../ObjectYAML/DXContainer/PSVv1-geometry.yaml     |  1 +
 llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml   |  1 +
 llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml   |  1 +
 llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml  |  1 +
 llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml |  1 +
 .../DXContainer/PSVv2-amplification.yaml           |  1 +
 .../test/ObjectYAML/DXContainer/PSVv2-compute.yaml |  1 +
 llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml |  1 +
 .../ObjectYAML/DXContainer/PSVv2-geometry.yaml     |  1 +
 llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml   |  1 +
 llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml   |  1 +
 llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml  |  1 +
 llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml |  1 +
 .../DXContainer/PSVv3-amplification.yaml           |  4 ++++
 .../test/ObjectYAML/DXContainer/PSVv3-compute.yaml |  4 ++++
 llvm/test/ObjectYAML/DXContainer/PSVv3-domain.yaml |  4 ++++
 .../ObjectYAML/DXContainer/PSVv3-geometry.yaml     |  4 ++++
 llvm/test/ObjectYAML/DXContainer/PSVv3-hull.yaml   |  4 ++++
 llvm/test/ObjectYAML/DXContainer/PSVv3-mesh.yaml   |  4 ++++
 llvm/test/ObjectYAML/DXContainer/PSVv3-pixel.yaml  |  4 ++++
 llvm/test/ObjectYAML/DXContainer/PSVv3-vertex.yaml |  4 ++++
 llvm/tools/obj2yaml/dxcontainer2yaml.cpp           | 14 ++++++++++++++
 28 files changed, 88 insertions(+)

diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h
index 1756ab0b555ff..99bd32a2ff87a 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainer.h
+++ b/llvm/include/llvm/BinaryFormat/DXContainer.h
@@ -562,6 +562,8 @@ struct ResourceBindInfo : public v0::ResourceBindInfo {
 
 namespace v3 {
 struct RuntimeInfo : public v2::RuntimeInfo {
+  // Offset into the string table, which is stored separately in the PSV0 part.
+  // The entry name string itself is not stored in the RuntimeInfo record.
   uint32_t EntryNameOffset;
 
   void swapBytes() {
diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
index fbfe3069566d3..c02e44e1362ec 100644
--- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
@@ -240,6 +240,11 @@ struct SignatureElement {
   uint8_t Stream;
 };
 
+struct StringTableEntry {
+  StringRef Name;
+  uint32_t Offset;
+};
+
 struct PSVInfo {
   // The version field isn't actually encoded in the file, but it is inferred by
   // the size of data regions. We include it in the yaml because it simplifies
@@ -262,6 +267,10 @@ struct PSVInfo {
 
   StringRef EntryName;
 
+  // Output-only fields populated by obj2yaml for inspection.
+  SmallVector<StringTableEntry> StringTable;
+  uint32_t RuntimeInfoSize = 0;
+
   LLVM_ABI void mapInfoForVersion(yaml::IO &IO);
 
   LLVM_ABI PSVInfo();
@@ -316,6 +325,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureParameter)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::RootParameterLocationYaml)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::DescriptorRangeYaml)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::StaticSamplerYamlDesc)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::StringTableEntry)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::SemanticKind)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::ComponentType)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::InterpolationMode)
@@ -384,6 +394,10 @@ template <> struct MappingTraits<DXContainerYAML::SignatureElement> {
                                llvm::DXContainerYAML::SignatureElement &El);
 };
 
+template <> struct MappingTraits<DXContainerYAML::StringTableEntry> {
+  static void mapping(IO &IO, DXContainerYAML::StringTableEntry &E);
+};
+
 template <> struct MappingTraits<DXContainerYAML::SignatureParameter> {
   LLVM_ABI static void mapping(IO &IO,
                                llvm::DXContainerYAML::SignatureParameter &El);
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 824e29dc5cbde..ff703530b063c 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -374,6 +374,10 @@ void MappingTraits<DXContainerYAML::PSVInfo>::mapping(
   PSV.mapInfoForVersion(IO);
 
   IO.mapRequired("ResourceStride", PSV.ResourceStride);
+  if (PSV.Version > 0) {
+    IO.mapOptional("RuntimeInfoSize", PSV.RuntimeInfoSize);
+    IO.mapOptional("StringTable", PSV.StringTable);
+  }
   IO.mapRequired("Resources", PSV.Resources);
   if (PSV.Version == 0)
     return;
@@ -586,6 +590,12 @@ void MappingTraits<DXContainerYAML::SignatureElement>::mapping(
   IO.mapRequired("Stream", El.Stream);
 }
 
+void MappingTraits<DXContainerYAML::StringTableEntry>::mapping(
+    IO &IO, DXContainerYAML::StringTableEntry &E) {
+  IO.mapRequired("Name", E.Name);
+  IO.mapRequired("Offset", E.Offset);
+}
+
 void ScalarEnumerationTraits<dxbc::PSV::SemanticKind>::enumeration(
     IO &IO, dxbc::PSV::SemanticKind &Value) {
   for (const auto &E : dxbc::PSV::getSemanticKinds())
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml
index beb85ee982820..9d58718a71004 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-amplification.yaml
@@ -61,6 +61,7 @@ Parts:
 # CHECK-NEXT: SigInputVectors: 0
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
 # CHECK-NEXT: ResourceStride: 16
+# CHECK-NEXT: RuntimeInfoSize: 36
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml
index 6c90fbb206c6a..ecdcb976ce660 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-compute.yaml
@@ -59,6 +59,7 @@ Parts:
 # CHECK-NEXT: SigInputVectors: 0
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
 # CHECK-NEXT: ResourceStride: 16
+# CHECK-NEXT: RuntimeInfoSize: 36
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml
index 28a4884d1228f..2122f4dced05a 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-domain.yaml
@@ -68,6 +68,7 @@ Parts:
 # CHECK-NEXT: SigInputVectors: 0
 # CHECK-NEXT: SigOutputVectors: [ 0, 16, 32, 64 ]
 # CHECK-NEXT: ResourceStride: 16
+# CHECK-NEXT: RuntimeInfoSize: 36
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml
index 2884fd75e73d5..54204c5d5ea5d 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-geometry.yaml
@@ -69,6 +69,7 @@ Parts:
 # CHECK-NEXT: SigInputVectors: 0
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
 # CHECK-NEXT: ResourceStride: 16
+# CHECK-NEXT: RuntimeInfoSize: 36
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml
index 0e71276ad1c16..53f3b859e90a9 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-hull.yaml
@@ -70,6 +70,7 @@ Parts:
 # CHECK-NEXT: SigInputVectors: 0
 # CHECK-NEXT: SigOutputVectors: [ 0, 16, 32, 64 ]
 # CHECK-NEXT: ResourceStride: 16
+# CHECK-NEXT: RuntimeInfoSize: 36
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml
index 1af47f95c5e72..77142c4aaa8d7 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-mesh.yaml
@@ -73,6 +73,7 @@ Parts:
 # CHECK-NEXT: SigInputVectors: 0
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
 # CHECK-NEXT: ResourceStride: 16
+# CHECK-NEXT: RuntimeInfoSize: 36
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml
index 156e83f655e4f..124f4cb674201 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-pixel.yaml
@@ -63,6 +63,7 @@ Parts:
 # CHECK-NEXT: SigInputVectors: 0
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
 # CHECK-NEXT: ResourceStride: 16
+# CHECK-NEXT: RuntimeInfoSize: 36
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml
index 020e2345c6eec..f01c6786a050f 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv1-vertex.yaml
@@ -61,6 +61,7 @@ Parts:
 # CHECK-NEXT: SigInputVectors: 0
 # CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ]
 # CHECK-NEXT: ResourceStride: 16
+# CHECK-NEXT: RuntimeInfoSize: 36
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml
index 1e00e604f3e24..beecb32f8603e 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-amplification.yaml
@@ -73,6 +73,7 @@ Parts:
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 48
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml
index c8bfd9acf68ef..b20a0b03fba5d 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-compute.yaml
@@ -71,6 +71,7 @@ Parts:
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 48
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml
index 021fb1b5fffb1..37c07c510d18f 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-domain.yaml
@@ -80,6 +80,7 @@ Parts:
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 48
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml
index 74e32efbe2c65..729809704b97d 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-geometry.yaml
@@ -81,6 +81,7 @@ Parts:
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 48
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml
index 79d92e2f0c5e6..d425672181ebf 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-hull.yaml
@@ -82,6 +82,7 @@ Parts:
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 48
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml
index 27bf148126005..1f2db59b1c42f 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-mesh.yaml
@@ -85,6 +85,7 @@ Parts:
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 48
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml
index 1a1a74d7f3121..bb5383c97de36 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-pixel.yaml
@@ -75,6 +75,7 @@ Parts:
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 48
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml
index 6b0ba5eb3d19f..d067b97a75f8e 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv2-vertex.yaml
@@ -73,6 +73,7 @@ Parts:
 # CHECK-NEXT: NumThreadsY:     1024
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 48
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-amplification.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-amplification.yaml
index 6f7d151b266c9..2d8f8782f8a46 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv3-amplification.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-amplification.yaml
@@ -75,6 +75,10 @@ Parts:
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: EntryName: ASEntry
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 52
+# CHECK-NEXT: StringTable:
+# CHECK-NEXT: - Name:            ASEntry
+# CHECK-NEXT: Offset:          1
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-compute.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-compute.yaml
index 2de3d435af1de..2fec467b84e97 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv3-compute.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-compute.yaml
@@ -73,6 +73,10 @@ Parts:
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: EntryName: CSEntry
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 52
+# CHECK-NEXT: StringTable:
+# CHECK-NEXT: - Name:            CSEntry
+# CHECK-NEXT: Offset:          1
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-domain.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-domain.yaml
index 91afb2f11fc7c..f0917abed8e1f 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv3-domain.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-domain.yaml
@@ -82,6 +82,10 @@ Parts:
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: EntryName: DSEntry
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 52
+# CHECK-NEXT: StringTable:
+# CHECK-NEXT: - Name:            DSEntry
+# CHECK-NEXT: Offset:          1
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-geometry.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-geometry.yaml
index f661e81fe869b..221b0c5d936ff 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv3-geometry.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-geometry.yaml
@@ -83,6 +83,10 @@ Parts:
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: EntryName: GSEntry
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 52
+# CHECK-NEXT: StringTable:
+# CHECK-NEXT: - Name:            GSEntry
+# CHECK-NEXT: Offset:          1
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-hull.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-hull.yaml
index 4140c3180e32c..23dd2996c3693 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv3-hull.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-hull.yaml
@@ -84,6 +84,10 @@ Parts:
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: EntryName: HSEntry
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 52
+# CHECK-NEXT: StringTable:
+# CHECK-NEXT: - Name:            HSEntry
+# CHECK-NEXT: Offset:          1
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-mesh.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-mesh.yaml
index 03ce5b583315d..4478dd043773a 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv3-mesh.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-mesh.yaml
@@ -87,6 +87,10 @@ Parts:
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: EntryName: MSEntry
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 52
+# CHECK-NEXT: StringTable:
+# CHECK-NEXT: - Name:            MSEntry
+# CHECK-NEXT: Offset:          1
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-pixel.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-pixel.yaml
index 2434567b2a6f5..26d2980e519fe 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv3-pixel.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-pixel.yaml
@@ -77,6 +77,10 @@ Parts:
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: EntryName: PSEntry
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 52
+# CHECK-NEXT: StringTable:
+# CHECK-NEXT: - Name:            PSEntry
+# CHECK-NEXT: Offset:          1
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-vertex.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-vertex.yaml
index b43f6aa6b71d4..2298ee8abba0c 100644
--- a/llvm/test/ObjectYAML/DXContainer/PSVv3-vertex.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-vertex.yaml
@@ -75,6 +75,10 @@ Parts:
 # CHECK-NEXT: NumThreadsZ:     2048
 # CHECK-NEXT: EntryName: VSEntry
 # CHECK-NEXT: ResourceStride: 24
+# CHECK-NEXT: RuntimeInfoSize: 52
+# CHECK-NEXT: StringTable:
+# CHECK-NEXT: - Name:            VSEntry
+# CHECK-NEXT: Offset:          1
 # CHECK-NEXT: Resources:
 # CHECK-NEXT: - Type:            Sampler
 # CHECK-NEXT: Space:           2
diff --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
index c727595406767..09a6422d0d7b9 100644
--- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
+++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
@@ -103,6 +103,20 @@ dumpDXContainer(MemoryBufferRef Source) {
                    std::get_if<dxbc::PSV::v3::RuntimeInfo>(&PSVInfo->getInfo()))
         NewPart.Info = DXContainerYAML::PSVInfo(P, PSVInfo->getStringTable());
       NewPart.Info->ResourceStride = PSVInfo->getResourceStride();
+      NewPart.Info->RuntimeInfoSize = PSVInfo->getSize();
+      if (PSVInfo->getVersion() > 0) {
+        StringRef ST = PSVInfo->getStringTable();
+        size_t Pos = 0;
+        while (Pos < ST.size()) {
+          size_t End = ST.find('\0', Pos);
+          if (End == StringRef::npos)
+            End = ST.size();
+          if (End > Pos)
+            NewPart.Info->StringTable.push_back(
+                {ST.slice(Pos, End), static_cast<uint32_t>(Pos)});
+          Pos = End + 1;
+        }
+      }
       for (auto Res : PSVInfo->getResources())
         NewPart.Info->Resources.push_back(Res);
 

>From 579aedc96f4fb2a37fdcd4d8ecb459da49f0d34a Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Wed, 29 Apr 2026 13:53:02 -0700
Subject: [PATCH 7/7] dont use yaml roundtrip test, use container unit tests,
 revert yaml parser

---
 llvm/include/llvm/MC/DXContainerPSVInfo.h     |  5 +-
 llvm/lib/MC/DXContainerPSVInfo.cpp            | 10 +--
 llvm/lib/ObjectYAML/DXContainerEmitter.cpp    |  6 +-
 llvm/lib/ObjectYAML/DXContainerYAML.cpp       | 23 ++----
 .../DXContainer/PSVv1-numthreads.yaml         | 66 -----------------
 .../DXContainer/PSVv2-entry-name.yaml         | 74 -------------------
 llvm/unittests/Object/CMakeLists.txt          |  1 +
 llvm/unittests/Object/DXContainerTest.cpp     | 45 +++++++++++
 8 files changed, 63 insertions(+), 167 deletions(-)
 delete mode 100644 llvm/test/ObjectYAML/DXContainer/PSVv1-numthreads.yaml
 delete mode 100644 llvm/test/ObjectYAML/DXContainer/PSVv2-entry-name.yaml

diff --git a/llvm/include/llvm/MC/DXContainerPSVInfo.h b/llvm/include/llvm/MC/DXContainerPSVInfo.h
index d3fcb1cfa207b..1129f520be2cc 100644
--- a/llvm/include/llvm/MC/DXContainerPSVInfo.h
+++ b/llvm/include/llvm/MC/DXContainerPSVInfo.h
@@ -68,7 +68,7 @@ struct PSVRuntimeInfo {
   std::array<SmallVector<uint32_t>, 4> InputOutputMap;
   SmallVector<uint32_t> InputPatchMap;
   SmallVector<uint32_t> PatchOutputMap;
-  std::optional<llvm::StringRef> EntryName;
+  StringRef EntryName;
 
   // Serialize PSVInfo into the provided raw_ostream. The version field
   // specifies the data version to encode, the default value specifies encoding
@@ -76,7 +76,8 @@ struct PSVRuntimeInfo {
   void write(raw_ostream &OS,
              uint32_t Version = std::numeric_limits<uint32_t>::max()) const;
 
-  void finalize(Triple::EnvironmentType Stage);
+  void finalize(Triple::EnvironmentType Stage,
+                uint32_t Version = std::numeric_limits<uint32_t>::max());
 
 private:
   SmallVector<uint32_t, 64> IndexBuffer;
diff --git a/llvm/lib/MC/DXContainerPSVInfo.cpp b/llvm/lib/MC/DXContainerPSVInfo.cpp
index 18b0a1c762b7d..a6aa556535b48 100644
--- a/llvm/lib/MC/DXContainerPSVInfo.cpp
+++ b/llvm/lib/MC/DXContainerPSVInfo.cpp
@@ -146,7 +146,7 @@ void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {
                                llvm::endianness::little);
 }
 
-void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {
+void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage, uint32_t Version) {
   IsFinalized = true;
   BaseData.SigInputElements = static_cast<uint32_t>(InputElements.size());
   BaseData.SigOutputElements = static_cast<uint32_t>(OutputElements.size());
@@ -164,8 +164,8 @@ void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {
   ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,
                      SemanticNames, PatchOrPrimElements);
 
-  if (EntryName)
-    DXConStrTabBuilder.add(*EntryName);
+  if (Version >= 3 && !EntryName.empty())
+    DXConStrTabBuilder.add(EntryName);
 
   DXConStrTabBuilder.finalize();
   for (auto ElAndName : zip(SignatureElements, SemanticNames)) {
@@ -176,9 +176,9 @@ void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {
       El.swapBytes();
   }
 
-  if (EntryName)
+  if (Version >= 3 && !EntryName.empty())
     BaseData.EntryNameOffset =
-        static_cast<uint32_t>(DXConStrTabBuilder.getOffset(*EntryName));
+        static_cast<uint32_t>(DXConStrTabBuilder.getOffset(EntryName));
 
   if (!sys::IsBigEndianHost)
     return;
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index 9c1f8387cdda7..312c74befd752 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -201,8 +201,7 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
       mcdxbc::PSVRuntimeInfo PSV;
       memcpy(&PSV.BaseData, &P.Info->Info, sizeof(dxbc::PSV::v3::RuntimeInfo));
       PSV.Resources = P.Info->Resources;
-      if (P.Info->Version >= 3)
-        PSV.EntryName = P.Info->EntryName;
+      PSV.EntryName = P.Info->EntryName;
 
       for (auto El : P.Info->SigInputElements)
         PSV.InputElements.push_back(mcdxbc::PSVSignatureElement{
@@ -243,7 +242,8 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
                                 P.Info->PatchOutputMap.end());
 
       PSV.finalize(static_cast<Triple::EnvironmentType>(
-          Triple::Pixel + P.Info->Info.ShaderStage));
+                       Triple::Pixel + P.Info->Info.ShaderStage),
+                   P.Info->Version);
       PSV.write(OS, P.Info->Version);
       break;
     }
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index ff703530b063c..7c1a65139b6bb 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -695,17 +695,6 @@ void ScalarEnumerationTraits<dxbc::ComparisonFunc>::enumeration(
 
 } // namespace yaml
 
-// Map a version-dependent field as required when the version includes it,
-// or as optional when reading YAML for an older version.
-template <typename T>
-static void mapRequiredOrOptional(yaml::IO &IO, bool Required, const char *Key,
-                                  T &Val) {
-  if (Required)
-    IO.mapRequired(Key, Val);
-  else
-    IO.mapOptional(Key, Val);
-}
-
 void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
   dxbc::PipelinePSVInfo &StageInfo = Info.StageInfo;
   Triple::EnvironmentType Stage = dxbc::getShaderStage(Info.ShaderStage);
@@ -784,17 +773,17 @@ void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
   MutableArrayRef<uint8_t> Vec(Info.SigOutputVectors);
   IO.mapRequired("SigOutputVectors", Vec);
 
-  if (IO.outputting() && Version == 1)
+  if (Version == 1)
     return;
 
-  mapRequiredOrOptional(IO, Version > 1, "NumThreadsX", Info.NumThreadsX);
-  mapRequiredOrOptional(IO, Version > 1, "NumThreadsY", Info.NumThreadsY);
-  mapRequiredOrOptional(IO, Version > 1, "NumThreadsZ", Info.NumThreadsZ);
+  IO.mapRequired("NumThreadsX", Info.NumThreadsX);
+  IO.mapRequired("NumThreadsY", Info.NumThreadsY);
+  IO.mapRequired("NumThreadsZ", Info.NumThreadsZ);
 
-  if (IO.outputting() && Version == 2)
+  if (Version == 2)
     return;
 
-  mapRequiredOrOptional(IO, Version > 2, "EntryName", EntryName);
+  IO.mapRequired("EntryName", EntryName);
 }
 
 } // namespace llvm
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv1-numthreads.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv1-numthreads.yaml
deleted file mode 100644
index 44b413fb3a278..0000000000000
--- a/llvm/test/ObjectYAML/DXContainer/PSVv1-numthreads.yaml
+++ /dev/null
@@ -1,66 +0,0 @@
-# Verify that specifying NumThreads fields for PSV v1 does not write them to
-# the binary. NumThreads fields are only used starting at PSV v2.
-
-# Produce the binary and round-trip it to YAML.
-# RUN: yaml2obj %s -o %t
-# RUN: obj2yaml %t | FileCheck %s --check-prefix=ROUNDTRIP
-
---- !dxcontainer
-Header:
-  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
-  Version:
-    Major:           1
-    Minor:           0
-  PartCount:       2
-Parts:
-  - Name:            PSV0
-    Size:            144
-    PSVInfo:
-      Version:         1
-      ShaderStage:     5
-      MinimumWaveLaneCount: 0
-      MaximumWaveLaneCount: 4294967295
-      UsesViewID:      0
-      SigInputVectors: 0
-      SigOutputVectors: [ 8, 16, 32, 64 ]
-      NumThreadsX:     512
-      NumThreadsY:     1024
-      NumThreadsZ:     2048
-      ResourceStride:       16
-      Resources:
-        - Type:            Sampler
-          Space:           2
-          LowerBound:      3
-          UpperBound:      4
-        - Type:            Invalid
-          Space:           32768
-          LowerBound:      8388608
-          UpperBound:      2147483648
-      SigInputElements: []
-      SigOutputElements: []
-      SigPatchOrPrimElements: []
-      InputOutputMap:
-        - [  ]
-        - [  ]
-        - [  ]
-        - [  ]
-  - Name:            DXIL
-    Size:            24
-    Program:
-      MajorVersion:    6
-      MinorVersion:    0
-      ShaderKind:      5
-      Size:            6
-      DXILMajorVersion: 0
-      DXILMinorVersion: 1
-      DXILSize:        0
-...
-
-# The round-tripped YAML should not contain NumThreads fields for PSV v1.
-# ROUNDTRIP:     Version:         1
-# ROUNDTRIP:     SigOutputVectors:
-# ROUNDTRIP-NOT: NumThreadsX
-# ROUNDTRIP-NOT: NumThreadsY
-# ROUNDTRIP-NOT: NumThreadsZ
-# ROUNDTRIP:     ResourceStride:  16
diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv2-entry-name.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv2-entry-name.yaml
deleted file mode 100644
index c3f944e035024..0000000000000
--- a/llvm/test/ObjectYAML/DXContainer/PSVv2-entry-name.yaml
+++ /dev/null
@@ -1,74 +0,0 @@
-# Verify that setting EntryName for PSV v2 does not place it in the string
-# table. The entry name is only used starting at PSV v3.
-
-# Produce the binary and round-trip it to YAML.
-# RUN: yaml2obj %s -o %t
-# RUN: obj2yaml %t | FileCheck %s --check-prefix=ROUNDTRIP
-
-# Verify the entry name string does not appear anywhere in the binary.
-# RUN: %python -c "data = open(r'%t', 'rb').read(); assert b'CSMain' not in data, 'Entry name should not be in binary for PSV v2'"
-
---- !dxcontainer
-Header:
-  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
-  Version:
-    Major:           1
-    Minor:           0
-  PartCount:       2
-Parts:
-  - Name:            PSV0
-    Size:            144
-    PSVInfo:
-      Version:         2
-      ShaderStage:     5
-      MinimumWaveLaneCount: 0
-      MaximumWaveLaneCount: 4294967295
-      UsesViewID:      0
-      SigInputVectors: 0
-      SigOutputVectors: [ 8, 16, 32, 64 ]
-      NumThreadsX:     512
-      NumThreadsY:     1024
-      NumThreadsZ:     2048
-      EntryName:       CSMain
-      ResourceStride:       24
-      Resources:
-        - Type:            Sampler
-          Space:           2
-          LowerBound:      3
-          UpperBound:      4
-          Kind:            TextureCube
-          Flags:
-            UsedByAtomic64:  false
-        - Type:            Invalid
-          Space:           32768
-          LowerBound:      8388608
-          UpperBound:      2147483648
-          Kind:            Invalid
-          Flags:
-            UsedByAtomic64:  false
-      SigInputElements: []
-      SigOutputElements: []
-      SigPatchOrPrimElements: []
-      InputOutputMap:
-        - [  ]
-        - [  ]
-        - [  ]
-        - [  ]
-  - Name:            DXIL
-    Size:            24
-    Program:
-      MajorVersion:    6
-      MinorVersion:    0
-      ShaderKind:      5
-      Size:            6
-      DXILMajorVersion: 0
-      DXILMinorVersion: 1
-      DXILSize:        0
-...
-
-# The round-tripped YAML should not contain EntryName for PSV v2.
-# ROUNDTRIP:     Version:         2
-# ROUNDTRIP:     NumThreadsZ:     2048
-# ROUNDTRIP-NOT: EntryName
-# ROUNDTRIP:     ResourceStride:  24
diff --git a/llvm/unittests/Object/CMakeLists.txt b/llvm/unittests/Object/CMakeLists.txt
index cd70a7b18b5f4..e61f6ec592e09 100644
--- a/llvm/unittests/Object/CMakeLists.txt
+++ b/llvm/unittests/Object/CMakeLists.txt
@@ -1,5 +1,6 @@
 set(LLVM_LINK_COMPONENTS
   BinaryFormat
+  MC
   Object
   ObjectYAML
   TargetParser
diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp
index d6f7b26b99cd7..ec6283e8e9b42 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -9,6 +9,7 @@
 #include "llvm/Object/DXContainer.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Magic.h"
+#include "llvm/MC/DXContainerPSVInfo.h"
 #include "llvm/ObjectYAML/DXContainerYAML.h"
 #include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/Support/Error.h"
@@ -1249,3 +1250,47 @@ TEST(RootSignature, ParseStaticSamplers) {
     ASSERT_EQ(Sampler.Flags, 1U);
   }
 }
+
+// PSVInfo:
+//   Version:         2
+//   ShaderStage:     5
+//   MinimumWaveLaneCount: 0
+//   MaximumWaveLaneCount: 4294967295
+//   NumThreadsX:     8
+//   NumThreadsY:     1
+//   NumThreadsZ:     1
+//   EntryName:       CSMain  <--- not serialized for version < 3
+//   ResourceStride:  0
+//   Resources:       []
+TEST(DXCFile, PSVv2EntryNameNotInStringTable) {
+  // Verify that when EntryName is set but PSV version is < 3,
+  // the entry name does not appear in the serialized string table.
+  mcdxbc::PSVRuntimeInfo PSV;
+  PSV.BaseData.ShaderStage =
+      static_cast<uint8_t>(Triple::EnvironmentType::Compute - Triple::Pixel);
+  PSV.BaseData.MinimumWaveLaneCount = 0;
+  PSV.BaseData.MaximumWaveLaneCount = 0xFFFFFFFF;
+  PSV.BaseData.NumThreadsX = 8;
+  PSV.BaseData.NumThreadsY = 1;
+  PSV.BaseData.NumThreadsZ = 1;
+  PSV.EntryName = "CSMain";
+
+  PSV.finalize(Triple::EnvironmentType::Compute, 2);
+
+  SmallVector<char> Buffer;
+  raw_svector_ostream OS(Buffer);
+  PSV.write(OS, 2);
+
+  // The serialized PSV data should not contain the entry name string.
+  StringRef Data(Buffer.data(), Buffer.size());
+  EXPECT_FALSE(Data.contains("CSMain"));
+
+  // Deserialize and verify the string table is empty (only null byte).
+  DirectX::PSVRuntimeInfo ParsedPSV(Data);
+  ASSERT_THAT_ERROR(ParsedPSV.parse(static_cast<uint16_t>(
+                        Triple::EnvironmentType::Compute - Triple::Pixel)),
+                    Succeeded());
+  EXPECT_EQ(ParsedPSV.getVersion(), 2u);
+  StringRef StrTab = ParsedPSV.getStringTable();
+  EXPECT_FALSE(StrTab.contains("CSMain"));
+}



More information about the llvm-commits mailing list