[docs] Fix build-docs.sh
[llvm-project.git] / clang / lib / Driver / ToolChains / HLSL.cpp
bloba80fea2e3efe2510168209e865b9eb1360ce3daf
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 //===----------------------------------------------------------------------===//
9 #include "HLSL.h"
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;
20 using namespace llvm;
22 namespace {
24 const unsigned OfflineLibMinor = 0xF;
26 bool isLegalShaderModel(Triple &T) {
27 if (T.getOS() != Triple::OSType::ShaderModel)
28 return false;
30 auto Version = T.getOSVersion();
31 if (Version.getBuild())
32 return false;
33 if (Version.getSubminor())
34 return false;
36 auto Kind = T.getEnvironment();
38 switch (Kind) {
39 default:
40 return false;
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;
49 } break;
50 case Triple::EnvironmentType::Library: {
51 VersionTuple SM6x(6, OfflineLibMinor);
52 if (Version == SM6x)
53 return true;
55 VersionTuple MinVer(6, 3);
56 return MinVer <= Version;
57 } break;
58 case Triple::EnvironmentType::Amplification:
59 case Triple::EnvironmentType::Mesh: {
60 VersionTuple MinVer(6, 5);
61 return MinVer <= Version;
62 } break;
64 return false;
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)
72 return NoneType();
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)
87 return NoneType();
89 unsigned long long Major = 0;
90 if (llvm::getAsUnsignedInteger(Parts[1], 0, Major))
91 return NoneType();
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))
97 return NoneType();
99 // dxil-unknown-shadermodel-hull
100 llvm::Triple T;
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();
107 else
108 return NoneType();
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)
116 << ValVersionStr;
117 return false;
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;
124 return false;
126 VersionTuple MinVer(1, 0);
127 if (Version < MinVer) {
128 D.Diag(diag::err_drv_invalid_range_dxil_validator_version) << ValVersionStr;
129 return false;
131 return true;
134 } // namespace
136 /// DirectX Toolchain
137 HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
138 const ArgList &Args)
139 : ToolChain(D, Triple, Args) {}
141 llvm::Optional<std::string>
142 clang::driver::toolchains::HLSLToolChain::parseTargetProfile(
143 StringRef TargetProfile) {
144 return tryParseProfile(TargetProfile);
147 DerivedArgList *
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()))
159 continue;
161 if (A->getOption().getID() == options::OPT_dxc_entrypoint) {
162 DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_hlsl_entrypoint),
163 A->getValue());
164 A->claim();
165 continue;
167 if (A->getOption().getID() == options::OPT__SLASH_O) {
168 StringRef OStr = A->getValue();
169 if (OStr == "d") {
170 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_O0));
171 A->claim();
172 continue;
173 } else {
174 DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O), OStr);
175 A->claim();
176 continue;
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));
185 A->claim();
186 continue;
188 DAL->append(A);
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));
196 } else
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
211 // shader model 6.2.
212 return DAL;