Skip to content

Commit 39cf545

Browse files
authored
[HLSL][Driver] Use temporary files correctly (#130436)
This updates the DXV and Metal Converter actions to properly use temporary files created by the driver. I've abstracted away a check to determine if an action is the last in the sequence because we may have between 1 and 3 actions depending on the arguments and environment.
1 parent 3b33560 commit 39cf545

File tree

5 files changed

+62
-17
lines changed

5 files changed

+62
-17
lines changed

clang/lib/Driver/Driver.cpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4669,7 +4669,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
46694669
Actions.push_back(C.MakeAction<BinaryAnalyzeJobAction>(
46704670
LastAction, types::TY_DX_CONTAINER));
46714671
}
4672-
if (Args.getLastArg(options::OPT_metal)) {
4672+
if (TC.requiresBinaryTranslation(Args)) {
46734673
Action *LastAction = Actions.back();
46744674
// Metal shader converter runs on DXIL containers, which can either be
46754675
// validated (in which case they are TY_DX_CONTAINER), or unvalidated
@@ -5219,8 +5219,14 @@ void Driver::BuildJobs(Compilation &C) const {
52195219
unsigned NumOutputs = 0;
52205220
unsigned NumIfsOutputs = 0;
52215221
for (const Action *A : C.getActions()) {
5222+
// The actions below do not increase the number of outputs, when operating
5223+
// on DX containers.
5224+
if (A->getType() == types::TY_DX_CONTAINER &&
5225+
(A->getKind() == clang::driver::Action::BinaryAnalyzeJobClass ||
5226+
A->getKind() == clang::driver::Action::BinaryTranslatorJobClass))
5227+
continue;
5228+
52225229
if (A->getType() != types::TY_Nothing &&
5223-
A->getType() != types::TY_DX_CONTAINER &&
52245230
!(A->getKind() == Action::IfsMergeJobClass ||
52255231
(A->getType() == clang::driver::types::TY_IFS_CPP &&
52265232
A->getKind() == clang::driver::Action::CompileJobClass &&
@@ -6221,11 +6227,27 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
62216227
return C.addResultFile(C.getArgs().MakeArgString(FcValue.str()), &JA);
62226228
}
62236229

6224-
if (JA.getType() == types::TY_Object &&
6225-
C.getArgs().hasArg(options::OPT_dxc_Fo)) {
6230+
if ((JA.getType() == types::TY_Object &&
6231+
C.getArgs().hasArg(options::OPT_dxc_Fo)) ||
6232+
JA.getType() == types::TY_DX_CONTAINER) {
62266233
StringRef FoValue = C.getArgs().getLastArgValue(options::OPT_dxc_Fo);
6227-
// TODO: Should we use `MakeCLOutputFilename` here? If so, we can probably
6228-
// handle this as part of the SLASH_Fo handling below.
6234+
// If we are targeting DXIL and not validating or translating, we should set
6235+
// the final result file. Otherwise we should emit to a temporary.
6236+
if (C.getDefaultToolChain().getTriple().isDXIL()) {
6237+
const auto &TC = static_cast<const toolchains::HLSLToolChain &>(
6238+
C.getDefaultToolChain());
6239+
// Fo can be empty here if the validator is running for a compiler flow
6240+
// that is using Fc or just printing disassembly.
6241+
if (TC.isLastJob(C.getArgs(), JA.getKind()) && !FoValue.empty())
6242+
return C.addResultFile(C.getArgs().MakeArgString(FoValue.str()), &JA);
6243+
StringRef Name = llvm::sys::path::filename(BaseInput);
6244+
std::pair<StringRef, StringRef> Split = Name.split('.');
6245+
const char *Suffix = types::getTypeTempSuffix(JA.getType(), true);
6246+
return CreateTempFile(C, Split.first, Suffix, false);
6247+
}
6248+
// We don't have SPIRV-val integrated (yet), so for now we can assume this
6249+
// is the final output.
6250+
assert(C.getDefaultToolChain().getTriple().isSPIRV());
62296251
return C.addResultFile(C.getArgs().MakeArgString(FoValue.str()), &JA);
62306252
}
62316253

clang/lib/Driver/ToolChains/HLSL.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,9 @@ void tools::hlsl::Validator::ConstructJob(Compilation &C, const JobAction &JA,
186186
ArgStringList CmdArgs;
187187
assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
188188
const InputInfo &Input = Inputs[0];
189-
assert(Input.isFilename() && "Unexpected verify input");
190-
// Grabbing the output of the earlier cc1 run.
191189
CmdArgs.push_back(Input.getFilename());
192-
// Use the same name as output.
193190
CmdArgs.push_back("-o");
194-
CmdArgs.push_back(Input.getFilename());
191+
CmdArgs.push_back(Output.getFilename());
195192

196193
const char *Exec = Args.MakeArgString(DxvPath);
197194
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
@@ -204,10 +201,11 @@ void tools::hlsl::MetalConverter::ConstructJob(
204201
const char *LinkingOutput) const {
205202
std::string MSCPath = getToolChain().GetProgramPath("metal-shaderconverter");
206203
ArgStringList CmdArgs;
204+
assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
207205
const InputInfo &Input = Inputs[0];
208206
CmdArgs.push_back(Input.getFilename());
209207
CmdArgs.push_back("-o");
210-
CmdArgs.push_back(Input.getFilename());
208+
CmdArgs.push_back(Output.getFilename());
211209

212210
const char *Exec = Args.MakeArgString(MSCPath);
213211
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
@@ -321,3 +319,21 @@ bool HLSLToolChain::requiresValidation(DerivedArgList &Args) const {
321319
getDriver().Diag(diag::warn_drv_dxc_missing_dxv);
322320
return false;
323321
}
322+
323+
bool HLSLToolChain::requiresBinaryTranslation(DerivedArgList &Args) const {
324+
return Args.hasArg(options::OPT_metal) && Args.hasArg(options::OPT_dxc_Fo);
325+
}
326+
327+
bool HLSLToolChain::isLastJob(DerivedArgList &Args,
328+
Action::ActionClass AC) const {
329+
bool HasTranslation = requiresBinaryTranslation(Args);
330+
bool HasValidation = requiresValidation(Args);
331+
// If translation and validation are not required, we should only have one
332+
// action.
333+
if (!HasTranslation && !HasValidation)
334+
return true;
335+
if ((HasTranslation && AC == Action::BinaryTranslatorJobClass) ||
336+
(!HasTranslation && HasValidation && AC == Action::BinaryAnalyzeJobClass))
337+
return true;
338+
return false;
339+
}

clang/lib/Driver/ToolChains/HLSL.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain {
6464
Action::OffloadKind DeviceOffloadKind) const override;
6565
static std::optional<std::string> parseTargetProfile(StringRef TargetProfile);
6666
bool requiresValidation(llvm::opt::DerivedArgList &Args) const;
67+
bool requiresBinaryTranslation(llvm::opt::DerivedArgList &Args) const;
68+
bool isLastJob(llvm::opt::DerivedArgList &Args, Action::ActionClass AC) const;
6769

6870
// Set default DWARF version to 4 for DXIL uses version 4.
6971
unsigned GetDefaultDwarfVersion() const override { return 4; }

clang/test/Driver/HLSL/metal-converter.hlsl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
// RUN: %clang_dxc -T cs_6_0 %s -metal -Fo tmp.mtl -### 2>&1 | FileCheck %s
2-
// RUN: %clang_dxc -T cs_6_0 %s -metal -Vd -Fo tmp.mtl -### 2>&1 | FileCheck %s
3-
// CHECK: "{{.*}}metal-shaderconverter{{(.exe)?}}" "tmp.mtl" "-o" "tmp.mtl"
1+
// RUN: %clang_dxc -T cs_6_0 %s -metal -Fo %t.mtl -### 2>&1 | FileCheck %s
2+
// RUN: %clang_dxc -T cs_6_0 %s -metal -Vd -Fo %t.mtl -### 2>&1 | FileCheck %s
3+
// CHECK: "{{.*}}metal-shaderconverter{{(.exe)?}}" "{{.*}}.obj" "-o" "{{.*}}.mtl"
44

55
// RUN: %clang_dxc -T cs_6_0 %s -metal -### 2>&1 | FileCheck --check-prefix=NO_MTL %s
66
// NO_MTL-NOT: metal-shaderconverter
77

8+
// RUN: echo "dxv" > %T/dxv && chmod 754 %T/dxv
9+
// RUN: %clang_dxc -T cs_6_0 %s --dxv-path=%T -metal -Fo %t.mtl -### 2>&1 | FileCheck --check-prefix=DXV %s
10+
// DXV: "{{.*}}dxv{{(.exe)?}}" "{{.*}}.obj" "-o" "{{.*}}.dxo"
11+
// DXV: "{{.*}}metal-shaderconverter{{(.exe)?}}" "{{.*}}.dxo" "-o" "{{.*}}.mtl"
12+
813
RWBuffer<float4> In : register(u0, space0);
914
RWBuffer<float4> Out : register(u1, space4);
1015

clang/test/Driver/dxc_dxv_path.hlsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
// CHECK:dxv not found
55

66
// RUN: echo "dxv" > %T/dxv && chmod 754 %T/dxv && %clang_dxc --dxv-path=%T %s -Tlib_6_3 -### 2>&1 | FileCheck %s --check-prefix=DXV_PATH
7-
// DXV_PATH:dxv{{(.exe)?}}" "-" "-o" "-"
7+
// DXV_PATH:dxv{{(.exe)?}}" "-" "-o" "{{.*}}.dxo"
88

99
// RUN: %clang_dxc -I test -Vd -Tlib_6_3 -### %s 2>&1 | FileCheck %s --check-prefix=VD
1010
// VD:"-cc1"{{.*}}"-triple" "dxilv1.3-unknown-shadermodel6.3-library"
1111
// VD-NOT:dxv not found
1212

1313
// RUN: %clang_dxc -Tlib_6_3 -ccc-print-bindings --dxv-path=%T -Fo %t.dxo %s 2>&1 | FileCheck %s --check-prefix=BINDINGS
14-
// BINDINGS: "dxilv1.3-unknown-shadermodel6.3-library" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[DXC:.+]].dxo"
15-
// BINDINGS-NEXT: "dxilv1.3-unknown-shadermodel6.3-library" - "hlsl::Validator", inputs: ["[[DXC]].dxo"]
14+
// BINDINGS: "dxilv1.3-unknown-shadermodel6.3-library" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[obj:.+]].obj"
15+
// BINDINGS-NEXT: "dxilv1.3-unknown-shadermodel6.3-library" - "hlsl::Validator", inputs: ["[[obj]].obj"], output: "{{.+}}.dxo"
1616

1717
// RUN: %clang_dxc -Tlib_6_3 -ccc-print-phases --dxv-path=%T -Fo %t.dxc %s 2>&1 | FileCheck %s --check-prefix=PHASES
1818

0 commit comments

Comments
 (0)