1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "CommonArgs.h" |
10 | #include "Arch/AArch64.h" |
11 | #include "Arch/ARM.h" |
12 | #include "Arch/Mips.h" |
13 | #include "Arch/PPC.h" |
14 | #include "Arch/SystemZ.h" |
15 | #include "Arch/X86.h" |
16 | #include "HIP.h" |
17 | #include "Hexagon.h" |
18 | #include "InputInfo.h" |
19 | #include "clang/Basic/CharInfo.h" |
20 | #include "clang/Basic/LangOptions.h" |
21 | #include "clang/Basic/ObjCRuntime.h" |
22 | #include "clang/Basic/Version.h" |
23 | #include "clang/Config/config.h" |
24 | #include "clang/Driver/Action.h" |
25 | #include "clang/Driver/Compilation.h" |
26 | #include "clang/Driver/Driver.h" |
27 | #include "clang/Driver/DriverDiagnostic.h" |
28 | #include "clang/Driver/Job.h" |
29 | #include "clang/Driver/Options.h" |
30 | #include "clang/Driver/SanitizerArgs.h" |
31 | #include "clang/Driver/ToolChain.h" |
32 | #include "clang/Driver/Util.h" |
33 | #include "clang/Driver/XRayArgs.h" |
34 | #include "llvm/ADT/STLExtras.h" |
35 | #include "llvm/ADT/SmallString.h" |
36 | #include "llvm/ADT/StringExtras.h" |
37 | #include "llvm/ADT/StringSwitch.h" |
38 | #include "llvm/ADT/Twine.h" |
39 | #include "llvm/Option/Arg.h" |
40 | #include "llvm/Option/ArgList.h" |
41 | #include "llvm/Option/Option.h" |
42 | #include "llvm/Support/CodeGen.h" |
43 | #include "llvm/Support/Compression.h" |
44 | #include "llvm/Support/Debug.h" |
45 | #include "llvm/Support/ErrorHandling.h" |
46 | #include "llvm/Support/FileSystem.h" |
47 | #include "llvm/Support/Host.h" |
48 | #include "llvm/Support/Path.h" |
49 | #include "llvm/Support/Process.h" |
50 | #include "llvm/Support/Program.h" |
51 | #include "llvm/Support/ScopedPrinter.h" |
52 | #include "llvm/Support/TargetParser.h" |
53 | #include "llvm/Support/VirtualFileSystem.h" |
54 | #include "llvm/Support/YAMLParser.h" |
55 | |
56 | using namespace clang::driver; |
57 | using namespace clang::driver::tools; |
58 | using namespace clang; |
59 | using namespace llvm::opt; |
60 | |
61 | void tools::addPathIfExists(const Driver &D, const Twine &Path, |
62 | ToolChain::path_list &Paths) { |
63 | if (D.getVFS().exists(Path)) |
64 | Paths.push_back(Path.str()); |
65 | } |
66 | |
67 | void tools::handleTargetFeaturesGroup(const ArgList &Args, |
68 | std::vector<StringRef> &Features, |
69 | OptSpecifier Group) { |
70 | for (const Arg *A : Args.filtered(Group)) { |
71 | StringRef Name = A->getOption().getName(); |
72 | A->claim(); |
73 | |
74 | |
75 | (0) . __assert_fail ("Name.startswith(\"m\") && \"Invalid feature name.\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/CommonArgs.cpp", 75, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Name.startswith("m") && "Invalid feature name."); |
76 | Name = Name.substr(1); |
77 | |
78 | bool IsNegative = Name.startswith("no-"); |
79 | if (IsNegative) |
80 | Name = Name.substr(3); |
81 | Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name)); |
82 | } |
83 | } |
84 | |
85 | void tools::addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs, |
86 | const char *ArgName, const char *EnvVar) { |
87 | const char *DirList = ::getenv(EnvVar); |
88 | bool CombinedArg = false; |
89 | |
90 | if (!DirList) |
91 | return; |
92 | |
93 | StringRef Name(ArgName); |
94 | if (Name.equals("-I") || Name.equals("-L")) |
95 | CombinedArg = true; |
96 | |
97 | StringRef Dirs(DirList); |
98 | if (Dirs.empty()) |
99 | return; |
100 | |
101 | StringRef::size_type Delim; |
102 | while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) { |
103 | if (Delim == 0) { |
104 | if (CombinedArg) { |
105 | CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + ".")); |
106 | } else { |
107 | CmdArgs.push_back(ArgName); |
108 | CmdArgs.push_back("."); |
109 | } |
110 | } else { |
111 | if (CombinedArg) { |
112 | CmdArgs.push_back( |
113 | Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim))); |
114 | } else { |
115 | CmdArgs.push_back(ArgName); |
116 | CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim))); |
117 | } |
118 | } |
119 | Dirs = Dirs.substr(Delim + 1); |
120 | } |
121 | |
122 | if (Dirs.empty()) { |
123 | if (CombinedArg) { |
124 | CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + ".")); |
125 | } else { |
126 | CmdArgs.push_back(ArgName); |
127 | CmdArgs.push_back("."); |
128 | } |
129 | } else { |
130 | if (CombinedArg) { |
131 | CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs)); |
132 | } else { |
133 | CmdArgs.push_back(ArgName); |
134 | CmdArgs.push_back(Args.MakeArgString(Dirs)); |
135 | } |
136 | } |
137 | } |
138 | |
139 | void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, |
140 | const ArgList &Args, ArgStringList &CmdArgs, |
141 | const JobAction &JA) { |
142 | const Driver &D = TC.getDriver(); |
143 | |
144 | |
145 | |
146 | Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input); |
147 | |
148 | for (const auto &II : Inputs) { |
149 | |
150 | |
151 | |
152 | if (auto *IA = II.getAction()) |
153 | if ((JA.isHostOffloading(Action::OFK_OpenMP) && |
154 | IA->isDeviceOffloading(Action::OFK_OpenMP)) || |
155 | (JA.isHostOffloading(Action::OFK_HIP) && |
156 | IA->isDeviceOffloading(Action::OFK_HIP))) |
157 | continue; |
158 | |
159 | if (!TC.HasNativeLLVMSupport() && types::isLLVMIR(II.getType())) |
160 | |
161 | D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString(); |
162 | |
163 | |
164 | if (II.isFilename()) { |
165 | CmdArgs.push_back(II.getFilename()); |
166 | continue; |
167 | } |
168 | |
169 | |
170 | const Arg &A = II.getInputArg(); |
171 | |
172 | |
173 | if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) |
174 | TC.AddCXXStdlibLibArgs(Args, CmdArgs); |
175 | else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) |
176 | TC.AddCCKextLibArgs(Args, CmdArgs); |
177 | else if (A.getOption().matches(options::OPT_z)) { |
178 | |
179 | A.claim(); |
180 | A.render(Args, CmdArgs); |
181 | } else { |
182 | A.renderAsInput(Args, CmdArgs); |
183 | } |
184 | } |
185 | |
186 | |
187 | |
188 | if (!TC.isCrossCompiling()) { |
189 | addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); |
190 | } |
191 | } |
192 | |
193 | void tools::AddTargetFeature(const ArgList &Args, |
194 | std::vector<StringRef> &Features, |
195 | OptSpecifier OnOpt, OptSpecifier OffOpt, |
196 | StringRef FeatureName) { |
197 | if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) { |
198 | if (A->getOption().matches(OnOpt)) |
199 | Features.push_back(Args.MakeArgString("+" + FeatureName)); |
200 | else |
201 | Features.push_back(Args.MakeArgString("-" + FeatureName)); |
202 | } |
203 | } |
204 | |
205 | |
206 | static std::string getR600TargetGPU(const ArgList &Args) { |
207 | if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { |
208 | const char *GPUName = A->getValue(); |
209 | return llvm::StringSwitch<const char *>(GPUName) |
210 | .Cases("rv630", "rv635", "r600") |
211 | .Cases("rv610", "rv620", "rs780", "rs880") |
212 | .Case("rv740", "rv770") |
213 | .Case("palm", "cedar") |
214 | .Cases("sumo", "sumo2", "sumo") |
215 | .Case("hemlock", "cypress") |
216 | .Case("aruba", "cayman") |
217 | .Default(GPUName); |
218 | } |
219 | return ""; |
220 | } |
221 | |
222 | static std::string getLanaiTargetCPU(const ArgList &Args) { |
223 | if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { |
224 | return A->getValue(); |
225 | } |
226 | return ""; |
227 | } |
228 | |
229 | |
230 | static StringRef getWebAssemblyTargetCPU(const ArgList &Args) { |
231 | |
232 | if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { |
233 | StringRef CPU = A->getValue(); |
234 | |
235 | #ifdef __wasm__ |
236 | |
237 | |
238 | if (CPU == "native") |
239 | return llvm::sys::getHostCPUName(); |
240 | #endif |
241 | |
242 | return CPU; |
243 | } |
244 | |
245 | return "generic"; |
246 | } |
247 | |
248 | std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T, |
249 | bool FromAs) { |
250 | Arg *A; |
251 | |
252 | switch (T.getArch()) { |
253 | default: |
254 | return ""; |
255 | |
256 | case llvm::Triple::aarch64: |
257 | case llvm::Triple::aarch64_be: |
258 | return aarch64::getAArch64TargetCPU(Args, T, A); |
259 | |
260 | case llvm::Triple::arm: |
261 | case llvm::Triple::armeb: |
262 | case llvm::Triple::thumb: |
263 | case llvm::Triple::thumbeb: { |
264 | StringRef MArch, MCPU; |
265 | arm::getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs); |
266 | return arm::getARMTargetCPU(MCPU, MArch, T); |
267 | } |
268 | |
269 | case llvm::Triple::avr: |
270 | if (const Arg *A = Args.getLastArg(options::OPT_mmcu_EQ)) |
271 | return A->getValue(); |
272 | return ""; |
273 | |
274 | case llvm::Triple::mips: |
275 | case llvm::Triple::mipsel: |
276 | case llvm::Triple::mips64: |
277 | case llvm::Triple::mips64el: { |
278 | StringRef CPUName; |
279 | StringRef ABIName; |
280 | mips::getMipsCPUAndABI(Args, T, CPUName, ABIName); |
281 | return CPUName; |
282 | } |
283 | |
284 | case llvm::Triple::nvptx: |
285 | case llvm::Triple::nvptx64: |
286 | if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) |
287 | return A->getValue(); |
288 | return ""; |
289 | |
290 | case llvm::Triple::ppc: |
291 | case llvm::Triple::ppc64: |
292 | case llvm::Triple::ppc64le: { |
293 | std::string TargetCPUName = ppc::getPPCTargetCPU(Args); |
294 | |
295 | |
296 | |
297 | if (TargetCPUName.empty() && !T.isOSDarwin()) { |
298 | if (T.getArch() == llvm::Triple::ppc64) |
299 | TargetCPUName = "ppc64"; |
300 | else if (T.getArch() == llvm::Triple::ppc64le) |
301 | TargetCPUName = "ppc64le"; |
302 | else |
303 | TargetCPUName = "ppc"; |
304 | } |
305 | return TargetCPUName; |
306 | } |
307 | |
308 | case llvm::Triple::bpfel: |
309 | case llvm::Triple::bpfeb: |
310 | case llvm::Triple::sparc: |
311 | case llvm::Triple::sparcel: |
312 | case llvm::Triple::sparcv9: |
313 | if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) |
314 | return A->getValue(); |
315 | return ""; |
316 | |
317 | case llvm::Triple::x86: |
318 | case llvm::Triple::x86_64: |
319 | return x86::getX86TargetCPU(Args, T); |
320 | |
321 | case llvm::Triple::hexagon: |
322 | return "hexagon" + |
323 | toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str(); |
324 | |
325 | case llvm::Triple::lanai: |
326 | return getLanaiTargetCPU(Args); |
327 | |
328 | case llvm::Triple::systemz: |
329 | return systemz::getSystemZTargetCPU(Args); |
330 | |
331 | case llvm::Triple::r600: |
332 | case llvm::Triple::amdgcn: |
333 | return getR600TargetGPU(Args); |
334 | |
335 | case llvm::Triple::wasm32: |
336 | case llvm::Triple::wasm64: |
337 | return getWebAssemblyTargetCPU(Args); |
338 | } |
339 | } |
340 | |
341 | unsigned tools::getLTOParallelism(const ArgList &Args, const Driver &D) { |
342 | unsigned Parallelism = 0; |
343 | Arg *LtoJobsArg = Args.getLastArg(options::OPT_flto_jobs_EQ); |
344 | if (LtoJobsArg && |
345 | StringRef(LtoJobsArg->getValue()).getAsInteger(10, Parallelism)) |
346 | D.Diag(diag::err_drv_invalid_int_value) << LtoJobsArg->getAsString(Args) |
347 | << LtoJobsArg->getValue(); |
348 | return Parallelism; |
349 | } |
350 | |
351 | |
352 | bool tools::isUseSeparateSections(const llvm::Triple &Triple) { |
353 | return Triple.getOS() == llvm::Triple::CloudABI; |
354 | } |
355 | |
356 | void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, |
357 | ArgStringList &CmdArgs, const InputInfo &Output, |
358 | const InputInfo &Input, bool IsThinLTO) { |
359 | |
360 | |
361 | |
362 | CmdArgs.push_back("-plugin"); |
363 | |
364 | #if defined(_WIN32) |
365 | const char *Suffix = ".dll"; |
366 | #elif defined(__APPLE__) |
367 | const char *Suffix = ".dylib"; |
368 | #else |
369 | const char *Suffix = ".so"; |
370 | #endif |
371 | |
372 | SmallString<1024> Plugin; |
373 | llvm::sys::path::native(Twine(ToolChain.getDriver().Dir) + |
374 | "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold" + |
375 | Suffix, |
376 | Plugin); |
377 | CmdArgs.push_back(Args.MakeArgString(Plugin)); |
378 | |
379 | |
380 | |
381 | |
382 | |
383 | std::string CPU = getCPUName(Args, ToolChain.getTriple()); |
384 | if (!CPU.empty()) |
385 | CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU)); |
386 | |
387 | if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { |
388 | StringRef OOpt; |
389 | if (A->getOption().matches(options::OPT_O4) || |
390 | A->getOption().matches(options::OPT_Ofast)) |
391 | OOpt = "3"; |
392 | else if (A->getOption().matches(options::OPT_O)) |
393 | OOpt = A->getValue(); |
394 | else if (A->getOption().matches(options::OPT_O0)) |
395 | OOpt = "0"; |
396 | if (!OOpt.empty()) |
397 | CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=O") + OOpt)); |
398 | } |
399 | |
400 | if (Args.hasArg(options::OPT_gsplit_dwarf)) { |
401 | CmdArgs.push_back( |
402 | Args.MakeArgString(Twine("-plugin-opt=dwo_dir=") + |
403 | Output.getFilename() + "_dwo")); |
404 | } |
405 | |
406 | if (IsThinLTO) |
407 | CmdArgs.push_back("-plugin-opt=thinlto"); |
408 | |
409 | if (unsigned Parallelism = getLTOParallelism(Args, ToolChain.getDriver())) |
410 | CmdArgs.push_back( |
411 | Args.MakeArgString("-plugin-opt=jobs=" + Twine(Parallelism))); |
412 | |
413 | |
414 | if (Arg *A = Args.getLastArg(options::OPT_gTune_Group, |
415 | options::OPT_ggdbN_Group)) { |
416 | if (A->getOption().matches(options::OPT_glldb)) |
417 | CmdArgs.push_back("-plugin-opt=-debugger-tune=lldb"); |
418 | else if (A->getOption().matches(options::OPT_gsce)) |
419 | CmdArgs.push_back("-plugin-opt=-debugger-tune=sce"); |
420 | else |
421 | CmdArgs.push_back("-plugin-opt=-debugger-tune=gdb"); |
422 | } |
423 | |
424 | bool UseSeparateSections = |
425 | isUseSeparateSections(ToolChain.getEffectiveTriple()); |
426 | |
427 | if (Args.hasFlag(options::OPT_ffunction_sections, |
428 | options::OPT_fno_function_sections, UseSeparateSections)) { |
429 | CmdArgs.push_back("-plugin-opt=-function-sections"); |
430 | } |
431 | |
432 | if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections, |
433 | UseSeparateSections)) { |
434 | CmdArgs.push_back("-plugin-opt=-data-sections"); |
435 | } |
436 | |
437 | if (Arg *A = getLastProfileSampleUseArg(Args)) { |
438 | StringRef FName = A->getValue(); |
439 | if (!llvm::sys::fs::exists(FName)) |
440 | ToolChain.getDriver().Diag(diag::err_drv_no_such_file) << FName; |
441 | else |
442 | CmdArgs.push_back( |
443 | Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName)); |
444 | } |
445 | |
446 | auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate, |
447 | options::OPT_fcs_profile_generate_EQ, |
448 | options::OPT_fno_profile_generate); |
449 | if (CSPGOGenerateArg && |
450 | CSPGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate)) |
451 | CSPGOGenerateArg = nullptr; |
452 | |
453 | auto *ProfileUseArg = getLastProfileUseArg(Args); |
454 | |
455 | if (CSPGOGenerateArg) { |
456 | CmdArgs.push_back(Args.MakeArgString("-plugin-opt=cs-profile-generate")); |
457 | if (CSPGOGenerateArg->getOption().matches( |
458 | options::OPT_fcs_profile_generate_EQ)) { |
459 | SmallString<128> Path(CSPGOGenerateArg->getValue()); |
460 | llvm::sys::path::append(Path, "default_%m.profraw"); |
461 | CmdArgs.push_back( |
462 | Args.MakeArgString(Twine("-plugin-opt=cs-profile-path=") + Path)); |
463 | } else |
464 | CmdArgs.push_back( |
465 | Args.MakeArgString("-plugin-opt=cs-profile-path=default_%m.profraw")); |
466 | } else if (ProfileUseArg) { |
467 | SmallString<128> Path( |
468 | ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue()); |
469 | if (Path.empty() || llvm::sys::fs::is_directory(Path)) |
470 | llvm::sys::path::append(Path, "default.profdata"); |
471 | CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=cs-profile-path=") + |
472 | Path)); |
473 | } |
474 | |
475 | |
476 | if (Args.hasFlag(options::OPT_fexperimental_new_pass_manager, |
477 | options::OPT_fno_experimental_new_pass_manager, |
478 | ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER)) { |
479 | CmdArgs.push_back("-plugin-opt=new-pass-manager"); |
480 | } |
481 | |
482 | |
483 | SmallString<128> StatsFile = |
484 | getStatsFileName(Args, Output, Input, ToolChain.getDriver()); |
485 | if (!StatsFile.empty()) |
486 | CmdArgs.push_back( |
487 | Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile)); |
488 | } |
489 | |
490 | void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, |
491 | ArgStringList &CmdArgs) { |
492 | if (!Args.hasFlag(options::OPT_frtlib_add_rpath, |
493 | options::OPT_fno_rtlib_add_rpath, false)) |
494 | return; |
495 | |
496 | std::string CandidateRPath = TC.getArchSpecificLibPath(); |
497 | if (TC.getVFS().exists(CandidateRPath)) { |
498 | CmdArgs.push_back("-rpath"); |
499 | CmdArgs.push_back(Args.MakeArgString(CandidateRPath.c_str())); |
500 | } |
501 | } |
502 | |
503 | bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, |
504 | const ArgList &Args, bool IsOffloadingHost, |
505 | bool GompNeedsRT) { |
506 | if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, |
507 | options::OPT_fno_openmp, false)) |
508 | return false; |
509 | |
510 | switch (TC.getDriver().getOpenMPRuntime(Args)) { |
511 | case Driver::OMPRT_OMP: |
512 | CmdArgs.push_back("-lomp"); |
513 | break; |
514 | case Driver::OMPRT_GOMP: |
515 | CmdArgs.push_back("-lgomp"); |
516 | |
517 | if (GompNeedsRT) |
518 | CmdArgs.push_back("-lrt"); |
519 | break; |
520 | case Driver::OMPRT_IOMP5: |
521 | CmdArgs.push_back("-liomp5"); |
522 | break; |
523 | case Driver::OMPRT_Unknown: |
524 | |
525 | return false; |
526 | } |
527 | |
528 | if (IsOffloadingHost) |
529 | CmdArgs.push_back("-lomptarget"); |
530 | |
531 | addArchSpecificRPath(TC, Args, CmdArgs); |
532 | |
533 | return true; |
534 | } |
535 | |
536 | static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args, |
537 | ArgStringList &CmdArgs, StringRef Sanitizer, |
538 | bool IsShared, bool IsWhole) { |
539 | |
540 | |
541 | if (IsWhole) CmdArgs.push_back("--whole-archive"); |
542 | CmdArgs.push_back(TC.getCompilerRTArgString( |
543 | Args, Sanitizer, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static)); |
544 | if (IsWhole) CmdArgs.push_back("--no-whole-archive"); |
545 | |
546 | if (IsShared) { |
547 | addArchSpecificRPath(TC, Args, CmdArgs); |
548 | } |
549 | } |
550 | |
551 | |
552 | |
553 | static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args, |
554 | ArgStringList &CmdArgs, |
555 | StringRef Sanitizer) { |
556 | |
557 | |
558 | if (TC.getTriple().getOS() == llvm::Triple::Solaris) |
559 | return true; |
560 | |
561 | |
562 | |
563 | if (TC.getTriple().getVendor() == llvm::Triple::Myriad) |
564 | return true; |
565 | SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer)); |
566 | if (llvm::sys::fs::exists(SanRT + ".syms")) { |
567 | CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms")); |
568 | return true; |
569 | } |
570 | return false; |
571 | } |
572 | |
573 | static void addSanitizerLibPath(const ToolChain &TC, const ArgList &Args, |
574 | ArgStringList &CmdArgs, StringRef Name) { |
575 | for (const auto &LibPath : TC.getLibraryPaths()) { |
576 | if (!LibPath.empty()) { |
577 | SmallString<128> P(LibPath); |
578 | llvm::sys::path::append(P, Name); |
579 | if (TC.getVFS().exists(P)) |
580 | CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + P)); |
581 | } |
582 | } |
583 | } |
584 | |
585 | void tools::addSanitizerPathLibArgs(const ToolChain &TC, const ArgList &Args, |
586 | ArgStringList &CmdArgs) { |
587 | const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); |
588 | if (SanArgs.needsAsanRt()) { |
589 | addSanitizerLibPath(TC, Args, CmdArgs, "asan"); |
590 | } |
591 | if (SanArgs.needsHwasanRt()) { |
592 | addSanitizerLibPath(TC, Args, CmdArgs, "hwasan"); |
593 | } |
594 | if (SanArgs.needsLsanRt()) { |
595 | addSanitizerLibPath(TC, Args, CmdArgs, "lsan"); |
596 | } |
597 | if (SanArgs.needsMsanRt()) { |
598 | addSanitizerLibPath(TC, Args, CmdArgs, "msan"); |
599 | } |
600 | if (SanArgs.needsTsanRt()) { |
601 | addSanitizerLibPath(TC, Args, CmdArgs, "tsan"); |
602 | } |
603 | } |
604 | |
605 | |
606 | |
607 | void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, |
608 | ArgStringList &CmdArgs) { |
609 | |
610 | |
611 | CmdArgs.push_back("--no-as-needed"); |
612 | |
613 | if (TC.getTriple().getOS() != llvm::Triple::RTEMS && |
614 | !TC.getTriple().isAndroid()) { |
615 | CmdArgs.push_back("-lpthread"); |
616 | if (!TC.getTriple().isOSOpenBSD()) |
617 | CmdArgs.push_back("-lrt"); |
618 | } |
619 | CmdArgs.push_back("-lm"); |
620 | |
621 | if (!TC.getTriple().isOSFreeBSD() && |
622 | !TC.getTriple().isOSNetBSD() && |
623 | !TC.getTriple().isOSOpenBSD() && |
624 | TC.getTriple().getOS() != llvm::Triple::RTEMS) |
625 | CmdArgs.push_back("-ldl"); |
626 | |
627 | if (TC.getTriple().isOSFreeBSD() || |
628 | TC.getTriple().isOSNetBSD()) |
629 | CmdArgs.push_back("-lexecinfo"); |
630 | } |
631 | |
632 | static void |
633 | collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, |
634 | SmallVectorImpl<StringRef> &SharedRuntimes, |
635 | SmallVectorImpl<StringRef> &StaticRuntimes, |
636 | SmallVectorImpl<StringRef> &NonWholeStaticRuntimes, |
637 | SmallVectorImpl<StringRef> &HelperStaticRuntimes, |
638 | SmallVectorImpl<StringRef> &RequiredSymbols) { |
639 | const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); |
640 | |
641 | if (SanArgs.needsSharedRt()) { |
642 | if (SanArgs.needsAsanRt()) { |
643 | SharedRuntimes.push_back("asan"); |
644 | if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) |
645 | HelperStaticRuntimes.push_back("asan-preinit"); |
646 | } |
647 | if (SanArgs.needsUbsanRt()) { |
648 | if (SanArgs.requiresMinimalRuntime()) |
649 | SharedRuntimes.push_back("ubsan_minimal"); |
650 | else |
651 | SharedRuntimes.push_back("ubsan_standalone"); |
652 | } |
653 | if (SanArgs.needsScudoRt()) { |
654 | if (SanArgs.requiresMinimalRuntime()) |
655 | SharedRuntimes.push_back("scudo_minimal"); |
656 | else |
657 | SharedRuntimes.push_back("scudo"); |
658 | } |
659 | if (SanArgs.needsHwasanRt()) |
660 | SharedRuntimes.push_back("hwasan"); |
661 | } |
662 | |
663 | |
664 | if (SanArgs.needsStatsRt()) |
665 | StaticRuntimes.push_back("stats_client"); |
666 | |
667 | |
668 | if (Args.hasArg(options::OPT_shared) || SanArgs.needsSharedRt()) { |
669 | |
670 | return; |
671 | } |
672 | if (SanArgs.needsAsanRt()) { |
673 | StaticRuntimes.push_back("asan"); |
674 | if (SanArgs.linkCXXRuntimes()) |
675 | StaticRuntimes.push_back("asan_cxx"); |
676 | } |
677 | |
678 | if (SanArgs.needsHwasanRt()) { |
679 | StaticRuntimes.push_back("hwasan"); |
680 | if (SanArgs.linkCXXRuntimes()) |
681 | StaticRuntimes.push_back("hwasan_cxx"); |
682 | } |
683 | if (SanArgs.needsDfsanRt()) |
684 | StaticRuntimes.push_back("dfsan"); |
685 | if (SanArgs.needsLsanRt()) |
686 | StaticRuntimes.push_back("lsan"); |
687 | if (SanArgs.needsMsanRt()) { |
688 | StaticRuntimes.push_back("msan"); |
689 | if (SanArgs.linkCXXRuntimes()) |
690 | StaticRuntimes.push_back("msan_cxx"); |
691 | } |
692 | if (SanArgs.needsTsanRt()) { |
693 | StaticRuntimes.push_back("tsan"); |
694 | if (SanArgs.linkCXXRuntimes()) |
695 | StaticRuntimes.push_back("tsan_cxx"); |
696 | } |
697 | if (SanArgs.needsUbsanRt()) { |
698 | if (SanArgs.requiresMinimalRuntime()) { |
699 | StaticRuntimes.push_back("ubsan_minimal"); |
700 | } else { |
701 | StaticRuntimes.push_back("ubsan_standalone"); |
702 | if (SanArgs.linkCXXRuntimes()) |
703 | StaticRuntimes.push_back("ubsan_standalone_cxx"); |
704 | } |
705 | } |
706 | if (SanArgs.needsSafeStackRt()) { |
707 | NonWholeStaticRuntimes.push_back("safestack"); |
708 | RequiredSymbols.push_back("__safestack_init"); |
709 | } |
710 | if (SanArgs.needsCfiRt()) |
711 | StaticRuntimes.push_back("cfi"); |
712 | if (SanArgs.needsCfiDiagRt()) { |
713 | StaticRuntimes.push_back("cfi_diag"); |
714 | if (SanArgs.linkCXXRuntimes()) |
715 | StaticRuntimes.push_back("ubsan_standalone_cxx"); |
716 | } |
717 | if (SanArgs.needsStatsRt()) { |
718 | NonWholeStaticRuntimes.push_back("stats"); |
719 | RequiredSymbols.push_back("__sanitizer_stats_register"); |
720 | } |
721 | if (SanArgs.needsScudoRt()) { |
722 | if (SanArgs.requiresMinimalRuntime()) { |
723 | StaticRuntimes.push_back("scudo_minimal"); |
724 | if (SanArgs.linkCXXRuntimes()) |
725 | StaticRuntimes.push_back("scudo_cxx_minimal"); |
726 | } else { |
727 | StaticRuntimes.push_back("scudo"); |
728 | if (SanArgs.linkCXXRuntimes()) |
729 | StaticRuntimes.push_back("scudo_cxx"); |
730 | } |
731 | } |
732 | } |
733 | |
734 | |
735 | |
736 | bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, |
737 | ArgStringList &CmdArgs) { |
738 | SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes, |
739 | NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols; |
740 | collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes, |
741 | NonWholeStaticRuntimes, HelperStaticRuntimes, |
742 | RequiredSymbols); |
743 | |
744 | |
745 | if (TC.getSanitizerArgs().needsFuzzer() |
746 | && !Args.hasArg(options::OPT_shared)) { |
747 | |
748 | addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true); |
749 | if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx)) |
750 | TC.AddCXXStdlibLibArgs(Args, CmdArgs); |
751 | } |
752 | |
753 | for (auto RT : SharedRuntimes) |
754 | addSanitizerRuntime(TC, Args, CmdArgs, RT, true, false); |
755 | for (auto RT : HelperStaticRuntimes) |
756 | addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true); |
757 | bool AddExportDynamic = false; |
758 | for (auto RT : StaticRuntimes) { |
759 | addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true); |
760 | AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT); |
761 | } |
762 | for (auto RT : NonWholeStaticRuntimes) { |
763 | addSanitizerRuntime(TC, Args, CmdArgs, RT, false, false); |
764 | AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT); |
765 | } |
766 | for (auto S : RequiredSymbols) { |
767 | CmdArgs.push_back("-u"); |
768 | CmdArgs.push_back(Args.MakeArgString(S)); |
769 | } |
770 | |
771 | |
772 | if (AddExportDynamic) |
773 | CmdArgs.push_back("--export-dynamic"); |
774 | |
775 | const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); |
776 | if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic) |
777 | CmdArgs.push_back("-export-dynamic-symbol=__cfi_check"); |
778 | |
779 | return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty(); |
780 | } |
781 | |
782 | bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringList &CmdArgs) { |
783 | if (Args.hasArg(options::OPT_shared)) |
784 | return false; |
785 | |
786 | if (TC.getXRayArgs().needsXRayRt()) { |
787 | CmdArgs.push_back("-whole-archive"); |
788 | CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray")); |
789 | for (const auto &Mode : TC.getXRayArgs().modeList()) |
790 | CmdArgs.push_back(TC.getCompilerRTArgString(Args, Mode)); |
791 | CmdArgs.push_back("-no-whole-archive"); |
792 | return true; |
793 | } |
794 | |
795 | return false; |
796 | } |
797 | |
798 | void tools::linkXRayRuntimeDeps(const ToolChain &TC, ArgStringList &CmdArgs) { |
799 | CmdArgs.push_back("--no-as-needed"); |
800 | CmdArgs.push_back("-lpthread"); |
801 | if (!TC.getTriple().isOSOpenBSD()) |
802 | CmdArgs.push_back("-lrt"); |
803 | CmdArgs.push_back("-lm"); |
804 | |
805 | if (!TC.getTriple().isOSFreeBSD() && |
806 | !TC.getTriple().isOSNetBSD() && |
807 | !TC.getTriple().isOSOpenBSD()) |
808 | CmdArgs.push_back("-ldl"); |
809 | } |
810 | |
811 | bool tools::areOptimizationsEnabled(const ArgList &Args) { |
812 | |
813 | if (Arg *A = Args.getLastArg(options::OPT_O_Group)) |
814 | return !A->getOption().matches(options::OPT_O0); |
815 | |
816 | return false; |
817 | } |
818 | |
819 | const char *tools::SplitDebugName(const ArgList &Args, const InputInfo &Input, |
820 | const InputInfo &Output) { |
821 | if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ)) |
822 | if (StringRef(A->getValue()) == "single") |
823 | return Args.MakeArgString(Output.getFilename()); |
824 | |
825 | Arg *FinalOutput = Args.getLastArg(options::OPT_o); |
826 | if (FinalOutput && Args.hasArg(options::OPT_c)) { |
827 | SmallString<128> T(FinalOutput->getValue()); |
828 | llvm::sys::path::replace_extension(T, "dwo"); |
829 | return Args.MakeArgString(T); |
830 | } else { |
831 | |
832 | SmallString<128> T( |
833 | Args.getLastArgValue(options::OPT_fdebug_compilation_dir)); |
834 | SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput())); |
835 | llvm::sys::path::replace_extension(F, "dwo"); |
836 | T += F; |
837 | return Args.MakeArgString(F); |
838 | } |
839 | } |
840 | |
841 | void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, |
842 | const JobAction &JA, const ArgList &Args, |
843 | const InputInfo &Output, const char *OutFile) { |
844 | ArgStringList ; |
845 | ExtractArgs.push_back("--extract-dwo"); |
846 | |
847 | ArgStringList StripArgs; |
848 | StripArgs.push_back("--strip-dwo"); |
849 | |
850 | |
851 | StripArgs.push_back(Output.getFilename()); |
852 | ExtractArgs.push_back(Output.getFilename()); |
853 | ExtractArgs.push_back(OutFile); |
854 | |
855 | const char *Exec = |
856 | Args.MakeArgString(TC.GetProgramPath(CLANG_DEFAULT_OBJCOPY)); |
857 | InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename()); |
858 | |
859 | |
860 | C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs, II)); |
861 | |
862 | |
863 | C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs, II)); |
864 | } |
865 | |
866 | |
867 | |
868 | |
869 | void tools::claimNoWarnArgs(const ArgList &Args) { |
870 | |
871 | |
872 | Args.ClaimAllArgs(options::OPT_flto_EQ); |
873 | Args.ClaimAllArgs(options::OPT_flto); |
874 | Args.ClaimAllArgs(options::OPT_fno_lto); |
875 | } |
876 | |
877 | Arg *tools::getLastProfileUseArg(const ArgList &Args) { |
878 | auto *ProfileUseArg = Args.getLastArg( |
879 | options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ, |
880 | options::OPT_fprofile_use, options::OPT_fprofile_use_EQ, |
881 | options::OPT_fno_profile_instr_use); |
882 | |
883 | if (ProfileUseArg && |
884 | ProfileUseArg->getOption().matches(options::OPT_fno_profile_instr_use)) |
885 | ProfileUseArg = nullptr; |
886 | |
887 | return ProfileUseArg; |
888 | } |
889 | |
890 | Arg *tools::getLastProfileSampleUseArg(const ArgList &Args) { |
891 | auto *ProfileSampleUseArg = Args.getLastArg( |
892 | options::OPT_fprofile_sample_use, options::OPT_fprofile_sample_use_EQ, |
893 | options::OPT_fauto_profile, options::OPT_fauto_profile_EQ, |
894 | options::OPT_fno_profile_sample_use, options::OPT_fno_auto_profile); |
895 | |
896 | if (ProfileSampleUseArg && |
897 | (ProfileSampleUseArg->getOption().matches( |
898 | options::OPT_fno_profile_sample_use) || |
899 | ProfileSampleUseArg->getOption().matches(options::OPT_fno_auto_profile))) |
900 | return nullptr; |
901 | |
902 | return Args.getLastArg(options::OPT_fprofile_sample_use_EQ, |
903 | options::OPT_fauto_profile_EQ); |
904 | } |
905 | |
906 | |
907 | |
908 | |
909 | |
910 | std::tuple<llvm::Reloc::Model, unsigned, bool> |
911 | tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) { |
912 | const llvm::Triple &EffectiveTriple = ToolChain.getEffectiveTriple(); |
913 | const llvm::Triple &Triple = ToolChain.getTriple(); |
914 | |
915 | bool PIE = ToolChain.isPIEDefault(); |
916 | bool PIC = PIE || ToolChain.isPICDefault(); |
917 | |
918 | if (Triple.isOSBinFormatMachO() && Args.hasArg(options::OPT_static)) |
919 | PIE = PIC = false; |
920 | bool IsPICLevelTwo = PIC; |
921 | |
922 | bool KernelOrKext = |
923 | Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); |
924 | |
925 | |
926 | if (Triple.isAndroid()) { |
927 | switch (Triple.getArch()) { |
928 | case llvm::Triple::arm: |
929 | case llvm::Triple::armeb: |
930 | case llvm::Triple::thumb: |
931 | case llvm::Triple::thumbeb: |
932 | case llvm::Triple::aarch64: |
933 | case llvm::Triple::mips: |
934 | case llvm::Triple::mipsel: |
935 | case llvm::Triple::mips64: |
936 | case llvm::Triple::mips64el: |
937 | PIC = true; |
938 | break; |
939 | |
940 | case llvm::Triple::x86: |
941 | case llvm::Triple::x86_64: |
942 | PIC = true; |
943 | IsPICLevelTwo = true; |
944 | break; |
945 | |
946 | default: |
947 | break; |
948 | } |
949 | } |
950 | |
951 | |
952 | if (Triple.isOSOpenBSD()) { |
953 | switch (ToolChain.getArch()) { |
954 | case llvm::Triple::arm: |
955 | case llvm::Triple::aarch64: |
956 | case llvm::Triple::mips64: |
957 | case llvm::Triple::mips64el: |
958 | case llvm::Triple::x86: |
959 | case llvm::Triple::x86_64: |
960 | IsPICLevelTwo = false; |
961 | break; |
962 | |
963 | case llvm::Triple::ppc: |
964 | case llvm::Triple::sparc: |
965 | case llvm::Triple::sparcel: |
966 | case llvm::Triple::sparcv9: |
967 | IsPICLevelTwo = true; |
968 | break; |
969 | |
970 | default: |
971 | break; |
972 | } |
973 | } |
974 | |
975 | |
976 | if (Triple.getArch() == llvm::Triple::amdgcn) |
977 | PIC = true; |
978 | |
979 | |
980 | |
981 | |
982 | |
983 | Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, |
984 | options::OPT_fpic, options::OPT_fno_pic, |
985 | options::OPT_fPIE, options::OPT_fno_PIE, |
986 | options::OPT_fpie, options::OPT_fno_pie); |
987 | if (Triple.isOSWindows() && LastPICArg && |
988 | LastPICArg == |
989 | Args.getLastArg(options::OPT_fPIC, options::OPT_fpic, |
990 | options::OPT_fPIE, options::OPT_fpie)) { |
991 | ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) |
992 | << LastPICArg->getSpelling() << Triple.str(); |
993 | if (Triple.getArch() == llvm::Triple::x86_64) |
994 | return std::make_tuple(llvm::Reloc::PIC_, 2U, false); |
995 | return std::make_tuple(llvm::Reloc::Static, 0U, false); |
996 | } |
997 | |
998 | |
999 | |
1000 | if (!ToolChain.isPICDefaultForced()) { |
1001 | if (LastPICArg) { |
1002 | Option O = LastPICArg->getOption(); |
1003 | if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) || |
1004 | O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) { |
1005 | PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie); |
1006 | PIC = |
1007 | PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic); |
1008 | IsPICLevelTwo = |
1009 | O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC); |
1010 | } else { |
1011 | PIE = PIC = false; |
1012 | if (EffectiveTriple.isPS4CPU()) { |
1013 | Arg *ModelArg = Args.getLastArg(options::OPT_mcmodel_EQ); |
1014 | StringRef Model = ModelArg ? ModelArg->getValue() : ""; |
1015 | if (Model != "kernel") { |
1016 | PIC = true; |
1017 | ToolChain.getDriver().Diag(diag::warn_drv_ps4_force_pic) |
1018 | << LastPICArg->getSpelling(); |
1019 | } |
1020 | } |
1021 | } |
1022 | } |
1023 | } |
1024 | |
1025 | |
1026 | |
1027 | |
1028 | if (PIC && (Triple.isOSDarwin() || EffectiveTriple.isPS4CPU())) |
1029 | IsPICLevelTwo |= ToolChain.isPICDefault(); |
1030 | |
1031 | |
1032 | |
1033 | if (KernelOrKext && |
1034 | ((!EffectiveTriple.isiOS() || EffectiveTriple.isOSVersionLT(6)) && |
1035 | !EffectiveTriple.isWatchOS())) |
1036 | PIC = PIE = false; |
1037 | |
1038 | if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) { |
1039 | |
1040 | |
1041 | if (!Triple.isOSDarwin()) |
1042 | ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) |
1043 | << A->getSpelling() << Triple.str(); |
1044 | |
1045 | |
1046 | |
1047 | |
1048 | |
1049 | |
1050 | PIC = ToolChain.isPICDefault() && ToolChain.isPICDefaultForced(); |
1051 | |
1052 | return std::make_tuple(llvm::Reloc::DynamicNoPIC, PIC ? 2U : 0U, false); |
1053 | } |
1054 | |
1055 | bool EmbeddedPISupported; |
1056 | switch (Triple.getArch()) { |
1057 | case llvm::Triple::arm: |
1058 | case llvm::Triple::armeb: |
1059 | case llvm::Triple::thumb: |
1060 | case llvm::Triple::thumbeb: |
1061 | EmbeddedPISupported = true; |
1062 | break; |
1063 | default: |
1064 | EmbeddedPISupported = false; |
1065 | break; |
1066 | } |
1067 | |
1068 | bool ROPI = false, RWPI = false; |
1069 | Arg* LastROPIArg = Args.getLastArg(options::OPT_fropi, options::OPT_fno_ropi); |
1070 | if (LastROPIArg && LastROPIArg->getOption().matches(options::OPT_fropi)) { |
1071 | if (!EmbeddedPISupported) |
1072 | ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) |
1073 | << LastROPIArg->getSpelling() << Triple.str(); |
1074 | ROPI = true; |
1075 | } |
1076 | Arg *LastRWPIArg = Args.getLastArg(options::OPT_frwpi, options::OPT_fno_rwpi); |
1077 | if (LastRWPIArg && LastRWPIArg->getOption().matches(options::OPT_frwpi)) { |
1078 | if (!EmbeddedPISupported) |
1079 | ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) |
1080 | << LastRWPIArg->getSpelling() << Triple.str(); |
1081 | RWPI = true; |
1082 | } |
1083 | |
1084 | |
1085 | if ((ROPI || RWPI) && (PIC || PIE)) |
1086 | ToolChain.getDriver().Diag(diag::err_drv_ropi_rwpi_incompatible_with_pic); |
1087 | |
1088 | if (Triple.isMIPS()) { |
1089 | StringRef CPUName; |
1090 | StringRef ABIName; |
1091 | mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
1092 | |
1093 | |
1094 | |
1095 | if (ABIName == "n64") |
1096 | PIC = true; |
1097 | |
1098 | if(Args.hasArg(options::OPT_mno_abicalls)) |
1099 | return std::make_tuple(llvm::Reloc::Static, 0U, false); |
1100 | |
1101 | |
1102 | IsPICLevelTwo = false; |
1103 | } |
1104 | |
1105 | if (PIC) |
1106 | return std::make_tuple(llvm::Reloc::PIC_, IsPICLevelTwo ? 2U : 1U, PIE); |
1107 | |
1108 | llvm::Reloc::Model RelocM = llvm::Reloc::Static; |
1109 | if (ROPI && RWPI) |
1110 | RelocM = llvm::Reloc::ROPI_RWPI; |
1111 | else if (ROPI) |
1112 | RelocM = llvm::Reloc::ROPI; |
1113 | else if (RWPI) |
1114 | RelocM = llvm::Reloc::RWPI; |
1115 | |
1116 | return std::make_tuple(RelocM, 0U, false); |
1117 | } |
1118 | |
1119 | |
1120 | |
1121 | |
1122 | |
1123 | |
1124 | |
1125 | |
1126 | |
1127 | |
1128 | |
1129 | |
1130 | |
1131 | |
1132 | |
1133 | |
1134 | |
1135 | unsigned tools::ParseFunctionAlignment(const ToolChain &TC, |
1136 | const ArgList &Args) { |
1137 | const Arg *A = Args.getLastArg(options::OPT_falign_functions, |
1138 | options::OPT_falign_functions_EQ, |
1139 | options::OPT_fno_align_functions); |
1140 | if (!A || A->getOption().matches(options::OPT_fno_align_functions)) |
1141 | return 0; |
1142 | |
1143 | if (A->getOption().matches(options::OPT_falign_functions)) |
1144 | return 0; |
1145 | |
1146 | unsigned Value = 0; |
1147 | if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 65536) |
1148 | TC.getDriver().Diag(diag::err_drv_invalid_int_value) |
1149 | << A->getAsString(Args) << A->getValue(); |
1150 | return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value; |
1151 | } |
1152 | |
1153 | void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args, |
1154 | ArgStringList &CmdArgs) { |
1155 | llvm::Reloc::Model RelocationModel; |
1156 | unsigned PICLevel; |
1157 | bool IsPIE; |
1158 | std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(ToolChain, Args); |
1159 | |
1160 | if (RelocationModel != llvm::Reloc::Static) |
1161 | CmdArgs.push_back("-KPIC"); |
1162 | } |
1163 | |
1164 | |
1165 | |
1166 | bool tools::isObjCAutoRefCount(const ArgList &Args) { |
1167 | return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false); |
1168 | } |
1169 | |
1170 | enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc }; |
1171 | |
1172 | static LibGccType getLibGccType(const ArgList &Args) { |
1173 | bool Static = Args.hasArg(options::OPT_static_libgcc) || |
1174 | Args.hasArg(options::OPT_static) || |
1175 | Args.hasArg(options::OPT_static_pie); |
1176 | |
1177 | bool Shared = Args.hasArg(options::OPT_shared_libgcc); |
1178 | if (Shared) |
1179 | return LibGccType::SharedLibGcc; |
1180 | if (Static) |
1181 | return LibGccType::StaticLibGcc; |
1182 | return LibGccType::UnspecifiedLibGcc; |
1183 | } |
1184 | |
1185 | |
1186 | |
1187 | |
1188 | |
1189 | |
1190 | |
1191 | |
1192 | |
1193 | |
1194 | |
1195 | |
1196 | |
1197 | |
1198 | static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, |
1199 | ArgStringList &CmdArgs, const ArgList &Args) { |
1200 | ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args); |
1201 | |
1202 | if (TC.getTriple().isAndroid() || TC.getTriple().isOSIAMCU() || |
1203 | TC.getTriple().isOSBinFormatWasm() || |
1204 | UNW == ToolChain::UNW_None) |
1205 | return; |
1206 | |
1207 | LibGccType LGT = getLibGccType(Args); |
1208 | bool AsNeeded = D.CCCIsCC() && LGT == LibGccType::UnspecifiedLibGcc && |
1209 | !TC.getTriple().isAndroid() && !TC.getTriple().isOSCygMing(); |
1210 | if (AsNeeded) |
1211 | CmdArgs.push_back("--as-needed"); |
1212 | |
1213 | switch (UNW) { |
1214 | case ToolChain::UNW_None: |
1215 | return; |
1216 | case ToolChain::UNW_Libgcc: { |
1217 | LibGccType LGT = getLibGccType(Args); |
1218 | if (LGT == LibGccType::UnspecifiedLibGcc || LGT == LibGccType::SharedLibGcc) |
1219 | CmdArgs.push_back("-lgcc_s"); |
1220 | else if (LGT == LibGccType::StaticLibGcc) |
1221 | CmdArgs.push_back("-lgcc_eh"); |
1222 | break; |
1223 | } |
1224 | case ToolChain::UNW_CompilerRT: |
1225 | CmdArgs.push_back("-lunwind"); |
1226 | break; |
1227 | } |
1228 | |
1229 | if (AsNeeded) |
1230 | CmdArgs.push_back("--no-as-needed"); |
1231 | } |
1232 | |
1233 | static void AddLibgcc(const ToolChain &TC, const Driver &D, |
1234 | ArgStringList &CmdArgs, const ArgList &Args) { |
1235 | bool isAndroid = TC.getTriple().isAndroid(); |
1236 | |
1237 | LibGccType LGT = getLibGccType(Args); |
1238 | bool LibGccFirst = (D.CCCIsCC() && LGT == LibGccType::UnspecifiedLibGcc) || |
1239 | LGT == LibGccType::StaticLibGcc; |
1240 | if (LibGccFirst) |
1241 | CmdArgs.push_back("-lgcc"); |
1242 | |
1243 | AddUnwindLibrary(TC, D, CmdArgs, Args); |
1244 | |
1245 | if (!LibGccFirst) |
1246 | CmdArgs.push_back("-lgcc"); |
1247 | |
1248 | |
1249 | |
1250 | |
1251 | |
1252 | |
1253 | if (isAndroid && getLibGccType(Args) != LibGccType::StaticLibGcc) |
1254 | CmdArgs.push_back("-ldl"); |
1255 | } |
1256 | |
1257 | void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, |
1258 | ArgStringList &CmdArgs, const ArgList &Args) { |
1259 | |
1260 | ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args); |
1261 | |
1262 | switch (RLT) { |
1263 | case ToolChain::RLT_CompilerRT: |
1264 | CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins")); |
1265 | AddUnwindLibrary(TC, D, CmdArgs, Args); |
1266 | break; |
1267 | case ToolChain::RLT_Libgcc: |
1268 | |
1269 | if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { |
1270 | |
1271 | |
1272 | if (Args.hasArg(options::OPT_rtlib_EQ)) { |
1273 | TC.getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform) |
1274 | << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "MSVC"; |
1275 | } |
1276 | } else |
1277 | AddLibgcc(TC, D, CmdArgs, Args); |
1278 | break; |
1279 | } |
1280 | } |
1281 | |
1282 | |
1283 | |
1284 | |
1285 | |
1286 | |
1287 | |
1288 | void tools::AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C, |
1289 | const InputInfo &Output, |
1290 | const InputInfoList &Inputs, |
1291 | const ArgList &Args, ArgStringList &CmdArgs, |
1292 | const JobAction &JA) { |
1293 | |
1294 | |
1295 | if (!JA.isHostOffloading(Action::OFK_OpenMP)) |
1296 | return; |
1297 | |
1298 | |
1299 | const char *LKS; |
1300 | SmallString<256> Name = llvm::sys::path::filename(Output.getFilename()); |
1301 | if (C.getDriver().isSaveTempsEnabled()) { |
1302 | llvm::sys::path::replace_extension(Name, "lk"); |
1303 | LKS = C.getArgs().MakeArgString(Name.c_str()); |
1304 | } else { |
1305 | llvm::sys::path::replace_extension(Name, ""); |
1306 | Name = C.getDriver().GetTemporaryPath(Name, "lk"); |
1307 | LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str())); |
1308 | } |
1309 | |
1310 | |
1311 | CmdArgs.push_back("-T"); |
1312 | CmdArgs.push_back(LKS); |
1313 | |
1314 | |
1315 | std::string LksBuffer; |
1316 | llvm::raw_string_ostream LksStream(LksBuffer); |
1317 | |
1318 | |
1319 | |
1320 | auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>(); |
1321 | (0) . __assert_fail ("OpenMPToolChains.first != OpenMPToolChains.second && \"No OpenMP toolchains??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/CommonArgs.cpp", 1322, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(OpenMPToolChains.first != OpenMPToolChains.second && |
1322 | (0) . __assert_fail ("OpenMPToolChains.first != OpenMPToolChains.second && \"No OpenMP toolchains??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/CommonArgs.cpp", 1322, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "No OpenMP toolchains??"); |
1323 | |
1324 | |
1325 | |
1326 | SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo; |
1327 | |
1328 | |
1329 | |
1330 | |
1331 | |
1332 | LksStream << "/*\n"; |
1333 | LksStream << " OpenMP Offload Linker Script\n"; |
1334 | LksStream << " *** Automatically generated by Clang ***\n"; |
1335 | LksStream << "*/\n"; |
1336 | LksStream << "TARGET(binary)\n"; |
1337 | auto DTC = OpenMPToolChains.first; |
1338 | for (auto &II : Inputs) { |
1339 | const Action *A = II.getAction(); |
1340 | |
1341 | if (A && isa<LinkJobAction>(A) && |
1342 | A->isDeviceOffloading(Action::OFK_OpenMP)) { |
1343 | (0) . __assert_fail ("DTC != OpenMPToolChains.second && \"More device inputs than device toolchains??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/CommonArgs.cpp", 1344, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(DTC != OpenMPToolChains.second && |
1344 | (0) . __assert_fail ("DTC != OpenMPToolChains.second && \"More device inputs than device toolchains??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/CommonArgs.cpp", 1344, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "More device inputs than device toolchains??"); |
1345 | InputBinaryInfo.push_back(std::make_pair( |
1346 | DTC->second->getTriple().normalize(), II.getFilename())); |
1347 | ++DTC; |
1348 | LksStream << "INPUT(" << II.getFilename() << ")\n"; |
1349 | } |
1350 | } |
1351 | |
1352 | (0) . __assert_fail ("DTC == OpenMPToolChains.second && \"Less device inputs than device toolchains??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/CommonArgs.cpp", 1353, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(DTC == OpenMPToolChains.second && |
1353 | (0) . __assert_fail ("DTC == OpenMPToolChains.second && \"Less device inputs than device toolchains??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/CommonArgs.cpp", 1353, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "Less device inputs than device toolchains??"); |
1354 | |
1355 | LksStream << "SECTIONS\n"; |
1356 | LksStream << "{\n"; |
1357 | |
1358 | |
1359 | for (const auto &BI : InputBinaryInfo) { |
1360 | LksStream << " .omp_offloading." << BI.first << " :\n"; |
1361 | LksStream << " ALIGN(0x10)\n"; |
1362 | LksStream << " {\n"; |
1363 | LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first |
1364 | << " = .);\n"; |
1365 | LksStream << " " << BI.second << "\n"; |
1366 | LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first |
1367 | << " = .);\n"; |
1368 | LksStream << " }\n"; |
1369 | } |
1370 | |
1371 | |
1372 | |
1373 | |
1374 | LksStream << " .omp_offloading.entries :\n"; |
1375 | LksStream << " ALIGN(0x10)\n"; |
1376 | LksStream << " SUBALIGN(0x01)\n"; |
1377 | LksStream << " {\n"; |
1378 | LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n"; |
1379 | LksStream << " *(.omp_offloading.entries)\n"; |
1380 | LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n"; |
1381 | LksStream << " }\n"; |
1382 | LksStream << "}\n"; |
1383 | LksStream << "INSERT BEFORE .data\n"; |
1384 | LksStream.flush(); |
1385 | |
1386 | |
1387 | |
1388 | if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script)) |
1389 | llvm::errs() << LksBuffer; |
1390 | |
1391 | |
1392 | if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) |
1393 | return; |
1394 | |
1395 | |
1396 | std::error_code EC; |
1397 | llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None); |
1398 | |
1399 | if (EC) { |
1400 | C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message(); |
1401 | return; |
1402 | } |
1403 | |
1404 | Lksf << LksBuffer; |
1405 | } |
1406 | |
1407 | |
1408 | |
1409 | |
1410 | |
1411 | |
1412 | void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, |
1413 | const InputInfo &Output, |
1414 | const InputInfoList &Inputs, const ArgList &Args, |
1415 | ArgStringList &CmdArgs, const JobAction &JA, |
1416 | const Tool &T) { |
1417 | |
1418 | |
1419 | if (!JA.isHostOffloading(Action::OFK_HIP)) |
1420 | return; |
1421 | |
1422 | InputInfoList DeviceInputs; |
1423 | for (const auto &II : Inputs) { |
1424 | const Action *A = II.getAction(); |
1425 | |
1426 | if (A && isa<LinkJobAction>(A) && A->isDeviceOffloading(Action::OFK_HIP)) { |
1427 | DeviceInputs.push_back(II); |
1428 | } |
1429 | } |
1430 | |
1431 | if (DeviceInputs.empty()) |
1432 | return; |
1433 | |
1434 | |
1435 | const char *LKS; |
1436 | SmallString<256> Name = llvm::sys::path::filename(Output.getFilename()); |
1437 | if (C.getDriver().isSaveTempsEnabled()) { |
1438 | llvm::sys::path::replace_extension(Name, "lk"); |
1439 | LKS = C.getArgs().MakeArgString(Name.c_str()); |
1440 | } else { |
1441 | llvm::sys::path::replace_extension(Name, ""); |
1442 | Name = C.getDriver().GetTemporaryPath(Name, "lk"); |
1443 | LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str())); |
1444 | } |
1445 | |
1446 | |
1447 | CmdArgs.push_back("-T"); |
1448 | CmdArgs.push_back(LKS); |
1449 | |
1450 | |
1451 | std::string LksBuffer; |
1452 | llvm::raw_string_ostream LksStream(LksBuffer); |
1453 | |
1454 | |
1455 | auto *HIPTC = static_cast<const toolchains::CudaToolChain *>( |
1456 | C.getSingleOffloadToolChain<Action::OFK_HIP>()); |
1457 | (0) . __assert_fail ("HIPTC->getTriple().getArch() == llvm..Triple..amdgcn && \"Wrong platform\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/CommonArgs.cpp", 1458, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(HIPTC->getTriple().getArch() == llvm::Triple::amdgcn && |
1458 | (0) . __assert_fail ("HIPTC->getTriple().getArch() == llvm..Triple..amdgcn && \"Wrong platform\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/ToolChains/CommonArgs.cpp", 1458, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "Wrong platform"); |
1459 | (void)HIPTC; |
1460 | |
1461 | |
1462 | |
1463 | std::string BundleFileName = C.getDriver().GetTemporaryPath("BUNDLE", "hipfb"); |
1464 | const char *BundleFile = |
1465 | C.addTempFile(C.getArgs().MakeArgString(BundleFileName.c_str())); |
1466 | AMDGCN::constructHIPFatbinCommand(C, JA, BundleFile, DeviceInputs, Args, T); |
1467 | |
1468 | |
1469 | |
1470 | |
1471 | |
1472 | LksStream << "/*\n"; |
1473 | LksStream << " HIP Offload Linker Script\n"; |
1474 | LksStream << " *** Automatically generated by Clang ***\n"; |
1475 | LksStream << "*/\n"; |
1476 | LksStream << "TARGET(binary)\n"; |
1477 | LksStream << "INPUT(" << BundleFileName << ")\n"; |
1478 | LksStream << "SECTIONS\n"; |
1479 | LksStream << "{\n"; |
1480 | LksStream << " .hip_fatbin :\n"; |
1481 | LksStream << " ALIGN(0x10)\n"; |
1482 | LksStream << " {\n"; |
1483 | LksStream << " PROVIDE_HIDDEN(__hip_fatbin = .);\n"; |
1484 | LksStream << " " << BundleFileName << "\n"; |
1485 | LksStream << " }\n"; |
1486 | LksStream << " /DISCARD/ :\n"; |
1487 | LksStream << " {\n"; |
1488 | LksStream << " * ( __CLANG_OFFLOAD_BUNDLE__* )\n"; |
1489 | LksStream << " }\n"; |
1490 | LksStream << "}\n"; |
1491 | LksStream << "INSERT BEFORE .data\n"; |
1492 | LksStream.flush(); |
1493 | |
1494 | |
1495 | |
1496 | if (C.getArgs().hasArg(options::OPT_fhip_dump_offload_linker_script)) |
1497 | llvm::errs() << LksBuffer; |
1498 | |
1499 | |
1500 | if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) |
1501 | return; |
1502 | |
1503 | |
1504 | std::error_code EC; |
1505 | llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None); |
1506 | |
1507 | if (EC) { |
1508 | C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message(); |
1509 | return; |
1510 | } |
1511 | |
1512 | Lksf << LksBuffer; |
1513 | } |
1514 | |
1515 | SmallString<128> tools::getStatsFileName(const llvm::opt::ArgList &Args, |
1516 | const InputInfo &Output, |
1517 | const InputInfo &Input, |
1518 | const Driver &D) { |
1519 | const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ); |
1520 | if (!A) |
1521 | return {}; |
1522 | |
1523 | StringRef SaveStats = A->getValue(); |
1524 | SmallString<128> StatsFile; |
1525 | if (SaveStats == "obj" && Output.isFilename()) { |
1526 | StatsFile.assign(Output.getFilename()); |
1527 | llvm::sys::path::remove_filename(StatsFile); |
1528 | } else if (SaveStats != "cwd") { |
1529 | D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats; |
1530 | return {}; |
1531 | } |
1532 | |
1533 | StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput()); |
1534 | llvm::sys::path::append(StatsFile, BaseName); |
1535 | llvm::sys::path::replace_extension(StatsFile, "stats"); |
1536 | return StatsFile; |
1537 | } |
1538 | |