1 //===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 #include "CommonArgs.h"
11 #include "clang/Driver/DriverDiagnostic.h"
12 #include "llvm/ADT/StringSwitch.h"
13 #include "llvm/ADT/Triple.h"
15 using namespace clang::driver
;
16 using namespace clang::driver::tools
;
17 using namespace clang::driver::toolchains
;
18 using namespace clang
;
19 using namespace llvm::opt
;
24 const unsigned OfflineLibMinor
= 0xF;
26 bool isLegalShaderModel(Triple
&T
) {
27 if (T
.getOS() != Triple::OSType::ShaderModel
)
30 auto Version
= T
.getOSVersion();
31 if (Version
.getBuild())
33 if (Version
.getSubminor())
36 auto Kind
= T
.getEnvironment();
41 case Triple::EnvironmentType::Vertex
:
42 case Triple::EnvironmentType::Hull
:
43 case Triple::EnvironmentType::Domain
:
44 case Triple::EnvironmentType::Geometry
:
45 case Triple::EnvironmentType::Pixel
:
46 case Triple::EnvironmentType::Compute
: {
47 VersionTuple
MinVer(4, 0);
48 return MinVer
<= Version
;
50 case Triple::EnvironmentType::Library
: {
51 VersionTuple
SM6x(6, OfflineLibMinor
);
55 VersionTuple
MinVer(6, 3);
56 return MinVer
<= Version
;
58 case Triple::EnvironmentType::Amplification
:
59 case Triple::EnvironmentType::Mesh
: {
60 VersionTuple
MinVer(6, 5);
61 return MinVer
<= Version
;
67 llvm::Optional
<std::string
> tryParseProfile(StringRef Profile
) {
68 // [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor]
69 SmallVector
<StringRef
, 3> Parts
;
70 Profile
.split(Parts
, "_");
71 if (Parts
.size() != 3)
74 Triple::EnvironmentType Kind
=
75 StringSwitch
<Triple::EnvironmentType
>(Parts
[0])
76 .Case("ps", Triple::EnvironmentType::Pixel
)
77 .Case("vs", Triple::EnvironmentType::Vertex
)
78 .Case("gs", Triple::EnvironmentType::Geometry
)
79 .Case("hs", Triple::EnvironmentType::Hull
)
80 .Case("ds", Triple::EnvironmentType::Domain
)
81 .Case("cs", Triple::EnvironmentType::Compute
)
82 .Case("lib", Triple::EnvironmentType::Library
)
83 .Case("ms", Triple::EnvironmentType::Mesh
)
84 .Case("as", Triple::EnvironmentType::Amplification
)
85 .Default(Triple::EnvironmentType::UnknownEnvironment
);
86 if (Kind
== Triple::EnvironmentType::UnknownEnvironment
)
89 unsigned long long Major
= 0;
90 if (llvm::getAsUnsignedInteger(Parts
[1], 0, Major
))
93 unsigned long long Minor
= 0;
94 if (Parts
[2] == "x" && Kind
== Triple::EnvironmentType::Library
)
95 Minor
= OfflineLibMinor
;
96 else if (llvm::getAsUnsignedInteger(Parts
[2], 0, Minor
))
99 // dxil-unknown-shadermodel-hull
101 T
.setArch(Triple::ArchType::dxil
);
102 T
.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel
).str() +
103 VersionTuple(Major
, Minor
).getAsString());
104 T
.setEnvironment(Kind
);
105 if (isLegalShaderModel(T
))
106 return T
.getTriple();
111 bool isLegalValidatorVersion(StringRef ValVersionStr
, const Driver
&D
) {
112 VersionTuple Version
;
113 if (Version
.tryParse(ValVersionStr
) || Version
.getBuild() ||
114 Version
.getSubminor() || !Version
.getMinor()) {
115 D
.Diag(diag::err_drv_invalid_format_dxil_validator_version
)
120 uint64_t Major
= Version
.getMajor();
121 uint64_t Minor
= *Version
.getMinor();
122 if (Major
== 0 && Minor
!= 0) {
123 D
.Diag(diag::err_drv_invalid_empty_dxil_validator_version
) << ValVersionStr
;
126 VersionTuple
MinVer(1, 0);
127 if (Version
< MinVer
) {
128 D
.Diag(diag::err_drv_invalid_range_dxil_validator_version
) << ValVersionStr
;
136 /// DirectX Toolchain
137 HLSLToolChain::HLSLToolChain(const Driver
&D
, const llvm::Triple
&Triple
,
139 : ToolChain(D
, Triple
, Args
) {}
141 llvm::Optional
<std::string
>
142 clang::driver::toolchains::HLSLToolChain::parseTargetProfile(
143 StringRef TargetProfile
) {
144 return tryParseProfile(TargetProfile
);
148 HLSLToolChain::TranslateArgs(const DerivedArgList
&Args
, StringRef BoundArch
,
149 Action::OffloadKind DeviceOffloadKind
) const {
150 DerivedArgList
*DAL
= new DerivedArgList(Args
.getBaseArgs());
152 const OptTable
&Opts
= getDriver().getOpts();
154 for (Arg
*A
: Args
) {
155 if (A
->getOption().getID() == options::OPT_dxil_validator_version
) {
156 StringRef ValVerStr
= A
->getValue();
157 std::string ErrorMsg
;
158 if (!isLegalValidatorVersion(ValVerStr
, getDriver()))
161 if (A
->getOption().getID() == options::OPT_dxc_entrypoint
) {
162 DAL
->AddSeparateArg(nullptr, Opts
.getOption(options::OPT_hlsl_entrypoint
),
167 if (A
->getOption().getID() == options::OPT__SLASH_O
) {
168 StringRef OStr
= A
->getValue();
170 DAL
->AddFlagArg(nullptr, Opts
.getOption(options::OPT_O0
));
174 DAL
->AddJoinedArg(nullptr, Opts
.getOption(options::OPT_O
), OStr
);
179 if (A
->getOption().getID() == options::OPT_emit_pristine_llvm
) {
180 // Translate fcgl into -S -emit-llvm and -disable-llvm-passes.
181 DAL
->AddFlagArg(nullptr, Opts
.getOption(options::OPT_S
));
182 DAL
->AddFlagArg(nullptr, Opts
.getOption(options::OPT_emit_llvm
));
183 DAL
->AddFlagArg(nullptr,
184 Opts
.getOption(options::OPT_disable_llvm_passes
));
191 if (DAL
->hasArg(options::OPT_o
)) {
192 // When run the whole pipeline.
193 if (!DAL
->hasArg(options::OPT_emit_llvm
))
194 // Emit obj if write to file.
195 DAL
->AddFlagArg(nullptr, Opts
.getOption(options::OPT_emit_obj
));
197 DAL
->AddSeparateArg(nullptr, Opts
.getOption(options::OPT_o
), "-");
199 // Add default validator version if not set.
200 // TODO: remove this once read validator version from validator.
201 if (!DAL
->hasArg(options::OPT_dxil_validator_version
)) {
202 const StringRef DefaultValidatorVer
= "1.7";
203 DAL
->AddSeparateArg(nullptr,
204 Opts
.getOption(options::OPT_dxil_validator_version
),
205 DefaultValidatorVer
);
207 if (!DAL
->hasArg(options::OPT_O_Group
)) {
208 DAL
->AddJoinedArg(nullptr, Opts
.getOption(options::OPT_O
), "3");
210 // FIXME: add validation for enable_16bit_types should be after HLSL 2018 and