/src/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- MinGW.cpp - MinGWToolChain Implementation ------------------------===// |
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 "MinGW.h" |
10 | | #include "CommonArgs.h" |
11 | | #include "clang/Config/config.h" |
12 | | #include "clang/Driver/Compilation.h" |
13 | | #include "clang/Driver/Driver.h" |
14 | | #include "clang/Driver/DriverDiagnostic.h" |
15 | | #include "clang/Driver/InputInfo.h" |
16 | | #include "clang/Driver/Options.h" |
17 | | #include "clang/Driver/SanitizerArgs.h" |
18 | | #include "llvm/Option/ArgList.h" |
19 | | #include "llvm/Support/FileSystem.h" |
20 | | #include "llvm/Support/Path.h" |
21 | | #include "llvm/Support/VirtualFileSystem.h" |
22 | | #include <system_error> |
23 | | |
24 | | using namespace clang::diag; |
25 | | using namespace clang::driver; |
26 | | using namespace clang; |
27 | | using namespace llvm::opt; |
28 | | |
29 | | /// MinGW Tools |
30 | | void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA, |
31 | | const InputInfo &Output, |
32 | | const InputInfoList &Inputs, |
33 | | const ArgList &Args, |
34 | 0 | const char *LinkingOutput) const { |
35 | 0 | claimNoWarnArgs(Args); |
36 | 0 | ArgStringList CmdArgs; |
37 | |
|
38 | 0 | if (getToolChain().getArch() == llvm::Triple::x86) { |
39 | 0 | CmdArgs.push_back("--32"); |
40 | 0 | } else if (getToolChain().getArch() == llvm::Triple::x86_64) { |
41 | 0 | CmdArgs.push_back("--64"); |
42 | 0 | } |
43 | |
|
44 | 0 | Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); |
45 | |
|
46 | 0 | CmdArgs.push_back("-o"); |
47 | 0 | CmdArgs.push_back(Output.getFilename()); |
48 | |
|
49 | 0 | for (const auto &II : Inputs) |
50 | 0 | CmdArgs.push_back(II.getFilename()); |
51 | |
|
52 | 0 | const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); |
53 | 0 | C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), |
54 | 0 | Exec, CmdArgs, Inputs, Output)); |
55 | |
|
56 | 0 | if (Args.hasArg(options::OPT_gsplit_dwarf)) |
57 | 0 | SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, |
58 | 0 | SplitDebugName(JA, Args, Inputs[0], Output)); |
59 | 0 | } |
60 | | |
61 | | void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, |
62 | 0 | ArgStringList &CmdArgs) const { |
63 | 0 | if (Args.hasArg(options::OPT_mthreads)) |
64 | 0 | CmdArgs.push_back("-lmingwthrd"); |
65 | 0 | CmdArgs.push_back("-lmingw32"); |
66 | | |
67 | | // Make use of compiler-rt if --rtlib option is used |
68 | 0 | ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args); |
69 | 0 | if (RLT == ToolChain::RLT_Libgcc) { |
70 | 0 | bool Static = Args.hasArg(options::OPT_static_libgcc) || |
71 | 0 | Args.hasArg(options::OPT_static); |
72 | 0 | bool Shared = Args.hasArg(options::OPT_shared); |
73 | 0 | bool CXX = getToolChain().getDriver().CCCIsCXX(); |
74 | |
|
75 | 0 | if (Static || (!CXX && !Shared)) { |
76 | 0 | CmdArgs.push_back("-lgcc"); |
77 | 0 | CmdArgs.push_back("-lgcc_eh"); |
78 | 0 | } else { |
79 | 0 | CmdArgs.push_back("-lgcc_s"); |
80 | 0 | CmdArgs.push_back("-lgcc"); |
81 | 0 | } |
82 | 0 | } else { |
83 | 0 | AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args); |
84 | 0 | } |
85 | |
|
86 | 0 | CmdArgs.push_back("-lmoldname"); |
87 | 0 | CmdArgs.push_back("-lmingwex"); |
88 | 0 | for (auto Lib : Args.getAllArgValues(options::OPT_l)) |
89 | 0 | if (StringRef(Lib).starts_with("msvcr") || |
90 | 0 | StringRef(Lib).starts_with("ucrt") || |
91 | 0 | StringRef(Lib).starts_with("crtdll")) |
92 | 0 | return; |
93 | 0 | CmdArgs.push_back("-lmsvcrt"); |
94 | 0 | } |
95 | | |
96 | | void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
97 | | const InputInfo &Output, |
98 | | const InputInfoList &Inputs, |
99 | | const ArgList &Args, |
100 | 0 | const char *LinkingOutput) const { |
101 | 0 | const ToolChain &TC = getToolChain(); |
102 | 0 | const Driver &D = TC.getDriver(); |
103 | 0 | const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args); |
104 | |
|
105 | 0 | ArgStringList CmdArgs; |
106 | | |
107 | | // Silence warning for "clang -g foo.o -o foo" |
108 | 0 | Args.ClaimAllArgs(options::OPT_g_Group); |
109 | | // and "clang -emit-llvm foo.o -o foo" |
110 | 0 | Args.ClaimAllArgs(options::OPT_emit_llvm); |
111 | | // and for "clang -w foo.o -o foo". Other warning options are already |
112 | | // handled somewhere else. |
113 | 0 | Args.ClaimAllArgs(options::OPT_w); |
114 | |
|
115 | 0 | if (!D.SysRoot.empty()) |
116 | 0 | CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); |
117 | |
|
118 | 0 | if (Args.hasArg(options::OPT_s)) |
119 | 0 | CmdArgs.push_back("-s"); |
120 | |
|
121 | 0 | CmdArgs.push_back("-m"); |
122 | 0 | switch (TC.getArch()) { |
123 | 0 | case llvm::Triple::x86: |
124 | 0 | CmdArgs.push_back("i386pe"); |
125 | 0 | break; |
126 | 0 | case llvm::Triple::x86_64: |
127 | 0 | CmdArgs.push_back("i386pep"); |
128 | 0 | break; |
129 | 0 | case llvm::Triple::arm: |
130 | 0 | case llvm::Triple::thumb: |
131 | | // FIXME: this is incorrect for WinCE |
132 | 0 | CmdArgs.push_back("thumb2pe"); |
133 | 0 | break; |
134 | 0 | case llvm::Triple::aarch64: |
135 | 0 | CmdArgs.push_back("arm64pe"); |
136 | 0 | break; |
137 | 0 | default: |
138 | 0 | D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str(); |
139 | 0 | } |
140 | | |
141 | 0 | Arg *SubsysArg = |
142 | 0 | Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole); |
143 | 0 | if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) { |
144 | 0 | CmdArgs.push_back("--subsystem"); |
145 | 0 | CmdArgs.push_back("windows"); |
146 | 0 | } else if (SubsysArg && |
147 | 0 | SubsysArg->getOption().matches(options::OPT_mconsole)) { |
148 | 0 | CmdArgs.push_back("--subsystem"); |
149 | 0 | CmdArgs.push_back("console"); |
150 | 0 | } |
151 | |
|
152 | 0 | if (Args.hasArg(options::OPT_mdll)) |
153 | 0 | CmdArgs.push_back("--dll"); |
154 | 0 | else if (Args.hasArg(options::OPT_shared)) |
155 | 0 | CmdArgs.push_back("--shared"); |
156 | 0 | if (Args.hasArg(options::OPT_static)) |
157 | 0 | CmdArgs.push_back("-Bstatic"); |
158 | 0 | else |
159 | 0 | CmdArgs.push_back("-Bdynamic"); |
160 | 0 | if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) { |
161 | 0 | CmdArgs.push_back("-e"); |
162 | 0 | if (TC.getArch() == llvm::Triple::x86) |
163 | 0 | CmdArgs.push_back("_DllMainCRTStartup@12"); |
164 | 0 | else |
165 | 0 | CmdArgs.push_back("DllMainCRTStartup"); |
166 | 0 | CmdArgs.push_back("--enable-auto-image-base"); |
167 | 0 | } |
168 | |
|
169 | 0 | if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) |
170 | 0 | CmdArgs.push_back("--no-demangle"); |
171 | |
|
172 | 0 | if (!Args.hasFlag(options::OPT_fauto_import, options::OPT_fno_auto_import, |
173 | 0 | true)) |
174 | 0 | CmdArgs.push_back("--disable-auto-import"); |
175 | |
|
176 | 0 | if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) { |
177 | 0 | StringRef GuardArgs = A->getValue(); |
178 | 0 | if (GuardArgs == "none") |
179 | 0 | CmdArgs.push_back("--no-guard-cf"); |
180 | 0 | else if (GuardArgs == "cf" || GuardArgs == "cf-nochecks") |
181 | 0 | CmdArgs.push_back("--guard-cf"); |
182 | 0 | else |
183 | 0 | D.Diag(diag::err_drv_unsupported_option_argument) |
184 | 0 | << A->getSpelling() << GuardArgs; |
185 | 0 | } |
186 | |
|
187 | 0 | CmdArgs.push_back("-o"); |
188 | 0 | const char *OutputFile = Output.getFilename(); |
189 | | // GCC implicitly adds an .exe extension if it is given an output file name |
190 | | // that lacks an extension. |
191 | | // GCC used to do this only when the compiler itself runs on windows, but |
192 | | // since GCC 8 it does the same when cross compiling as well. |
193 | 0 | if (!llvm::sys::path::has_extension(OutputFile)) { |
194 | 0 | CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe")); |
195 | 0 | OutputFile = CmdArgs.back(); |
196 | 0 | } else |
197 | 0 | CmdArgs.push_back(OutputFile); |
198 | | |
199 | | // FIXME: add -N, -n flags |
200 | 0 | Args.AddLastArg(CmdArgs, options::OPT_r); |
201 | 0 | Args.AddLastArg(CmdArgs, options::OPT_s); |
202 | 0 | Args.AddLastArg(CmdArgs, options::OPT_t); |
203 | 0 | Args.AddAllArgs(CmdArgs, options::OPT_u_Group); |
204 | | |
205 | | // Add asan_dynamic as the first import lib before other libs. This allows |
206 | | // asan to be initialized as early as possible to increase its instrumentation |
207 | | // coverage to include other user DLLs which has not been built with asan. |
208 | 0 | if (Sanitize.needsAsanRt() && !Args.hasArg(options::OPT_nostdlib) && |
209 | 0 | !Args.hasArg(options::OPT_nodefaultlibs)) { |
210 | | // MinGW always links against a shared MSVCRT. |
211 | 0 | CmdArgs.push_back( |
212 | 0 | TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared)); |
213 | 0 | } |
214 | |
|
215 | 0 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { |
216 | 0 | if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { |
217 | 0 | CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o"))); |
218 | 0 | } else { |
219 | 0 | if (Args.hasArg(options::OPT_municode)) |
220 | 0 | CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o"))); |
221 | 0 | else |
222 | 0 | CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o"))); |
223 | 0 | } |
224 | 0 | if (Args.hasArg(options::OPT_pg)) |
225 | 0 | CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o"))); |
226 | 0 | CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); |
227 | 0 | } |
228 | |
|
229 | 0 | Args.AddAllArgs(CmdArgs, options::OPT_L); |
230 | 0 | TC.AddFilePathLibArgs(Args, CmdArgs); |
231 | | |
232 | | // Add the compiler-rt library directories if they exist to help |
233 | | // the linker find the various sanitizer, builtin, and profiling runtimes. |
234 | 0 | for (const auto &LibPath : TC.getLibraryPaths()) { |
235 | 0 | if (TC.getVFS().exists(LibPath)) |
236 | 0 | CmdArgs.push_back(Args.MakeArgString("-L" + LibPath)); |
237 | 0 | } |
238 | 0 | auto CRTPath = TC.getCompilerRTPath(); |
239 | 0 | if (TC.getVFS().exists(CRTPath)) |
240 | 0 | CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath)); |
241 | |
|
242 | 0 | AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); |
243 | |
|
244 | 0 | if (D.isUsingLTO()) { |
245 | 0 | assert(!Inputs.empty() && "Must have at least one input."); |
246 | 0 | addLTOOptions(TC, Args, CmdArgs, Output, Inputs[0], |
247 | 0 | D.getLTOMode() == LTOK_Thin); |
248 | 0 | } |
249 | | |
250 | 0 | if (C.getDriver().IsFlangMode()) { |
251 | 0 | addFortranRuntimeLibraryPath(TC, Args, CmdArgs); |
252 | 0 | addFortranRuntimeLibs(TC, Args, CmdArgs); |
253 | 0 | } |
254 | | |
255 | | // TODO: Add profile stuff here |
256 | |
|
257 | 0 | if (TC.ShouldLinkCXXStdlib(Args)) { |
258 | 0 | bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && |
259 | 0 | !Args.hasArg(options::OPT_static); |
260 | 0 | if (OnlyLibstdcxxStatic) |
261 | 0 | CmdArgs.push_back("-Bstatic"); |
262 | 0 | TC.AddCXXStdlibLibArgs(Args, CmdArgs); |
263 | 0 | if (OnlyLibstdcxxStatic) |
264 | 0 | CmdArgs.push_back("-Bdynamic"); |
265 | 0 | } |
266 | |
|
267 | 0 | bool HasWindowsApp = false; |
268 | 0 | for (auto Lib : Args.getAllArgValues(options::OPT_l)) { |
269 | 0 | if (Lib == "windowsapp") { |
270 | 0 | HasWindowsApp = true; |
271 | 0 | break; |
272 | 0 | } |
273 | 0 | } |
274 | |
|
275 | 0 | if (!Args.hasArg(options::OPT_nostdlib)) { |
276 | 0 | if (!Args.hasArg(options::OPT_nodefaultlibs)) { |
277 | 0 | if (Args.hasArg(options::OPT_static)) |
278 | 0 | CmdArgs.push_back("--start-group"); |
279 | |
|
280 | 0 | if (Args.hasArg(options::OPT_fstack_protector) || |
281 | 0 | Args.hasArg(options::OPT_fstack_protector_strong) || |
282 | 0 | Args.hasArg(options::OPT_fstack_protector_all)) { |
283 | 0 | CmdArgs.push_back("-lssp_nonshared"); |
284 | 0 | CmdArgs.push_back("-lssp"); |
285 | 0 | } |
286 | |
|
287 | 0 | if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, |
288 | 0 | options::OPT_fno_openmp, false)) { |
289 | 0 | switch (TC.getDriver().getOpenMPRuntime(Args)) { |
290 | 0 | case Driver::OMPRT_OMP: |
291 | 0 | CmdArgs.push_back("-lomp"); |
292 | 0 | break; |
293 | 0 | case Driver::OMPRT_IOMP5: |
294 | 0 | CmdArgs.push_back("-liomp5md"); |
295 | 0 | break; |
296 | 0 | case Driver::OMPRT_GOMP: |
297 | 0 | CmdArgs.push_back("-lgomp"); |
298 | 0 | break; |
299 | 0 | case Driver::OMPRT_Unknown: |
300 | | // Already diagnosed. |
301 | 0 | break; |
302 | 0 | } |
303 | 0 | } |
304 | | |
305 | 0 | AddLibGCC(Args, CmdArgs); |
306 | |
|
307 | 0 | if (Args.hasArg(options::OPT_pg)) |
308 | 0 | CmdArgs.push_back("-lgmon"); |
309 | |
|
310 | 0 | if (Args.hasArg(options::OPT_pthread)) |
311 | 0 | CmdArgs.push_back("-lpthread"); |
312 | |
|
313 | 0 | if (Sanitize.needsAsanRt()) { |
314 | | // MinGW always links against a shared MSVCRT. |
315 | 0 | CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic", |
316 | 0 | ToolChain::FT_Shared)); |
317 | 0 | CmdArgs.push_back( |
318 | 0 | TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); |
319 | 0 | CmdArgs.push_back("--require-defined"); |
320 | 0 | CmdArgs.push_back(TC.getArch() == llvm::Triple::x86 |
321 | 0 | ? "___asan_seh_interceptor" |
322 | 0 | : "__asan_seh_interceptor"); |
323 | | // Make sure the linker consider all object files from the dynamic |
324 | | // runtime thunk. |
325 | 0 | CmdArgs.push_back("--whole-archive"); |
326 | 0 | CmdArgs.push_back( |
327 | 0 | TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); |
328 | 0 | CmdArgs.push_back("--no-whole-archive"); |
329 | 0 | } |
330 | |
|
331 | 0 | TC.addProfileRTLibs(Args, CmdArgs); |
332 | |
|
333 | 0 | if (!HasWindowsApp) { |
334 | | // Add system libraries. If linking to libwindowsapp.a, that import |
335 | | // library replaces all these and we shouldn't accidentally try to |
336 | | // link to the normal desktop mode dlls. |
337 | 0 | if (Args.hasArg(options::OPT_mwindows)) { |
338 | 0 | CmdArgs.push_back("-lgdi32"); |
339 | 0 | CmdArgs.push_back("-lcomdlg32"); |
340 | 0 | } |
341 | 0 | CmdArgs.push_back("-ladvapi32"); |
342 | 0 | CmdArgs.push_back("-lshell32"); |
343 | 0 | CmdArgs.push_back("-luser32"); |
344 | 0 | CmdArgs.push_back("-lkernel32"); |
345 | 0 | } |
346 | |
|
347 | 0 | if (Args.hasArg(options::OPT_static)) { |
348 | 0 | CmdArgs.push_back("--end-group"); |
349 | 0 | } else { |
350 | 0 | AddLibGCC(Args, CmdArgs); |
351 | 0 | if (!HasWindowsApp) |
352 | 0 | CmdArgs.push_back("-lkernel32"); |
353 | 0 | } |
354 | 0 | } |
355 | | |
356 | 0 | if (!Args.hasArg(options::OPT_nostartfiles)) { |
357 | | // Add crtfastmath.o if available and fast math is enabled. |
358 | 0 | TC.addFastMathRuntimeIfAvailable(Args, CmdArgs); |
359 | |
|
360 | 0 | CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); |
361 | 0 | } |
362 | 0 | } |
363 | 0 | const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); |
364 | 0 | C.addCommand(std::make_unique<Command>(JA, *this, |
365 | 0 | ResponseFileSupport::AtFileUTF8(), |
366 | 0 | Exec, CmdArgs, Inputs, Output)); |
367 | 0 | } |
368 | | |
369 | 0 | static bool isCrossCompiling(const llvm::Triple &T, bool RequireArchMatch) { |
370 | 0 | llvm::Triple HostTriple(llvm::Triple::normalize(LLVM_HOST_TRIPLE)); |
371 | 0 | if (HostTriple.getOS() != llvm::Triple::Win32) |
372 | 0 | return true; |
373 | 0 | if (RequireArchMatch && HostTriple.getArch() != T.getArch()) |
374 | 0 | return true; |
375 | 0 | return false; |
376 | 0 | } |
377 | | |
378 | | // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. |
379 | | static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, |
380 | | std::string &Ver, |
381 | 0 | toolchains::Generic_GCC::GCCVersion &Version) { |
382 | 0 | Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); |
383 | 0 | std::error_code EC; |
384 | 0 | for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE; |
385 | 0 | LI = LI.increment(EC)) { |
386 | 0 | StringRef VersionText = llvm::sys::path::filename(LI->path()); |
387 | 0 | auto CandidateVersion = |
388 | 0 | toolchains::Generic_GCC::GCCVersion::Parse(VersionText); |
389 | 0 | if (CandidateVersion.Major == -1) |
390 | 0 | continue; |
391 | 0 | if (CandidateVersion <= Version) |
392 | 0 | continue; |
393 | 0 | Version = CandidateVersion; |
394 | 0 | Ver = std::string(VersionText); |
395 | 0 | GccLibDir = LI->path(); |
396 | 0 | } |
397 | 0 | return Ver.size(); |
398 | 0 | } |
399 | | |
400 | 0 | static llvm::Triple getLiteralTriple(const Driver &D, const llvm::Triple &T) { |
401 | 0 | llvm::Triple LiteralTriple(D.getTargetTriple()); |
402 | | // The arch portion of the triple may be overridden by -m32/-m64. |
403 | 0 | LiteralTriple.setArchName(T.getArchName()); |
404 | 0 | return LiteralTriple; |
405 | 0 | } |
406 | | |
407 | 0 | void toolchains::MinGW::findGccLibDir(const llvm::Triple &LiteralTriple) { |
408 | 0 | llvm::SmallVector<llvm::SmallString<32>, 5> SubdirNames; |
409 | 0 | SubdirNames.emplace_back(LiteralTriple.str()); |
410 | 0 | SubdirNames.emplace_back(getTriple().str()); |
411 | 0 | SubdirNames.emplace_back(getTriple().getArchName()); |
412 | 0 | SubdirNames.back() += "-w64-mingw32"; |
413 | 0 | SubdirNames.emplace_back(getTriple().getArchName()); |
414 | 0 | SubdirNames.back() += "-w64-mingw32ucrt"; |
415 | 0 | SubdirNames.emplace_back("mingw32"); |
416 | 0 | if (SubdirName.empty()) { |
417 | 0 | SubdirName = getTriple().getArchName(); |
418 | 0 | SubdirName += "-w64-mingw32"; |
419 | 0 | } |
420 | | // lib: Arch Linux, Ubuntu, Windows |
421 | | // lib64: openSUSE Linux |
422 | 0 | for (StringRef CandidateLib : {"lib", "lib64"}) { |
423 | 0 | for (StringRef CandidateSysroot : SubdirNames) { |
424 | 0 | llvm::SmallString<1024> LibDir(Base); |
425 | 0 | llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot); |
426 | 0 | if (findGccVersion(LibDir, GccLibDir, Ver, GccVer)) { |
427 | 0 | SubdirName = std::string(CandidateSysroot); |
428 | 0 | return; |
429 | 0 | } |
430 | 0 | } |
431 | 0 | } |
432 | 0 | } |
433 | | |
434 | | static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &LiteralTriple, |
435 | 0 | const llvm::Triple &T) { |
436 | 0 | llvm::SmallVector<llvm::SmallString<32>, 5> Gccs; |
437 | 0 | Gccs.emplace_back(LiteralTriple.str()); |
438 | 0 | Gccs.back() += "-gcc"; |
439 | 0 | Gccs.emplace_back(T.str()); |
440 | 0 | Gccs.back() += "-gcc"; |
441 | 0 | Gccs.emplace_back(T.getArchName()); |
442 | 0 | Gccs.back() += "-w64-mingw32-gcc"; |
443 | 0 | Gccs.emplace_back(T.getArchName()); |
444 | 0 | Gccs.back() += "-w64-mingw32ucrt-gcc"; |
445 | 0 | Gccs.emplace_back("mingw32-gcc"); |
446 | | // Please do not add "gcc" here |
447 | 0 | for (StringRef CandidateGcc : Gccs) |
448 | 0 | if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc)) |
449 | 0 | return GPPName; |
450 | 0 | return make_error_code(std::errc::no_such_file_or_directory); |
451 | 0 | } |
452 | | |
453 | | static llvm::ErrorOr<std::string> |
454 | | findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple, |
455 | 0 | const llvm::Triple &T, std::string &SubdirName) { |
456 | 0 | llvm::SmallVector<llvm::SmallString<32>, 4> Subdirs; |
457 | 0 | Subdirs.emplace_back(LiteralTriple.str()); |
458 | 0 | Subdirs.emplace_back(T.str()); |
459 | 0 | Subdirs.emplace_back(T.getArchName()); |
460 | 0 | Subdirs.back() += "-w64-mingw32"; |
461 | 0 | Subdirs.emplace_back(T.getArchName()); |
462 | 0 | Subdirs.back() += "-w64-mingw32ucrt"; |
463 | 0 | StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir()); |
464 | 0 | StringRef Sep = llvm::sys::path::get_separator(); |
465 | 0 | for (StringRef CandidateSubdir : Subdirs) { |
466 | 0 | if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) { |
467 | 0 | SubdirName = std::string(CandidateSubdir); |
468 | 0 | return (ClangRoot + Sep + CandidateSubdir).str(); |
469 | 0 | } |
470 | 0 | } |
471 | 0 | return make_error_code(std::errc::no_such_file_or_directory); |
472 | 0 | } |
473 | | |
474 | 0 | static bool looksLikeMinGWSysroot(const std::string &Directory) { |
475 | 0 | StringRef Sep = llvm::sys::path::get_separator(); |
476 | 0 | if (!llvm::sys::fs::exists(Directory + Sep + "include" + Sep + "_mingw.h")) |
477 | 0 | return false; |
478 | 0 | if (!llvm::sys::fs::exists(Directory + Sep + "lib" + Sep + "libkernel32.a")) |
479 | 0 | return false; |
480 | 0 | return true; |
481 | 0 | } |
482 | | |
483 | | toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, |
484 | | const ArgList &Args) |
485 | | : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), |
486 | 0 | RocmInstallation(D, Triple, Args) { |
487 | 0 | getProgramPaths().push_back(getDriver().getInstalledDir()); |
488 | |
|
489 | 0 | std::string InstallBase = |
490 | 0 | std::string(llvm::sys::path::parent_path(getDriver().getInstalledDir())); |
491 | | // The sequence for detecting a sysroot here should be kept in sync with |
492 | | // the testTriple function below. |
493 | 0 | llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple()); |
494 | 0 | if (getDriver().SysRoot.size()) |
495 | 0 | Base = getDriver().SysRoot; |
496 | | // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the |
497 | | // base as it could still be a base for a gcc setup with libgcc. |
498 | 0 | else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot( |
499 | 0 | getDriver(), LiteralTriple, getTriple(), SubdirName)) |
500 | 0 | Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get())); |
501 | | // If the install base of Clang seems to have mingw sysroot files directly |
502 | | // in the toplevel include and lib directories, use this as base instead of |
503 | | // looking for a triple prefixed GCC in the path. |
504 | 0 | else if (looksLikeMinGWSysroot(InstallBase)) |
505 | 0 | Base = InstallBase; |
506 | 0 | else if (llvm::ErrorOr<std::string> GPPName = |
507 | 0 | findGcc(LiteralTriple, getTriple())) |
508 | 0 | Base = std::string(llvm::sys::path::parent_path( |
509 | 0 | llvm::sys::path::parent_path(GPPName.get()))); |
510 | 0 | else |
511 | 0 | Base = InstallBase; |
512 | |
|
513 | 0 | Base += llvm::sys::path::get_separator(); |
514 | 0 | findGccLibDir(LiteralTriple); |
515 | 0 | TripleDirName = SubdirName; |
516 | | // GccLibDir must precede Base/lib so that the |
517 | | // correct crtbegin.o ,cetend.o would be found. |
518 | 0 | getFilePaths().push_back(GccLibDir); |
519 | | |
520 | | // openSUSE/Fedora |
521 | 0 | std::string CandidateSubdir = SubdirName + "/sys-root/mingw"; |
522 | 0 | if (getDriver().getVFS().exists(Base + CandidateSubdir)) |
523 | 0 | SubdirName = CandidateSubdir; |
524 | |
|
525 | 0 | getFilePaths().push_back( |
526 | 0 | (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str()); |
527 | | |
528 | | // Gentoo |
529 | 0 | getFilePaths().push_back( |
530 | 0 | (Base + SubdirName + llvm::sys::path::get_separator() + "mingw/lib").str()); |
531 | | |
532 | | // Only include <base>/lib if we're not cross compiling (not even for |
533 | | // windows->windows to a different arch), or if the sysroot has been set |
534 | | // (where we presume the user has pointed it at an arch specific |
535 | | // subdirectory). |
536 | 0 | if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/true) || |
537 | 0 | getDriver().SysRoot.size()) |
538 | 0 | getFilePaths().push_back(Base + "lib"); |
539 | |
|
540 | 0 | NativeLLVMSupport = |
541 | 0 | Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) |
542 | 0 | .equals_insensitive("lld"); |
543 | 0 | } |
544 | | |
545 | 0 | Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const { |
546 | 0 | switch (AC) { |
547 | 0 | case Action::PreprocessJobClass: |
548 | 0 | if (!Preprocessor) |
549 | 0 | Preprocessor.reset(new tools::gcc::Preprocessor(*this)); |
550 | 0 | return Preprocessor.get(); |
551 | 0 | case Action::CompileJobClass: |
552 | 0 | if (!Compiler) |
553 | 0 | Compiler.reset(new tools::gcc::Compiler(*this)); |
554 | 0 | return Compiler.get(); |
555 | 0 | default: |
556 | 0 | return ToolChain::getTool(AC); |
557 | 0 | } |
558 | 0 | } |
559 | | |
560 | 0 | Tool *toolchains::MinGW::buildAssembler() const { |
561 | 0 | return new tools::MinGW::Assembler(*this); |
562 | 0 | } |
563 | | |
564 | 0 | Tool *toolchains::MinGW::buildLinker() const { |
565 | 0 | return new tools::MinGW::Linker(*this); |
566 | 0 | } |
567 | | |
568 | 0 | bool toolchains::MinGW::HasNativeLLVMSupport() const { |
569 | 0 | return NativeLLVMSupport; |
570 | 0 | } |
571 | | |
572 | | ToolChain::UnwindTableLevel |
573 | 0 | toolchains::MinGW::getDefaultUnwindTableLevel(const ArgList &Args) const { |
574 | 0 | Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions, |
575 | 0 | options::OPT_fseh_exceptions, |
576 | 0 | options::OPT_fdwarf_exceptions); |
577 | 0 | if (ExceptionArg && |
578 | 0 | ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) |
579 | 0 | return UnwindTableLevel::Asynchronous; |
580 | | |
581 | 0 | if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || |
582 | 0 | getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64) |
583 | 0 | return UnwindTableLevel::Asynchronous; |
584 | 0 | return UnwindTableLevel::None; |
585 | 0 | } |
586 | | |
587 | 0 | bool toolchains::MinGW::isPICDefault() const { |
588 | 0 | return getArch() == llvm::Triple::x86_64 || |
589 | 0 | getArch() == llvm::Triple::aarch64; |
590 | 0 | } |
591 | | |
592 | 0 | bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const { |
593 | 0 | return false; |
594 | 0 | } |
595 | | |
596 | 0 | bool toolchains::MinGW::isPICDefaultForced() const { return true; } |
597 | | |
598 | | llvm::ExceptionHandling |
599 | 0 | toolchains::MinGW::GetExceptionModel(const ArgList &Args) const { |
600 | 0 | if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 || |
601 | 0 | getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb) |
602 | 0 | return llvm::ExceptionHandling::WinEH; |
603 | 0 | return llvm::ExceptionHandling::DwarfCFI; |
604 | 0 | } |
605 | | |
606 | 0 | SanitizerMask toolchains::MinGW::getSupportedSanitizers() const { |
607 | 0 | SanitizerMask Res = ToolChain::getSupportedSanitizers(); |
608 | 0 | Res |= SanitizerKind::Address; |
609 | 0 | Res |= SanitizerKind::PointerCompare; |
610 | 0 | Res |= SanitizerKind::PointerSubtract; |
611 | 0 | Res |= SanitizerKind::Vptr; |
612 | 0 | return Res; |
613 | 0 | } |
614 | | |
615 | | void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, |
616 | 0 | ArgStringList &CC1Args) const { |
617 | 0 | CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); |
618 | 0 | } |
619 | | |
620 | | void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs, |
621 | 0 | ArgStringList &CC1Args) const { |
622 | 0 | RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); |
623 | 0 | } |
624 | | |
625 | 0 | void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { |
626 | 0 | CudaInstallation.print(OS); |
627 | 0 | RocmInstallation.print(OS); |
628 | 0 | } |
629 | | |
630 | | // Include directories for various hosts: |
631 | | |
632 | | // Windows, mingw.org |
633 | | // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++ |
634 | | // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32 |
635 | | // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward |
636 | | // c:\mingw\include |
637 | | // c:\mingw\mingw32\include |
638 | | |
639 | | // Windows, mingw-w64 mingw-builds |
640 | | // c:\mingw32\i686-w64-mingw32\include |
641 | | // c:\mingw32\i686-w64-mingw32\include\c++ |
642 | | // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32 |
643 | | // c:\mingw32\i686-w64-mingw32\include\c++\backward |
644 | | |
645 | | // Windows, mingw-w64 msys2 |
646 | | // c:\msys64\mingw32\include |
647 | | // c:\msys64\mingw32\i686-w64-mingw32\include |
648 | | // c:\msys64\mingw32\include\c++\4.9.2 |
649 | | // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32 |
650 | | // c:\msys64\mingw32\include\c++\4.9.2\backward |
651 | | |
652 | | // openSUSE |
653 | | // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++ |
654 | | // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32 |
655 | | // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward |
656 | | // /usr/x86_64-w64-mingw32/sys-root/mingw/include |
657 | | |
658 | | // Arch Linux |
659 | | // /usr/i686-w64-mingw32/include/c++/5.1.0 |
660 | | // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32 |
661 | | // /usr/i686-w64-mingw32/include/c++/5.1.0/backward |
662 | | // /usr/i686-w64-mingw32/include |
663 | | |
664 | | // Ubuntu |
665 | | // /usr/include/c++/4.8 |
666 | | // /usr/include/c++/4.8/x86_64-w64-mingw32 |
667 | | // /usr/include/c++/4.8/backward |
668 | | // /usr/x86_64-w64-mingw32/include |
669 | | |
670 | | // Fedora |
671 | | // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/x86_64-w64-mingw32ucrt |
672 | | // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/backward |
673 | | // /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include |
674 | | // /usr/lib/gcc/x86_64-w64-mingw32ucrt/12.2.1/include-fixed |
675 | | |
676 | | void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
677 | 0 | ArgStringList &CC1Args) const { |
678 | 0 | if (DriverArgs.hasArg(options::OPT_nostdinc)) |
679 | 0 | return; |
680 | | |
681 | 0 | if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { |
682 | 0 | SmallString<1024> P(getDriver().ResourceDir); |
683 | 0 | llvm::sys::path::append(P, "include"); |
684 | 0 | addSystemInclude(DriverArgs, CC1Args, P.str()); |
685 | 0 | } |
686 | |
|
687 | 0 | if (DriverArgs.hasArg(options::OPT_nostdlibinc)) |
688 | 0 | return; |
689 | | |
690 | 0 | addSystemInclude(DriverArgs, CC1Args, |
691 | 0 | Base + SubdirName + llvm::sys::path::get_separator() + |
692 | 0 | "include"); |
693 | | |
694 | | // Gentoo |
695 | 0 | addSystemInclude(DriverArgs, CC1Args, |
696 | 0 | Base + SubdirName + llvm::sys::path::get_separator() + "usr/include"); |
697 | | |
698 | | // Only include <base>/include if we're not cross compiling (but do allow it |
699 | | // if we're on Windows and building for Windows on another architecture), |
700 | | // or if the sysroot has been set (where we presume the user has pointed it |
701 | | // at an arch specific subdirectory). |
702 | 0 | if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/false) || |
703 | 0 | getDriver().SysRoot.size()) |
704 | 0 | addSystemInclude(DriverArgs, CC1Args, Base + "include"); |
705 | 0 | } |
706 | | |
707 | | void toolchains::MinGW::addClangTargetOptions( |
708 | | const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, |
709 | 0 | Action::OffloadKind DeviceOffloadKind) const { |
710 | 0 | if (Arg *A = DriverArgs.getLastArg(options::OPT_mguard_EQ)) { |
711 | 0 | StringRef GuardArgs = A->getValue(); |
712 | 0 | if (GuardArgs == "none") { |
713 | | // Do nothing. |
714 | 0 | } else if (GuardArgs == "cf") { |
715 | | // Emit CFG instrumentation and the table of address-taken functions. |
716 | 0 | CC1Args.push_back("-cfguard"); |
717 | 0 | } else if (GuardArgs == "cf-nochecks") { |
718 | | // Emit only the table of address-taken functions. |
719 | 0 | CC1Args.push_back("-cfguard-no-checks"); |
720 | 0 | } else { |
721 | 0 | getDriver().Diag(diag::err_drv_unsupported_option_argument) |
722 | 0 | << A->getSpelling() << GuardArgs; |
723 | 0 | } |
724 | 0 | } |
725 | |
|
726 | 0 | CC1Args.push_back("-fno-use-init-array"); |
727 | |
|
728 | 0 | for (auto Opt : {options::OPT_mthreads, options::OPT_mwindows, |
729 | 0 | options::OPT_mconsole, options::OPT_mdll}) { |
730 | 0 | if (Arg *A = DriverArgs.getLastArgNoClaim(Opt)) |
731 | 0 | A->ignoreTargetSpecific(); |
732 | 0 | } |
733 | 0 | } |
734 | | |
735 | | void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( |
736 | 0 | const ArgList &DriverArgs, ArgStringList &CC1Args) const { |
737 | 0 | if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, |
738 | 0 | options::OPT_nostdincxx)) |
739 | 0 | return; |
740 | | |
741 | 0 | StringRef Slash = llvm::sys::path::get_separator(); |
742 | |
|
743 | 0 | switch (GetCXXStdlibType(DriverArgs)) { |
744 | 0 | case ToolChain::CST_Libcxx: { |
745 | 0 | std::string TargetDir = (Base + "include" + Slash + getTripleString() + |
746 | 0 | Slash + "c++" + Slash + "v1") |
747 | 0 | .str(); |
748 | 0 | if (getDriver().getVFS().exists(TargetDir)) |
749 | 0 | addSystemInclude(DriverArgs, CC1Args, TargetDir); |
750 | 0 | addSystemInclude(DriverArgs, CC1Args, |
751 | 0 | Base + SubdirName + Slash + "include" + Slash + "c++" + |
752 | 0 | Slash + "v1"); |
753 | 0 | addSystemInclude(DriverArgs, CC1Args, |
754 | 0 | Base + "include" + Slash + "c++" + Slash + "v1"); |
755 | 0 | break; |
756 | 0 | } |
757 | | |
758 | 0 | case ToolChain::CST_Libstdcxx: |
759 | 0 | llvm::SmallVector<llvm::SmallString<1024>, 7> CppIncludeBases; |
760 | 0 | CppIncludeBases.emplace_back(Base); |
761 | 0 | llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++"); |
762 | 0 | CppIncludeBases.emplace_back(Base); |
763 | 0 | llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++", |
764 | 0 | Ver); |
765 | 0 | CppIncludeBases.emplace_back(Base); |
766 | 0 | llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver); |
767 | 0 | CppIncludeBases.emplace_back(GccLibDir); |
768 | 0 | llvm::sys::path::append(CppIncludeBases[3], "include", "c++"); |
769 | 0 | CppIncludeBases.emplace_back(GccLibDir); |
770 | 0 | llvm::sys::path::append(CppIncludeBases[4], "include", |
771 | 0 | "g++-v" + GccVer.Text); |
772 | 0 | CppIncludeBases.emplace_back(GccLibDir); |
773 | 0 | llvm::sys::path::append(CppIncludeBases[5], "include", |
774 | 0 | "g++-v" + GccVer.MajorStr + "." + GccVer.MinorStr); |
775 | 0 | CppIncludeBases.emplace_back(GccLibDir); |
776 | 0 | llvm::sys::path::append(CppIncludeBases[6], "include", |
777 | 0 | "g++-v" + GccVer.MajorStr); |
778 | 0 | for (auto &CppIncludeBase : CppIncludeBases) { |
779 | 0 | addSystemInclude(DriverArgs, CC1Args, CppIncludeBase); |
780 | 0 | CppIncludeBase += Slash; |
781 | 0 | addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + TripleDirName); |
782 | 0 | addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward"); |
783 | 0 | } |
784 | 0 | break; |
785 | 0 | } |
786 | 0 | } |
787 | | |
788 | | static bool testTriple(const Driver &D, const llvm::Triple &Triple, |
789 | 0 | const ArgList &Args) { |
790 | | // If an explicit sysroot is set, that will be used and we shouldn't try to |
791 | | // detect anything else. |
792 | 0 | std::string SubdirName; |
793 | 0 | if (D.SysRoot.size()) |
794 | 0 | return true; |
795 | 0 | llvm::Triple LiteralTriple = getLiteralTriple(D, Triple); |
796 | 0 | std::string InstallBase = |
797 | 0 | std::string(llvm::sys::path::parent_path(D.getInstalledDir())); |
798 | 0 | if (llvm::ErrorOr<std::string> TargetSubdir = |
799 | 0 | findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName)) |
800 | 0 | return true; |
801 | | // If the install base itself looks like a mingw sysroot, we'll use that |
802 | | // - don't use any potentially unrelated gcc to influence what triple to use. |
803 | 0 | if (looksLikeMinGWSysroot(InstallBase)) |
804 | 0 | return false; |
805 | 0 | if (llvm::ErrorOr<std::string> GPPName = findGcc(LiteralTriple, Triple)) |
806 | 0 | return true; |
807 | | // If we neither found a colocated sysroot or a matching gcc executable, |
808 | | // conclude that we can't know if this is the correct spelling of the triple. |
809 | 0 | return false; |
810 | 0 | } |
811 | | |
812 | | static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple, |
813 | 0 | const ArgList &Args) { |
814 | | // First test if the original triple can find a sysroot with the triple |
815 | | // name. |
816 | 0 | if (testTriple(D, Triple, Args)) |
817 | 0 | return Triple; |
818 | 0 | llvm::SmallVector<llvm::StringRef, 3> Archs; |
819 | | // If not, test a couple other possible arch names that might be what was |
820 | | // intended. |
821 | 0 | if (Triple.getArch() == llvm::Triple::x86) { |
822 | 0 | Archs.emplace_back("i386"); |
823 | 0 | Archs.emplace_back("i586"); |
824 | 0 | Archs.emplace_back("i686"); |
825 | 0 | } else if (Triple.getArch() == llvm::Triple::arm || |
826 | 0 | Triple.getArch() == llvm::Triple::thumb) { |
827 | 0 | Archs.emplace_back("armv7"); |
828 | 0 | } |
829 | 0 | for (auto A : Archs) { |
830 | 0 | llvm::Triple TestTriple(Triple); |
831 | 0 | TestTriple.setArchName(A); |
832 | 0 | if (testTriple(D, TestTriple, Args)) |
833 | 0 | return TestTriple; |
834 | 0 | } |
835 | | // If none was found, just proceed with the original value. |
836 | 0 | return Triple; |
837 | 0 | } |
838 | | |
839 | | void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple, |
840 | 0 | const ArgList &Args) { |
841 | 0 | if (Triple.getArch() == llvm::Triple::x86 || |
842 | 0 | Triple.getArch() == llvm::Triple::arm || |
843 | 0 | Triple.getArch() == llvm::Triple::thumb) |
844 | 0 | Triple = adjustTriple(D, Triple, Args); |
845 | 0 | } |