https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/188150
>From 26229c0a9b848bbbd02e42b644b465f4c4ae224b Mon Sep 17 00:00:00 2001 From: Joshua Batista <[email protected]> Date: Mon, 23 Mar 2026 16:31:43 -0700 Subject: [PATCH 1/3] first attempt --- .../clang/Basic/DiagnosticDriverKinds.td | 3 + clang/include/clang/Basic/DiagnosticGroups.td | 3 + clang/include/clang/Options/Options.td | 2 + clang/lib/Driver/Driver.cpp | 38 +++++++++--- clang/lib/Driver/ToolChains/HLSL.cpp | 58 ++++++++++++++++--- clang/lib/Driver/ToolChains/HLSL.h | 17 +++++- clang/test/Driver/dxc_spirv-val_path.hlsl | 26 +++++++++ 7 files changed, 131 insertions(+), 16 deletions(-) create mode 100644 clang/test/Driver/dxc_spirv-val_path.hlsl diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index ed6a9107002af..89486026d9b48 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -873,6 +873,9 @@ def err_drv_hlsl_bad_shader_unsupported : Error< def warn_drv_dxc_missing_dxv : Warning< "dxv not found; resulting DXIL will not be validated or signed for use in " "release environment">, InGroup<DXILValidation>; +def warn_drv_dxc_missing_spirv_val : Warning< + "spirv-val not found; resulting SPIR-V will not be validated">, + InGroup<SPIRVValidation>; def err_drv_invalid_range_dxil_validator_version : Error< "invalid validator version : %0; validator version must be less than or " diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index e440c9d2fb982..11fe963f8066a 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1875,6 +1875,9 @@ def HLSLExplicitBinding : DiagGroup<"hlsl-explicit-binding">; // Warnings for DXIL validation def DXILValidation : DiagGroup<"dxil-validation">; +// Warnings for SPIRV validation +def SPIRVValidation : DiagGroup<"spirv-validation">; + // Warning for HLSL API availability def HLSLAvailability : DiagGroup<"hlsl-availability">; diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 8b0c701521728..9b7909b1a5d60 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -9976,6 +9976,8 @@ def dxc_hlsl_version : Option<["/", "-"], "HV", KIND_JOINED_OR_SEPARATE>, Values<"2016, 2017, 2018, 2021, 202x, 202y">; def dxc_validator_path_EQ : Joined<["--"], "dxv-path=">, Group<dxc_Group>, HelpText<"DXIL validator installation path">; +def spirv_validator_path_EQ : Joined<["--"], "spirv-val-path=">, Group<dxc_Group>, + HelpText<"SPIRV validator installation path">; def dxc_disable_validation : DXCFlag<"Vd">, HelpText<"Disable validation">; def dxc_gis : DXCFlag<"Gis">, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 3e2553686d87f..70dd8285f346a 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4739,6 +4739,18 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, } } + if (C.getDefaultToolChain().getTriple().isSPIRV()) { + const auto &TC = + static_cast<const toolchains::HLSLToolChain &>(C.getDefaultToolChain()); + + // Call spirv-val for SPIR-V when -Vd not in Args. + if (TC.requiresValidation(Args)) { + Action *LastAction = Actions.back(); + Actions.push_back( + C.MakeAction<BinaryAnalyzeJobAction>(LastAction, types::TY_Object)); + } + } + // Claim ignored clang-cl options. Args.ClaimAllArgs(options::OPT_cl_ignored_Group); } @@ -5381,11 +5393,9 @@ void Driver::BuildJobs(Compilation &C) const { unsigned NumOutputs = 0; unsigned NumIfsOutputs = 0; for (const Action *A : C.getActions()) { - // The actions below do not increase the number of outputs, when operating - // on DX containers. - if (A->getType() == types::TY_DX_CONTAINER && - (A->getKind() == clang::driver::Action::BinaryAnalyzeJobClass || - A->getKind() == clang::driver::Action::BinaryTranslatorJobClass)) + // The actions below do not increase the number of outputs. + if (A->getKind() == clang::driver::Action::BinaryAnalyzeJobClass || + A->getKind() == clang::driver::Action::BinaryTranslatorJobClass) continue; if (A->getType() != types::TY_Nothing && @@ -6434,10 +6444,22 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, const char *Suffix = types::getTypeTempSuffix(JA.getType(), true); return CreateTempFile(C, Split.first, Suffix, false); } - // We don't have SPIRV-val integrated (yet), so for now we can assume this - // is the final output. + assert(C.getDefaultToolChain().getTriple().isSPIRV()); - return C.addResultFile(C.getArgs().MakeArgString(FoValue.str()), &JA); + const auto &TC = + static_cast<const toolchains::HLSLToolChain &>(C.getDefaultToolChain()); + + // If this is the last job in the compilation for this input, and Fo is + // non-empty, we can return the Fo file (the final output) + if (TC.isLastJob(C.getArgs(), JA.getKind()) && !FoValue.empty()) + return C.addResultFile(C.getArgs().MakeArgString(FoValue.str()), &JA); + + // Otherwise, create a temporary file for validation (like DXIL creates + // temp files). + StringRef Name = llvm::sys::path::filename(BaseInput); + std::pair<StringRef, StringRef> Split = Name.split('.'); + const char *Suffix = types::getTypeTempSuffix(JA.getType(), true); + return CreateTempFile(C, Split.first, Suffix, false); } // Is this the assembly listing for /FA? diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index 1070f0ef6ee9e..be0e2ccdc911b 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -315,6 +315,23 @@ void tools::hlsl::Validator::ConstructJob(Compilation &C, const JobAction &JA, Exec, CmdArgs, Inputs, Input)); } +void tools::hlsl::SPIRV_Validator::ConstructJob( + Compilation &C, const JobAction &JA, const InputInfo &Output, + const InputInfoList &Inputs, const ArgList &Args, + const char *LinkingOutput) const { + std::string SPIRVValPath = getToolChain().GetProgramPath("spirv-val"); + assert(SPIRVValPath != "spirv-val" && "cannot find spirv-val"); + + ArgStringList CmdArgs; + assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); + const InputInfo &Input = Inputs[0]; + CmdArgs.push_back(Input.getFilename()); + + const char *Exec = Args.MakeArgString(SPIRVValPath); + C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), + Exec, CmdArgs, Inputs, Input)); +} + void tools::hlsl::MetalConverter::ConstructJob( Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, @@ -384,12 +401,20 @@ HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple, if (Args.hasArg(options::OPT_dxc_validator_path_EQ)) getProgramPaths().push_back( Args.getLastArgValue(options::OPT_dxc_validator_path_EQ).str()); + if (Args.hasArg(options::OPT_spirv_validator_path_EQ)) + getProgramPaths().push_back( + Args.getLastArgValue(options::OPT_spirv_validator_path_EQ).str()); } Tool *clang::driver::toolchains::HLSLToolChain::getTool( Action::ActionClass AC) const { switch (AC) { case Action::BinaryAnalyzeJobClass: + if (getTriple().isSPIRV()) { + if (!SPIRVValidator) + SPIRVValidator.reset(new tools::hlsl::SPIRV_Validator(*this)); + return SPIRVValidator.get(); + } if (!Validator) Validator.reset(new tools::hlsl::Validator(*this)); return Validator.get(); @@ -574,18 +599,31 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch, return DAL; } -bool HLSLToolChain::requiresValidation(DerivedArgList &Args) const { - if (!Args.hasArg(options::OPT_dxc_Fo)) +bool HLSLToolChain::requiresValidation(DerivedArgList &Args, + bool Diagnose) const { + bool HasFo = Args.hasArg(options::OPT_dxc_Fo); + bool DisableValidation = + Args.getLastArg(options::OPT_dxc_disable_validation) != nullptr; + + if (DisableValidation || !HasFo) return false; - if (Args.getLastArg(options::OPT_dxc_disable_validation)) + if (getArch() != llvm::Triple::spirv) { + std::string DxvPath = GetProgramPath("dxv"); + if (DxvPath != "dxv") + return true; + + if (Diagnose) + getDriver().Diag(diag::warn_drv_dxc_missing_dxv); return false; + } - std::string DxvPath = GetProgramPath("dxv"); - if (DxvPath != "dxv") + std::string SpirvValPath = GetProgramPath("spirv-val"); + if (SpirvValPath != "spirv-val") return true; - getDriver().Diag(diag::warn_drv_dxc_missing_dxv); + if (Diagnose) + getDriver().Diag(diag::warn_drv_dxc_missing_spirv_val); return false; } @@ -604,8 +642,14 @@ bool HLSLToolChain::isLastJob(DerivedArgList &Args, // Note: we check in the reverse order of execution if (requiresBinaryTranslation(Args)) return AC == Action::Action::BinaryTranslatorJobClass; - if (requiresValidation(Args)) + // For SPIR-V, spirv-val is a pure validator that doesn't produce output + // files, so the compile step is the output-producing step. For DXIL, dxv + // validates and signs, producing the final output. + if (requiresValidation(Args, /*Diagnose=*/false)) { + if (getTriple().isSPIRV()) + return AC != Action::Action::BinaryAnalyzeJobClass; return AC == Action::Action::BinaryAnalyzeJobClass; + } if (requiresObjcopy(Args)) return AC == Action::Action::ObjcopyJobClass; diff --git a/clang/lib/Driver/ToolChains/HLSL.h b/clang/lib/Driver/ToolChains/HLSL.h index 5bf385e13e962..2bc592e44f84d 100644 --- a/clang/lib/Driver/ToolChains/HLSL.h +++ b/clang/lib/Driver/ToolChains/HLSL.h @@ -30,6 +30,19 @@ class LLVM_LIBRARY_VISIBILITY Validator : public Tool { const char *LinkingOutput) const override; }; +class LLVM_LIBRARY_VISIBILITY SPIRV_Validator : public Tool { +public: + SPIRV_Validator(const ToolChain &TC) + : Tool("hlsl::SPIRV_Validator", "spirv-val", TC) {} + + bool hasIntegratedCPP() const override { return false; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; + class LLVM_LIBRARY_VISIBILITY MetalConverter : public Tool { public: MetalConverter(const ToolChain &TC) @@ -77,7 +90,8 @@ class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain { TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const override; static std::optional<std::string> parseTargetProfile(StringRef TargetProfile); - bool requiresValidation(llvm::opt::DerivedArgList &Args) const; + bool requiresValidation(llvm::opt::DerivedArgList &Args, + bool Diagnose = true) const; bool requiresBinaryTranslation(llvm::opt::DerivedArgList &Args) const; bool requiresObjcopy(llvm::opt::DerivedArgList &Args) const; @@ -95,6 +109,7 @@ class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain { private: mutable std::unique_ptr<tools::hlsl::Validator> Validator; + mutable std::unique_ptr<tools::hlsl::SPIRV_Validator> SPIRVValidator; mutable std::unique_ptr<tools::hlsl::MetalConverter> MetalConverter; mutable std::unique_ptr<tools::hlsl::LLVMObjcopy> LLVMObjcopy; }; diff --git a/clang/test/Driver/dxc_spirv-val_path.hlsl b/clang/test/Driver/dxc_spirv-val_path.hlsl new file mode 100644 index 0000000000000..1ae21ca356510 --- /dev/null +++ b/clang/test/Driver/dxc_spirv-val_path.hlsl @@ -0,0 +1,26 @@ +// RUN: mkdir -p %t.dir +// RUN: env PATH="" %clang_dxc -spirv -I test -Tlib_6_3 -Fo %t.dir/a.spv -### %s 2>&1 | FileCheck %s + +// Make sure report warning, and only once. +// CHECK:spirv-val not found +// CHECK-NOT:spirv-val not found + +// RUN: echo "spirv-val" > %t.dir/spirv-val && chmod 754 %t.dir/spirv-val && %clang_dxc -spirv --spirv-val-path=%t.dir %s -Tlib_6_3 -Fo %t.dir/a.spv -### 2>&1 | FileCheck %s --check-prefix=SPIRV_VAL_PATH +// SPIRV_VAL_PATH:spirv-val{{(.exe)?}}" "{{.*}}.spv" + +// RUN: %clang_dxc -spirv -I test -Vd -Tlib_6_3 -### %s 2>&1 | FileCheck %s --check-prefix=VD +// VD:"-cc1"{{.*}}"-triple" "spirv1.6-unknown-vulkan1.3-library" +// VD-NOT:spirv-val not found + +// RUN: %clang_dxc -spirv -Tlib_6_3 -ccc-print-bindings --spirv-val-path=%t.dir -Fo %t.spv %s 2>&1 | FileCheck %s --check-prefix=BINDINGS +// BINDINGS: "spirv1.6-unknown-vulkan1.3-library" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[spv:.+]].spv" +// BINDINGS-NEXT: "spirv1.6-unknown-vulkan1.3-library" - "hlsl::SPIRV_Validator", inputs: ["[[spv]].spv"], output: "{{.+}}.obj" + +// RUN: %clang_dxc -spirv -Tlib_6_3 -ccc-print-phases --spirv-val-path=%t.dir -Fo %t.spv %s 2>&1 | FileCheck %s --check-prefix=PHASES + +// PHASES: 0: input, "[[INPUT:.+]]", hlsl +// PHASES-NEXT: 1: preprocessor, {0}, c++-cpp-output +// PHASES-NEXT: 2: compiler, {1}, ir +// PHASES-NEXT: 3: backend, {2}, assembler +// PHASES-NEXT: 4: assembler, {3}, object +// PHASES-NEXT: 5: binary-analyzer, {4}, object \ No newline at end of file >From b084fa7a5172e2502324f9df2723e22dad071e3a Mon Sep 17 00:00:00 2001 From: Joshua Batista <[email protected]> Date: Fri, 27 Mar 2026 10:39:06 -0700 Subject: [PATCH 2/3] address Finn and Steven --- clang/lib/Driver/ToolChains/HLSL.cpp | 9 ++++++++- clang/test/Driver/dxc_spirv-val_path.hlsl | 13 ++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index be0e2ccdc911b..634e22bcf3a22 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -325,6 +325,13 @@ void tools::hlsl::SPIRV_Validator::ConstructJob( ArgStringList CmdArgs; assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); const InputInfo &Input = Inputs[0]; + + const llvm::Triple &T = getToolChain().getTriple(); + CmdArgs.push_back("--target-env"); + CmdArgs.push_back(Args.MakeArgString(T.getOSName())); + + CmdArgs.push_back("--scalar-block-layout"); + CmdArgs.push_back(Input.getFilename()); const char *Exec = Args.MakeArgString(SPIRVValPath); @@ -608,7 +615,7 @@ bool HLSLToolChain::requiresValidation(DerivedArgList &Args, if (DisableValidation || !HasFo) return false; - if (getArch() != llvm::Triple::spirv) { + if (getArch() == llvm::Triple::dxil) { std::string DxvPath = GetProgramPath("dxv"); if (DxvPath != "dxv") return true; diff --git a/clang/test/Driver/dxc_spirv-val_path.hlsl b/clang/test/Driver/dxc_spirv-val_path.hlsl index 1ae21ca356510..4f39fa37c69e5 100644 --- a/clang/test/Driver/dxc_spirv-val_path.hlsl +++ b/clang/test/Driver/dxc_spirv-val_path.hlsl @@ -2,15 +2,18 @@ // RUN: env PATH="" %clang_dxc -spirv -I test -Tlib_6_3 -Fo %t.dir/a.spv -### %s 2>&1 | FileCheck %s // Make sure report warning, and only once. -// CHECK:spirv-val not found -// CHECK-NOT:spirv-val not found +// CHECK:spirv-val not found; resulting SPIR-V will not be validated +// CHECK-NOT:spirv-val not found; resulting SPIR-V will not be validated // RUN: echo "spirv-val" > %t.dir/spirv-val && chmod 754 %t.dir/spirv-val && %clang_dxc -spirv --spirv-val-path=%t.dir %s -Tlib_6_3 -Fo %t.dir/a.spv -### 2>&1 | FileCheck %s --check-prefix=SPIRV_VAL_PATH -// SPIRV_VAL_PATH:spirv-val{{(.exe)?}}" "{{.*}}.spv" +// SPIRV_VAL_PATH:spirv-val{{(.exe)?}}" "--target-env" "vulkan1.3" "--scalar-block-layout" "{{.*}}.spv" + +// RUN: echo "spirv-val" > %t.dir/spirv-val && chmod 754 %t.dir/spirv-val && %clang_dxc -spirv --spirv-val-path=%t.dir %s -Tlib_6_3 -fspv-target-env=vulkan1.2 -Fo %t.dir/a.spv -### 2>&1 | FileCheck %s --check-prefix=SPIRV_VAL_VK12 +// SPIRV_VAL_VK12:spirv-val{{(.exe)?}}" "--target-env" "vulkan1.2" "--scalar-block-layout" "{{.*}}.spv" // RUN: %clang_dxc -spirv -I test -Vd -Tlib_6_3 -### %s 2>&1 | FileCheck %s --check-prefix=VD // VD:"-cc1"{{.*}}"-triple" "spirv1.6-unknown-vulkan1.3-library" -// VD-NOT:spirv-val not found +// VD-NOT:spirv-val not found; resulting SPIR-V will not be validated // RUN: %clang_dxc -spirv -Tlib_6_3 -ccc-print-bindings --spirv-val-path=%t.dir -Fo %t.spv %s 2>&1 | FileCheck %s --check-prefix=BINDINGS // BINDINGS: "spirv1.6-unknown-vulkan1.3-library" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[spv:.+]].spv" @@ -23,4 +26,4 @@ // PHASES-NEXT: 2: compiler, {1}, ir // PHASES-NEXT: 3: backend, {2}, assembler // PHASES-NEXT: 4: assembler, {3}, object -// PHASES-NEXT: 5: binary-analyzer, {4}, object \ No newline at end of file +// PHASES-NEXT: 5: binary-analyzer, {4}, object >From 2dcfc33aed1d4fbc5a542fa952bbb28b2dca0c65 Mon Sep 17 00:00:00 2001 From: Joshua Batista <[email protected]> Date: Fri, 3 Apr 2026 16:11:33 -0700 Subject: [PATCH 3/3] address Justin --- clang/lib/Driver/Driver.cpp | 5 +- clang/lib/Driver/ToolChains/HLSL.cpp | 80 ++++++++++------------- clang/lib/Driver/ToolChains/HLSL.h | 29 +++----- clang/test/Driver/dxc_spirv-val_path.hlsl | 2 +- 4 files changed, 49 insertions(+), 67 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 70dd8285f346a..225af09c60552 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4746,8 +4746,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, // Call spirv-val for SPIR-V when -Vd not in Args. if (TC.requiresValidation(Args)) { Action *LastAction = Actions.back(); - Actions.push_back( - C.MakeAction<BinaryAnalyzeJobAction>(LastAction, types::TY_Object)); + if (LastAction->getType() == types::TY_Object) + Actions.push_back( + C.MakeAction<BinaryAnalyzeJobAction>(LastAction, types::TY_Object)); } } diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index 634e22bcf3a22..d1f41c8f127cb 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -300,43 +300,35 @@ void tools::hlsl::Validator::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { - std::string DxvPath = getToolChain().GetProgramPath("dxv"); - assert(DxvPath != "dxv" && "cannot find dxv"); - - ArgStringList CmdArgs; - assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); - const InputInfo &Input = Inputs[0]; - CmdArgs.push_back(Input.getFilename()); - CmdArgs.push_back("-o"); - CmdArgs.push_back(Output.getFilename()); - - const char *Exec = Args.MakeArgString(DxvPath); - C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs, Input)); -} - -void tools::hlsl::SPIRV_Validator::ConstructJob( - Compilation &C, const JobAction &JA, const InputInfo &Output, - const InputInfoList &Inputs, const ArgList &Args, - const char *LinkingOutput) const { - std::string SPIRVValPath = getToolChain().GetProgramPath("spirv-val"); - assert(SPIRVValPath != "spirv-val" && "cannot find spirv-val"); - ArgStringList CmdArgs; assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); const InputInfo &Input = Inputs[0]; const llvm::Triple &T = getToolChain().getTriple(); - CmdArgs.push_back("--target-env"); - CmdArgs.push_back(Args.MakeArgString(T.getOSName())); - - CmdArgs.push_back("--scalar-block-layout"); - - CmdArgs.push_back(Input.getFilename()); - - const char *Exec = Args.MakeArgString(SPIRVValPath); - C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs, Input)); + if (T.isSPIRV()) { + std::string SPIRVValPath = getToolChain().GetProgramPath("spirv-val"); + assert(SPIRVValPath != "spirv-val" && "cannot find spirv-val"); + + CmdArgs.push_back("--target-env"); + CmdArgs.push_back(Args.MakeArgString(T.getOSName())); + CmdArgs.push_back("--scalar-block-layout"); + CmdArgs.push_back(Input.getFilename()); + + const char *Exec = Args.MakeArgString(SPIRVValPath); + C.addCommand(std::make_unique<Command>( + JA, *this, ResponseFileSupport::None(), Exec, CmdArgs, Inputs, Input)); + } else { + std::string DxvPath = getToolChain().GetProgramPath("dxv"); + assert(DxvPath != "dxv" && "cannot find dxv"); + + CmdArgs.push_back(Input.getFilename()); + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + const char *Exec = Args.MakeArgString(DxvPath); + C.addCommand(std::make_unique<Command>( + JA, *this, ResponseFileSupport::None(), Exec, CmdArgs, Inputs, Input)); + } } void tools::hlsl::MetalConverter::ConstructJob( @@ -417,11 +409,6 @@ Tool *clang::driver::toolchains::HLSLToolChain::getTool( Action::ActionClass AC) const { switch (AC) { case Action::BinaryAnalyzeJobClass: - if (getTriple().isSPIRV()) { - if (!SPIRVValidator) - SPIRVValidator.reset(new tools::hlsl::SPIRV_Validator(*this)); - return SPIRVValidator.get(); - } if (!Validator) Validator.reset(new tools::hlsl::Validator(*this)); return Validator.get(); @@ -625,12 +612,15 @@ bool HLSLToolChain::requiresValidation(DerivedArgList &Args, return false; } - std::string SpirvValPath = GetProgramPath("spirv-val"); - if (SpirvValPath != "spirv-val") - return true; + if (getTriple().isSPIRV()) { + std::string SpirvValPath = GetProgramPath("spirv-val"); + if (SpirvValPath != "spirv-val") + return true; + + if (Diagnose) + getDriver().Diag(diag::warn_drv_dxc_missing_spirv_val); + } - if (Diagnose) - getDriver().Diag(diag::warn_drv_dxc_missing_spirv_val); return false; } @@ -650,11 +640,11 @@ bool HLSLToolChain::isLastJob(DerivedArgList &Args, if (requiresBinaryTranslation(Args)) return AC == Action::Action::BinaryTranslatorJobClass; // For SPIR-V, spirv-val is a pure validator that doesn't produce output - // files, so the compile step is the output-producing step. For DXIL, dxv - // validates and signs, producing the final output. + // files, so the compile step is the last output-producing job. For DXIL, + // dxv validates and signs, producing the final output. if (requiresValidation(Args, /*Diagnose=*/false)) { if (getTriple().isSPIRV()) - return AC != Action::Action::BinaryAnalyzeJobClass; + return AC == Action::Action::AssembleJobClass; return AC == Action::Action::BinaryAnalyzeJobClass; } if (requiresObjcopy(Args)) diff --git a/clang/lib/Driver/ToolChains/HLSL.h b/clang/lib/Driver/ToolChains/HLSL.h index 2bc592e44f84d..ced551a4aa24c 100644 --- a/clang/lib/Driver/ToolChains/HLSL.h +++ b/clang/lib/Driver/ToolChains/HLSL.h @@ -20,20 +20,9 @@ namespace tools { namespace hlsl { class LLVM_LIBRARY_VISIBILITY Validator : public Tool { public: - Validator(const ToolChain &TC) : Tool("hlsl::Validator", "dxv", TC) {} - - bool hasIntegratedCPP() const override { return false; } - - void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const override; -}; - -class LLVM_LIBRARY_VISIBILITY SPIRV_Validator : public Tool { -public: - SPIRV_Validator(const ToolChain &TC) - : Tool("hlsl::SPIRV_Validator", "spirv-val", TC) {} + Validator(const ToolChain &TC) + : Tool("hlsl::Validator", TC.getTriple().isSPIRV() ? "spirv-val" : "dxv", + TC) {} bool hasIntegratedCPP() const override { return false; } @@ -95,11 +84,14 @@ class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain { bool requiresBinaryTranslation(llvm::opt::DerivedArgList &Args) const; bool requiresObjcopy(llvm::opt::DerivedArgList &Args) const; - /// If we are targeting DXIL then the last job should output the DXContainer - /// to the specified output file with /Fo. Otherwise, we will emit to a - /// temporary file for the next job to use. + /// Determines whether the given action class is the last job that produces + /// an output file. This is used to decide whether to write to the -Fo + /// output path or to a temporary file. /// - /// Returns true if we should output to the final result file. + /// For example, spirv-val is a pure validator that runs after the compile + /// step but doesn't produce output, so the compile step is the last + /// output-producing job. For DXIL, dxv validates and signs, producing the + /// final output. bool isLastJob(llvm::opt::DerivedArgList &Args, Action::ActionClass AC) const; // Set default DWARF version to 4 for DXIL uses version 4. @@ -109,7 +101,6 @@ class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain { private: mutable std::unique_ptr<tools::hlsl::Validator> Validator; - mutable std::unique_ptr<tools::hlsl::SPIRV_Validator> SPIRVValidator; mutable std::unique_ptr<tools::hlsl::MetalConverter> MetalConverter; mutable std::unique_ptr<tools::hlsl::LLVMObjcopy> LLVMObjcopy; }; diff --git a/clang/test/Driver/dxc_spirv-val_path.hlsl b/clang/test/Driver/dxc_spirv-val_path.hlsl index 4f39fa37c69e5..4a5090fc56863 100644 --- a/clang/test/Driver/dxc_spirv-val_path.hlsl +++ b/clang/test/Driver/dxc_spirv-val_path.hlsl @@ -17,7 +17,7 @@ // RUN: %clang_dxc -spirv -Tlib_6_3 -ccc-print-bindings --spirv-val-path=%t.dir -Fo %t.spv %s 2>&1 | FileCheck %s --check-prefix=BINDINGS // BINDINGS: "spirv1.6-unknown-vulkan1.3-library" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[spv:.+]].spv" -// BINDINGS-NEXT: "spirv1.6-unknown-vulkan1.3-library" - "hlsl::SPIRV_Validator", inputs: ["[[spv]].spv"], output: "{{.+}}.obj" +// BINDINGS-NEXT: "spirv1.6-unknown-vulkan1.3-library" - "hlsl::Validator", inputs: ["[[spv]].spv"], output: "{{.+}}.obj" // RUN: %clang_dxc -spirv -Tlib_6_3 -ccc-print-phases --spirv-val-path=%t.dir -Fo %t.spv %s 2>&1 | FileCheck %s --check-prefix=PHASES _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
