Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/HLSL.cpp
35266 views
1
//===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "HLSL.h"
10
#include "CommonArgs.h"
11
#include "clang/Driver/Compilation.h"
12
#include "clang/Driver/DriverDiagnostic.h"
13
#include "clang/Driver/Job.h"
14
#include "llvm/ADT/StringSwitch.h"
15
#include "llvm/TargetParser/Triple.h"
16
17
using namespace clang::driver;
18
using namespace clang::driver::tools;
19
using namespace clang::driver::toolchains;
20
using namespace clang;
21
using namespace llvm::opt;
22
using namespace llvm;
23
24
namespace {
25
26
const unsigned OfflineLibMinor = 0xF;
27
28
bool isLegalShaderModel(Triple &T) {
29
if (T.getOS() != Triple::OSType::ShaderModel)
30
return false;
31
32
auto Version = T.getOSVersion();
33
if (Version.getBuild())
34
return false;
35
if (Version.getSubminor())
36
return false;
37
38
auto Kind = T.getEnvironment();
39
40
switch (Kind) {
41
default:
42
return false;
43
case Triple::EnvironmentType::Vertex:
44
case Triple::EnvironmentType::Hull:
45
case Triple::EnvironmentType::Domain:
46
case Triple::EnvironmentType::Geometry:
47
case Triple::EnvironmentType::Pixel:
48
case Triple::EnvironmentType::Compute: {
49
VersionTuple MinVer(4, 0);
50
return MinVer <= Version;
51
} break;
52
case Triple::EnvironmentType::Library: {
53
VersionTuple SM6x(6, OfflineLibMinor);
54
if (Version == SM6x)
55
return true;
56
57
VersionTuple MinVer(6, 3);
58
return MinVer <= Version;
59
} break;
60
case Triple::EnvironmentType::Amplification:
61
case Triple::EnvironmentType::Mesh: {
62
VersionTuple MinVer(6, 5);
63
return MinVer <= Version;
64
} break;
65
}
66
return false;
67
}
68
69
std::optional<std::string> tryParseProfile(StringRef Profile) {
70
// [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor]
71
SmallVector<StringRef, 3> Parts;
72
Profile.split(Parts, "_");
73
if (Parts.size() != 3)
74
return std::nullopt;
75
76
Triple::EnvironmentType Kind =
77
StringSwitch<Triple::EnvironmentType>(Parts[0])
78
.Case("ps", Triple::EnvironmentType::Pixel)
79
.Case("vs", Triple::EnvironmentType::Vertex)
80
.Case("gs", Triple::EnvironmentType::Geometry)
81
.Case("hs", Triple::EnvironmentType::Hull)
82
.Case("ds", Triple::EnvironmentType::Domain)
83
.Case("cs", Triple::EnvironmentType::Compute)
84
.Case("lib", Triple::EnvironmentType::Library)
85
.Case("ms", Triple::EnvironmentType::Mesh)
86
.Case("as", Triple::EnvironmentType::Amplification)
87
.Default(Triple::EnvironmentType::UnknownEnvironment);
88
if (Kind == Triple::EnvironmentType::UnknownEnvironment)
89
return std::nullopt;
90
91
unsigned long long Major = 0;
92
if (llvm::getAsUnsignedInteger(Parts[1], 0, Major))
93
return std::nullopt;
94
95
unsigned long long Minor = 0;
96
if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library)
97
Minor = OfflineLibMinor;
98
else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor))
99
return std::nullopt;
100
101
// Determine DXIL version using the minor version number of Shader
102
// Model version specified in target profile. Prior to decoupling DXIL version
103
// numbering from that of Shader Model DXIL version 1.Y corresponds to SM 6.Y.
104
// E.g., dxilv1.Y-unknown-shadermodelX.Y-hull
105
llvm::Triple T;
106
Triple::SubArchType SubArch = llvm::Triple::NoSubArch;
107
switch (Minor) {
108
case 0:
109
SubArch = llvm::Triple::DXILSubArch_v1_0;
110
break;
111
case 1:
112
SubArch = llvm::Triple::DXILSubArch_v1_1;
113
break;
114
case 2:
115
SubArch = llvm::Triple::DXILSubArch_v1_2;
116
break;
117
case 3:
118
SubArch = llvm::Triple::DXILSubArch_v1_3;
119
break;
120
case 4:
121
SubArch = llvm::Triple::DXILSubArch_v1_4;
122
break;
123
case 5:
124
SubArch = llvm::Triple::DXILSubArch_v1_5;
125
break;
126
case 6:
127
SubArch = llvm::Triple::DXILSubArch_v1_6;
128
break;
129
case 7:
130
SubArch = llvm::Triple::DXILSubArch_v1_7;
131
break;
132
case 8:
133
SubArch = llvm::Triple::DXILSubArch_v1_8;
134
break;
135
case OfflineLibMinor:
136
// Always consider minor version x as the latest supported DXIL version
137
SubArch = llvm::Triple::LatestDXILSubArch;
138
break;
139
default:
140
// No DXIL Version corresponding to specified Shader Model version found
141
return std::nullopt;
142
}
143
T.setArch(Triple::ArchType::dxil, SubArch);
144
T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() +
145
VersionTuple(Major, Minor).getAsString());
146
T.setEnvironment(Kind);
147
if (isLegalShaderModel(T))
148
return T.getTriple();
149
else
150
return std::nullopt;
151
}
152
153
bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) {
154
VersionTuple Version;
155
if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
156
Version.getSubminor() || !Version.getMinor()) {
157
D.Diag(diag::err_drv_invalid_format_dxil_validator_version)
158
<< ValVersionStr;
159
return false;
160
}
161
162
uint64_t Major = Version.getMajor();
163
uint64_t Minor = *Version.getMinor();
164
if (Major == 0 && Minor != 0) {
165
D.Diag(diag::err_drv_invalid_empty_dxil_validator_version) << ValVersionStr;
166
return false;
167
}
168
VersionTuple MinVer(1, 0);
169
if (Version < MinVer) {
170
D.Diag(diag::err_drv_invalid_range_dxil_validator_version) << ValVersionStr;
171
return false;
172
}
173
return true;
174
}
175
176
} // namespace
177
178
void tools::hlsl::Validator::ConstructJob(Compilation &C, const JobAction &JA,
179
const InputInfo &Output,
180
const InputInfoList &Inputs,
181
const ArgList &Args,
182
const char *LinkingOutput) const {
183
std::string DxvPath = getToolChain().GetProgramPath("dxv");
184
assert(DxvPath != "dxv" && "cannot find dxv");
185
186
ArgStringList CmdArgs;
187
assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
188
const InputInfo &Input = Inputs[0];
189
assert(Input.isFilename() && "Unexpected verify input");
190
// Grabbing the output of the earlier cc1 run.
191
CmdArgs.push_back(Input.getFilename());
192
// Use the same name as output.
193
CmdArgs.push_back("-o");
194
CmdArgs.push_back(Input.getFilename());
195
196
const char *Exec = Args.MakeArgString(DxvPath);
197
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
198
Exec, CmdArgs, Inputs, Input));
199
}
200
201
/// DirectX Toolchain
202
HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
203
const ArgList &Args)
204
: ToolChain(D, Triple, Args) {
205
if (Args.hasArg(options::OPT_dxc_validator_path_EQ))
206
getProgramPaths().push_back(
207
Args.getLastArgValue(options::OPT_dxc_validator_path_EQ).str());
208
}
209
210
Tool *clang::driver::toolchains::HLSLToolChain::getTool(
211
Action::ActionClass AC) const {
212
switch (AC) {
213
case Action::BinaryAnalyzeJobClass:
214
if (!Validator)
215
Validator.reset(new tools::hlsl::Validator(*this));
216
return Validator.get();
217
default:
218
return ToolChain::getTool(AC);
219
}
220
}
221
222
std::optional<std::string>
223
clang::driver::toolchains::HLSLToolChain::parseTargetProfile(
224
StringRef TargetProfile) {
225
return tryParseProfile(TargetProfile);
226
}
227
228
DerivedArgList *
229
HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
230
Action::OffloadKind DeviceOffloadKind) const {
231
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
232
233
const OptTable &Opts = getDriver().getOpts();
234
235
for (Arg *A : Args) {
236
if (A->getOption().getID() == options::OPT_dxil_validator_version) {
237
StringRef ValVerStr = A->getValue();
238
std::string ErrorMsg;
239
if (!isLegalValidatorVersion(ValVerStr, getDriver()))
240
continue;
241
}
242
if (A->getOption().getID() == options::OPT_dxc_entrypoint) {
243
DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_hlsl_entrypoint),
244
A->getValue());
245
A->claim();
246
continue;
247
}
248
if (A->getOption().getID() == options::OPT__SLASH_O) {
249
StringRef OStr = A->getValue();
250
if (OStr == "d") {
251
DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_O0));
252
A->claim();
253
continue;
254
} else {
255
DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O), OStr);
256
A->claim();
257
continue;
258
}
259
}
260
if (A->getOption().getID() == options::OPT_emit_pristine_llvm) {
261
// Translate -fcgl into -emit-llvm and -disable-llvm-passes.
262
DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_emit_llvm));
263
DAL->AddFlagArg(nullptr,
264
Opts.getOption(options::OPT_disable_llvm_passes));
265
A->claim();
266
continue;
267
}
268
if (A->getOption().getID() == options::OPT_dxc_hlsl_version) {
269
// Translate -HV into -std for llvm
270
// depending on the value given
271
LangStandard::Kind LangStd = LangStandard::getHLSLLangKind(A->getValue());
272
if (LangStd != LangStandard::lang_unspecified) {
273
LangStandard l = LangStandard::getLangStandardForKind(LangStd);
274
DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_std_EQ),
275
l.getName());
276
} else {
277
getDriver().Diag(diag::err_drv_invalid_value) << "HV" << A->getValue();
278
}
279
280
A->claim();
281
continue;
282
}
283
DAL->append(A);
284
}
285
286
// Add default validator version if not set.
287
// TODO: remove this once read validator version from validator.
288
if (!DAL->hasArg(options::OPT_dxil_validator_version)) {
289
const StringRef DefaultValidatorVer = "1.7";
290
DAL->AddSeparateArg(nullptr,
291
Opts.getOption(options::OPT_dxil_validator_version),
292
DefaultValidatorVer);
293
}
294
if (!DAL->hasArg(options::OPT_O_Group)) {
295
DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O), "3");
296
}
297
298
return DAL;
299
}
300
301
bool HLSLToolChain::requiresValidation(DerivedArgList &Args) const {
302
if (Args.getLastArg(options::OPT_dxc_disable_validation))
303
return false;
304
305
std::string DxvPath = GetProgramPath("dxv");
306
if (DxvPath != "dxv")
307
return true;
308
309
getDriver().Diag(diag::warn_drv_dxc_missing_dxv);
310
return false;
311
}
312
313