[llvm] [docs][tools][DirectX] Document DXContainer debug info parts (PR #204021)
Vladislav Dzhidzhoev via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 23 07:19:09 PDT 2026
https://github.com/dzhidzhoev updated https://github.com/llvm/llvm-project/pull/204021
>From 1aeae6aad4bd8bcc317249c0a8f4ff76ea0db61c Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Mon, 8 Jun 2026 00:40:30 +0200
Subject: [PATCH 1/5] [docs][tools][DirectX] Document DXContainer debug info
parts
This patch adds ILDB, ILDN, VERS, SRCI parts format documentation.
It describes how to use LLVM tools to inspect them.
Additionally, llvm-pdbutil documentation has been expanded with information
on how to inspect PDB files generated by the DirectX compiler.
---
llvm/docs/CommandGuide/llvm-pdbutil.rst | 71 +++++++
llvm/docs/DirectX/DXContainer.rst | 272 +++++++++++++++++++++++-
2 files changed, 339 insertions(+), 4 deletions(-)
diff --git a/llvm/docs/CommandGuide/llvm-pdbutil.rst b/llvm/docs/CommandGuide/llvm-pdbutil.rst
index 74e1444794dff..5f90c4ec958f2 100644
--- a/llvm/docs/CommandGuide/llvm-pdbutil.rst
+++ b/llvm/docs/CommandGuide/llvm-pdbutil.rst
@@ -40,6 +40,7 @@ in the sections that follow.
reconstructed.
* :ref:`merge_subcommand` - Given two PDBs, produce a third PDB that is the
result of merging the two input PDBs.
+ * :ref:`export_subcommand` - Write the contents of a PDB stream to a file.
.. _pretty_subcommand:
@@ -407,6 +408,14 @@ Miscellaneous Options
Dump image section headers.
+.. option:: -dxcontainer
+
+ Dump a summary of the DXContainer stored in the PDB file's DXContainer stream.
+ Shader companion PDB files produced by the DirectX backend store debug-related
+ container parts in this stream. For example::
+
+ llvm-pdbutil dump --dxcontainer shader.pdb
+
.. option:: -section-map
Dump section map.
@@ -539,9 +548,22 @@ USAGE: :program:`llvm-pdbutil` pdb2yaml [*options*] <input PDB file>
Summary
^^^^^^^
+Produce a YAML description of some or all of a PDB file's contents.
+
Options
^^^^^^^
+.. option:: -all
+
+ Implies most other options in this category.
+
+.. option:: -dxcontainer
+
+ Dump the DXContainer stored in the PDB file's DXContainer stream to YAML.
+ For example::
+
+ llvm-pdbutil pdb2yaml --dxcontainer shader.pdb
+
.. _yaml2pdb_subcommand:
yaml2pdb
@@ -565,6 +587,55 @@ Options
Write the resulting PDB to the specified file.
+.. _export_subcommand:
+
+export
+~~~~~~
+
+USAGE: :program:`llvm-pdbutil` export --out=<file> [*options*] <input PDB file>
+
+.. program:: llvm-pdbutil export
+
+Summary
+^^^^^^^
+
+Write the binary contents of a PDB stream to a file.
+
+DirectX Shader PDBs
+^^^^^^^^^^^^^^^^^^^
+
+When a DirectX shader is compiled with debug information and a companion PDB
+file is requested, the PDB contains a DXContainer stream with debug-related
+parts such as ILDB, ILDN, SRCI, and VERS. To extract that container as a
+standalone DXContainer file::
+
+ llvm-pdbutil export --dxcontainer --out=shader.dxbc shader.pdb
+
+The resulting file can be inspected with the same DXContainer tooling used for
+the main shader output, such as :program:`obj2yaml` and
+:program:`llvm-objcopy`. See :doc:`../DirectX/DXContainer` for part format
+details. To inspect the embedded container without extracting it, use
+:ref:`llvm-pdbutil dump <dump_subcommand>` or
+:ref:`llvm-pdbutil pdb2yaml <pdb2yaml_subcommand>`.
+
+Options
+^^^^^^^
+
+.. option:: --out=<file>
+
+ The file to write the exported stream data to.
+
+.. option:: --dxcontainer
+
+ A synonym for the :option:`--stream=5` option.
+ Export the DXContainer stored in the PDB file's DXContainer stream. This is
+ the usual way to recover the debug-related container parts from a shader
+ companion PDB file.
+
+.. option:: --stream=<index-or-name>
+
+ Export the contents of the specified PDB stream.
+
.. _merge_subcommand:
merge
diff --git a/llvm/docs/DirectX/DXContainer.rst b/llvm/docs/DirectX/DXContainer.rst
index 4473f4ed8d002..2f2ada341d5c7 100644
--- a/llvm/docs/DirectX/DXContainer.rst
+++ b/llvm/docs/DirectX/DXContainer.rst
@@ -97,8 +97,8 @@ FXC are marked with \*.
#. `DXIL`_† - Stores the DXIL bytecode.
#. `HASH`_† - Stores the shader MD5 hash.
-#. ILDB† - Stores the DXIL bytecode with LLVM Debug Information embedded in the module.
-#. ILDN† - Stores shader debug name for external debug information.
+#. `ILDB`_† - Stores the DXIL bytecode with LLVM Debug Information embedded in the module.
+#. `ILDN`_† - Stores shader debug name for external debug information.
#. `ISG1`_ - Stores the input signature for Shader Model 5.1+.
#. ISGN\* - Stores the input signature for Shader Model 4 and earlier.
#. `OSG1`_ - Stores the output signature for Shader Model 5.1+.
@@ -116,9 +116,9 @@ FXC are marked with \*.
#. SHDR\* - Stores compiled DXBC bytecode.
#. SHEX\* - Stores compiled DXBC bytecode.
#. DXBC\* - Stores compiled DXBC bytecode.
-#. SRCI† - Stores shader source information.
+#. `SRCI`_† - Stores shader source information.
#. STAT† - Stores shader statistics.
-#. VERS† - Stores shader compiler version information.
+#. `VERS`_† - Stores shader compiler version information.
DXIL Part
---------
@@ -143,6 +143,270 @@ a 128-bit MD5 hash digest. The flags field can either have the value ``0`` to
indicate no flags, or ``1`` to indicate that the file hash was computed
including the source code that produced the binary.
+ILDB Part
+---------
+.. _ILDB:
+
+The ILDB part follows the structure of the `DXIL`_ part. It stores the
+unstripped DXIL bitcode module with debug information embedded.
+
+The ILDB part is emitted when the shader is compiled with debug information.
+The stripped `DXIL`_ part has the ``Dwarf Version`` and ``Debug Info Version``
+module flags removed, and ``dx.source`` metadata nodes are stripped from it.
+Those nodes are preserved in the ILDB module when source is embedded in the
+debug module; otherwise they are replaced with empty placeholder values in the
+ILDB module written to the companion PDB file.
+
+By default, when debug information is present and no companion PDB file is
+requested, the ILDB part is embedded in the main DXContainer output. When a
+companion PDB file is requested, the ILDB part is written to the PDB unless
+llc's ``--dx-embed-debug`` is specified, in which case it is written to both the main
+DXContainer and the PDB.
+
+.. rubric:: Reading this part
+
+When the ILDB part is present in a DXContainer file, :program:`obj2yaml` prints
+it under a ``Program`` mapping with the embedded DXIL bitcode. Use
+:program:`llvm-objcopy` to extract the raw bitcode, then :program:`llvm-dis` to
+disassemble it::
+
+ llvm-objcopy --dump-section=ILDB=shader.bc shader.dxbc
+ llvm-dis shader.bc
+
+When the ILDB part is stored in a companion PDB file, use :program:`llvm-pdbutil`
+to access it (see :doc:`llvm-pdbutil <../CommandGuide/llvm-pdbutil>`).
+
+ILDN Part
+---------
+.. _ILDN:
+
+The ILDN part stores the name of the companion PDB file used for external
+debug information. It is always emitted when the shader is compiled with debug
+information, and is included in both the main DXContainer output and the
+companion PDB file.
+
+The part begins with a ``DebugNameHeader`` followed by a null-terminated UTF-8
+string containing the debug file name:
+
+.. code-block:: c
+
+ struct DebugNameHeader {
+ uint16_t Flags;
+ uint16_t NameLength;
+ };
+
+The ``Flags`` field is reserved and must be zero. ``NameLength`` is the length
+of the debug file name in bytes, not including the null terminator.
+
+If no PDB output path is specified, the debug file name defaults to
+``<MD5 hash>.pdb``, where ``<MD5 hash>`` is the stringified MD5 digest from the
+`HASH`_ part. When the ``-dx-Zss`` flag is used, the digest is computed from the
+ILDB bitcode; otherwise it is computed from the stripped `DXIL`_ bitcode. If a
+PDB output path is specified with `-dx-Fd`, that path is used as the debug file name.
+When the path names a directory, the default ``<MD5 hash>.pdb`` file name is placed in
+that directory.
+
+.. rubric:: Reading this part
+
+When the ILDN part is present in a DXContainer file, :program:`obj2yaml` prints
+it under a ``DebugName`` mapping.
+
+SRCI Part
+---------
+.. _SRCI:
+
+The SRCI part stores shader source information extracted from ``dx.source``
+metadata in the LLVM module. It is emitted when source information is available
+and source is not embedded in the debug module. When source is embedded in the
+debug module, the ``dx.source`` metadata nodes remain in the `ILDB`_ module
+instead and the SRCI part is not generated.
+
+The SRCI part is written to the companion PDB file. It consists of a part
+header followed by three 4-byte aligned sections. Each section begins with a
+``SectionHeader`` and is followed by section-specific data:
+
+.. code-block:: c
+
+ struct Header {
+ uint32_t AlignedSizeInBytes;
+ uint16_t Flags;
+ uint16_t SectionCount;
+ };
+
+ struct SectionHeader {
+ uint32_t AlignedSizeInBytes;
+ uint16_t Flags;
+ uint16_t Type;
+ };
+
+The part ``Flags`` field is reserved and must be zero. ``SectionCount`` must be
+``3``. Each section ``Flags`` field is reserved and must be zero. The
+``Type`` field identifies the section. The section type values are:
+
+.. code-block:: c
+
+ SOURCE_INFO_TYPE(0, SourceContents)
+ SOURCE_INFO_TYPE(1, SourceNames)
+ SOURCE_INFO_TYPE(2, Args)
+
+Source Names Section
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The source names section stores the file names of the HLSL translation units
+that contributed source to the shader. It begins with a section header of type
+``SourceNames``, followed by a section-specific header and a sequence of name
+entries:
+
+.. code-block:: c
+
+ struct SourceNamesHeader {
+ uint32_t Flags;
+ uint32_t Count;
+ uint16_t EntriesSizeInBytes;
+ };
+
+ struct SourceNamesEntry {
+ uint32_t AlignedSizeInBytes;
+ uint32_t Flags;
+ uint32_t NameSizeInBytes;
+ uint32_t ContentSizeInBytes;
+ };
+
+The section-specific ``Flags`` field is reserved and must be zero. ``Count`` is
+the number of entries that follow. ``EntriesSizeInBytes`` is the total size of
+the entry data following the section-specific header, including entry padding.
+
+Each entry is 4-byte aligned. The first entry is usually the main shader source
+file, and the remaining entries are sorted by file name.
+
+Each entry is followed by a null-terminated UTF-8 file name of length
+``NameSizeInBytes``. The ``ContentSizeInBytes`` field records the size of the
+corresponding source content entry in the source contents section, including its
+null terminator.
+
+Source Contents Section
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The source contents section stores the HLSL source text for each file named in
+the source names section. It begins with a section header of type
+``SourceContents``, followed by a section-specific header and the (optionally
+compressed) entry data:
+
+.. code-block:: c
+
+ struct SourceContentsHeader {
+ uint32_t AlignedSizeInBytes;
+ uint16_t Flags;
+ uint16_t Type;
+ uint32_t EntriesSizeInBytes;
+ uint32_t UncompressedEntriesSizeInBytes;
+ uint32_t Count;
+ };
+
+ struct SourceContentsEntry {
+ uint32_t AlignedSizeInBytes;
+ uint32_t Flags;
+ uint32_t ContentSizeInBytes;
+ };
+
+The section-specific ``Flags`` field is reserved and must be zero. The
+``Type`` field specifies the compression applied to the entry data. The
+compression type values are:
+
+.. code-block:: c
+
+ COMPRESSION_TYPE(0, None)
+ COMPRESSION_TYPE(1, Zlib)
+
+When no compression is used, ``EntriesSizeInBytes`` and
+``UncompressedEntriesSizeInBytes`` are equal.
+
+When Zlib compression is used, the bytes following the section-specific header
+contain the compressed aggregate of all entries. After decompression, the data is
+a sequence of ``Count`` entries.
+
+Each uncompressed entry is 4-byte aligned and is followed by a null-terminated
+UTF-8 string containing the file source text.
+
+The entries must appear in the same order as the entries in the source names
+section.
+
+Args Section
+~~~~~~~~~~~~~~~~~
+
+The args section stores the HLSL compiler command-line arguments used to produce
+the shader. It begins with a section header of type ``Args``, followed by a
+section-specific header and the argument data:
+
+.. code-block:: c
+
+ struct ArgsHeader {
+ uint32_t Flags;
+ uint32_t SizeInBytes;
+ uint32_t Count;
+ };
+
+The section-specific ``Flags`` field is reserved and must be zero.
+``SizeInBytes`` is the total size of the argument data following the
+section-specific header. ``Count`` is the number of argument pairs that
+follow.
+
+The header is followed by ``Count`` argument pairs. Each pair consists of two
+null-terminated UTF-8 strings: an argument name and an argument value.
+
+Padding is not applied between argument pairs. The section is padded with zero
+bytes at the end to a 4-byte boundary.
+
+.. rubric:: Reading this part
+
+The SRCI part is normally found in a companion PDB file rather than the main
+DXContainer output. When present, :program:`obj2yaml` prints it under a
+``SourceInfo`` mapping.
+
+To read SRCI part from a companion PDB file, use :program:`llvm-pdbutil`.
+
+VERS Part
+---------
+.. _VERS:
+
+The VERS part stores compiler version information. It is emitted when the
+shader is compiled with debug information. When a companion PDB file is produced,
+the VERS part is written to that file. When compiling a shader library, the VERS
+part is also written to the main DXContainer output.
+
+The part begins with a ``CompilerVersionHeader`` followed by two sequential
+null-terminated UTF-8 strings: the compiler commit SHA and a custom version
+string:
+
+.. code-block:: c
+
+ struct CompilerVersionHeader {
+ uint16_t Major;
+ uint16_t Minor;
+ uint32_t Flags;
+ uint32_t CommitCount;
+ uint32_t ContentSizeInBytes;
+ };
+
+``Major`` and ``Minor`` encode the compiler version. ``CommitCount`` is the
+value produced by ``git rev-list --count HEAD`` in the compiler repository, or
+``0`` when that value is unavailable. ``ContentSizeInBytes`` is the combined
+size of the commit SHA and custom version strings, including their null
+terminators but excluding any trailing part padding.
+
+The ``Flags`` field is a bitmask. The flag values are:
+
+* ``Default`` (``0``) - default value
+* ``Debug`` (``1``) - indicates whether the compiler was built in debug mode
+* ``Internal`` (``2``) - indicates whether the shader was modified by a validator
+
+.. rubric:: Reading this part
+
+When the VERS part is present in a DXContainer file, :program:`obj2yaml` prints
+it under a ``CompilerVersion`` mapping.
+
+To read VERS part from a companion PDB file, use :program:`llvm-pdbutil`.
+
Program Signature (SG1) Parts
-----------------------------
.. _ISG1:
>From e02153cef96f595433a641e22bdffdc21d27f60e Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Tue, 23 Jun 2026 14:49:03 +0200
Subject: [PATCH 2/5] Add PRIV part description
---
llvm/docs/DirectX/DXContainer.rst | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/llvm/docs/DirectX/DXContainer.rst b/llvm/docs/DirectX/DXContainer.rst
index 2f2ada341d5c7..798250c120ab2 100644
--- a/llvm/docs/DirectX/DXContainer.rst
+++ b/llvm/docs/DirectX/DXContainer.rst
@@ -87,6 +87,9 @@ implement this restriction in the writer code (because it's a good idea). The
LLVM object reader code does not assume inputs are correctly aligned to avoid
undefined behavior caused by misaligned inputs generated by other compilers.
+The :ref:`PRIV <PRIV>` part is an exception: DXContainer writer code in LLVM may
+produce a PRIV part with size which is not a multiple of four bytes.
+
Part Formats
============
@@ -106,7 +109,7 @@ FXC are marked with \*.
#. OSGN\* - Stores the output signature for Shader Model 4 and earlier.
#. PCSG\* - Stores the patch constant signature for Shader Model 5.1 and earlier.
#. PDBI† - Stores PDB information.
-#. PRIV - Stores arbitrary private data (Not encoded by either FXC or DXC).
+#. `PRIV`_† - Stores private data, including embedded companion PDB files.
#. `PSG1`_ - Stores the patch constant signature for Shader Model 6+.
#. `PSV0`_ - Stores Pipeline State Validation data.
#. RDAT† - Stores Runtime Data.
@@ -211,6 +214,30 @@ that directory.
When the ILDN part is present in a DXContainer file, :program:`obj2yaml` prints
it under a ``DebugName`` mapping.
+PRIV Part
+---------
+.. _PRIV:
+
+The PRIV part stores opaque binary data. DXC may emit it when the ``/Qpdb_in_private``
+flag is used to embed the companion debug info PDB file in the main DXContainer output.
+The part data may also hold arbitrary user-provided binary blobs attached by
+custom tooling.
+
+Unlike most other parts, the PRIV part data does not need to be padded to a
+4-byte boundary. Thus, when a PRIV part is present, it must be the last part in the
+container. LLVM enforces this constraint in both the object reader and the
+ObjectYAML writer. A DXContainer may contain at most one PRIV part.
+
+.. rubric:: Reading this part
+
+When the PRIV part is present in a DXContainer file, :program:`obj2yaml` prints
+it under a ``PrivateData`` mapping.
+
+Use :program:`llvm-objcopy` to extract the raw part data::
+
+ llvm-objcopy --dump-section=PRIV=output.priv shader.dxbc
+
+
SRCI Part
---------
.. _SRCI:
>From 6b892db4b5fcfea90a1437a69589919e22c23260 Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Tue, 23 Jun 2026 14:59:05 +0200
Subject: [PATCH 3/5] Update info about CommitCount in VERS part description
---
llvm/docs/DirectX/DXContainer.rst | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/llvm/docs/DirectX/DXContainer.rst b/llvm/docs/DirectX/DXContainer.rst
index 798250c120ab2..9e7e708c0441b 100644
--- a/llvm/docs/DirectX/DXContainer.rst
+++ b/llvm/docs/DirectX/DXContainer.rst
@@ -415,11 +415,7 @@ string:
uint32_t ContentSizeInBytes;
};
-``Major`` and ``Minor`` encode the compiler version. ``CommitCount`` is the
-value produced by ``git rev-list --count HEAD`` in the compiler repository, or
-``0`` when that value is unavailable. ``ContentSizeInBytes`` is the combined
-size of the commit SHA and custom version strings, including their null
-terminators but excluding any trailing part padding.
+``Major`` and ``Minor`` encode the compiler version.
The ``Flags`` field is a bitmask. The flag values are:
@@ -427,6 +423,16 @@ The ``Flags`` field is a bitmask. The flag values are:
* ``Debug`` (``1``) - indicates whether the compiler was built in debug mode
* ``Internal`` (``2``) - indicates whether the shader was modified by a validator
+``CommitCount`` records how many commits are reachable from the compiler's HEAD
+revision. In DXC, this is the value produced by ``git rev-list --count HEAD``
+in the compiler repository.
+LLVM always emits ``0`` for ``CommitCount``. This is a deliberate difference
+from DXC; the commit SHA in the part data is considered sufficient for
+identifying the compiler build.
+
+``ContentSizeInBytes`` is the combined size of the commit SHA and custom version
+strings, including their null terminators but excluding any trailing part padding.
+
.. rubric:: Reading this part
When the VERS part is present in a DXContainer file, :program:`obj2yaml` prints
>From 897e6f6380375a80c97c4413d789b63a3b946958 Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Tue, 23 Jun 2026 16:15:01 +0200
Subject: [PATCH 4/5] Add flags description
---
llvm/docs/DirectX/DXContainer.rst | 211 +++++++++++++++++++++++++++---
1 file changed, 190 insertions(+), 21 deletions(-)
diff --git a/llvm/docs/DirectX/DXContainer.rst b/llvm/docs/DirectX/DXContainer.rst
index 9e7e708c0441b..b6bfea778eb78 100644
--- a/llvm/docs/DirectX/DXContainer.rst
+++ b/llvm/docs/DirectX/DXContainer.rst
@@ -144,7 +144,8 @@ HASH Part
The HASH part contains a 32-bit unsigned integer with the shader hash flags, and
a 128-bit MD5 hash digest. The flags field can either have the value ``0`` to
indicate no flags, or ``1`` to indicate that the file hash was computed
-including the source code that produced the binary.
+including the source code that produced the binary. See :ref:`Compiler Flags
+<compiler_flags>` for how ``/Zss`` and ``/Zsb`` select the hashed bitcode.
ILDB Part
---------
@@ -153,18 +154,17 @@ ILDB Part
The ILDB part follows the structure of the `DXIL`_ part. It stores the
unstripped DXIL bitcode module with debug information embedded.
-The ILDB part is emitted when the shader is compiled with debug information.
+The ILDB part is emitted when the shader is compiled with full debug information
+(``/Zi``). It is omitted from all outputs when slim debug (``/Zs``) is used.
+See :ref:`Compiler Flags <compiler_flags>` for how ``/Qembed_debug``,
+``/Qstrip_debug``, ``/Fd``, and ``/Zs`` control whether it appears in the main
+output, the companion PDB, or both.
+
The stripped `DXIL`_ part has the ``Dwarf Version`` and ``Debug Info Version``
module flags removed, and ``dx.source`` metadata nodes are stripped from it.
-Those nodes are preserved in the ILDB module when source is embedded in the
-debug module; otherwise they are replaced with empty placeholder values in the
-ILDB module written to the companion PDB file.
-
-By default, when debug information is present and no companion PDB file is
-requested, the ILDB part is embedded in the main DXContainer output. When a
-companion PDB file is requested, the ILDB part is written to the PDB unless
-llc's ``--dx-embed-debug`` is specified, in which case it is written to both the main
-DXContainer and the PDB.
+Those nodes are preserved in the ILDB module when ``/Qsource_in_debug_module``
+is used; otherwise they are replaced with empty placeholder values in the ILDB
+module written to the companion PDB file.
.. rubric:: Reading this part
@@ -203,11 +203,8 @@ of the debug file name in bytes, not including the null terminator.
If no PDB output path is specified, the debug file name defaults to
``<MD5 hash>.pdb``, where ``<MD5 hash>`` is the stringified MD5 digest from the
-`HASH`_ part. When the ``-dx-Zss`` flag is used, the digest is computed from the
-ILDB bitcode; otherwise it is computed from the stripped `DXIL`_ bitcode. If a
-PDB output path is specified with `-dx-Fd`, that path is used as the debug file name.
-When the path names a directory, the default ``<MD5 hash>.pdb`` file name is placed in
-that directory.
+`HASH`_ part. See :ref:`Compiler Flags <compiler_flags>` for how ``/Fd``, ``/Zss``,
+and ``/Zsb`` affect the debug file name and hash computation.
.. rubric:: Reading this part
@@ -220,6 +217,7 @@ PRIV Part
The PRIV part stores opaque binary data. DXC may emit it when the ``/Qpdb_in_private``
flag is used to embed the companion debug info PDB file in the main DXContainer output.
+
The part data may also hold arbitrary user-provided binary blobs attached by
custom tooling.
@@ -243,12 +241,10 @@ SRCI Part
.. _SRCI:
The SRCI part stores shader source information extracted from ``dx.source``
-metadata in the LLVM module. It is emitted when source information is available
-and source is not embedded in the debug module. When source is embedded in the
-debug module, the ``dx.source`` metadata nodes remain in the `ILDB`_ module
-instead and the SRCI part is not generated.
+metadata in the LLVM module. It is emitted when source information is available.
+See :ref:`Compiler Flags <compiler_flags>` for output placement and related flags.
-The SRCI part is written to the companion PDB file. It consists of a part
+The SRCI part is written only to the companion PDB file. It consists of a part
header followed by three 4-byte aligned sections. Each section begins with a
``SectionHeader`` and is followed by section-specific data:
@@ -882,3 +878,176 @@ SFI0 Part
The SFI0 part encodes a 64-bit unsigned integer bitmask of the feature flags.
This denotes which optional features the shader requires. The flag values are
defined in `llvm/include/llvm/BinaryFormat/DXContainerConstants.def <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/DXContainerConstants.def>`_.
+
+Compiler Flags
+==============
+
+.. _compiler_flags:
+
+When compiling HLSL with :program:`clang-dxc`, several flags control whether
+debug information is embedded in the main DXContainer output, written to a
+companion PDB file, or both. Use ``/Zi`` for full debug output or ``/Zs`` for
+slim debug output without an `ILDB`_ part. Most dxc-style flags are forwarded
+to :program:`llc` as ``-mllvm`` options.
+
+Debug Output Locations
+----------------------
+
+Debug information is enabled with either ``/Zi`` (full debug) or ``/Zs`` (slim
+debug). The two flags are mutually exclusive.
+
+**Full debug with ``/Zi``**
+
+When ``/Zi`` is enabled, the `ILDB`_ part can appear in the main DXContainer
+output, in a companion PDB, or both:
+
+* **Embedded in the main DXContainer output.** The `ILDB`_ part holds the
+ unstripped DXIL module with debug information. It is included when
+ ``/Qembed_debug`` is used. The main output always contains the stripped `DXIL`_
+ part alongside other parts such as `HASH`_, `ILDN`_, and `VERS`_.
+* **Omitted from the main DXContainer output.** When ``/Qstrip_debug`` is used,
+ the `ILDB`_ part is not written to the main output. Other debug-related parts
+ such as `ILDN`_ are still emitted. If ``/Fd`` is also specified, the `ILDB`_
+ part is still written to the companion PDB. ``/Qstrip_debug`` takes precedence
+ over the default ``/Qembed_debug`` behavior when ``/Zi`` is used without
+ ``/Fd``. If both ``/Qstrip_debug`` and ``/Qembed_debug`` are specified,
+ ``/Qstrip_debug`` is ignored and the `ILDB`_ part is embedded.
+* **In a companion PDB file.** A sidecar ``.pdb`` stores a DXContainer stream
+ with debug-related parts including `ILDB`_, `SRCI`_, and `VERS`_. This is
+ produced when ``/Fd`` names an output path. Use :program:`llvm-pdbutil` to
+ inspect or extract that stream (see
+ :doc:`llvm-pdbutil <../CommandGuide/llvm-pdbutil>`).
+* **Embedded in the private data of the main output.** When
+ ``/Qpdb_in_private`` is used, a copy of the companion PDB file is stored as
+ opaque bytes in `PRIV`_. This can be used with or without ``/Fd``; without
+ ``/Fd``, the PDB is not retained as a separate file on disk. After extraction,
+ tools treat the bytes as a standalone ``.pdb`` file.
+
+``/Fd`` can be combined with ``/Qembed_debug`` or ``/Qpdb_in_private`` to
+write full debug information to more than one location.
+
+**Slim debug with ``/Zs``**
+
+When ``/Zs`` is enabled, LLVM emits slim debug information. The `ILDB`_ part is
+omitted from the main DXContainer output and from any companion PDB or `PRIV`_
+embedding, but other debug-related parts such as `HASH`_, `ILDN`_, `SRCI`_, and
+`VERS`_ are still emitted. A companion PDB from ``/Fd`` or a `PRIV`_ embedding
+from ``/Qpdb_in_private`` therefore contains slim debug data only.
+
+``/Zs`` cannot be combined with ``/Qembed_debug`` or ``/Qsource_in_debug_module``.
+
+The table below summarizes the dxc-compatible flags that affect this behavior.
+The **llc flag** column lists the ``-mllvm`` option the driver forwards when
+invoking the backend.
+
+.. list-table::
+ :header-rows: 1
+ :widths: 20 20 60
+
+ * - clang-dxc flag
+ - llc flag
+ - Effect
+ * - ``/Zi``, ``-g``
+ -
+ - Enable full debug information. Mutually exclusive with ``/Zs``. Required
+ for ``/Qembed_debug`` and ``/Qstrip_debug``. The main `DXIL`_ part is
+ stripped of debug metadata. If ``/Zi`` is used without ``/Fd``,
+ ``/Qembed_debug``, and ``/Qstrip_debug``, the driver warns and enables
+ ``/Qembed_debug`` by default.
+ * - ``/Zs``
+ - ``--dx-Zs``
+ - Enable slim debug information. Mutually exclusive with ``/Zi``. Omits
+ the `ILDB`_ part from all outputs while still emitting parts such as
+ `ILDN`_, `SRCI`_, and `VERS`_. Incompatible with ``/Qembed_debug`` and
+ ``/Qsource_in_debug_module``.
+ * - ``/Fd``\ *path*
+ - ``--dx-Fd=``\ *path*
+ - Write a companion PDB file. Requires ``/Zi`` or ``/Zs``. The path is
+ recorded in the `ILDN`_ part. If *path* ends with a directory separator,
+ the file name defaults to ``<MD5 hash>.pdb`` from the `HASH`_ part in that
+ directory; otherwise *path* is used as the PDB file name.
+ * - ``/Qembed_debug``
+ - ``--dx-embed-debug``
+ - Embed the `ILDB`_ part and other debug parts in the main DXContainer
+ output. Requires ``/Zi``. Takes precedence over ``/Qstrip_debug`` when
+ both are specified.
+ * - ``/Qstrip_debug``
+ - ``--dx-strip-debug``
+ - Omit the `ILDB`_ part from the main DXContainer output. Requires ``/Zi``.
+ The `ILDB`_ part is still written to a companion PDB
+ when ``/Fd`` is specified. Prevents the default ``/Qembed_debug`` behavior
+ when ``/Zi`` is used without ``/Fd``. Otherwise, ignored when
+ ``/Qembed_debug`` is also specified.
+ * - ``/Qpdb_in_private``
+ - ``--dx-pdb-in-private``
+ - Embed a copy of the companion PDB in the `PRIV`_ part of the main
+ DXContainer output. Requires ``/Zi`` or ``/Zs``. When ``/Fd`` is also
+ specified, the PDB is written to that path as well. Without ``/Fd``, the
+ PDB is built in a temporary file, copied into `PRIV`_, and not retained
+ on disk. With ``/Zs``, the embedded PDB contains slim debug data without
+ an `ILDB`_ part.
+ * - ``/Zss``
+ - ``--dx-Zss``
+ - Compute the `HASH`_ digest from the `ILDB`_ bitcode and set the
+ ``IncludesSource`` hash flag. Requires ``/Zi`` or ``/Zs``.
+ * - ``/Zsb``
+ -
+ - Default behavior. Compute the `HASH`_ digest from the stripped `DXIL`_
+ bitcode.
+ * - ``/Qsource_in_debug_module``
+ - ``--dx-source-in-debug-module``
+ - Embed HLSL source in the `ILDB`_ module via ``dx.source`` metadata
+ instead of emitting a separate `SRCI`_ part.
+ * - ``-fdx-no-source-metadata``
+ -
+ - Do not embed ``dx.source`` metadata in the LLVM module, which prevents
+ `SRCI`_ generation.
+
+Part Placement
+--------------
+
+The table below shows where each debug-related part is written for a typical
+shader compile. ``Yes`` means the part is present in that output whenever its
+preconditions are met.
+
+.. list-table::
+ :header-rows: 1
+ :widths: 12 28 28 32
+
+ * - Part
+ - Main output
+ - Companion PDB (as a separate file or embedded into private data)
+ - Preconditions / notes
+ * - `DXIL`_
+ - Yes
+ - No
+ -
+ * - `ILDB`_
+ - If ``/Qembed_debug`` (default when ``/Zi`` is used without ``/Fd`` and
+ ``/Qstrip_debug``)
+ - Yes
+ - Omitted when ``/Zs`` is used. Omitted from the main output when
+ ``/Qstrip_debug`` is used, or when ``/Fd`` is used without
+ ``/Qembed_debug``.
+ * - `ILDN`_
+ - Yes
+ - Yes
+ -
+ * - `HASH`_
+ - Yes
+ - Yes
+ -
+ * - `SRCI`_
+ - No
+ - Yes
+ - Requires available source metadata. Not emitted when
+ ``/Qsource_in_debug_module`` or ``-fdx-no-source-metadata`` is used.
+ * - `VERS`_
+ - Yes
+ - Yes
+ -
+ * - `PRIV`_
+ - If ``/Qpdb_in_private``
+ - No
+ - Holds a copy of the companion PDB file. Always the last part in the
+ container.
>From f7141c18353d364775f588f42efd83c6d38750c3 Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Tue, 23 Jun 2026 16:18:52 +0200
Subject: [PATCH 5/5] Small fix
---
llvm/docs/DirectX/DXContainer.rst | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/docs/DirectX/DXContainer.rst b/llvm/docs/DirectX/DXContainer.rst
index b6bfea778eb78..e35dcfd89920e 100644
--- a/llvm/docs/DirectX/DXContainer.rst
+++ b/llvm/docs/DirectX/DXContainer.rst
@@ -1049,5 +1049,4 @@ preconditions are met.
* - `PRIV`_
- If ``/Qpdb_in_private``
- No
- - Holds a copy of the companion PDB file. Always the last part in the
- container.
+ - Holds a copy of the companion PDB file.
More information about the llvm-commits
mailing list