150
|
1 //===- ToolChain.cpp - Collections of tools for one platform --------------===//
|
|
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 "clang/Driver/ToolChain.h"
|
|
10 #include "InputInfo.h"
|
|
11 #include "ToolChains/Arch/ARM.h"
|
|
12 #include "ToolChains/Clang.h"
|
|
13 #include "ToolChains/InterfaceStubs.h"
|
|
14 #include "ToolChains/Flang.h"
|
|
15 #include "clang/Basic/ObjCRuntime.h"
|
|
16 #include "clang/Basic/Sanitizers.h"
|
|
17 #include "clang/Config/config.h"
|
|
18 #include "clang/Driver/Action.h"
|
|
19 #include "clang/Driver/Driver.h"
|
|
20 #include "clang/Driver/DriverDiagnostic.h"
|
|
21 #include "clang/Driver/Job.h"
|
|
22 #include "clang/Driver/Options.h"
|
|
23 #include "clang/Driver/SanitizerArgs.h"
|
|
24 #include "clang/Driver/XRayArgs.h"
|
|
25 #include "llvm/ADT/STLExtras.h"
|
|
26 #include "llvm/ADT/SmallString.h"
|
|
27 #include "llvm/ADT/StringRef.h"
|
|
28 #include "llvm/ADT/Triple.h"
|
|
29 #include "llvm/ADT/Twine.h"
|
|
30 #include "llvm/Config/llvm-config.h"
|
|
31 #include "llvm/MC/MCTargetOptions.h"
|
|
32 #include "llvm/Option/Arg.h"
|
|
33 #include "llvm/Option/ArgList.h"
|
|
34 #include "llvm/Option/OptTable.h"
|
|
35 #include "llvm/Option/Option.h"
|
|
36 #include "llvm/Support/ErrorHandling.h"
|
|
37 #include "llvm/Support/FileSystem.h"
|
|
38 #include "llvm/Support/Path.h"
|
|
39 #include "llvm/Support/TargetParser.h"
|
|
40 #include "llvm/Support/TargetRegistry.h"
|
|
41 #include "llvm/Support/VersionTuple.h"
|
|
42 #include "llvm/Support/VirtualFileSystem.h"
|
|
43 #include <cassert>
|
|
44 #include <cstddef>
|
|
45 #include <cstring>
|
|
46 #include <string>
|
|
47
|
|
48 using namespace clang;
|
|
49 using namespace driver;
|
|
50 using namespace tools;
|
|
51 using namespace llvm;
|
|
52 using namespace llvm::opt;
|
|
53
|
|
54 static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) {
|
|
55 return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext,
|
|
56 options::OPT_fno_rtti, options::OPT_frtti);
|
|
57 }
|
|
58
|
|
59 static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
|
|
60 const llvm::Triple &Triple,
|
|
61 const Arg *CachedRTTIArg) {
|
|
62 // Explicit rtti/no-rtti args
|
|
63 if (CachedRTTIArg) {
|
|
64 if (CachedRTTIArg->getOption().matches(options::OPT_frtti))
|
|
65 return ToolChain::RM_Enabled;
|
|
66 else
|
|
67 return ToolChain::RM_Disabled;
|
|
68 }
|
|
69
|
|
70 // -frtti is default, except for the PS4 CPU.
|
|
71 return (Triple.isPS4CPU()) ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
|
|
72 }
|
|
73
|
|
74 ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
|
|
75 const ArgList &Args)
|
|
76 : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
|
|
77 CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
|
|
78 if (D.CCCIsCXX()) {
|
|
79 if (auto CXXStdlibPath = getCXXStdlibPath())
|
|
80 getFilePaths().push_back(*CXXStdlibPath);
|
|
81 }
|
|
82
|
|
83 if (auto RuntimePath = getRuntimePath())
|
|
84 getLibraryPaths().push_back(*RuntimePath);
|
|
85
|
|
86 std::string CandidateLibPath = getArchSpecificLibPath();
|
|
87 if (getVFS().exists(CandidateLibPath))
|
|
88 getFilePaths().push_back(CandidateLibPath);
|
|
89 }
|
|
90
|
|
91 void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
|
|
92 Triple.setEnvironment(Env);
|
|
93 if (EffectiveTriple != llvm::Triple())
|
|
94 EffectiveTriple.setEnvironment(Env);
|
|
95 }
|
|
96
|
|
97 ToolChain::~ToolChain() = default;
|
|
98
|
|
99 llvm::vfs::FileSystem &ToolChain::getVFS() const {
|
|
100 return getDriver().getVFS();
|
|
101 }
|
|
102
|
|
103 bool ToolChain::useIntegratedAs() const {
|
|
104 return Args.hasFlag(options::OPT_fintegrated_as,
|
|
105 options::OPT_fno_integrated_as,
|
|
106 IsIntegratedAssemblerDefault());
|
|
107 }
|
|
108
|
|
109 bool ToolChain::useRelaxRelocations() const {
|
|
110 return ENABLE_X86_RELAX_RELOCATIONS;
|
|
111 }
|
|
112
|
|
113 bool ToolChain::isNoExecStackDefault() const {
|
|
114 return false;
|
|
115 }
|
|
116
|
|
117 const SanitizerArgs& ToolChain::getSanitizerArgs() const {
|
|
118 if (!SanitizerArguments.get())
|
|
119 SanitizerArguments.reset(new SanitizerArgs(*this, Args));
|
|
120 return *SanitizerArguments.get();
|
|
121 }
|
|
122
|
|
123 const XRayArgs& ToolChain::getXRayArgs() const {
|
|
124 if (!XRayArguments.get())
|
|
125 XRayArguments.reset(new XRayArgs(*this, Args));
|
|
126 return *XRayArguments.get();
|
|
127 }
|
|
128
|
|
129 namespace {
|
|
130
|
|
131 struct DriverSuffix {
|
|
132 const char *Suffix;
|
|
133 const char *ModeFlag;
|
|
134 };
|
|
135
|
|
136 } // namespace
|
|
137
|
|
138 static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
|
|
139 // A list of known driver suffixes. Suffixes are compared against the
|
|
140 // program name in order. If there is a match, the frontend type is updated as
|
|
141 // necessary by applying the ModeFlag.
|
|
142 static const DriverSuffix DriverSuffixes[] = {
|
|
143 {"clang", nullptr},
|
|
144 {"clang++", "--driver-mode=g++"},
|
|
145 {"clang-c++", "--driver-mode=g++"},
|
|
146 {"clang-cc", nullptr},
|
|
147 {"clang-cpp", "--driver-mode=cpp"},
|
|
148 {"clang-g++", "--driver-mode=g++"},
|
|
149 {"clang-gcc", nullptr},
|
|
150 {"clang-cl", "--driver-mode=cl"},
|
|
151 {"cc", nullptr},
|
|
152 {"cpp", "--driver-mode=cpp"},
|
|
153 {"cl", "--driver-mode=cl"},
|
|
154 {"++", "--driver-mode=g++"},
|
|
155 {"flang", "--driver-mode=flang"},
|
|
156 };
|
|
157
|
|
158 for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) {
|
|
159 StringRef Suffix(DriverSuffixes[i].Suffix);
|
|
160 if (ProgName.endswith(Suffix)) {
|
|
161 Pos = ProgName.size() - Suffix.size();
|
|
162 return &DriverSuffixes[i];
|
|
163 }
|
|
164 }
|
|
165 return nullptr;
|
|
166 }
|
|
167
|
|
168 /// Normalize the program name from argv[0] by stripping the file extension if
|
|
169 /// present and lower-casing the string on Windows.
|
|
170 static std::string normalizeProgramName(llvm::StringRef Argv0) {
|
|
171 std::string ProgName = std::string(llvm::sys::path::stem(Argv0));
|
|
172 #ifdef _WIN32
|
|
173 // Transform to lowercase for case insensitive file systems.
|
|
174 std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), ::tolower);
|
|
175 #endif
|
|
176 return ProgName;
|
|
177 }
|
|
178
|
|
179 static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
|
|
180 // Try to infer frontend type and default target from the program name by
|
|
181 // comparing it against DriverSuffixes in order.
|
|
182
|
|
183 // If there is a match, the function tries to identify a target as prefix.
|
|
184 // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target
|
|
185 // prefix "x86_64-linux". If such a target prefix is found, it may be
|
|
186 // added via -target as implicit first argument.
|
|
187 const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);
|
|
188
|
|
189 if (!DS) {
|
|
190 // Try again after stripping any trailing version number:
|
|
191 // clang++3.5 -> clang++
|
|
192 ProgName = ProgName.rtrim("0123456789.");
|
|
193 DS = FindDriverSuffix(ProgName, Pos);
|
|
194 }
|
|
195
|
|
196 if (!DS) {
|
|
197 // Try again after stripping trailing -component.
|
|
198 // clang++-tot -> clang++
|
|
199 ProgName = ProgName.slice(0, ProgName.rfind('-'));
|
|
200 DS = FindDriverSuffix(ProgName, Pos);
|
|
201 }
|
|
202 return DS;
|
|
203 }
|
|
204
|
|
205 ParsedClangName
|
|
206 ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
|
|
207 std::string ProgName = normalizeProgramName(PN);
|
|
208 size_t SuffixPos;
|
|
209 const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
|
|
210 if (!DS)
|
|
211 return {};
|
|
212 size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);
|
|
213
|
|
214 size_t LastComponent = ProgName.rfind('-', SuffixPos);
|
|
215 if (LastComponent == std::string::npos)
|
|
216 return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);
|
|
217 std::string ModeSuffix = ProgName.substr(LastComponent + 1,
|
|
218 SuffixEnd - LastComponent - 1);
|
|
219
|
|
220 // Infer target from the prefix.
|
|
221 StringRef Prefix(ProgName);
|
|
222 Prefix = Prefix.slice(0, LastComponent);
|
|
223 std::string IgnoredError;
|
|
224 bool IsRegistered =
|
|
225 llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError);
|
|
226 return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag,
|
|
227 IsRegistered};
|
|
228 }
|
|
229
|
|
230 StringRef ToolChain::getDefaultUniversalArchName() const {
|
|
231 // In universal driver terms, the arch name accepted by -arch isn't exactly
|
|
232 // the same as the ones that appear in the triple. Roughly speaking, this is
|
|
233 // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the
|
|
234 // only interesting special case is powerpc.
|
|
235 switch (Triple.getArch()) {
|
|
236 case llvm::Triple::ppc:
|
|
237 return "ppc";
|
|
238 case llvm::Triple::ppc64:
|
|
239 return "ppc64";
|
|
240 case llvm::Triple::ppc64le:
|
|
241 return "ppc64le";
|
|
242 default:
|
|
243 return Triple.getArchName();
|
|
244 }
|
|
245 }
|
|
246
|
|
247 std::string ToolChain::getInputFilename(const InputInfo &Input) const {
|
|
248 return Input.getFilename();
|
|
249 }
|
|
250
|
|
251 bool ToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
|
|
252 return false;
|
|
253 }
|
|
254
|
|
255 Tool *ToolChain::getClang() const {
|
|
256 if (!Clang)
|
|
257 Clang.reset(new tools::Clang(*this));
|
|
258 return Clang.get();
|
|
259 }
|
|
260
|
|
261 Tool *ToolChain::getFlang() const {
|
|
262 if (!Flang)
|
|
263 Flang.reset(new tools::Flang(*this));
|
|
264 return Flang.get();
|
|
265 }
|
|
266
|
|
267 Tool *ToolChain::buildAssembler() const {
|
|
268 return new tools::ClangAs(*this);
|
|
269 }
|
|
270
|
|
271 Tool *ToolChain::buildLinker() const {
|
|
272 llvm_unreachable("Linking is not supported by this toolchain");
|
|
273 }
|
|
274
|
|
275 Tool *ToolChain::getAssemble() const {
|
|
276 if (!Assemble)
|
|
277 Assemble.reset(buildAssembler());
|
|
278 return Assemble.get();
|
|
279 }
|
|
280
|
|
281 Tool *ToolChain::getClangAs() const {
|
|
282 if (!Assemble)
|
|
283 Assemble.reset(new tools::ClangAs(*this));
|
|
284 return Assemble.get();
|
|
285 }
|
|
286
|
|
287 Tool *ToolChain::getLink() const {
|
|
288 if (!Link)
|
|
289 Link.reset(buildLinker());
|
|
290 return Link.get();
|
|
291 }
|
|
292
|
|
293 Tool *ToolChain::getIfsMerge() const {
|
|
294 if (!IfsMerge)
|
|
295 IfsMerge.reset(new tools::ifstool::Merger(*this));
|
|
296 return IfsMerge.get();
|
|
297 }
|
|
298
|
|
299 Tool *ToolChain::getOffloadBundler() const {
|
|
300 if (!OffloadBundler)
|
|
301 OffloadBundler.reset(new tools::OffloadBundler(*this));
|
|
302 return OffloadBundler.get();
|
|
303 }
|
|
304
|
|
305 Tool *ToolChain::getOffloadWrapper() const {
|
|
306 if (!OffloadWrapper)
|
|
307 OffloadWrapper.reset(new tools::OffloadWrapper(*this));
|
|
308 return OffloadWrapper.get();
|
|
309 }
|
|
310
|
|
311 Tool *ToolChain::getTool(Action::ActionClass AC) const {
|
|
312 switch (AC) {
|
|
313 case Action::AssembleJobClass:
|
|
314 return getAssemble();
|
|
315
|
|
316 case Action::IfsMergeJobClass:
|
|
317 return getIfsMerge();
|
|
318
|
|
319 case Action::LinkJobClass:
|
|
320 return getLink();
|
|
321
|
|
322 case Action::InputClass:
|
|
323 case Action::BindArchClass:
|
|
324 case Action::OffloadClass:
|
|
325 case Action::LipoJobClass:
|
|
326 case Action::DsymutilJobClass:
|
|
327 case Action::VerifyDebugInfoJobClass:
|
|
328 llvm_unreachable("Invalid tool kind.");
|
|
329
|
|
330 case Action::CompileJobClass:
|
|
331 case Action::PrecompileJobClass:
|
|
332 case Action::HeaderModulePrecompileJobClass:
|
|
333 case Action::PreprocessJobClass:
|
|
334 case Action::AnalyzeJobClass:
|
|
335 case Action::MigrateJobClass:
|
|
336 case Action::VerifyPCHJobClass:
|
|
337 case Action::BackendJobClass:
|
|
338 return getClang();
|
|
339
|
|
340 case Action::OffloadBundlingJobClass:
|
|
341 case Action::OffloadUnbundlingJobClass:
|
|
342 return getOffloadBundler();
|
|
343
|
|
344 case Action::OffloadWrapperJobClass:
|
|
345 return getOffloadWrapper();
|
|
346 }
|
|
347
|
|
348 llvm_unreachable("Invalid tool kind.");
|
|
349 }
|
|
350
|
|
351 static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
|
|
352 const ArgList &Args) {
|
|
353 const llvm::Triple &Triple = TC.getTriple();
|
|
354 bool IsWindows = Triple.isOSWindows();
|
|
355
|
|
356 if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
|
|
357 return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)
|
|
358 ? "armhf"
|
|
359 : "arm";
|
|
360
|
|
361 // For historic reasons, Android library is using i686 instead of i386.
|
|
362 if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid())
|
|
363 return "i686";
|
|
364
|
|
365 return llvm::Triple::getArchTypeName(TC.getArch());
|
|
366 }
|
|
367
|
|
368 StringRef ToolChain::getOSLibName() const {
|
|
369 switch (Triple.getOS()) {
|
|
370 case llvm::Triple::FreeBSD:
|
|
371 return "freebsd";
|
|
372 case llvm::Triple::NetBSD:
|
|
373 return "netbsd";
|
|
374 case llvm::Triple::OpenBSD:
|
|
375 return "openbsd";
|
|
376 case llvm::Triple::Solaris:
|
|
377 return "sunos";
|
|
378 default:
|
|
379 return getOS();
|
|
380 }
|
|
381 }
|
|
382
|
|
383 std::string ToolChain::getCompilerRTPath() const {
|
|
384 SmallString<128> Path(getDriver().ResourceDir);
|
|
385 if (Triple.isOSUnknown()) {
|
|
386 llvm::sys::path::append(Path, "lib");
|
|
387 } else {
|
|
388 llvm::sys::path::append(Path, "lib", getOSLibName());
|
|
389 }
|
|
390 return std::string(Path.str());
|
|
391 }
|
|
392
|
173
|
393 std::string ToolChain::getCompilerRTBasename(const ArgList &Args,
|
|
394 StringRef Component, FileType Type,
|
|
395 bool AddArch) const {
|
150
|
396 const llvm::Triple &TT = getTriple();
|
|
397 bool IsITANMSVCWindows =
|
|
398 TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
|
|
399
|
|
400 const char *Prefix =
|
|
401 IsITANMSVCWindows || Type == ToolChain::FT_Object ? "" : "lib";
|
|
402 const char *Suffix;
|
|
403 switch (Type) {
|
|
404 case ToolChain::FT_Object:
|
|
405 Suffix = IsITANMSVCWindows ? ".obj" : ".o";
|
|
406 break;
|
|
407 case ToolChain::FT_Static:
|
|
408 Suffix = IsITANMSVCWindows ? ".lib" : ".a";
|
|
409 break;
|
|
410 case ToolChain::FT_Shared:
|
|
411 Suffix = Triple.isOSWindows()
|
|
412 ? (Triple.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")
|
|
413 : ".so";
|
|
414 break;
|
|
415 }
|
|
416
|
173
|
417 std::string ArchAndEnv;
|
|
418 if (AddArch) {
|
|
419 StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
|
|
420 const char *Env = TT.isAndroid() ? "-android" : "";
|
|
421 ArchAndEnv = ("-" + Arch + Env).str();
|
|
422 }
|
|
423 return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str();
|
|
424 }
|
|
425
|
|
426 std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
|
|
427 FileType Type) const {
|
|
428 // Check for runtime files in the new layout without the architecture first.
|
|
429 std::string CRTBasename =
|
|
430 getCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
|
150
|
431 for (const auto &LibPath : getLibraryPaths()) {
|
|
432 SmallString<128> P(LibPath);
|
173
|
433 llvm::sys::path::append(P, CRTBasename);
|
150
|
434 if (getVFS().exists(P))
|
|
435 return std::string(P.str());
|
|
436 }
|
|
437
|
173
|
438 // Fall back to the old expected compiler-rt name if the new one does not
|
|
439 // exist.
|
|
440 CRTBasename = getCompilerRTBasename(Args, Component, Type, /*AddArch=*/true);
|
150
|
441 SmallString<128> Path(getCompilerRTPath());
|
173
|
442 llvm::sys::path::append(Path, CRTBasename);
|
150
|
443 return std::string(Path.str());
|
|
444 }
|
|
445
|
|
446 const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
|
|
447 StringRef Component,
|
|
448 FileType Type) const {
|
|
449 return Args.MakeArgString(getCompilerRT(Args, Component, Type));
|
|
450 }
|
|
451
|
|
452
|
|
453 Optional<std::string> ToolChain::getRuntimePath() const {
|
|
454 SmallString<128> P;
|
|
455
|
|
456 // First try the triple passed to driver as --target=<triple>.
|
|
457 P.assign(D.ResourceDir);
|
|
458 llvm::sys::path::append(P, "lib", D.getTargetTriple());
|
|
459 if (getVFS().exists(P))
|
|
460 return llvm::Optional<std::string>(std::string(P.str()));
|
|
461
|
|
462 // Second try the normalized triple.
|
|
463 P.assign(D.ResourceDir);
|
|
464 llvm::sys::path::append(P, "lib", Triple.str());
|
|
465 if (getVFS().exists(P))
|
|
466 return llvm::Optional<std::string>(std::string(P.str()));
|
|
467
|
|
468 return None;
|
|
469 }
|
|
470
|
|
471 Optional<std::string> ToolChain::getCXXStdlibPath() const {
|
|
472 SmallString<128> P;
|
|
473
|
|
474 // First try the triple passed to driver as --target=<triple>.
|
|
475 P.assign(D.Dir);
|
|
476 llvm::sys::path::append(P, "..", "lib", D.getTargetTriple(), "c++");
|
|
477 if (getVFS().exists(P))
|
|
478 return llvm::Optional<std::string>(std::string(P.str()));
|
|
479
|
|
480 // Second try the normalized triple.
|
|
481 P.assign(D.Dir);
|
|
482 llvm::sys::path::append(P, "..", "lib", Triple.str(), "c++");
|
|
483 if (getVFS().exists(P))
|
|
484 return llvm::Optional<std::string>(std::string(P.str()));
|
|
485
|
|
486 return None;
|
|
487 }
|
|
488
|
|
489 std::string ToolChain::getArchSpecificLibPath() const {
|
|
490 SmallString<128> Path(getDriver().ResourceDir);
|
|
491 llvm::sys::path::append(Path, "lib", getOSLibName(),
|
|
492 llvm::Triple::getArchTypeName(getArch()));
|
|
493 return std::string(Path.str());
|
|
494 }
|
|
495
|
|
496 bool ToolChain::needsProfileRT(const ArgList &Args) {
|
|
497 if (Args.hasArg(options::OPT_noprofilelib))
|
|
498 return false;
|
|
499
|
173
|
500 return Args.hasArg(options::OPT_fprofile_generate) ||
|
|
501 Args.hasArg(options::OPT_fprofile_generate_EQ) ||
|
|
502 Args.hasArg(options::OPT_fcs_profile_generate) ||
|
|
503 Args.hasArg(options::OPT_fcs_profile_generate_EQ) ||
|
|
504 Args.hasArg(options::OPT_fprofile_instr_generate) ||
|
|
505 Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
|
|
506 Args.hasArg(options::OPT_fcreate_profile) ||
|
|
507 Args.hasArg(options::OPT_forder_file_instrumentation);
|
150
|
508 }
|
|
509
|
|
510 bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
|
173
|
511 return Args.hasArg(options::OPT_coverage) ||
|
|
512 Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
|
|
513 false);
|
150
|
514 }
|
|
515
|
|
516 Tool *ToolChain::SelectTool(const JobAction &JA) const {
|
|
517 if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();
|
|
518 if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
|
|
519 Action::ActionClass AC = JA.getKind();
|
|
520 if (AC == Action::AssembleJobClass && useIntegratedAs())
|
|
521 return getClangAs();
|
|
522 return getTool(AC);
|
|
523 }
|
|
524
|
|
525 std::string ToolChain::GetFilePath(const char *Name) const {
|
|
526 return D.GetFilePath(Name, *this);
|
|
527 }
|
|
528
|
|
529 std::string ToolChain::GetProgramPath(const char *Name) const {
|
|
530 return D.GetProgramPath(Name, *this);
|
|
531 }
|
|
532
|
|
533 std::string ToolChain::GetLinkerPath() const {
|
|
534 const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
|
|
535 StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
|
|
536
|
|
537 if (llvm::sys::path::is_absolute(UseLinker)) {
|
|
538 // If we're passed what looks like an absolute path, don't attempt to
|
|
539 // second-guess that.
|
|
540 if (llvm::sys::fs::can_execute(UseLinker))
|
|
541 return std::string(UseLinker);
|
|
542 } else if (UseLinker.empty() || UseLinker == "ld") {
|
|
543 // If we're passed -fuse-ld= with no argument, or with the argument ld,
|
|
544 // then use whatever the default system linker is.
|
|
545 return GetProgramPath(getDefaultLinker());
|
|
546 } else {
|
|
547 llvm::SmallString<8> LinkerName;
|
|
548 if (Triple.isOSDarwin())
|
|
549 LinkerName.append("ld64.");
|
|
550 else
|
|
551 LinkerName.append("ld.");
|
|
552 LinkerName.append(UseLinker);
|
|
553
|
|
554 std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
|
|
555 if (llvm::sys::fs::can_execute(LinkerPath))
|
|
556 return LinkerPath;
|
|
557 }
|
|
558
|
|
559 if (A)
|
|
560 getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
|
|
561
|
|
562 return GetProgramPath(getDefaultLinker());
|
|
563 }
|
|
564
|
|
565 types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
|
|
566 types::ID id = types::lookupTypeForExtension(Ext);
|
|
567
|
|
568 // Flang always runs the preprocessor and has no notion of "preprocessed
|
|
569 // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating
|
|
570 // them differently.
|
|
571 if (D.IsFlangMode() && id == types::TY_PP_Fortran)
|
|
572 id = types::TY_Fortran;
|
|
573
|
|
574 return id;
|
|
575 }
|
|
576
|
|
577 bool ToolChain::HasNativeLLVMSupport() const {
|
|
578 return false;
|
|
579 }
|
|
580
|
|
581 bool ToolChain::isCrossCompiling() const {
|
|
582 llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
|
|
583 switch (HostTriple.getArch()) {
|
|
584 // The A32/T32/T16 instruction sets are not separate architectures in this
|
|
585 // context.
|
|
586 case llvm::Triple::arm:
|
|
587 case llvm::Triple::armeb:
|
|
588 case llvm::Triple::thumb:
|
|
589 case llvm::Triple::thumbeb:
|
|
590 return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&
|
|
591 getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;
|
|
592 default:
|
|
593 return HostTriple.getArch() != getArch();
|
|
594 }
|
|
595 }
|
|
596
|
|
597 ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
|
|
598 return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,
|
|
599 VersionTuple());
|
|
600 }
|
|
601
|
|
602 llvm::ExceptionHandling
|
|
603 ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const {
|
|
604 return llvm::ExceptionHandling::None;
|
|
605 }
|
|
606
|
|
607 bool ToolChain::isThreadModelSupported(const StringRef Model) const {
|
|
608 if (Model == "single") {
|
|
609 // FIXME: 'single' is only supported on ARM and WebAssembly so far.
|
|
610 return Triple.getArch() == llvm::Triple::arm ||
|
|
611 Triple.getArch() == llvm::Triple::armeb ||
|
|
612 Triple.getArch() == llvm::Triple::thumb ||
|
|
613 Triple.getArch() == llvm::Triple::thumbeb ||
|
|
614 Triple.getArch() == llvm::Triple::wasm32 ||
|
|
615 Triple.getArch() == llvm::Triple::wasm64;
|
|
616 } else if (Model == "posix")
|
|
617 return true;
|
|
618
|
|
619 return false;
|
|
620 }
|
|
621
|
|
622 std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
|
|
623 types::ID InputType) const {
|
|
624 switch (getTriple().getArch()) {
|
|
625 default:
|
|
626 return getTripleString();
|
|
627
|
|
628 case llvm::Triple::x86_64: {
|
|
629 llvm::Triple Triple = getTriple();
|
|
630 if (!Triple.isOSBinFormatMachO())
|
|
631 return getTripleString();
|
|
632
|
|
633 if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
|
|
634 // x86_64h goes in the triple. Other -march options just use the
|
|
635 // vanilla triple we already have.
|
|
636 StringRef MArch = A->getValue();
|
|
637 if (MArch == "x86_64h")
|
|
638 Triple.setArchName(MArch);
|
|
639 }
|
|
640 return Triple.getTriple();
|
|
641 }
|
|
642 case llvm::Triple::aarch64: {
|
|
643 llvm::Triple Triple = getTriple();
|
|
644 if (!Triple.isOSBinFormatMachO())
|
|
645 return getTripleString();
|
|
646
|
|
647 // FIXME: older versions of ld64 expect the "arm64" component in the actual
|
|
648 // triple string and query it to determine whether an LTO file can be
|
|
649 // handled. Remove this when we don't care any more.
|
|
650 Triple.setArchName("arm64");
|
|
651 return Triple.getTriple();
|
|
652 }
|
|
653 case llvm::Triple::aarch64_32:
|
|
654 return getTripleString();
|
|
655 case llvm::Triple::arm:
|
|
656 case llvm::Triple::armeb:
|
|
657 case llvm::Triple::thumb:
|
|
658 case llvm::Triple::thumbeb: {
|
|
659 // FIXME: Factor into subclasses.
|
|
660 llvm::Triple Triple = getTriple();
|
|
661 bool IsBigEndian = getTriple().getArch() == llvm::Triple::armeb ||
|
|
662 getTriple().getArch() == llvm::Triple::thumbeb;
|
|
663
|
|
664 // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
|
|
665 // '-mbig-endian'/'-EB'.
|
|
666 if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
|
|
667 options::OPT_mbig_endian)) {
|
|
668 IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
|
|
669 }
|
|
670
|
|
671 // Thumb2 is the default for V7 on Darwin.
|
|
672 //
|
|
673 // FIXME: Thumb should just be another -target-feaure, not in the triple.
|
|
674 StringRef MCPU, MArch;
|
|
675 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
|
|
676 MCPU = A->getValue();
|
|
677 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
|
|
678 MArch = A->getValue();
|
|
679 std::string CPU =
|
|
680 Triple.isOSBinFormatMachO()
|
|
681 ? tools::arm::getARMCPUForMArch(MArch, Triple).str()
|
|
682 : tools::arm::getARMTargetCPU(MCPU, MArch, Triple);
|
|
683 StringRef Suffix =
|
|
684 tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
|
|
685 bool IsMProfile = ARM::parseArchProfile(Suffix) == ARM::ProfileKind::M;
|
|
686 bool ThumbDefault = IsMProfile || (ARM::parseArchVersion(Suffix) == 7 &&
|
|
687 getTriple().isOSBinFormatMachO());
|
|
688 // FIXME: this is invalid for WindowsCE
|
|
689 if (getTriple().isOSWindows())
|
|
690 ThumbDefault = true;
|
|
691 std::string ArchName;
|
|
692 if (IsBigEndian)
|
|
693 ArchName = "armeb";
|
|
694 else
|
|
695 ArchName = "arm";
|
|
696
|
|
697 // Check if ARM ISA was explicitly selected (using -mno-thumb or -marm) for
|
|
698 // M-Class CPUs/architecture variants, which is not supported.
|
|
699 bool ARMModeRequested = !Args.hasFlag(options::OPT_mthumb,
|
|
700 options::OPT_mno_thumb, ThumbDefault);
|
|
701 if (IsMProfile && ARMModeRequested) {
|
|
702 if (!MCPU.empty())
|
|
703 getDriver().Diag(diag::err_cpu_unsupported_isa) << CPU << "ARM";
|
|
704 else
|
|
705 getDriver().Diag(diag::err_arch_unsupported_isa)
|
|
706 << tools::arm::getARMArch(MArch, getTriple()) << "ARM";
|
|
707 }
|
|
708
|
|
709 // Check to see if an explicit choice to use thumb has been made via
|
|
710 // -mthumb. For assembler files we must check for -mthumb in the options
|
|
711 // passed to the assembler via -Wa or -Xassembler.
|
|
712 bool IsThumb = false;
|
|
713 if (InputType != types::TY_PP_Asm)
|
|
714 IsThumb = Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb,
|
|
715 ThumbDefault);
|
|
716 else {
|
|
717 // Ideally we would check for these flags in
|
|
718 // CollectArgsForIntegratedAssembler but we can't change the ArchName at
|
|
719 // that point. There is no assembler equivalent of -mno-thumb, -marm, or
|
|
720 // -mno-arm.
|
|
721 for (const auto *A :
|
|
722 Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
|
|
723 for (StringRef Value : A->getValues()) {
|
|
724 if (Value == "-mthumb")
|
|
725 IsThumb = true;
|
|
726 }
|
|
727 }
|
|
728 }
|
|
729 // Assembly files should start in ARM mode, unless arch is M-profile, or
|
|
730 // -mthumb has been passed explicitly to the assembler. Windows is always
|
|
731 // thumb.
|
|
732 if (IsThumb || IsMProfile || getTriple().isOSWindows()) {
|
|
733 if (IsBigEndian)
|
|
734 ArchName = "thumbeb";
|
|
735 else
|
|
736 ArchName = "thumb";
|
|
737 }
|
|
738 Triple.setArchName(ArchName + Suffix.str());
|
|
739
|
|
740 return Triple.getTriple();
|
|
741 }
|
|
742 }
|
|
743 }
|
|
744
|
|
745 std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
|
|
746 types::ID InputType) const {
|
|
747 return ComputeLLVMTriple(Args, InputType);
|
|
748 }
|
|
749
|
|
750 void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
|
|
751 ArgStringList &CC1Args) const {
|
|
752 // Each toolchain should provide the appropriate include flags.
|
|
753 }
|
|
754
|
|
755 void ToolChain::addClangTargetOptions(
|
|
756 const ArgList &DriverArgs, ArgStringList &CC1Args,
|
|
757 Action::OffloadKind DeviceOffloadKind) const {}
|
|
758
|
|
759 void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
|
|
760
|
|
761 void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
|
|
762 llvm::opt::ArgStringList &CmdArgs) const {
|
173
|
763 if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
|
|
764 return;
|
150
|
765
|
|
766 CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));
|
|
767 }
|
|
768
|
|
769 ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
|
|
770 const ArgList &Args) const {
|
|
771 const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);
|
|
772 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;
|
|
773
|
|
774 // Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!
|
|
775 if (LibName == "compiler-rt")
|
|
776 return ToolChain::RLT_CompilerRT;
|
|
777 else if (LibName == "libgcc")
|
|
778 return ToolChain::RLT_Libgcc;
|
|
779 else if (LibName == "platform")
|
|
780 return GetDefaultRuntimeLibType();
|
|
781
|
|
782 if (A)
|
|
783 getDriver().Diag(diag::err_drv_invalid_rtlib_name) << A->getAsString(Args);
|
|
784
|
|
785 return GetDefaultRuntimeLibType();
|
|
786 }
|
|
787
|
|
788 ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
|
|
789 const ArgList &Args) const {
|
|
790 const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);
|
|
791 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB;
|
|
792
|
|
793 if (LibName == "none")
|
|
794 return ToolChain::UNW_None;
|
|
795 else if (LibName == "platform" || LibName == "") {
|
|
796 ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args);
|
|
797 if (RtLibType == ToolChain::RLT_CompilerRT)
|
|
798 return ToolChain::UNW_None;
|
|
799 else if (RtLibType == ToolChain::RLT_Libgcc)
|
|
800 return ToolChain::UNW_Libgcc;
|
|
801 } else if (LibName == "libunwind") {
|
|
802 if (GetRuntimeLibType(Args) == RLT_Libgcc)
|
|
803 getDriver().Diag(diag::err_drv_incompatible_unwindlib);
|
|
804 return ToolChain::UNW_CompilerRT;
|
|
805 } else if (LibName == "libgcc")
|
|
806 return ToolChain::UNW_Libgcc;
|
|
807
|
|
808 if (A)
|
|
809 getDriver().Diag(diag::err_drv_invalid_unwindlib_name)
|
|
810 << A->getAsString(Args);
|
|
811
|
|
812 return GetDefaultUnwindLibType();
|
|
813 }
|
|
814
|
|
815 ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
|
|
816 const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
|
|
817 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB;
|
|
818
|
|
819 // Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB!
|
|
820 if (LibName == "libc++")
|
|
821 return ToolChain::CST_Libcxx;
|
|
822 else if (LibName == "libstdc++")
|
|
823 return ToolChain::CST_Libstdcxx;
|
|
824 else if (LibName == "platform")
|
|
825 return GetDefaultCXXStdlibType();
|
|
826
|
|
827 if (A)
|
|
828 getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
|
|
829
|
|
830 return GetDefaultCXXStdlibType();
|
|
831 }
|
|
832
|
|
833 /// Utility function to add a system include directory to CC1 arguments.
|
|
834 /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
|
|
835 ArgStringList &CC1Args,
|
|
836 const Twine &Path) {
|
|
837 CC1Args.push_back("-internal-isystem");
|
|
838 CC1Args.push_back(DriverArgs.MakeArgString(Path));
|
|
839 }
|
|
840
|
|
841 /// Utility function to add a system include directory with extern "C"
|
|
842 /// semantics to CC1 arguments.
|
|
843 ///
|
|
844 /// Note that this should be used rarely, and only for directories that
|
|
845 /// historically and for legacy reasons are treated as having implicit extern
|
|
846 /// "C" semantics. These semantics are *ignored* by and large today, but its
|
|
847 /// important to preserve the preprocessor changes resulting from the
|
|
848 /// classification.
|
|
849 /*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,
|
|
850 ArgStringList &CC1Args,
|
|
851 const Twine &Path) {
|
|
852 CC1Args.push_back("-internal-externc-isystem");
|
|
853 CC1Args.push_back(DriverArgs.MakeArgString(Path));
|
|
854 }
|
|
855
|
|
856 void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
|
|
857 ArgStringList &CC1Args,
|
|
858 const Twine &Path) {
|
|
859 if (llvm::sys::fs::exists(Path))
|
|
860 addExternCSystemInclude(DriverArgs, CC1Args, Path);
|
|
861 }
|
|
862
|
|
863 /// Utility function to add a list of system include directories to CC1.
|
|
864 /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
|
|
865 ArgStringList &CC1Args,
|
|
866 ArrayRef<StringRef> Paths) {
|
|
867 for (const auto &Path : Paths) {
|
|
868 CC1Args.push_back("-internal-isystem");
|
|
869 CC1Args.push_back(DriverArgs.MakeArgString(Path));
|
|
870 }
|
|
871 }
|
|
872
|
|
873 void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
|
|
874 ArgStringList &CC1Args) const {
|
|
875 // Header search paths should be handled by each of the subclasses.
|
|
876 // Historically, they have not been, and instead have been handled inside of
|
|
877 // the CC1-layer frontend. As the logic is hoisted out, this generic function
|
|
878 // will slowly stop being called.
|
|
879 //
|
|
880 // While it is being called, replicate a bit of a hack to propagate the
|
|
881 // '-stdlib=' flag down to CC1 so that it can in turn customize the C++
|
|
882 // header search paths with it. Once all systems are overriding this
|
|
883 // function, the CC1 flag and this line can be removed.
|
|
884 DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
|
|
885 }
|
|
886
|
|
887 void ToolChain::AddClangCXXStdlibIsystemArgs(
|
|
888 const llvm::opt::ArgList &DriverArgs,
|
|
889 llvm::opt::ArgStringList &CC1Args) const {
|
|
890 DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem);
|
|
891 if (!DriverArgs.hasArg(options::OPT_nostdincxx))
|
|
892 for (const auto &P :
|
|
893 DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem))
|
|
894 addSystemInclude(DriverArgs, CC1Args, P);
|
|
895 }
|
|
896
|
|
897 bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const {
|
|
898 return getDriver().CCCIsCXX() &&
|
|
899 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
|
|
900 options::OPT_nostdlibxx);
|
|
901 }
|
|
902
|
|
903 void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
|
|
904 ArgStringList &CmdArgs) const {
|
|
905 assert(!Args.hasArg(options::OPT_nostdlibxx) &&
|
|
906 "should not have called this");
|
|
907 CXXStdlibType Type = GetCXXStdlibType(Args);
|
|
908
|
|
909 switch (Type) {
|
|
910 case ToolChain::CST_Libcxx:
|
|
911 CmdArgs.push_back("-lc++");
|
|
912 break;
|
|
913
|
|
914 case ToolChain::CST_Libstdcxx:
|
|
915 CmdArgs.push_back("-lstdc++");
|
|
916 break;
|
|
917 }
|
|
918 }
|
|
919
|
|
920 void ToolChain::AddFilePathLibArgs(const ArgList &Args,
|
|
921 ArgStringList &CmdArgs) const {
|
|
922 for (const auto &LibPath : getFilePaths())
|
|
923 if(LibPath.length() > 0)
|
|
924 CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
|
|
925 }
|
|
926
|
|
927 void ToolChain::AddCCKextLibArgs(const ArgList &Args,
|
|
928 ArgStringList &CmdArgs) const {
|
|
929 CmdArgs.push_back("-lcc_kext");
|
|
930 }
|
|
931
|
|
932 bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,
|
|
933 std::string &Path) const {
|
|
934 // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed
|
|
935 // (to keep the linker options consistent with gcc and clang itself).
|
|
936 if (!isOptimizationLevelFast(Args)) {
|
|
937 // Check if -ffast-math or -funsafe-math.
|
|
938 Arg *A =
|
|
939 Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math,
|
|
940 options::OPT_funsafe_math_optimizations,
|
|
941 options::OPT_fno_unsafe_math_optimizations);
|
|
942
|
|
943 if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
|
|
944 A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
|
|
945 return false;
|
|
946 }
|
|
947 // If crtfastmath.o exists add it to the arguments.
|
|
948 Path = GetFilePath("crtfastmath.o");
|
|
949 return (Path != "crtfastmath.o"); // Not found.
|
|
950 }
|
|
951
|
|
952 bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args,
|
|
953 ArgStringList &CmdArgs) const {
|
|
954 std::string Path;
|
|
955 if (isFastMathRuntimeAvailable(Args, Path)) {
|
|
956 CmdArgs.push_back(Args.MakeArgString(Path));
|
|
957 return true;
|
|
958 }
|
|
959
|
|
960 return false;
|
|
961 }
|
|
962
|
|
963 SanitizerMask ToolChain::getSupportedSanitizers() const {
|
|
964 // Return sanitizers which don't require runtime support and are not
|
|
965 // platform dependent.
|
|
966
|
|
967 SanitizerMask Res = (SanitizerKind::Undefined & ~SanitizerKind::Vptr &
|
|
968 ~SanitizerKind::Function) |
|
|
969 (SanitizerKind::CFI & ~SanitizerKind::CFIICall) |
|
|
970 SanitizerKind::CFICastStrict |
|
|
971 SanitizerKind::FloatDivideByZero |
|
|
972 SanitizerKind::UnsignedIntegerOverflow |
|
|
973 SanitizerKind::ImplicitConversion |
|
|
974 SanitizerKind::Nullability | SanitizerKind::LocalBounds;
|
|
975 if (getTriple().getArch() == llvm::Triple::x86 ||
|
|
976 getTriple().getArch() == llvm::Triple::x86_64 ||
|
|
977 getTriple().getArch() == llvm::Triple::arm ||
|
|
978 getTriple().getArch() == llvm::Triple::aarch64 ||
|
|
979 getTriple().getArch() == llvm::Triple::wasm32 ||
|
|
980 getTriple().getArch() == llvm::Triple::wasm64)
|
|
981 Res |= SanitizerKind::CFIICall;
|
|
982 if (getTriple().getArch() == llvm::Triple::x86_64 ||
|
|
983 getTriple().getArch() == llvm::Triple::aarch64)
|
|
984 Res |= SanitizerKind::ShadowCallStack;
|
|
985 if (getTriple().getArch() == llvm::Triple::aarch64 ||
|
|
986 getTriple().getArch() == llvm::Triple::aarch64_be)
|
|
987 Res |= SanitizerKind::MemTag;
|
|
988 return Res;
|
|
989 }
|
|
990
|
|
991 void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
|
|
992 ArgStringList &CC1Args) const {}
|
|
993
|
|
994 void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
|
|
995 ArgStringList &CC1Args) const {}
|
|
996
|
|
997 static VersionTuple separateMSVCFullVersion(unsigned Version) {
|
|
998 if (Version < 100)
|
|
999 return VersionTuple(Version);
|
|
1000
|
|
1001 if (Version < 10000)
|
|
1002 return VersionTuple(Version / 100, Version % 100);
|
|
1003
|
|
1004 unsigned Build = 0, Factor = 1;
|
|
1005 for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)
|
|
1006 Build = Build + (Version % 10) * Factor;
|
|
1007 return VersionTuple(Version / 100, Version % 100, Build);
|
|
1008 }
|
|
1009
|
|
1010 VersionTuple
|
|
1011 ToolChain::computeMSVCVersion(const Driver *D,
|
|
1012 const llvm::opt::ArgList &Args) const {
|
|
1013 const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
|
|
1014 const Arg *MSCompatibilityVersion =
|
|
1015 Args.getLastArg(options::OPT_fms_compatibility_version);
|
|
1016
|
|
1017 if (MSCVersion && MSCompatibilityVersion) {
|
|
1018 if (D)
|
|
1019 D->Diag(diag::err_drv_argument_not_allowed_with)
|
|
1020 << MSCVersion->getAsString(Args)
|
|
1021 << MSCompatibilityVersion->getAsString(Args);
|
|
1022 return VersionTuple();
|
|
1023 }
|
|
1024
|
|
1025 if (MSCompatibilityVersion) {
|
|
1026 VersionTuple MSVT;
|
|
1027 if (MSVT.tryParse(MSCompatibilityVersion->getValue())) {
|
|
1028 if (D)
|
|
1029 D->Diag(diag::err_drv_invalid_value)
|
|
1030 << MSCompatibilityVersion->getAsString(Args)
|
|
1031 << MSCompatibilityVersion->getValue();
|
|
1032 } else {
|
|
1033 return MSVT;
|
|
1034 }
|
|
1035 }
|
|
1036
|
|
1037 if (MSCVersion) {
|
|
1038 unsigned Version = 0;
|
|
1039 if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) {
|
|
1040 if (D)
|
|
1041 D->Diag(diag::err_drv_invalid_value)
|
|
1042 << MSCVersion->getAsString(Args) << MSCVersion->getValue();
|
|
1043 } else {
|
|
1044 return separateMSVCFullVersion(Version);
|
|
1045 }
|
|
1046 }
|
|
1047
|
|
1048 return VersionTuple();
|
|
1049 }
|
|
1050
|
|
1051 llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
|
|
1052 const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost,
|
|
1053 SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const {
|
|
1054 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
|
|
1055 const OptTable &Opts = getDriver().getOpts();
|
|
1056 bool Modified = false;
|
|
1057
|
|
1058 // Handle -Xopenmp-target flags
|
|
1059 for (auto *A : Args) {
|
|
1060 // Exclude flags which may only apply to the host toolchain.
|
|
1061 // Do not exclude flags when the host triple (AuxTriple)
|
|
1062 // matches the current toolchain triple. If it is not present
|
|
1063 // at all, target and host share a toolchain.
|
|
1064 if (A->getOption().matches(options::OPT_m_Group)) {
|
|
1065 if (SameTripleAsHost)
|
|
1066 DAL->append(A);
|
|
1067 else
|
|
1068 Modified = true;
|
|
1069 continue;
|
|
1070 }
|
|
1071
|
|
1072 unsigned Index;
|
|
1073 unsigned Prev;
|
|
1074 bool XOpenMPTargetNoTriple =
|
|
1075 A->getOption().matches(options::OPT_Xopenmp_target);
|
|
1076
|
|
1077 if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) {
|
|
1078 // Passing device args: -Xopenmp-target=<triple> -opt=val.
|
|
1079 if (A->getValue(0) == getTripleString())
|
|
1080 Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
|
|
1081 else
|
|
1082 continue;
|
|
1083 } else if (XOpenMPTargetNoTriple) {
|
|
1084 // Passing device args: -Xopenmp-target -opt=val.
|
|
1085 Index = Args.getBaseArgs().MakeIndex(A->getValue(0));
|
|
1086 } else {
|
|
1087 DAL->append(A);
|
|
1088 continue;
|
|
1089 }
|
|
1090
|
|
1091 // Parse the argument to -Xopenmp-target.
|
|
1092 Prev = Index;
|
|
1093 std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index));
|
|
1094 if (!XOpenMPTargetArg || Index > Prev + 1) {
|
|
1095 getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)
|
|
1096 << A->getAsString(Args);
|
|
1097 continue;
|
|
1098 }
|
|
1099 if (XOpenMPTargetNoTriple && XOpenMPTargetArg &&
|
|
1100 Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) {
|
|
1101 getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple);
|
|
1102 continue;
|
|
1103 }
|
|
1104 XOpenMPTargetArg->setBaseArg(A);
|
|
1105 A = XOpenMPTargetArg.release();
|
|
1106 AllocatedArgs.push_back(A);
|
|
1107 DAL->append(A);
|
|
1108 Modified = true;
|
|
1109 }
|
|
1110
|
|
1111 if (Modified)
|
|
1112 return DAL;
|
|
1113
|
|
1114 delete DAL;
|
|
1115 return nullptr;
|
|
1116 }
|
173
|
1117
|
|
1118 // TODO: Currently argument values separated by space e.g.
|
|
1119 // -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be
|
|
1120 // fixed.
|
|
1121 void ToolChain::TranslateXarchArgs(
|
|
1122 const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A,
|
|
1123 llvm::opt::DerivedArgList *DAL,
|
|
1124 SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
|
|
1125 const OptTable &Opts = getDriver().getOpts();
|
|
1126 unsigned ValuePos = 1;
|
|
1127 if (A->getOption().matches(options::OPT_Xarch_device) ||
|
|
1128 A->getOption().matches(options::OPT_Xarch_host))
|
|
1129 ValuePos = 0;
|
|
1130
|
|
1131 unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos));
|
|
1132 unsigned Prev = Index;
|
|
1133 std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index));
|
|
1134
|
|
1135 // If the argument parsing failed or more than one argument was
|
|
1136 // consumed, the -Xarch_ argument's parameter tried to consume
|
|
1137 // extra arguments. Emit an error and ignore.
|
|
1138 //
|
|
1139 // We also want to disallow any options which would alter the
|
|
1140 // driver behavior; that isn't going to work in our model. We
|
|
1141 // use isDriverOption() as an approximation, although things
|
|
1142 // like -O4 are going to slip through.
|
|
1143 if (!XarchArg || Index > Prev + 1) {
|
|
1144 getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
|
|
1145 << A->getAsString(Args);
|
|
1146 return;
|
|
1147 } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
|
|
1148 getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
|
|
1149 << A->getAsString(Args);
|
|
1150 return;
|
|
1151 }
|
|
1152 XarchArg->setBaseArg(A);
|
|
1153 A = XarchArg.release();
|
|
1154 if (!AllocatedArgs)
|
|
1155 DAL->AddSynthesizedArg(A);
|
|
1156 else
|
|
1157 AllocatedArgs->push_back(A);
|
|
1158 }
|
|
1159
|
|
1160 llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(
|
|
1161 const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
|
|
1162 Action::OffloadKind OFK,
|
|
1163 SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
|
|
1164 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
|
|
1165 bool Modified = false;
|
|
1166
|
|
1167 bool IsGPU = OFK == Action::OFK_Cuda || OFK == Action::OFK_HIP;
|
|
1168 for (Arg *A : Args) {
|
|
1169 bool NeedTrans = false;
|
|
1170 bool Skip = false;
|
|
1171 if (A->getOption().matches(options::OPT_Xarch_device)) {
|
|
1172 NeedTrans = IsGPU;
|
|
1173 Skip = !IsGPU;
|
|
1174 } else if (A->getOption().matches(options::OPT_Xarch_host)) {
|
|
1175 NeedTrans = !IsGPU;
|
|
1176 Skip = IsGPU;
|
|
1177 } else if (A->getOption().matches(options::OPT_Xarch__) && IsGPU) {
|
|
1178 // Do not translate -Xarch_ options for non CUDA/HIP toolchain since
|
|
1179 // they may need special translation.
|
|
1180 // Skip this argument unless the architecture matches BoundArch
|
|
1181 if (BoundArch.empty() || A->getValue(0) != BoundArch)
|
|
1182 Skip = true;
|
|
1183 else
|
|
1184 NeedTrans = true;
|
|
1185 }
|
|
1186 if (NeedTrans || Skip)
|
|
1187 Modified = true;
|
|
1188 if (NeedTrans)
|
|
1189 TranslateXarchArgs(Args, A, DAL, AllocatedArgs);
|
|
1190 if (!Skip)
|
|
1191 DAL->append(A);
|
|
1192 }
|
|
1193
|
|
1194 if (Modified)
|
|
1195 return DAL;
|
|
1196
|
|
1197 delete DAL;
|
|
1198 return nullptr;
|
|
1199 }
|