[clang] [Metal][HLSL] Add support for dumping reflection (PR #185444)

Chris B via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 9 08:43:34 PDT 2026


https://github.com/llvm-beanz updated https://github.com/llvm/llvm-project/pull/185444

>From 30bc3ace39b882f6b827cd35d082ee5056ec2bfa Mon Sep 17 00:00:00 2001
From: Chris B <chris.bieneman at me.com>
Date: Thu, 26 Feb 2026 13:47:33 -0600
Subject: [PATCH 1/2] [Metal][HLSL] Add support for dumping reflection
 (#181258)

The Metal Shader converter can output shader reflection information into
a JSON file. This connects the -Fre flag (DXC's flag for reflection) to
the Metal Shader Converter tool step to produce the JSON file. As a
temporary state the -Fre flag will error when used without the -metal
flag.

This is required to address
https://github.com/llvm/offload-test-suite/issues/452

../clang/include/clang/Basic/DiagnosticDriverKinds.td
---
 .../clang/Basic/DiagnosticDriverKinds.td      |  2 ++
 clang/include/clang/Options/Options.td        |  2 ++
 clang/lib/Driver/ToolChains/HLSL.cpp          | 22 +++++++++++++++++++
 clang/test/Driver/HLSL/fre-errors.hlsl        |  8 +++++++
 clang/test/Driver/HLSL/metal-converter.hlsl   |  8 +++++++
 5 files changed, 42 insertions(+)
 create mode 100644 clang/test/Driver/HLSL/fre-errors.hlsl

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 972cc87464769..8d36b4d8dcb79 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -849,6 +849,8 @@ def err_drv_dxc_invalid_matrix_layout : Error<
   "cannot specify /Zpr and /Zpc together">;
 def err_drv_dxc_missing_target_profile : Error<
   "target profile option (-T) is missing">;
+def err_drv_dxc_Fre_requires_Fo_metal
+    : Error<"-Fre option requires -Fo option when targeting Metal">;
 def err_drv_hlsl_unsupported_target : Error<
   "HLSL code generation is unsupported for target '%0'">;
 def err_drv_hlsl_bad_shader_required_in_target : Error<
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 45902aee92f72..5e33e12acc152 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -9835,6 +9835,8 @@ def dxc_no_stdinc : DXCFlag<"hlsl-no-stdinc">,
   HelpText<"HLSL only. Disables all standard includes containing non-native compiler types and functions.">;
 def dxc_Fo : DXCJoinedOrSeparate<"Fo">,
   HelpText<"Output object file">;
+def dxc_Fre : DXCJoinedOrSeparate<"Fre">,
+              HelpText<"Set output file name for reflection files">;
 def dxc_Fc : DXCJoinedOrSeparate<"Fc">,
   HelpText<"Output assembly listing file">;
 def dxc_Frs : DXCJoinedOrSeparate<"Frs">,
diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp
index 28835d5077db7..1070f0ef6ee9e 100644
--- a/clang/lib/Driver/ToolChains/HLSL.cpp
+++ b/clang/lib/Driver/ToolChains/HLSL.cpp
@@ -327,6 +327,13 @@ void tools::hlsl::MetalConverter::ConstructJob(
   CmdArgs.push_back("-o");
   CmdArgs.push_back(Output.getFilename());
 
+  StringRef Reflection = Args.getLastArgValue(options::OPT_dxc_Fre);
+  if (!Reflection.empty()) {
+    const char *ReflectionStr =
+        Args.MakeArgString(StringRef("--output-reflection-file=") + Reflection);
+    CmdArgs.push_back(ReflectionStr);
+  }
+
   const char *Exec = Args.MakeArgString(MSCPath);
   C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
                                          Exec, CmdArgs, Inputs, Input));
@@ -531,6 +538,21 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
       continue;
     }
 
+    // This is a temporary check until we support reflection generation for
+    // other targets.
+    if (A->getOption().getID() == options::OPT_dxc_Fre) {
+      if (Args.hasArg(options::OPT_metal)) {
+        if (!Args.hasArg(options::OPT_dxc_Fo))
+          getDriver().Diag(diag::err_drv_dxc_Fre_requires_Fo_metal);
+      } else
+        getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+            << "-Fre" << getTriple().getArchName();
+      A->claim();
+      DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_dxc_Fre),
+                          A->getValue());
+      continue;
+    }
+
     DAL->append(A);
   }
 
diff --git a/clang/test/Driver/HLSL/fre-errors.hlsl b/clang/test/Driver/HLSL/fre-errors.hlsl
new file mode 100644
index 0000000000000..5eb51ddbd4f29
--- /dev/null
+++ b/clang/test/Driver/HLSL/fre-errors.hlsl
@@ -0,0 +1,8 @@
+// These are placeholder errors since we do not currently support -Fre to
+// generate reflection data for DXIL or SPIRV targets.
+
+// RUN: not %clang_dxc -T cs_6_0 %s -Fre blah.json -Vd -### 2>&1 | FileCheck --check-prefix=FRE_DXIL %s
+// FRE_DXIL: error: unsupported option '-Fre' for target 'dxilv1.0'
+
+// RUN: not %clang_dxc -T cs_6_0 %s -spirv -Fre blah.json -Vd -### 2>&1 | FileCheck --check-prefix=FRE_SPV %s
+// FRE_SPV: error: unsupported option '-Fre' for target 'spirv1.6'
diff --git a/clang/test/Driver/HLSL/metal-converter.hlsl b/clang/test/Driver/HLSL/metal-converter.hlsl
index 5c139c62e826b..46a9e06a147fc 100644
--- a/clang/test/Driver/HLSL/metal-converter.hlsl
+++ b/clang/test/Driver/HLSL/metal-converter.hlsl
@@ -6,6 +6,14 @@
 // RUN: env PATH="" %clang_dxc -T cs_6_0 %s --dxv-path=%t.dir -metal -Vd -Fo %t.mtl -### 2>&1 | FileCheck --check-prefix=NO_DXV %s
 // NO_DXV: "{{.*}}metal-shaderconverter{{(.exe)?}}" "{{.*}}.obj" "-o" "{{.*}}.mtl"
 
+// RUN: env PATH="" %clang_dxc -T cs_6_0 %s -metal -Fre blah.json -Vd -Fo %t.mtl -### 2>&1 | FileCheck --check-prefix=FRE %s
+// FRE: "{{.*}}metal-shaderconverter{{(.exe)?}}" "{{.*}}.obj" "-o" "{{.*}}.mtl" "--output-reflection-file=blah.json"
+
+// RUN: env PATH="" not %clang_dxc -T cs_6_0 %s -metal -Fre blah.json -Vd -### 2>&1 | FileCheck --check-prefix=FRE_ERR %s
+// FRE_ERR: error: -Fre option requires -Fo option when targeting Metal
+
+// Does not generate the metal IR when the output file is not specified since we
+// cannot disassemble the metal IR reliably.
 // RUN: %clang_dxc -T cs_6_0 %s -metal -### 2>&1 | FileCheck --check-prefix=NO_MTL %s
 // NO_MTL-NOT: metal-shaderconverter
 

>From e1e77698edf029f850a7c2fcb6e649220df6b431 Mon Sep 17 00:00:00 2001
From: Chris Bieneman <chris.bieneman at me.com>
Date: Mon, 9 Mar 2026 10:43:17 -0500
Subject: [PATCH 2/2] Fix one more test

---
 clang/test/Driver/HLSL/metal-converter.hlsl | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/test/Driver/HLSL/metal-converter.hlsl b/clang/test/Driver/HLSL/metal-converter.hlsl
index 46a9e06a147fc..77d3d0864af77 100644
--- a/clang/test/Driver/HLSL/metal-converter.hlsl
+++ b/clang/test/Driver/HLSL/metal-converter.hlsl
@@ -9,7 +9,9 @@
 // RUN: env PATH="" %clang_dxc -T cs_6_0 %s -metal -Fre blah.json -Vd -Fo %t.mtl -### 2>&1 | FileCheck --check-prefix=FRE %s
 // FRE: "{{.*}}metal-shaderconverter{{(.exe)?}}" "{{.*}}.obj" "-o" "{{.*}}.mtl" "--output-reflection-file=blah.json"
 
-// RUN: env PATH="" not %clang_dxc -T cs_6_0 %s -metal -Fre blah.json -Vd -### 2>&1 | FileCheck --check-prefix=FRE_ERR %s
+// Require -Fo when using -Fre with Metal since the metal shader converter
+// generates the reflection information.
+// RUN: not %clang_dxc -T cs_6_0 %s -metal -Fre blah.json -Vd -### 2>&1 | FileCheck --check-prefix=FRE_ERR %s
 // FRE_ERR: error: -Fre option requires -Fo option when targeting Metal
 
 // Does not generate the metal IR when the output file is not specified since we



More information about the cfe-commits mailing list