/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChain.cpp
Line | Count | Source (jump to first uncovered line) |
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 "ToolChains/Arch/AArch64.h" |
11 | | #include "ToolChains/Arch/ARM.h" |
12 | | #include "ToolChains/Clang.h" |
13 | | #include "ToolChains/CommonArgs.h" |
14 | | #include "ToolChains/Flang.h" |
15 | | #include "ToolChains/InterfaceStubs.h" |
16 | | #include "clang/Basic/ObjCRuntime.h" |
17 | | #include "clang/Basic/Sanitizers.h" |
18 | | #include "clang/Config/config.h" |
19 | | #include "clang/Driver/Action.h" |
20 | | #include "clang/Driver/Driver.h" |
21 | | #include "clang/Driver/DriverDiagnostic.h" |
22 | | #include "clang/Driver/InputInfo.h" |
23 | | #include "clang/Driver/Job.h" |
24 | | #include "clang/Driver/Options.h" |
25 | | #include "clang/Driver/SanitizerArgs.h" |
26 | | #include "clang/Driver/XRayArgs.h" |
27 | | #include "llvm/ADT/STLExtras.h" |
28 | | #include "llvm/ADT/SmallString.h" |
29 | | #include "llvm/ADT/StringExtras.h" |
30 | | #include "llvm/ADT/StringRef.h" |
31 | | #include "llvm/ADT/Twine.h" |
32 | | #include "llvm/Config/llvm-config.h" |
33 | | #include "llvm/MC/MCTargetOptions.h" |
34 | | #include "llvm/MC/TargetRegistry.h" |
35 | | #include "llvm/Option/Arg.h" |
36 | | #include "llvm/Option/ArgList.h" |
37 | | #include "llvm/Option/OptTable.h" |
38 | | #include "llvm/Option/Option.h" |
39 | | #include "llvm/Support/ErrorHandling.h" |
40 | | #include "llvm/Support/FileSystem.h" |
41 | | #include "llvm/Support/FileUtilities.h" |
42 | | #include "llvm/Support/Path.h" |
43 | | #include "llvm/Support/VersionTuple.h" |
44 | | #include "llvm/Support/VirtualFileSystem.h" |
45 | | #include "llvm/TargetParser/AArch64TargetParser.h" |
46 | | #include "llvm/TargetParser/TargetParser.h" |
47 | | #include "llvm/TargetParser/Triple.h" |
48 | | #include <cassert> |
49 | | #include <cstddef> |
50 | | #include <cstring> |
51 | | #include <string> |
52 | | |
53 | | using namespace clang; |
54 | | using namespace driver; |
55 | | using namespace tools; |
56 | | using namespace llvm; |
57 | | using namespace llvm::opt; |
58 | | |
59 | 52.6k | static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) { |
60 | 52.6k | return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext, |
61 | 52.6k | options::OPT_fno_rtti, options::OPT_frtti); |
62 | 52.6k | } |
63 | | |
64 | | static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args, |
65 | | const llvm::Triple &Triple, |
66 | 52.6k | const Arg *CachedRTTIArg) { |
67 | | // Explicit rtti/no-rtti args |
68 | 52.6k | if (CachedRTTIArg) { |
69 | 24.0k | if (CachedRTTIArg->getOption().matches(options::OPT_frtti)) |
70 | 23.9k | return ToolChain::RM_Enabled; |
71 | 78 | else |
72 | 78 | return ToolChain::RM_Disabled; |
73 | 24.0k | } |
74 | | |
75 | | // -frtti is default, except for the PS4/PS5 and DriverKit. |
76 | 28.5k | bool NoRTTI = Triple.isPS() || Triple.isDriverKit()28.2k ; |
77 | 28.5k | return NoRTTI ? ToolChain::RM_Disabled311 : ToolChain::RM_Enabled28.2k ; |
78 | 52.6k | } |
79 | | |
80 | | ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, |
81 | | const ArgList &Args) |
82 | 52.6k | : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)), |
83 | 52.6k | CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) { |
84 | 105k | auto addIfExists = [this](path_list &List, const std::string &Path) { |
85 | 105k | if (getVFS().exists(Path)) |
86 | 96 | List.push_back(Path); |
87 | 105k | }; |
88 | | |
89 | 52.6k | if (std::optional<std::string> Path = getRuntimePath()) |
90 | 71 | getLibraryPaths().push_back(*Path); |
91 | 52.6k | if (std::optional<std::string> Path = getStdlibPath()) |
92 | 29 | getFilePaths().push_back(*Path); |
93 | 52.6k | for (const auto &Path : getArchSpecificLibPaths()) |
94 | 105k | addIfExists(getFilePaths(), Path); |
95 | 52.6k | } |
96 | | |
97 | | llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> |
98 | 0 | ToolChain::executeToolChainProgram(StringRef Executable) const { |
99 | 0 | llvm::SmallString<64> OutputFile; |
100 | 0 | llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile); |
101 | 0 | llvm::FileRemover OutputRemover(OutputFile.c_str()); |
102 | 0 | std::optional<llvm::StringRef> Redirects[] = { |
103 | 0 | {""}, |
104 | 0 | OutputFile.str(), |
105 | 0 | {""}, |
106 | 0 | }; |
107 | |
|
108 | 0 | std::string ErrorMessage; |
109 | 0 | if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects, |
110 | 0 | /* SecondsToWait */ 0, |
111 | 0 | /*MemoryLimit*/ 0, &ErrorMessage)) |
112 | 0 | return llvm::createStringError(std::error_code(), |
113 | 0 | Executable + ": " + ErrorMessage); |
114 | | |
115 | 0 | llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf = |
116 | 0 | llvm::MemoryBuffer::getFile(OutputFile.c_str()); |
117 | 0 | if (!OutputBuf) |
118 | 0 | return llvm::createStringError(OutputBuf.getError(), |
119 | 0 | "Failed to read stdout of " + Executable + |
120 | 0 | ": " + OutputBuf.getError().message()); |
121 | 0 | return std::move(*OutputBuf); |
122 | 0 | } |
123 | | |
124 | 130 | void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) { |
125 | 130 | Triple.setEnvironment(Env); |
126 | 130 | if (EffectiveTriple != llvm::Triple()) |
127 | 0 | EffectiveTriple.setEnvironment(Env); |
128 | 130 | } |
129 | | |
130 | 52.6k | ToolChain::~ToolChain() = default; |
131 | | |
132 | 302k | llvm::vfs::FileSystem &ToolChain::getVFS() const { |
133 | 302k | return getDriver().getVFS(); |
134 | 302k | } |
135 | | |
136 | 232k | bool ToolChain::useIntegratedAs() const { |
137 | 232k | return Args.hasFlag(options::OPT_fintegrated_as, |
138 | 232k | options::OPT_fno_integrated_as, |
139 | 232k | IsIntegratedAssemblerDefault()); |
140 | 232k | } |
141 | | |
142 | 47.4k | bool ToolChain::useIntegratedBackend() const { |
143 | 47.4k | assert( |
144 | 47.4k | ((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) || |
145 | 47.4k | (!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) && |
146 | 47.4k | "(Non-)integrated backend set incorrectly!"); |
147 | | |
148 | 47.4k | bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter, |
149 | 47.4k | options::OPT_fno_integrated_objemitter, |
150 | 47.4k | IsIntegratedBackendDefault()); |
151 | | |
152 | | // Diagnose when integrated-objemitter options are not supported by this |
153 | | // toolchain. |
154 | 47.4k | unsigned DiagID; |
155 | 47.4k | if ((IBackend && !IsIntegratedBackendSupported()47.4k ) || |
156 | 47.4k | (47.4k !IBackend47.4k && !IsNonIntegratedBackendSupported()22 )) |
157 | 1 | DiagID = clang::diag::err_drv_unsupported_opt_for_target; |
158 | 47.4k | else |
159 | 47.4k | DiagID = clang::diag::warn_drv_unsupported_opt_for_target; |
160 | 47.4k | Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter); |
161 | 47.4k | if (A && !IsNonIntegratedBackendSupported()2 ) |
162 | 1 | D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple(); |
163 | 47.4k | A = Args.getLastArg(options::OPT_fintegrated_objemitter); |
164 | 47.4k | if (A && !IsIntegratedBackendSupported()2 ) |
165 | 0 | D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple(); |
166 | | |
167 | 47.4k | return IBackend; |
168 | 47.4k | } |
169 | | |
170 | 11.7k | bool ToolChain::useRelaxRelocations() const { |
171 | 11.7k | return ENABLE_X86_RELAX_RELOCATIONS; |
172 | 11.7k | } |
173 | | |
174 | 595 | bool ToolChain::defaultToIEEELongDouble() const { |
175 | 595 | return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux()0 ; |
176 | 595 | } |
177 | | |
178 | | static void getAArch64MultilibFlags(const Driver &D, |
179 | | const llvm::Triple &Triple, |
180 | | const llvm::opt::ArgList &Args, |
181 | 5 | Multilib::flags_list &Result) { |
182 | 5 | std::vector<StringRef> Features; |
183 | 5 | tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, false); |
184 | 5 | const auto UnifiedFeatures = tools::unifyTargetFeatures(Features); |
185 | 5 | llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(), |
186 | 5 | UnifiedFeatures.end()); |
187 | 5 | std::vector<std::string> MArch; |
188 | 5 | for (const auto &Ext : AArch64::Extensions) |
189 | 405 | if (FeatureSet.contains(Ext.Feature)) |
190 | 10 | MArch.push_back(Ext.Name.str()); |
191 | 5 | for (const auto &Ext : AArch64::Extensions) |
192 | 405 | if (FeatureSet.contains(Ext.NegFeature)) |
193 | 0 | MArch.push_back(("no" + Ext.Name).str()); |
194 | 5 | MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str()); |
195 | 5 | Result.push_back(llvm::join(MArch, "+")); |
196 | 5 | } |
197 | | |
198 | | static void getARMMultilibFlags(const Driver &D, |
199 | | const llvm::Triple &Triple, |
200 | | const llvm::opt::ArgList &Args, |
201 | 13 | Multilib::flags_list &Result) { |
202 | 13 | std::vector<StringRef> Features; |
203 | 13 | llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures( |
204 | 13 | D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/); |
205 | 13 | const auto UnifiedFeatures = tools::unifyTargetFeatures(Features); |
206 | 13 | llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(), |
207 | 13 | UnifiedFeatures.end()); |
208 | 13 | std::vector<std::string> MArch; |
209 | 13 | for (const auto &Ext : ARM::ARCHExtNames) |
210 | 494 | if (FeatureSet.contains(Ext.Feature)) |
211 | 6 | MArch.push_back(Ext.Name.str()); |
212 | 13 | for (const auto &Ext : ARM::ARCHExtNames) |
213 | 494 | if (FeatureSet.contains(Ext.NegFeature)) |
214 | 73 | MArch.push_back(("no" + Ext.Name).str()); |
215 | 13 | MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str()); |
216 | 13 | Result.push_back(llvm::join(MArch, "+")); |
217 | | |
218 | 13 | switch (FPUKind) { |
219 | 0 | #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ |
220 | 13 | case llvm::ARM::KIND: \ |
221 | 13 | Result.push_back("-mfpu=" NAME); \ |
222 | 13 | break; |
223 | 0 | #include "llvm/TargetParser/ARMTargetParser.def" |
224 | 0 | default: |
225 | 0 | llvm_unreachable("Invalid FPUKind"); |
226 | 13 | } |
227 | | |
228 | 13 | switch (arm::getARMFloatABI(D, Triple, Args)) { |
229 | 2 | case arm::FloatABI::Soft: |
230 | 2 | Result.push_back("-mfloat-abi=soft"); |
231 | 2 | break; |
232 | 7 | case arm::FloatABI::SoftFP: |
233 | 7 | Result.push_back("-mfloat-abi=softfp"); |
234 | 7 | break; |
235 | 4 | case arm::FloatABI::Hard: |
236 | 4 | Result.push_back("-mfloat-abi=hard"); |
237 | 4 | break; |
238 | 0 | case arm::FloatABI::Invalid: |
239 | 0 | llvm_unreachable("Invalid float ABI"); |
240 | 13 | } |
241 | 13 | } |
242 | | |
243 | | Multilib::flags_list |
244 | 18 | ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const { |
245 | 18 | using namespace clang::driver::options; |
246 | | |
247 | 18 | std::vector<std::string> Result; |
248 | 18 | const llvm::Triple Triple(ComputeEffectiveClangTriple(Args)); |
249 | 18 | Result.push_back("--target=" + Triple.str()); |
250 | | |
251 | 18 | switch (Triple.getArch()) { |
252 | 5 | case llvm::Triple::aarch64: |
253 | 5 | case llvm::Triple::aarch64_32: |
254 | 5 | case llvm::Triple::aarch64_be: |
255 | 5 | getAArch64MultilibFlags(D, Triple, Args, Result); |
256 | 5 | break; |
257 | 4 | case llvm::Triple::arm: |
258 | 4 | case llvm::Triple::armeb: |
259 | 13 | case llvm::Triple::thumb: |
260 | 13 | case llvm::Triple::thumbeb: |
261 | 13 | getARMMultilibFlags(D, Triple, Args, Result); |
262 | 13 | break; |
263 | 0 | default: |
264 | 0 | break; |
265 | 18 | } |
266 | | |
267 | | // Sort and remove duplicates. |
268 | 18 | std::sort(Result.begin(), Result.end()); |
269 | 18 | Result.erase(std::unique(Result.begin(), Result.end()), Result.end()); |
270 | 18 | return Result; |
271 | 18 | } |
272 | | |
273 | | SanitizerArgs |
274 | 58.1k | ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const { |
275 | 58.1k | SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked); |
276 | 58.1k | SanitizerArgsChecked = true; |
277 | 58.1k | return SanArgs; |
278 | 58.1k | } |
279 | | |
280 | 53.1k | const XRayArgs& ToolChain::getXRayArgs() const { |
281 | 53.1k | if (!XRayArguments) |
282 | 50.1k | XRayArguments.reset(new XRayArgs(*this, Args)); |
283 | 53.1k | return *XRayArguments; |
284 | 53.1k | } |
285 | | |
286 | | namespace { |
287 | | |
288 | | struct DriverSuffix { |
289 | | const char *Suffix; |
290 | | const char *ModeFlag; |
291 | | }; |
292 | | |
293 | | } // namespace |
294 | | |
295 | 212k | static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) { |
296 | | // A list of known driver suffixes. Suffixes are compared against the |
297 | | // program name in order. If there is a match, the frontend type is updated as |
298 | | // necessary by applying the ModeFlag. |
299 | 212k | static const DriverSuffix DriverSuffixes[] = { |
300 | 212k | {"clang", nullptr}, |
301 | 212k | {"clang++", "--driver-mode=g++"}, |
302 | 212k | {"clang-c++", "--driver-mode=g++"}, |
303 | 212k | {"clang-cc", nullptr}, |
304 | 212k | {"clang-cpp", "--driver-mode=cpp"}, |
305 | 212k | {"clang-g++", "--driver-mode=g++"}, |
306 | 212k | {"clang-gcc", nullptr}, |
307 | 212k | {"clang-cl", "--driver-mode=cl"}, |
308 | 212k | {"cc", nullptr}, |
309 | 212k | {"cpp", "--driver-mode=cpp"}, |
310 | 212k | {"cl", "--driver-mode=cl"}, |
311 | 212k | {"++", "--driver-mode=g++"}, |
312 | 212k | {"flang", "--driver-mode=flang"}, |
313 | 212k | {"clang-dxc", "--driver-mode=dxc"}, |
314 | 212k | }; |
315 | | |
316 | 1.41M | for (const auto &DS : DriverSuffixes) { |
317 | 1.41M | StringRef Suffix(DS.Suffix); |
318 | 1.41M | if (ProgName.endswith(Suffix)) { |
319 | 120k | Pos = ProgName.size() - Suffix.size(); |
320 | 120k | return &DS; |
321 | 120k | } |
322 | 1.41M | } |
323 | 92.4k | return nullptr; |
324 | 212k | } |
325 | | |
326 | | /// Normalize the program name from argv[0] by stripping the file extension if |
327 | | /// present and lower-casing the string on Windows. |
328 | 123k | static std::string normalizeProgramName(llvm::StringRef Argv0) { |
329 | 123k | std::string ProgName = std::string(llvm::sys::path::filename(Argv0)); |
330 | 123k | if (is_style_windows(llvm::sys::path::Style::native)) { |
331 | | // Transform to lowercase for case insensitive file systems. |
332 | 0 | std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), |
333 | 0 | ::tolower); |
334 | 0 | } |
335 | 123k | return ProgName; |
336 | 123k | } |
337 | | |
338 | 123k | static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) { |
339 | | // Try to infer frontend type and default target from the program name by |
340 | | // comparing it against DriverSuffixes in order. |
341 | | |
342 | | // If there is a match, the function tries to identify a target as prefix. |
343 | | // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target |
344 | | // prefix "x86_64-linux". If such a target prefix is found, it may be |
345 | | // added via -target as implicit first argument. |
346 | 123k | const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos); |
347 | | |
348 | 123k | if (!DS && ProgName.endswith(".exe")44.7k ) { |
349 | | // Try again after stripping the executable suffix: |
350 | | // clang++.exe -> clang++ |
351 | 2 | ProgName = ProgName.drop_back(StringRef(".exe").size()); |
352 | 2 | DS = FindDriverSuffix(ProgName, Pos); |
353 | 2 | } |
354 | | |
355 | 123k | if (!DS) { |
356 | | // Try again after stripping any trailing version number: |
357 | | // clang++3.5 -> clang++ |
358 | 44.7k | ProgName = ProgName.rtrim("0123456789."); |
359 | 44.7k | DS = FindDriverSuffix(ProgName, Pos); |
360 | 44.7k | } |
361 | | |
362 | 123k | if (!DS) { |
363 | | // Try again after stripping trailing -component. |
364 | | // clang++-tot -> clang++ |
365 | 44.7k | ProgName = ProgName.slice(0, ProgName.rfind('-')); |
366 | 44.7k | DS = FindDriverSuffix(ProgName, Pos); |
367 | 44.7k | } |
368 | 123k | return DS; |
369 | 123k | } |
370 | | |
371 | | ParsedClangName |
372 | 123k | ToolChain::getTargetAndModeFromProgramName(StringRef PN) { |
373 | 123k | std::string ProgName = normalizeProgramName(PN); |
374 | 123k | size_t SuffixPos; |
375 | 123k | const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos); |
376 | 123k | if (!DS) |
377 | 3.00k | return {}; |
378 | 120k | size_t SuffixEnd = SuffixPos + strlen(DS->Suffix); |
379 | | |
380 | 120k | size_t LastComponent = ProgName.rfind('-', SuffixPos); |
381 | 120k | if (LastComponent == std::string::npos) |
382 | 119k | return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag); |
383 | 92 | std::string ModeSuffix = ProgName.substr(LastComponent + 1, |
384 | 92 | SuffixEnd - LastComponent - 1); |
385 | | |
386 | | // Infer target from the prefix. |
387 | 92 | StringRef Prefix(ProgName); |
388 | 92 | Prefix = Prefix.slice(0, LastComponent); |
389 | 92 | std::string IgnoredError; |
390 | 92 | bool IsRegistered = |
391 | 92 | llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError); |
392 | 92 | return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag, |
393 | 92 | IsRegistered}; |
394 | 120k | } |
395 | | |
396 | 29.6k | StringRef ToolChain::getDefaultUniversalArchName() const { |
397 | | // In universal driver terms, the arch name accepted by -arch isn't exactly |
398 | | // the same as the ones that appear in the triple. Roughly speaking, this is |
399 | | // an inverse of the darwin::getArchTypeForDarwinArchName() function. |
400 | 29.6k | switch (Triple.getArch()) { |
401 | 166 | case llvm::Triple::aarch64: { |
402 | 166 | if (getTriple().isArm64e()) |
403 | 12 | return "arm64e"; |
404 | 154 | return "arm64"; |
405 | 166 | } |
406 | 4 | case llvm::Triple::aarch64_32: |
407 | 4 | return "arm64_32"; |
408 | 1 | case llvm::Triple::ppc: |
409 | 1 | return "ppc"; |
410 | 0 | case llvm::Triple::ppcle: |
411 | 0 | return "ppcle"; |
412 | 0 | case llvm::Triple::ppc64: |
413 | 0 | return "ppc64"; |
414 | 0 | case llvm::Triple::ppc64le: |
415 | 0 | return "ppc64le"; |
416 | 29.4k | default: |
417 | 29.4k | return Triple.getArchName(); |
418 | 29.6k | } |
419 | 29.6k | } |
420 | | |
421 | 311 | std::string ToolChain::getInputFilename(const InputInfo &Input) const { |
422 | 311 | return Input.getFilename(); |
423 | 311 | } |
424 | | |
425 | | ToolChain::UnwindTableLevel |
426 | 3.44k | ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const { |
427 | 3.44k | return UnwindTableLevel::None; |
428 | 3.44k | } |
429 | | |
430 | 451 | unsigned ToolChain::GetDefaultDwarfVersion() const { |
431 | | // TODO: Remove the RISC-V special case when R_RISCV_SET_ULEB128 linker |
432 | | // support becomes more widely available. |
433 | 451 | return getTriple().isRISCV() ? 415 : 5436 ; |
434 | 451 | } |
435 | | |
436 | 48.0k | Tool *ToolChain::getClang() const { |
437 | 48.0k | if (!Clang) |
438 | 47.4k | Clang.reset(new tools::Clang(*this, useIntegratedBackend())); |
439 | 48.0k | return Clang.get(); |
440 | 48.0k | } |
441 | | |
442 | 15 | Tool *ToolChain::getFlang() const { |
443 | 15 | if (!Flang) |
444 | 14 | Flang.reset(new tools::Flang(*this)); |
445 | 15 | return Flang.get(); |
446 | 15 | } |
447 | | |
448 | 0 | Tool *ToolChain::buildAssembler() const { |
449 | 0 | return new tools::ClangAs(*this); |
450 | 0 | } |
451 | | |
452 | 0 | Tool *ToolChain::buildLinker() const { |
453 | 0 | llvm_unreachable("Linking is not supported by this toolchain"); |
454 | 0 | } |
455 | | |
456 | 0 | Tool *ToolChain::buildStaticLibTool() const { |
457 | 0 | llvm_unreachable("Creating static lib is not supported by this toolchain"); |
458 | 0 | } |
459 | | |
460 | 397 | Tool *ToolChain::getAssemble() const { |
461 | 397 | if (!Assemble) |
462 | 395 | Assemble.reset(buildAssembler()); |
463 | 397 | return Assemble.get(); |
464 | 397 | } |
465 | | |
466 | 486 | Tool *ToolChain::getClangAs() const { |
467 | 486 | if (!Assemble) |
468 | 479 | Assemble.reset(new tools::ClangAs(*this)); |
469 | 486 | return Assemble.get(); |
470 | 486 | } |
471 | | |
472 | 7.86k | Tool *ToolChain::getLink() const { |
473 | 7.86k | if (!Link) |
474 | 7.54k | Link.reset(buildLinker()); |
475 | 7.86k | return Link.get(); |
476 | 7.86k | } |
477 | | |
478 | 12 | Tool *ToolChain::getStaticLibTool() const { |
479 | 12 | if (!StaticLibTool) |
480 | 12 | StaticLibTool.reset(buildStaticLibTool()); |
481 | 12 | return StaticLibTool.get(); |
482 | 12 | } |
483 | | |
484 | 23 | Tool *ToolChain::getIfsMerge() const { |
485 | 23 | if (!IfsMerge) |
486 | 21 | IfsMerge.reset(new tools::ifstool::Merger(*this)); |
487 | 23 | return IfsMerge.get(); |
488 | 23 | } |
489 | | |
490 | 74 | Tool *ToolChain::getOffloadBundler() const { |
491 | 74 | if (!OffloadBundler) |
492 | 53 | OffloadBundler.reset(new tools::OffloadBundler(*this)); |
493 | 74 | return OffloadBundler.get(); |
494 | 74 | } |
495 | | |
496 | 13 | Tool *ToolChain::getOffloadPackager() const { |
497 | 13 | if (!OffloadPackager) |
498 | 13 | OffloadPackager.reset(new tools::OffloadPackager(*this)); |
499 | 13 | return OffloadPackager.get(); |
500 | 13 | } |
501 | | |
502 | 11 | Tool *ToolChain::getLinkerWrapper() const { |
503 | 11 | if (!LinkerWrapper) |
504 | 11 | LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink())); |
505 | 11 | return LinkerWrapper.get(); |
506 | 11 | } |
507 | | |
508 | 8.49k | Tool *ToolChain::getTool(Action::ActionClass AC) const { |
509 | 8.49k | switch (AC) { |
510 | 397 | case Action::AssembleJobClass: |
511 | 397 | return getAssemble(); |
512 | | |
513 | 23 | case Action::IfsMergeJobClass: |
514 | 23 | return getIfsMerge(); |
515 | | |
516 | 7.85k | case Action::LinkJobClass: |
517 | 7.85k | return getLink(); |
518 | | |
519 | 12 | case Action::StaticLibJobClass: |
520 | 12 | return getStaticLibTool(); |
521 | | |
522 | 0 | case Action::InputClass: |
523 | 0 | case Action::BindArchClass: |
524 | 0 | case Action::OffloadClass: |
525 | 0 | case Action::LipoJobClass: |
526 | 0 | case Action::DsymutilJobClass: |
527 | 0 | case Action::VerifyDebugInfoJobClass: |
528 | 0 | case Action::BinaryAnalyzeJobClass: |
529 | 0 | llvm_unreachable("Invalid tool kind."); |
530 | |
|
531 | 44 | case Action::CompileJobClass: |
532 | 44 | case Action::PrecompileJobClass: |
533 | 45 | case Action::PreprocessJobClass: |
534 | 48 | case Action::ExtractAPIJobClass: |
535 | 104 | case Action::AnalyzeJobClass: |
536 | 104 | case Action::MigrateJobClass: |
537 | 106 | case Action::VerifyPCHJobClass: |
538 | 106 | case Action::BackendJobClass: |
539 | 106 | return getClang(); |
540 | | |
541 | 35 | case Action::OffloadBundlingJobClass: |
542 | 74 | case Action::OffloadUnbundlingJobClass: |
543 | 74 | return getOffloadBundler(); |
544 | | |
545 | 13 | case Action::OffloadPackagerJobClass: |
546 | 13 | return getOffloadPackager(); |
547 | 11 | case Action::LinkerWrapperJobClass: |
548 | 11 | return getLinkerWrapper(); |
549 | 8.49k | } |
550 | | |
551 | 0 | llvm_unreachable("Invalid tool kind."); |
552 | 0 | } |
553 | | |
554 | | static StringRef getArchNameForCompilerRTLib(const ToolChain &TC, |
555 | 2.32k | const ArgList &Args) { |
556 | 2.32k | const llvm::Triple &Triple = TC.getTriple(); |
557 | 2.32k | bool IsWindows = Triple.isOSWindows(); |
558 | | |
559 | 2.32k | if (TC.isBareMetal()) |
560 | 706 | return Triple.getArchName(); |
561 | | |
562 | 1.61k | if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb1.42k ) |
563 | 192 | return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows24 ) |
564 | 192 | ? "armhf"12 |
565 | 192 | : "arm"180 ; |
566 | | |
567 | | // For historic reasons, Android library is using i686 instead of i386. |
568 | 1.42k | if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid()175 ) |
569 | 25 | return "i686"; |
570 | | |
571 | 1.39k | if (TC.getArch() == llvm::Triple::x86_64 && Triple.isX32()843 ) |
572 | 6 | return "x32"; |
573 | | |
574 | 1.39k | return llvm::Triple::getArchTypeName(TC.getArch()); |
575 | 1.39k | } |
576 | | |
577 | 64.2k | StringRef ToolChain::getOSLibName() const { |
578 | 64.2k | if (Triple.isOSDarwin()) |
579 | 22.0k | return "darwin"; |
580 | | |
581 | 42.1k | switch (Triple.getOS()) { |
582 | 577 | case llvm::Triple::FreeBSD: |
583 | 577 | return "freebsd"; |
584 | 929 | case llvm::Triple::NetBSD: |
585 | 929 | return "netbsd"; |
586 | 281 | case llvm::Triple::OpenBSD: |
587 | 281 | return "openbsd"; |
588 | 507 | case llvm::Triple::Solaris: |
589 | 507 | return "sunos"; |
590 | 604 | case llvm::Triple::AIX: |
591 | 604 | return "aix"; |
592 | 39.2k | default: |
593 | 39.2k | return getOS(); |
594 | 42.1k | } |
595 | 42.1k | } |
596 | | |
597 | 12.6k | std::string ToolChain::getCompilerRTPath() const { |
598 | 12.6k | SmallString<128> Path(getDriver().ResourceDir); |
599 | 12.6k | if (isBareMetal()) { |
600 | 706 | llvm::sys::path::append(Path, "lib", getOSLibName()); |
601 | 706 | if (!SelectedMultilibs.empty()) { |
602 | 73 | Path += SelectedMultilibs.back().gccSuffix(); |
603 | 73 | } |
604 | 11.9k | } else if (Triple.isOSUnknown()) { |
605 | 365 | llvm::sys::path::append(Path, "lib"); |
606 | 11.6k | } else { |
607 | 11.6k | llvm::sys::path::append(Path, "lib", getOSLibName()); |
608 | 11.6k | } |
609 | 12.6k | return std::string(Path.str()); |
610 | 12.6k | } |
611 | | |
612 | | std::string ToolChain::getCompilerRTBasename(const ArgList &Args, |
613 | | StringRef Component, |
614 | 28 | FileType Type) const { |
615 | 28 | std::string CRTAbsolutePath = getCompilerRT(Args, Component, Type); |
616 | 28 | return llvm::sys::path::filename(CRTAbsolutePath).str(); |
617 | 28 | } |
618 | | |
619 | | std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args, |
620 | | StringRef Component, |
621 | | FileType Type, |
622 | 4.71k | bool AddArch) const { |
623 | 4.71k | const llvm::Triple &TT = getTriple(); |
624 | 4.71k | bool IsITANMSVCWindows = |
625 | 4.71k | TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment()4.50k ; |
626 | | |
627 | 4.71k | const char *Prefix = |
628 | 4.71k | IsITANMSVCWindows || Type == ToolChain::FT_Object4.47k ? ""320 : "lib"4.39k ; |
629 | 4.71k | const char *Suffix; |
630 | 4.71k | switch (Type) { |
631 | 80 | case ToolChain::FT_Object: |
632 | 80 | Suffix = IsITANMSVCWindows ? ".obj"0 : ".o"; |
633 | 80 | break; |
634 | 4.54k | case ToolChain::FT_Static: |
635 | 4.54k | Suffix = IsITANMSVCWindows ? ".lib"240 : ".a"4.30k ; |
636 | 4.54k | break; |
637 | 91 | case ToolChain::FT_Shared: |
638 | 91 | Suffix = TT.isOSWindows() |
639 | 91 | ? (8 TT.isWindowsGNUEnvironment()8 ? ".dll.a"8 : ".lib"0 ) |
640 | 91 | : ".so"83 ; |
641 | 91 | break; |
642 | 4.71k | } |
643 | | |
644 | 4.71k | std::string ArchAndEnv; |
645 | 4.71k | if (AddArch) { |
646 | 2.32k | StringRef Arch = getArchNameForCompilerRTLib(*this, Args); |
647 | 2.32k | const char *Env = TT.isAndroid() ? "-android"308 : ""2.01k ; |
648 | 2.32k | ArchAndEnv = ("-" + Arch + Env).str(); |
649 | 2.32k | } |
650 | 4.71k | return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str(); |
651 | 4.71k | } |
652 | | |
653 | | std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, |
654 | 2.38k | FileType Type) const { |
655 | | // Check for runtime files in the new layout without the architecture first. |
656 | 2.38k | std::string CRTBasename = |
657 | 2.38k | buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false); |
658 | 2.38k | for (const auto &LibPath : getLibraryPaths()) { |
659 | 925 | SmallString<128> P(LibPath); |
660 | 925 | llvm::sys::path::append(P, CRTBasename); |
661 | 925 | if (getVFS().exists(P)) |
662 | 67 | return std::string(P.str()); |
663 | 925 | } |
664 | | |
665 | | // Fall back to the old expected compiler-rt name if the new one does not |
666 | | // exist. |
667 | 2.32k | CRTBasename = |
668 | 2.32k | buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/true); |
669 | 2.32k | SmallString<128> Path(getCompilerRTPath()); |
670 | 2.32k | llvm::sys::path::append(Path, CRTBasename); |
671 | 2.32k | return std::string(Path.str()); |
672 | 2.38k | } |
673 | | |
674 | | const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args, |
675 | | StringRef Component, |
676 | 1.32k | FileType Type) const { |
677 | 1.32k | return Args.MakeArgString(getCompilerRT(Args, Component, Type)); |
678 | 1.32k | } |
679 | | |
680 | | // Android target triples contain a target version. If we don't have libraries |
681 | | // for the exact target version, we should fall back to the next newest version |
682 | | // or a versionless path, if any. |
683 | | std::optional<std::string> |
684 | 483 | ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const { |
685 | 483 | llvm::Triple TripleWithoutLevel(getTriple()); |
686 | 483 | TripleWithoutLevel.setEnvironmentName("android"); // remove any version number |
687 | 483 | const std::string &TripleWithoutLevelStr = TripleWithoutLevel.str(); |
688 | 483 | unsigned TripleVersion = getTriple().getEnvironmentVersion().getMajor(); |
689 | 483 | unsigned BestVersion = 0; |
690 | | |
691 | 483 | SmallString<32> TripleDir; |
692 | 483 | bool UsingUnversionedDir = false; |
693 | 483 | std::error_code EC; |
694 | 483 | for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE; |
695 | 73.1k | !EC && LI != LE72.9k ; LI = LI.increment(EC)72.6k ) { |
696 | 72.6k | StringRef DirName = llvm::sys::path::filename(LI->path()); |
697 | 72.6k | StringRef DirNameSuffix = DirName; |
698 | 72.6k | if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) { |
699 | 34 | if (DirNameSuffix.empty() && TripleDir.empty()14 ) { |
700 | 10 | TripleDir = DirName; |
701 | 10 | UsingUnversionedDir = true; |
702 | 24 | } else { |
703 | 24 | unsigned Version; |
704 | 24 | if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion20 && |
705 | 24 | Version < TripleVersion18 ) { |
706 | 8 | BestVersion = Version; |
707 | 8 | TripleDir = DirName; |
708 | 8 | UsingUnversionedDir = false; |
709 | 8 | } |
710 | 24 | } |
711 | 34 | } |
712 | 72.6k | } |
713 | | |
714 | 483 | if (TripleDir.empty()) |
715 | 469 | return {}; |
716 | | |
717 | 14 | SmallString<128> P(BaseDir); |
718 | 14 | llvm::sys::path::append(P, TripleDir); |
719 | 14 | if (UsingUnversionedDir) |
720 | 6 | D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString(); |
721 | 14 | return std::string(P); |
722 | 483 | } |
723 | | |
724 | | std::optional<std::string> |
725 | 105k | ToolChain::getTargetSubDirPath(StringRef BaseDir) const { |
726 | 105k | auto getPathForTriple = |
727 | 109k | [&](const llvm::Triple &Triple) -> std::optional<std::string> { |
728 | 109k | SmallString<128> P(BaseDir); |
729 | 109k | llvm::sys::path::append(P, Triple.str()); |
730 | 109k | if (getVFS().exists(P)) |
731 | 218 | return std::string(P); |
732 | 109k | return {}; |
733 | 109k | }; |
734 | | |
735 | 105k | if (auto Path = getPathForTriple(getTriple())) |
736 | 214 | return *Path; |
737 | | |
738 | | // When building with per target runtime directories, various ways of naming |
739 | | // the Arm architecture may have been normalised to simply "arm". |
740 | | // For example "armv8l" (Armv8 AArch32 little endian) is replaced with "arm". |
741 | | // Since an armv8l system can use libraries built for earlier architecture |
742 | | // versions assuming endian and float ABI match. |
743 | | // |
744 | | // Original triple: armv8l-unknown-linux-gnueabihf |
745 | | // Runtime triple: arm-unknown-linux-gnueabihf |
746 | | // |
747 | | // We do not do this for armeb (big endian) because doing so could make us |
748 | | // select little endian libraries. In addition, all known armeb triples only |
749 | | // use the "armeb" architecture name. |
750 | | // |
751 | | // M profile Arm is bare metal and we know they will not be using the per |
752 | | // target runtime directory layout. |
753 | 105k | if (getTriple().getArch() == Triple::arm && !getTriple().isArmMClass()4.06k ) { |
754 | 3.93k | llvm::Triple ArmTriple = getTriple(); |
755 | 3.93k | ArmTriple.setArch(Triple::arm); |
756 | 3.93k | if (auto Path = getPathForTriple(ArmTriple)) |
757 | 4 | return *Path; |
758 | 3.93k | } |
759 | | |
760 | 105k | if (getTriple().isAndroid()) |
761 | 483 | return getFallbackAndroidTargetPath(BaseDir); |
762 | | |
763 | 105k | return {}; |
764 | 105k | } |
765 | | |
766 | 52.6k | std::optional<std::string> ToolChain::getRuntimePath() const { |
767 | 52.6k | SmallString<128> P(D.ResourceDir); |
768 | 52.6k | llvm::sys::path::append(P, "lib"); |
769 | 52.6k | return getTargetSubDirPath(P); |
770 | 52.6k | } |
771 | | |
772 | 53.1k | std::optional<std::string> ToolChain::getStdlibPath() const { |
773 | 53.1k | SmallString<128> P(D.Dir); |
774 | 53.1k | llvm::sys::path::append(P, "..", "lib"); |
775 | 53.1k | return getTargetSubDirPath(P); |
776 | 53.1k | } |
777 | | |
778 | 52.6k | ToolChain::path_list ToolChain::getArchSpecificLibPaths() const { |
779 | 52.6k | path_list Paths; |
780 | | |
781 | 105k | auto AddPath = [&](const ArrayRef<StringRef> &SS) { |
782 | 105k | SmallString<128> Path(getDriver().ResourceDir); |
783 | 105k | llvm::sys::path::append(Path, "lib"); |
784 | 105k | for (auto &S : SS) |
785 | 157k | llvm::sys::path::append(Path, S); |
786 | 105k | Paths.push_back(std::string(Path.str())); |
787 | 105k | }; |
788 | | |
789 | 52.6k | AddPath({getTriple().str()}); |
790 | 52.6k | AddPath({getOSLibName(), llvm::Triple::getArchTypeName(getArch())}); |
791 | 52.6k | return Paths; |
792 | 52.6k | } |
793 | | |
794 | 7.64k | bool ToolChain::needsProfileRT(const ArgList &Args) { |
795 | 7.64k | if (Args.hasArg(options::OPT_noprofilelib)) |
796 | 4 | return false; |
797 | | |
798 | 7.64k | return Args.hasArg(options::OPT_fprofile_generate) || |
799 | 7.64k | Args.hasArg(options::OPT_fprofile_generate_EQ)7.62k || |
800 | 7.64k | Args.hasArg(options::OPT_fcs_profile_generate)7.62k || |
801 | 7.64k | Args.hasArg(options::OPT_fcs_profile_generate_EQ)7.62k || |
802 | 7.64k | Args.hasArg(options::OPT_fprofile_instr_generate)7.62k || |
803 | 7.64k | Args.hasArg(options::OPT_fprofile_instr_generate_EQ)7.58k || |
804 | 7.64k | Args.hasArg(options::OPT_fcreate_profile)7.58k || |
805 | 7.64k | Args.hasArg(options::OPT_forder_file_instrumentation)7.58k ; |
806 | 7.64k | } |
807 | | |
808 | 53.0k | bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) { |
809 | 53.0k | return Args.hasArg(options::OPT_coverage) || |
810 | 53.0k | Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, |
811 | 53.0k | false); |
812 | 53.0k | } |
813 | | |
814 | 56.9k | Tool *ToolChain::SelectTool(const JobAction &JA) const { |
815 | 56.9k | if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)20 ) return getFlang()15 ; |
816 | 56.9k | if (getDriver().ShouldUseClangCompiler(JA)) return getClang()47.9k ; |
817 | 9.03k | Action::ActionClass AC = JA.getKind(); |
818 | 9.03k | if (AC == Action::AssembleJobClass && useIntegratedAs()883 && |
819 | 9.03k | !getTriple().isOSAIX()491 ) |
820 | 486 | return getClangAs(); |
821 | 8.54k | return getTool(AC); |
822 | 9.03k | } |
823 | | |
824 | 9.91k | std::string ToolChain::GetFilePath(const char *Name) const { |
825 | 9.91k | return D.GetFilePath(Name, *this); |
826 | 9.91k | } |
827 | | |
828 | 8.94k | std::string ToolChain::GetProgramPath(const char *Name) const { |
829 | 8.94k | return D.GetProgramPath(Name, *this); |
830 | 8.94k | } |
831 | | |
832 | 6.39k | std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const { |
833 | 6.39k | if (LinkerIsLLD) |
834 | 3.35k | *LinkerIsLLD = false; |
835 | | |
836 | | // Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is |
837 | | // considered as the linker flavor, e.g. "bfd", "gold", or "lld". |
838 | 6.39k | const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ); |
839 | 6.39k | StringRef UseLinker = A ? A->getValue()481 : CLANG_DEFAULT_LINKER5.91k ; |
840 | | |
841 | | // --ld-path= takes precedence over -fuse-ld= and specifies the executable |
842 | | // name. -B, COMPILER_PATH and PATH and consulted if the value does not |
843 | | // contain a path component separator. |
844 | | // -fuse-ld=lld can be used with --ld-path= to inform clang that the binary |
845 | | // that --ld-path= points to is lld. |
846 | 6.39k | if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) { |
847 | 12 | std::string Path(A->getValue()); |
848 | 12 | if (!Path.empty()) { |
849 | 11 | if (llvm::sys::path::parent_path(Path).empty()) |
850 | 5 | Path = GetProgramPath(A->getValue()); |
851 | 11 | if (llvm::sys::fs::can_execute(Path)) { |
852 | 9 | if (LinkerIsLLD) |
853 | 1 | *LinkerIsLLD = UseLinker == "lld"; |
854 | 9 | return std::string(Path); |
855 | 9 | } |
856 | 11 | } |
857 | 3 | getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args); |
858 | 3 | return GetProgramPath(getDefaultLinker()); |
859 | 12 | } |
860 | | // If we're passed -fuse-ld= with no argument, or with the argument ld, |
861 | | // then use whatever the default system linker is. |
862 | 6.38k | if (UseLinker.empty() || UseLinker == "ld"371 ) { |
863 | 6.27k | const char *DefaultLinker = getDefaultLinker(); |
864 | 6.27k | if (llvm::sys::path::is_absolute(DefaultLinker)) |
865 | 6 | return std::string(DefaultLinker); |
866 | 6.26k | else |
867 | 6.26k | return GetProgramPath(DefaultLinker); |
868 | 6.27k | } |
869 | | |
870 | | // Extending -fuse-ld= to an absolute or relative path is unexpected. Checking |
871 | | // for the linker flavor is brittle. In addition, prepending "ld." or "ld64." |
872 | | // to a relative path is surprising. This is more complex due to priorities |
873 | | // among -B, COMPILER_PATH and PATH. --ld-path= should be used instead. |
874 | 111 | if (UseLinker.contains('/')) |
875 | 5 | getDriver().Diag(diag::warn_drv_fuse_ld_path); |
876 | | |
877 | 111 | if (llvm::sys::path::is_absolute(UseLinker)) { |
878 | | // If we're passed what looks like an absolute path, don't attempt to |
879 | | // second-guess that. |
880 | 5 | if (llvm::sys::fs::can_execute(UseLinker)) |
881 | 2 | return std::string(UseLinker); |
882 | 106 | } else { |
883 | 106 | llvm::SmallString<8> LinkerName; |
884 | 106 | if (Triple.isOSDarwin()) |
885 | 14 | LinkerName.append("ld64."); |
886 | 92 | else |
887 | 92 | LinkerName.append("ld."); |
888 | 106 | LinkerName.append(UseLinker); |
889 | | |
890 | 106 | std::string LinkerPath(GetProgramPath(LinkerName.c_str())); |
891 | 106 | if (llvm::sys::fs::can_execute(LinkerPath)) { |
892 | 102 | if (LinkerIsLLD) |
893 | 14 | *LinkerIsLLD = UseLinker == "lld"; |
894 | 102 | return LinkerPath; |
895 | 102 | } |
896 | 106 | } |
897 | | |
898 | 7 | if (A) |
899 | 7 | getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args); |
900 | | |
901 | 7 | return GetProgramPath(getDefaultLinker()); |
902 | 111 | } |
903 | | |
904 | 8 | std::string ToolChain::GetStaticLibToolPath() const { |
905 | | // TODO: Add support for static lib archiving on Windows |
906 | 8 | if (Triple.isOSDarwin()) |
907 | 2 | return GetProgramPath("libtool"); |
908 | 6 | return GetProgramPath("llvm-ar"); |
909 | 8 | } |
910 | | |
911 | 45.4k | types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const { |
912 | 45.4k | types::ID id = types::lookupTypeForExtension(Ext); |
913 | | |
914 | | // Flang always runs the preprocessor and has no notion of "preprocessed |
915 | | // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating |
916 | | // them differently. |
917 | 45.4k | if (D.IsFlangMode() && id == types::TY_PP_Fortran16 ) |
918 | 9 | id = types::TY_Fortran; |
919 | | |
920 | 45.4k | return id; |
921 | 45.4k | } |
922 | | |
923 | 365 | bool ToolChain::HasNativeLLVMSupport() const { |
924 | 365 | return false; |
925 | 365 | } |
926 | | |
927 | 2.60k | bool ToolChain::isCrossCompiling() const { |
928 | 2.60k | llvm::Triple HostTriple(LLVM_HOST_TRIPLE); |
929 | 2.60k | switch (HostTriple.getArch()) { |
930 | | // The A32/T32/T16 instruction sets are not separate architectures in this |
931 | | // context. |
932 | 0 | case llvm::Triple::arm: |
933 | 0 | case llvm::Triple::armeb: |
934 | 0 | case llvm::Triple::thumb: |
935 | 0 | case llvm::Triple::thumbeb: |
936 | 0 | return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb && |
937 | 0 | getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb; |
938 | 2.60k | default: |
939 | 2.60k | return HostTriple.getArch() != getArch(); |
940 | 2.60k | } |
941 | 2.60k | } |
942 | | |
943 | 30.0k | ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { |
944 | 30.0k | return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep1.67k : ObjCRuntime::GCC28.3k , |
945 | 30.0k | VersionTuple()); |
946 | 30.0k | } |
947 | | |
948 | | llvm::ExceptionHandling |
949 | 29.6k | ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const { |
950 | 29.6k | return llvm::ExceptionHandling::None; |
951 | 29.6k | } |
952 | | |
953 | 14 | bool ToolChain::isThreadModelSupported(const StringRef Model) const { |
954 | 14 | if (Model == "single") { |
955 | | // FIXME: 'single' is only supported on ARM and WebAssembly so far. |
956 | 5 | return Triple.getArch() == llvm::Triple::arm || |
957 | 5 | Triple.getArch() == llvm::Triple::armeb2 || |
958 | 5 | Triple.getArch() == llvm::Triple::thumb2 || |
959 | 5 | Triple.getArch() == llvm::Triple::thumbeb2 || Triple.isWasm()2 ; |
960 | 9 | } else if (Model == "posix") |
961 | 5 | return true; |
962 | | |
963 | 4 | return false; |
964 | 14 | } |
965 | | |
966 | | std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, |
967 | 57.3k | types::ID InputType) const { |
968 | 57.3k | switch (getTriple().getArch()) { |
969 | 17.8k | default: |
970 | 17.8k | return getTripleString(); |
971 | | |
972 | 34.2k | case llvm::Triple::x86_64: { |
973 | 34.2k | llvm::Triple Triple = getTriple(); |
974 | 34.2k | if (!Triple.isOSBinFormatMachO()) |
975 | 13.3k | return getTripleString(); |
976 | | |
977 | 20.8k | if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { |
978 | | // x86_64h goes in the triple. Other -march options just use the |
979 | | // vanilla triple we already have. |
980 | 2 | StringRef MArch = A->getValue(); |
981 | 2 | if (MArch == "x86_64h") |
982 | 0 | Triple.setArchName(MArch); |
983 | 2 | } |
984 | 20.8k | return Triple.getTriple(); |
985 | 34.2k | } |
986 | 2.06k | case llvm::Triple::aarch64: { |
987 | 2.06k | llvm::Triple Triple = getTriple(); |
988 | 2.06k | if (!Triple.isOSBinFormatMachO()) |
989 | 1.77k | return getTripleString(); |
990 | | |
991 | 286 | if (Triple.isArm64e()) |
992 | 19 | return getTripleString(); |
993 | | |
994 | | // FIXME: older versions of ld64 expect the "arm64" component in the actual |
995 | | // triple string and query it to determine whether an LTO file can be |
996 | | // handled. Remove this when we don't care any more. |
997 | 267 | Triple.setArchName("arm64"); |
998 | 267 | return Triple.getTriple(); |
999 | 286 | } |
1000 | 11 | case llvm::Triple::aarch64_32: |
1001 | 11 | return getTripleString(); |
1002 | 2.88k | case llvm::Triple::arm: |
1003 | 3.07k | case llvm::Triple::armeb: |
1004 | 3.17k | case llvm::Triple::thumb: |
1005 | 3.20k | case llvm::Triple::thumbeb: { |
1006 | 3.20k | llvm::Triple Triple = getTriple(); |
1007 | 3.20k | tools::arm::setArchNameInTriple(getDriver(), Args, InputType, Triple); |
1008 | 3.20k | tools::arm::setFloatABIInTriple(getDriver(), Args, Triple); |
1009 | 3.20k | return Triple.getTriple(); |
1010 | 3.17k | } |
1011 | 57.3k | } |
1012 | 57.3k | } |
1013 | | |
1014 | | std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, |
1015 | 35.3k | types::ID InputType) const { |
1016 | 35.3k | return ComputeLLVMTriple(Args, InputType); |
1017 | 35.3k | } |
1018 | | |
1019 | 46 | std::string ToolChain::computeSysRoot() const { |
1020 | 46 | return D.SysRoot; |
1021 | 46 | } |
1022 | | |
1023 | | void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
1024 | 13.0k | ArgStringList &CC1Args) const { |
1025 | | // Each toolchain should provide the appropriate include flags. |
1026 | 13.0k | } |
1027 | | |
1028 | | void ToolChain::addClangTargetOptions( |
1029 | | const ArgList &DriverArgs, ArgStringList &CC1Args, |
1030 | 187 | Action::OffloadKind DeviceOffloadKind) const {} |
1031 | | |
1032 | | void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args, |
1033 | 410 | ArgStringList &CC1ASArgs) const {} |
1034 | | |
1035 | 29.9k | void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {} |
1036 | | |
1037 | | void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args, |
1038 | 2.60k | llvm::opt::ArgStringList &CmdArgs) const { |
1039 | 2.60k | if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args)2.56k ) |
1040 | 2.55k | return; |
1041 | | |
1042 | 45 | CmdArgs.push_back(getCompilerRTArgString(Args, "profile")); |
1043 | 45 | } |
1044 | | |
1045 | | ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( |
1046 | 11.2k | const ArgList &Args) const { |
1047 | 11.2k | if (runtimeLibType) |
1048 | 7.14k | return *runtimeLibType; |
1049 | | |
1050 | 4.09k | const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ); |
1051 | 4.09k | StringRef LibName = A ? A->getValue()279 : CLANG_DEFAULT_RTLIB3.81k ; |
1052 | | |
1053 | | // Only use "platform" in tests to override CLANG_DEFAULT_RTLIB! |
1054 | 4.09k | if (LibName == "compiler-rt") |
1055 | 58 | runtimeLibType = ToolChain::RLT_CompilerRT; |
1056 | 4.04k | else if (LibName == "libgcc") |
1057 | 51 | runtimeLibType = ToolChain::RLT_Libgcc; |
1058 | 3.98k | else if (LibName == "platform") |
1059 | 168 | runtimeLibType = GetDefaultRuntimeLibType(); |
1060 | 3.82k | else { |
1061 | 3.82k | if (A) |
1062 | 2 | getDriver().Diag(diag::err_drv_invalid_rtlib_name) |
1063 | 2 | << A->getAsString(Args); |
1064 | | |
1065 | 3.82k | runtimeLibType = GetDefaultRuntimeLibType(); |
1066 | 3.82k | } |
1067 | | |
1068 | 4.09k | return *runtimeLibType; |
1069 | 11.2k | } |
1070 | | |
1071 | | ToolChain::UnwindLibType ToolChain::GetUnwindLibType( |
1072 | 3.29k | const ArgList &Args) const { |
1073 | 3.29k | if (unwindLibType) |
1074 | 1.49k | return *unwindLibType; |
1075 | | |
1076 | 1.80k | const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ); |
1077 | 1.80k | StringRef LibName = A ? A->getValue()184 : CLANG_DEFAULT_UNWINDLIB1.61k ; |
1078 | | |
1079 | 1.80k | if (LibName == "none") |
1080 | 0 | unwindLibType = ToolChain::UNW_None; |
1081 | 1.80k | else if (LibName == "platform" || LibName == ""1.66k ) { |
1082 | 1.75k | ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args); |
1083 | 1.75k | if (RtLibType == ToolChain::RLT_CompilerRT) { |
1084 | 377 | if (getTriple().isAndroid() || getTriple().isOSAIX()235 ) |
1085 | 237 | unwindLibType = ToolChain::UNW_CompilerRT; |
1086 | 140 | else |
1087 | 140 | unwindLibType = ToolChain::UNW_None; |
1088 | 1.37k | } else if (RtLibType == ToolChain::RLT_Libgcc) |
1089 | 1.37k | unwindLibType = ToolChain::UNW_Libgcc; |
1090 | 1.75k | } else if (47 LibName == "libunwind"47 ) { |
1091 | 40 | if (GetRuntimeLibType(Args) == RLT_Libgcc) |
1092 | 5 | getDriver().Diag(diag::err_drv_incompatible_unwindlib); |
1093 | 40 | unwindLibType = ToolChain::UNW_CompilerRT; |
1094 | 40 | } else if (7 LibName == "libgcc"7 ) |
1095 | 6 | unwindLibType = ToolChain::UNW_Libgcc; |
1096 | 1 | else { |
1097 | 1 | if (A) |
1098 | 1 | getDriver().Diag(diag::err_drv_invalid_unwindlib_name) |
1099 | 1 | << A->getAsString(Args); |
1100 | | |
1101 | 1 | unwindLibType = GetDefaultUnwindLibType(); |
1102 | 1 | } |
1103 | | |
1104 | 1.80k | return *unwindLibType; |
1105 | 3.29k | } |
1106 | | |
1107 | 27.2k | ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ |
1108 | 27.2k | if (cxxStdlibType) |
1109 | 2.56k | return *cxxStdlibType; |
1110 | | |
1111 | 24.7k | const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); |
1112 | 24.7k | StringRef LibName = A ? A->getValue()204 : CLANG_DEFAULT_CXX_STDLIB24.5k ; |
1113 | | |
1114 | | // Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB! |
1115 | 24.7k | if (LibName == "libc++") |
1116 | 61 | cxxStdlibType = ToolChain::CST_Libcxx; |
1117 | 24.6k | else if (LibName == "libstdc++") |
1118 | 81 | cxxStdlibType = ToolChain::CST_Libstdcxx; |
1119 | 24.5k | else if (LibName == "platform") |
1120 | 61 | cxxStdlibType = GetDefaultCXXStdlibType(); |
1121 | 24.5k | else { |
1122 | 24.5k | if (A) |
1123 | 1 | getDriver().Diag(diag::err_drv_invalid_stdlib_name) |
1124 | 1 | << A->getAsString(Args); |
1125 | | |
1126 | 24.5k | cxxStdlibType = GetDefaultCXXStdlibType(); |
1127 | 24.5k | } |
1128 | | |
1129 | 24.7k | return *cxxStdlibType; |
1130 | 27.2k | } |
1131 | | |
1132 | | /// Utility function to add a system include directory to CC1 arguments. |
1133 | | /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs, |
1134 | | ArgStringList &CC1Args, |
1135 | 66.1k | const Twine &Path) { |
1136 | 66.1k | CC1Args.push_back("-internal-isystem"); |
1137 | 66.1k | CC1Args.push_back(DriverArgs.MakeArgString(Path)); |
1138 | 66.1k | } |
1139 | | |
1140 | | /// Utility function to add a system include directory with extern "C" |
1141 | | /// semantics to CC1 arguments. |
1142 | | /// |
1143 | | /// Note that this should be used rarely, and only for directories that |
1144 | | /// historically and for legacy reasons are treated as having implicit extern |
1145 | | /// "C" semantics. These semantics are *ignored* by and large today, but its |
1146 | | /// important to preserve the preprocessor changes resulting from the |
1147 | | /// classification. |
1148 | | /*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs, |
1149 | | ArgStringList &CC1Args, |
1150 | 31.0k | const Twine &Path) { |
1151 | 31.0k | CC1Args.push_back("-internal-externc-isystem"); |
1152 | 31.0k | CC1Args.push_back(DriverArgs.MakeArgString(Path)); |
1153 | 31.0k | } |
1154 | | |
1155 | | void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs, |
1156 | | ArgStringList &CC1Args, |
1157 | 18 | const Twine &Path) { |
1158 | 18 | if (llvm::sys::fs::exists(Path)) |
1159 | 16 | addExternCSystemInclude(DriverArgs, CC1Args, Path); |
1160 | 18 | } |
1161 | | |
1162 | | /// Utility function to add a list of system include directories to CC1. |
1163 | | /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs, |
1164 | | ArgStringList &CC1Args, |
1165 | 6 | ArrayRef<StringRef> Paths) { |
1166 | 7 | for (const auto &Path : Paths) { |
1167 | 7 | CC1Args.push_back("-internal-isystem"); |
1168 | 7 | CC1Args.push_back(DriverArgs.MakeArgString(Path)); |
1169 | 7 | } |
1170 | 6 | } |
1171 | | |
1172 | | /*static*/ std::string ToolChain::concat(StringRef Path, const Twine &A, |
1173 | | const Twine &B, const Twine &C, |
1174 | 85.2k | const Twine &D) { |
1175 | 85.2k | SmallString<128> Result(Path); |
1176 | 85.2k | llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D); |
1177 | 85.2k | return std::string(Result); |
1178 | 85.2k | } |
1179 | | |
1180 | 163 | std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const { |
1181 | 163 | std::error_code EC; |
1182 | 163 | int MaxVersion = 0; |
1183 | 163 | std::string MaxVersionString; |
1184 | 163 | SmallString<128> Path(IncludePath); |
1185 | 163 | llvm::sys::path::append(Path, "c++"); |
1186 | 163 | for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE; |
1187 | 253 | !EC && LI != LE176 ; LI = LI.increment(EC)90 ) { |
1188 | 90 | StringRef VersionText = llvm::sys::path::filename(LI->path()); |
1189 | 90 | int Version; |
1190 | 90 | if (VersionText[0] == 'v' && |
1191 | 90 | !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)89 ) { |
1192 | 89 | if (Version > MaxVersion) { |
1193 | 89 | MaxVersion = Version; |
1194 | 89 | MaxVersionString = std::string(VersionText); |
1195 | 89 | } |
1196 | 89 | } |
1197 | 90 | } |
1198 | 163 | if (!MaxVersion) |
1199 | 77 | return ""; |
1200 | 86 | return MaxVersionString; |
1201 | 163 | } |
1202 | | |
1203 | | void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, |
1204 | 13.3k | ArgStringList &CC1Args) const { |
1205 | | // Header search paths should be handled by each of the subclasses. |
1206 | | // Historically, they have not been, and instead have been handled inside of |
1207 | | // the CC1-layer frontend. As the logic is hoisted out, this generic function |
1208 | | // will slowly stop being called. |
1209 | | // |
1210 | | // While it is being called, replicate a bit of a hack to propagate the |
1211 | | // '-stdlib=' flag down to CC1 so that it can in turn customize the C++ |
1212 | | // header search paths with it. Once all systems are overriding this |
1213 | | // function, the CC1 flag and this line can be removed. |
1214 | 13.3k | DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ); |
1215 | 13.3k | } |
1216 | | |
1217 | | void ToolChain::AddClangCXXStdlibIsystemArgs( |
1218 | | const llvm::opt::ArgList &DriverArgs, |
1219 | 10 | llvm::opt::ArgStringList &CC1Args) const { |
1220 | 10 | DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem); |
1221 | | // This intentionally only looks at -nostdinc++, and not -nostdinc or |
1222 | | // -nostdlibinc. The purpose of -stdlib++-isystem is to support toolchain |
1223 | | // setups with non-standard search logic for the C++ headers, while still |
1224 | | // allowing users of the toolchain to bring their own C++ headers. Such a |
1225 | | // toolchain likely also has non-standard search logic for the C headers and |
1226 | | // uses -nostdinc to suppress the default logic, but -stdlib++-isystem should |
1227 | | // still work in that case and only be suppressed by an explicit -nostdinc++ |
1228 | | // in a project using the toolchain. |
1229 | 10 | if (!DriverArgs.hasArg(options::OPT_nostdincxx)) |
1230 | 8 | for (const auto &P : |
1231 | 8 | DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem)) |
1232 | 14 | addSystemInclude(DriverArgs, CC1Args, P); |
1233 | 10 | } |
1234 | | |
1235 | 4.11k | bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const { |
1236 | 4.11k | return getDriver().CCCIsCXX() && |
1237 | 4.11k | !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, |
1238 | 2.71k | options::OPT_nostdlibxx); |
1239 | 4.11k | } |
1240 | | |
1241 | | void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, |
1242 | 85 | ArgStringList &CmdArgs) const { |
1243 | 85 | assert(!Args.hasArg(options::OPT_nostdlibxx) && |
1244 | 85 | "should not have called this"); |
1245 | 85 | CXXStdlibType Type = GetCXXStdlibType(Args); |
1246 | | |
1247 | 85 | switch (Type) { |
1248 | 33 | case ToolChain::CST_Libcxx: |
1249 | 33 | CmdArgs.push_back("-lc++"); |
1250 | 33 | if (Args.hasArg(options::OPT_fexperimental_library)) |
1251 | 0 | CmdArgs.push_back("-lc++experimental"); |
1252 | 33 | break; |
1253 | | |
1254 | 52 | case ToolChain::CST_Libstdcxx: |
1255 | 52 | CmdArgs.push_back("-lstdc++"); |
1256 | 52 | break; |
1257 | 85 | } |
1258 | 85 | } |
1259 | | |
1260 | | void ToolChain::AddFilePathLibArgs(const ArgList &Args, |
1261 | 2.62k | ArgStringList &CmdArgs) const { |
1262 | 2.62k | for (const auto &LibPath : getFilePaths()) |
1263 | 3.97k | if(LibPath.length() > 0) |
1264 | 3.92k | CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); |
1265 | 2.62k | } |
1266 | | |
1267 | | void ToolChain::AddCCKextLibArgs(const ArgList &Args, |
1268 | 0 | ArgStringList &CmdArgs) const { |
1269 | 0 | CmdArgs.push_back("-lcc_kext"); |
1270 | 0 | } |
1271 | | |
1272 | | bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args, |
1273 | 7.27k | std::string &Path) const { |
1274 | | // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed |
1275 | | // (to keep the linker options consistent with gcc and clang itself). |
1276 | 7.27k | if (!isOptimizationLevelFast(Args)) { |
1277 | | // Check if -ffast-math or -funsafe-math. |
1278 | 7.25k | Arg *A = |
1279 | 7.25k | Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math, |
1280 | 7.25k | options::OPT_funsafe_math_optimizations, |
1281 | 7.25k | options::OPT_fno_unsafe_math_optimizations); |
1282 | | |
1283 | 7.25k | if (!A || A->getOption().getID() == options::OPT_fno_fast_math33 || |
1284 | 7.25k | A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations26 ) |
1285 | 7.22k | return false; |
1286 | 7.25k | } |
1287 | | // If crtfastmath.o exists add it to the arguments. |
1288 | 50 | Path = GetFilePath("crtfastmath.o"); |
1289 | 50 | return (Path != "crtfastmath.o"); // Not found. |
1290 | 7.27k | } |
1291 | | |
1292 | | bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args, |
1293 | 1.67k | ArgStringList &CmdArgs) const { |
1294 | 1.67k | std::string Path; |
1295 | 1.67k | if (isFastMathRuntimeAvailable(Args, Path)) { |
1296 | 13 | CmdArgs.push_back(Args.MakeArgString(Path)); |
1297 | 13 | return true; |
1298 | 13 | } |
1299 | | |
1300 | 1.66k | return false; |
1301 | 1.67k | } |
1302 | | |
1303 | | Expected<SmallVector<std::string>> |
1304 | 0 | ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const { |
1305 | 0 | return SmallVector<std::string>(); |
1306 | 0 | } |
1307 | | |
1308 | 58.1k | SanitizerMask ToolChain::getSupportedSanitizers() const { |
1309 | | // Return sanitizers which don't require runtime support and are not |
1310 | | // platform dependent. |
1311 | | |
1312 | 58.1k | SanitizerMask Res = |
1313 | 58.1k | (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | |
1314 | 58.1k | (SanitizerKind::CFI & ~SanitizerKind::CFIICall) | |
1315 | 58.1k | SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero | |
1316 | 58.1k | SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow | |
1317 | 58.1k | SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion | |
1318 | 58.1k | SanitizerKind::Nullability | SanitizerKind::LocalBounds; |
1319 | 58.1k | if (getTriple().getArch() == llvm::Triple::x86 || |
1320 | 58.1k | getTriple().getArch() == llvm::Triple::x86_6446.1k || |
1321 | 58.1k | getTriple().getArch() == llvm::Triple::arm9.56k || getTriple().isWasm()7.01k || |
1322 | 58.1k | getTriple().isAArch64()6.88k || getTriple().isRISCV()4.46k ) |
1323 | 54.4k | Res |= SanitizerKind::CFIICall; |
1324 | 58.1k | if (getTriple().getArch() == llvm::Triple::x86_64 || |
1325 | 58.1k | getTriple().isAArch64(64)21.5k || getTriple().isRISCV()19.1k ) |
1326 | 39.8k | Res |= SanitizerKind::ShadowCallStack; |
1327 | 58.1k | if (getTriple().isAArch64(64)) |
1328 | 2.40k | Res |= SanitizerKind::MemTag; |
1329 | 58.1k | return Res; |
1330 | 58.1k | } |
1331 | | |
1332 | | void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, |
1333 | 5 | ArgStringList &CC1Args) const {} |
1334 | | |
1335 | | void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs, |
1336 | 1 | ArgStringList &CC1Args) const {} |
1337 | | |
1338 | | llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12> |
1339 | 0 | ToolChain::getDeviceLibs(const ArgList &DriverArgs) const { |
1340 | 0 | return {}; |
1341 | 0 | } |
1342 | | |
1343 | | void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs, |
1344 | 0 | ArgStringList &CC1Args) const {} |
1345 | | |
1346 | 38 | static VersionTuple separateMSVCFullVersion(unsigned Version) { |
1347 | 38 | if (Version < 100) |
1348 | 2 | return VersionTuple(Version); |
1349 | | |
1350 | 36 | if (Version < 10000) |
1351 | 34 | return VersionTuple(Version / 100, Version % 100); |
1352 | | |
1353 | 2 | unsigned Build = 0, Factor = 1; |
1354 | 12 | for (; Version > 10000; Version = Version / 10, Factor = Factor * 1010 ) |
1355 | 10 | Build = Build + (Version % 10) * Factor; |
1356 | 2 | return VersionTuple(Version / 100, Version % 100, Build); |
1357 | 36 | } |
1358 | | |
1359 | | VersionTuple |
1360 | | ToolChain::computeMSVCVersion(const Driver *D, |
1361 | 56.9k | const llvm::opt::ArgList &Args) const { |
1362 | 56.9k | const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version); |
1363 | 56.9k | const Arg *MSCompatibilityVersion = |
1364 | 56.9k | Args.getLastArg(options::OPT_fms_compatibility_version); |
1365 | | |
1366 | 56.9k | if (MSCVersion && MSCompatibilityVersion40 ) { |
1367 | 2 | if (D) |
1368 | 1 | D->Diag(diag::err_drv_argument_not_allowed_with) |
1369 | 1 | << MSCVersion->getAsString(Args) |
1370 | 1 | << MSCompatibilityVersion->getAsString(Args); |
1371 | 2 | return VersionTuple(); |
1372 | 2 | } |
1373 | | |
1374 | 56.9k | if (MSCompatibilityVersion) { |
1375 | 21 | VersionTuple MSVT; |
1376 | 21 | if (MSVT.tryParse(MSCompatibilityVersion->getValue())) { |
1377 | 0 | if (D) |
1378 | 0 | D->Diag(diag::err_drv_invalid_value) |
1379 | 0 | << MSCompatibilityVersion->getAsString(Args) |
1380 | 0 | << MSCompatibilityVersion->getValue(); |
1381 | 21 | } else { |
1382 | 21 | return MSVT; |
1383 | 21 | } |
1384 | 21 | } |
1385 | | |
1386 | 56.9k | if (MSCVersion) { |
1387 | 38 | unsigned Version = 0; |
1388 | 38 | if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) { |
1389 | 0 | if (D) |
1390 | 0 | D->Diag(diag::err_drv_invalid_value) |
1391 | 0 | << MSCVersion->getAsString(Args) << MSCVersion->getValue(); |
1392 | 38 | } else { |
1393 | 38 | return separateMSVCFullVersion(Version); |
1394 | 38 | } |
1395 | 38 | } |
1396 | | |
1397 | 56.9k | return VersionTuple(); |
1398 | 56.9k | } |
1399 | | |
1400 | | llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs( |
1401 | | const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost, |
1402 | 25 | SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const { |
1403 | 25 | DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); |
1404 | 25 | const OptTable &Opts = getDriver().getOpts(); |
1405 | 25 | bool Modified = false; |
1406 | | |
1407 | | // Handle -Xopenmp-target flags |
1408 | 240 | for (auto *A : Args) { |
1409 | | // Exclude flags which may only apply to the host toolchain. |
1410 | | // Do not exclude flags when the host triple (AuxTriple) |
1411 | | // matches the current toolchain triple. If it is not present |
1412 | | // at all, target and host share a toolchain. |
1413 | 240 | if (A->getOption().matches(options::OPT_m_Group)) { |
1414 | | // Pass code object version to device toolchain |
1415 | | // to correctly set metadata in intermediate files. |
1416 | 25 | if (SameTripleAsHost || |
1417 | 25 | A->getOption().matches(options::OPT_mcode_object_version_EQ)13 ) |
1418 | 12 | DAL->append(A); |
1419 | 13 | else |
1420 | 13 | Modified = true; |
1421 | 25 | continue; |
1422 | 25 | } |
1423 | | |
1424 | 215 | unsigned Index; |
1425 | 215 | unsigned Prev; |
1426 | 215 | bool XOpenMPTargetNoTriple = |
1427 | 215 | A->getOption().matches(options::OPT_Xopenmp_target); |
1428 | | |
1429 | 215 | if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) { |
1430 | 8 | llvm::Triple TT(getOpenMPTriple(A->getValue(0))); |
1431 | | |
1432 | | // Passing device args: -Xopenmp-target=<triple> -opt=val. |
1433 | 8 | if (TT.getTriple() == getTripleString()) |
1434 | 4 | Index = Args.getBaseArgs().MakeIndex(A->getValue(1)); |
1435 | 4 | else |
1436 | 4 | continue; |
1437 | 207 | } else if (XOpenMPTargetNoTriple) { |
1438 | | // Passing device args: -Xopenmp-target -opt=val. |
1439 | 0 | Index = Args.getBaseArgs().MakeIndex(A->getValue(0)); |
1440 | 207 | } else { |
1441 | 207 | DAL->append(A); |
1442 | 207 | continue; |
1443 | 207 | } |
1444 | | |
1445 | | // Parse the argument to -Xopenmp-target. |
1446 | 4 | Prev = Index; |
1447 | 4 | std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index)); |
1448 | 4 | if (!XOpenMPTargetArg || Index > Prev + 1) { |
1449 | 0 | getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args) |
1450 | 0 | << A->getAsString(Args); |
1451 | 0 | continue; |
1452 | 0 | } |
1453 | 4 | if (XOpenMPTargetNoTriple && XOpenMPTargetArg0 && |
1454 | 4 | Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 10 ) { |
1455 | 0 | getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple); |
1456 | 0 | continue; |
1457 | 0 | } |
1458 | 4 | XOpenMPTargetArg->setBaseArg(A); |
1459 | 4 | A = XOpenMPTargetArg.release(); |
1460 | 4 | AllocatedArgs.push_back(A); |
1461 | 4 | DAL->append(A); |
1462 | 4 | Modified = true; |
1463 | 4 | } |
1464 | | |
1465 | 25 | if (Modified) |
1466 | 13 | return DAL; |
1467 | | |
1468 | 12 | delete DAL; |
1469 | 12 | return nullptr; |
1470 | 25 | } |
1471 | | |
1472 | | // TODO: Currently argument values separated by space e.g. |
1473 | | // -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be |
1474 | | // fixed. |
1475 | | void ToolChain::TranslateXarchArgs( |
1476 | | const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A, |
1477 | | llvm::opt::DerivedArgList *DAL, |
1478 | 29 | SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const { |
1479 | 29 | const OptTable &Opts = getDriver().getOpts(); |
1480 | 29 | unsigned ValuePos = 1; |
1481 | 29 | if (A->getOption().matches(options::OPT_Xarch_device) || |
1482 | 29 | A->getOption().matches(options::OPT_Xarch_host)20 ) |
1483 | 12 | ValuePos = 0; |
1484 | | |
1485 | 29 | unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos)); |
1486 | 29 | unsigned Prev = Index; |
1487 | 29 | std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index)); |
1488 | | |
1489 | | // If the argument parsing failed or more than one argument was |
1490 | | // consumed, the -Xarch_ argument's parameter tried to consume |
1491 | | // extra arguments. Emit an error and ignore. |
1492 | | // |
1493 | | // We also want to disallow any options which would alter the |
1494 | | // driver behavior; that isn't going to work in our model. We |
1495 | | // use options::NoXarchOption to control this. |
1496 | 29 | if (!XarchArg || Index > Prev + 126 ) { |
1497 | 3 | getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args) |
1498 | 3 | << A->getAsString(Args); |
1499 | 3 | return; |
1500 | 26 | } else if (XarchArg->getOption().hasFlag(options::NoXarchOption)) { |
1501 | 1 | auto &Diags = getDriver().getDiags(); |
1502 | 1 | unsigned DiagID = |
1503 | 1 | Diags.getCustomDiagID(DiagnosticsEngine::Error, |
1504 | 1 | "invalid Xarch argument: '%0', not all driver " |
1505 | 1 | "options can be forwared via Xarch argument"); |
1506 | 1 | Diags.Report(DiagID) << A->getAsString(Args); |
1507 | 1 | return; |
1508 | 1 | } |
1509 | 25 | XarchArg->setBaseArg(A); |
1510 | 25 | A = XarchArg.release(); |
1511 | 25 | if (!AllocatedArgs) |
1512 | 12 | DAL->AddSynthesizedArg(A); |
1513 | 13 | else |
1514 | 13 | AllocatedArgs->push_back(A); |
1515 | 25 | } |
1516 | | |
1517 | | llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs( |
1518 | | const llvm::opt::DerivedArgList &Args, StringRef BoundArch, |
1519 | | Action::OffloadKind OFK, |
1520 | 51.5k | SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const { |
1521 | 51.5k | DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); |
1522 | 51.5k | bool Modified = false; |
1523 | | |
1524 | 51.5k | bool IsDevice = OFK != Action::OFK_None && OFK != Action::OFK_Host777 ; |
1525 | 796k | for (Arg *A : Args) { |
1526 | 796k | bool NeedTrans = false; |
1527 | 796k | bool Skip = false; |
1528 | 796k | if (A->getOption().matches(options::OPT_Xarch_device)) { |
1529 | 18 | NeedTrans = IsDevice; |
1530 | 18 | Skip = !IsDevice; |
1531 | 796k | } else if (A->getOption().matches(options::OPT_Xarch_host)) { |
1532 | 6 | NeedTrans = !IsDevice; |
1533 | 6 | Skip = IsDevice; |
1534 | 796k | } else if (A->getOption().matches(options::OPT_Xarch__) && IsDevice28 ) { |
1535 | | // Do not translate -Xarch_ options for non CUDA/HIP toolchain since |
1536 | | // they may need special translation. |
1537 | | // Skip this argument unless the architecture matches BoundArch |
1538 | 1 | if (BoundArch.empty() || A->getValue(0) != BoundArch) |
1539 | 0 | Skip = true; |
1540 | 1 | else |
1541 | 1 | NeedTrans = true; |
1542 | 1 | } |
1543 | 796k | if (NeedTrans || Skip796k ) |
1544 | 25 | Modified = true; |
1545 | 796k | if (NeedTrans) |
1546 | 13 | TranslateXarchArgs(Args, A, DAL, AllocatedArgs); |
1547 | 796k | if (!Skip) |
1548 | 796k | DAL->append(A); |
1549 | 796k | } |
1550 | | |
1551 | 51.5k | if (Modified) |
1552 | 13 | return DAL; |
1553 | | |
1554 | 51.5k | delete DAL; |
1555 | 51.5k | return nullptr; |
1556 | 51.5k | } |