1 //===--- PS4CPU.cpp - PS4CPU ToolChain Implementations ----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "PS4CPU.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/Options.h" 16 #include "clang/Driver/SanitizerArgs.h" 17 #include "llvm/Option/ArgList.h" 18 #include "llvm/Support/FileSystem.h" 19 #include "llvm/Support/Path.h" 20 #include <cstdlib> // ::getenv 21 22 using namespace clang::driver; 23 using namespace clang; 24 using namespace llvm::opt; 25 26 // Helper to paste bits of an option together and return a saved string. 27 static const char *makeArgString(const ArgList &Args, const char *Prefix, 28 const char *Base, const char *Suffix) { 29 // Basically "Prefix + Base + Suffix" all converted to Twine then saved. 30 return Args.MakeArgString(Twine(StringRef(Prefix), Base) + Suffix); 31 } 32 33 void tools::PScpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args, 34 ArgStringList &CmdArgs) { 35 assert(TC.getTriple().isPS()); 36 auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC); 37 38 if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, 39 false) || 40 Args.hasFlag(options::OPT_fprofile_generate, 41 options::OPT_fno_profile_generate, false) || 42 Args.hasFlag(options::OPT_fprofile_generate_EQ, 43 options::OPT_fno_profile_generate, false) || 44 Args.hasFlag(options::OPT_fprofile_instr_generate, 45 options::OPT_fno_profile_instr_generate, false) || 46 Args.hasFlag(options::OPT_fprofile_instr_generate_EQ, 47 options::OPT_fno_profile_instr_generate, false) || 48 Args.hasFlag(options::OPT_fcs_profile_generate, 49 options::OPT_fno_profile_generate, false) || 50 Args.hasFlag(options::OPT_fcs_profile_generate_EQ, 51 options::OPT_fno_profile_generate, false) || 52 Args.hasArg(options::OPT_fcreate_profile) || 53 Args.hasArg(options::OPT_coverage))) 54 CmdArgs.push_back(makeArgString( 55 Args, "--dependent-lib=", PSTC.getProfileRTLibName(), "")); 56 } 57 58 void tools::PScpu::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 59 const InputInfo &Output, 60 const InputInfoList &Inputs, 61 const ArgList &Args, 62 const char *LinkingOutput) const { 63 auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain()); 64 claimNoWarnArgs(Args); 65 ArgStringList CmdArgs; 66 67 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 68 69 CmdArgs.push_back("-o"); 70 CmdArgs.push_back(Output.getFilename()); 71 72 assert(Inputs.size() == 1 && "Unexpected number of inputs."); 73 const InputInfo &Input = Inputs[0]; 74 assert(Input.isFilename() && "Invalid input."); 75 CmdArgs.push_back(Input.getFilename()); 76 77 std::string AsName = TC.qualifyPSCmdName("as"); 78 const char *Exec = Args.MakeArgString(TC.GetProgramPath(AsName.c_str())); 79 C.addCommand(std::make_unique<Command>(JA, *this, 80 ResponseFileSupport::AtFileUTF8(), 81 Exec, CmdArgs, Inputs, Output)); 82 } 83 84 void tools::PScpu::addSanitizerArgs(const ToolChain &TC, const ArgList &Args, 85 ArgStringList &CmdArgs) { 86 assert(TC.getTriple().isPS()); 87 auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC); 88 PSTC.addSanitizerArgs(Args, CmdArgs, "--dependent-lib=lib", ".a"); 89 } 90 91 void toolchains::PS4CPU::addSanitizerArgs(const ArgList &Args, 92 ArgStringList &CmdArgs, 93 const char *Prefix, 94 const char *Suffix) const { 95 auto arg = [&](const char *Name) -> const char * { 96 return makeArgString(Args, Prefix, Name, Suffix); 97 }; 98 const SanitizerArgs &SanArgs = getSanitizerArgs(Args); 99 if (SanArgs.needsUbsanRt()) 100 CmdArgs.push_back(arg("SceDbgUBSanitizer_stub_weak")); 101 if (SanArgs.needsAsanRt()) 102 CmdArgs.push_back(arg("SceDbgAddressSanitizer_stub_weak")); 103 } 104 105 void toolchains::PS5CPU::addSanitizerArgs(const ArgList &Args, 106 ArgStringList &CmdArgs, 107 const char *Prefix, 108 const char *Suffix) const { 109 auto arg = [&](const char *Name) -> const char * { 110 return makeArgString(Args, Prefix, Name, Suffix); 111 }; 112 const SanitizerArgs &SanArgs = getSanitizerArgs(Args); 113 if (SanArgs.needsUbsanRt()) 114 CmdArgs.push_back(arg("SceUBSanitizer_nosubmission_stub_weak")); 115 if (SanArgs.needsAsanRt()) 116 CmdArgs.push_back(arg("SceAddressSanitizer_nosubmission_stub_weak")); 117 if (SanArgs.needsTsanRt()) 118 CmdArgs.push_back(arg("SceThreadSanitizer_nosubmission_stub_weak")); 119 } 120 121 void tools::PS4cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, 122 const InputInfo &Output, 123 const InputInfoList &Inputs, 124 const ArgList &Args, 125 const char *LinkingOutput) const { 126 auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain()); 127 const Driver &D = TC.getDriver(); 128 ArgStringList CmdArgs; 129 130 // Silence warning for "clang -g foo.o -o foo" 131 Args.ClaimAllArgs(options::OPT_g_Group); 132 // and "clang -emit-llvm foo.o -o foo" 133 Args.ClaimAllArgs(options::OPT_emit_llvm); 134 // and for "clang -w foo.o -o foo". Other warning options are already 135 // handled somewhere else. 136 Args.ClaimAllArgs(options::OPT_w); 137 138 CmdArgs.push_back( 139 Args.MakeArgString("--sysroot=" + TC.getSDKLibraryRootDir())); 140 141 if (Args.hasArg(options::OPT_pie)) 142 CmdArgs.push_back("-pie"); 143 144 if (Args.hasArg(options::OPT_static)) 145 CmdArgs.push_back("-static"); 146 if (Args.hasArg(options::OPT_rdynamic)) 147 CmdArgs.push_back("-export-dynamic"); 148 if (Args.hasArg(options::OPT_shared)) 149 CmdArgs.push_back("--shared"); 150 151 assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 152 if (Output.isFilename()) { 153 CmdArgs.push_back("-o"); 154 CmdArgs.push_back(Output.getFilename()); 155 } 156 157 const bool UseJMC = 158 Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false); 159 160 const char *LTOArgs = ""; 161 auto AddLTOFlag = [&](Twine Flag) { 162 LTOArgs = Args.MakeArgString(Twine(LTOArgs) + " " + Flag); 163 }; 164 165 // If the linker sees bitcode objects it will perform LTO. We can't tell 166 // whether or not that will be the case at this point. So, unconditionally 167 // pass LTO options to ensure proper codegen, metadata production, etc if 168 // LTO indeed occurs. 169 if (Args.hasFlag(options::OPT_funified_lto, options::OPT_fno_unified_lto, 170 true)) 171 CmdArgs.push_back(D.getLTOMode() == LTOK_Thin ? "--lto=thin" 172 : "--lto=full"); 173 if (UseJMC) 174 AddLTOFlag("-enable-jmc-instrument"); 175 176 if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir)) 177 AddLTOFlag(Twine("-crash-diagnostics-dir=") + A->getValue()); 178 179 if (StringRef Threads = getLTOParallelism(Args, D); !Threads.empty()) 180 AddLTOFlag(Twine("-threads=") + Threads); 181 182 if (*LTOArgs) 183 CmdArgs.push_back( 184 Args.MakeArgString(Twine("-lto-debug-options=") + LTOArgs)); 185 186 // Sanitizer runtimes must be supplied before all other objects and libs. 187 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) 188 TC.addSanitizerArgs(Args, CmdArgs, "-l", ""); 189 190 // Other drivers typically add library search paths (`-L`) here via 191 // TC.AddFilePathLibArgs(). We don't do that on PS4 as the PS4 linker 192 // searches those locations by default. 193 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, 194 options::OPT_s, options::OPT_t}); 195 196 if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) 197 CmdArgs.push_back("--no-demangle"); 198 199 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 200 201 if (Args.hasArg(options::OPT_pthread)) { 202 CmdArgs.push_back("-lpthread"); 203 } 204 205 if (UseJMC) { 206 CmdArgs.push_back("--whole-archive"); 207 CmdArgs.push_back("-lSceDbgJmc"); 208 CmdArgs.push_back("--no-whole-archive"); 209 } 210 211 if (Args.hasArg(options::OPT_fuse_ld_EQ)) { 212 D.Diag(diag::err_drv_unsupported_opt_for_target) 213 << "-fuse-ld" << TC.getTriple().str(); 214 } 215 216 std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName()); 217 const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str())); 218 219 C.addCommand(std::make_unique<Command>(JA, *this, 220 ResponseFileSupport::AtFileUTF8(), 221 Exec, CmdArgs, Inputs, Output)); 222 } 223 224 void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, 225 const InputInfo &Output, 226 const InputInfoList &Inputs, 227 const ArgList &Args, 228 const char *LinkingOutput) const { 229 auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain()); 230 const Driver &D = TC.getDriver(); 231 ArgStringList CmdArgs; 232 233 const bool Relocatable = Args.hasArg(options::OPT_r); 234 const bool Shared = Args.hasArg(options::OPT_shared); 235 const bool Static = Args.hasArg(options::OPT_static); 236 237 // Silence warning for "clang -g foo.o -o foo" 238 Args.ClaimAllArgs(options::OPT_g_Group); 239 // and "clang -emit-llvm foo.o -o foo" 240 Args.ClaimAllArgs(options::OPT_emit_llvm); 241 // and for "clang -w foo.o -o foo". Other warning options are already 242 // handled somewhere else. 243 Args.ClaimAllArgs(options::OPT_w); 244 245 CmdArgs.push_back("-m"); 246 CmdArgs.push_back("elf_x86_64_fbsd"); 247 248 CmdArgs.push_back( 249 Args.MakeArgString("--sysroot=" + TC.getSDKLibraryRootDir())); 250 251 // Default to PIE for non-static executables. 252 const bool PIE = Args.hasFlag(options::OPT_pie, options::OPT_no_pie, 253 !Relocatable && !Shared && !Static); 254 if (PIE) 255 CmdArgs.push_back("-pie"); 256 257 if (!Relocatable) { 258 CmdArgs.push_back("--eh-frame-hdr"); 259 CmdArgs.push_back("--hash-style=sysv"); 260 261 // Add a build-id by default to allow the PlayStation symbol server to 262 // index the symbols. `uuid` is the cheapest fool-proof method. 263 // (The non-determinism and alternative methods are noted in the downstream 264 // PlayStation docs). 265 // Static executables are only used for a handful of specialized components, 266 // where the extra section is not wanted. 267 if (!Static) 268 CmdArgs.push_back("--build-id=uuid"); 269 270 // All references are expected to be resolved at static link time for both 271 // executables and dynamic libraries. This has been the default linking 272 // behaviour for numerous PlayStation generations. 273 CmdArgs.push_back("--unresolved-symbols=report-all"); 274 275 // Lazy binding of PLTs is not supported on PlayStation. They are placed in 276 // the RelRo segment. 277 CmdArgs.push_back("-z"); 278 CmdArgs.push_back("now"); 279 280 // Don't export linker-generated __start/stop... section bookends. 281 CmdArgs.push_back("-z"); 282 CmdArgs.push_back("start-stop-visibility=hidden"); 283 284 // DT_DEBUG is not supported on PlayStation. 285 CmdArgs.push_back("-z"); 286 CmdArgs.push_back("rodynamic"); 287 288 CmdArgs.push_back("-z"); 289 CmdArgs.push_back("common-page-size=0x4000"); 290 291 CmdArgs.push_back("-z"); 292 CmdArgs.push_back("max-page-size=0x4000"); 293 294 // Patch relocated regions of DWARF whose targets are eliminated at link 295 // time with specific tombstones, such that they're recognisable by the 296 // PlayStation debugger. 297 CmdArgs.push_back("-z"); 298 CmdArgs.push_back("dead-reloc-in-nonalloc=.debug_*=0xffffffffffffffff"); 299 CmdArgs.push_back("-z"); 300 CmdArgs.push_back( 301 "dead-reloc-in-nonalloc=.debug_ranges=0xfffffffffffffffe"); 302 CmdArgs.push_back("-z"); 303 CmdArgs.push_back("dead-reloc-in-nonalloc=.debug_loc=0xfffffffffffffffe"); 304 305 // The PlayStation loader expects linked objects to be laid out in a 306 // particular way. This is achieved by linker scripts that are supplied 307 // with the SDK. The scripts are inside <sdkroot>/target/lib, which is 308 // added as a search path elsewhere. 309 // "PRX" has long stood for "PlayStation Relocatable eXecutable". 310 if (!Args.hasArgNoClaim(options::OPT_T)) { 311 CmdArgs.push_back("--default-script"); 312 CmdArgs.push_back(Static ? "static.script" 313 : Shared ? "prx.script" 314 : "main.script"); 315 } 316 } 317 318 if (Static) 319 CmdArgs.push_back("-static"); 320 if (Args.hasArg(options::OPT_rdynamic)) 321 CmdArgs.push_back("-export-dynamic"); 322 if (Shared) 323 CmdArgs.push_back("--shared"); 324 325 // Provide a base address for non-PIE executables. This includes cases where 326 // -static is supplied without -pie. 327 if (!Relocatable && !Shared && !PIE) 328 CmdArgs.push_back("--image-base=0x400000"); 329 330 assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 331 if (Output.isFilename()) { 332 CmdArgs.push_back("-o"); 333 CmdArgs.push_back(Output.getFilename()); 334 } 335 336 const bool UseJMC = 337 Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false); 338 339 auto AddLTOFlag = [&](Twine Flag) { 340 CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=") + Flag)); 341 }; 342 343 // If the linker sees bitcode objects it will perform LTO. We can't tell 344 // whether or not that will be the case at this point. So, unconditionally 345 // pass LTO options to ensure proper codegen, metadata production, etc if 346 // LTO indeed occurs. 347 if (Args.hasFlag(options::OPT_funified_lto, options::OPT_fno_unified_lto, 348 true)) 349 CmdArgs.push_back(D.getLTOMode() == LTOK_Thin ? "--lto=thin" 350 : "--lto=full"); 351 352 AddLTOFlag("-emit-jump-table-sizes-section"); 353 354 if (UseJMC) 355 AddLTOFlag("-enable-jmc-instrument"); 356 357 if (Args.hasFlag(options::OPT_fstack_size_section, 358 options::OPT_fno_stack_size_section, false)) 359 AddLTOFlag("-stack-size-section"); 360 361 if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir)) 362 AddLTOFlag(Twine("-crash-diagnostics-dir=") + A->getValue()); 363 364 if (StringRef Jobs = getLTOParallelism(Args, D); !Jobs.empty()) 365 AddLTOFlag(Twine("jobs=") + Jobs); 366 367 Args.AddAllArgs(CmdArgs, options::OPT_L); 368 TC.AddFilePathLibArgs(Args, CmdArgs); 369 Args.addAllArgs(CmdArgs, 370 {options::OPT_T_Group, options::OPT_s, options::OPT_t}); 371 372 if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) 373 CmdArgs.push_back("--no-demangle"); 374 375 // Sanitizer runtimes must be supplied before all other objects and libs. 376 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) 377 TC.addSanitizerArgs(Args, CmdArgs, "-l", ""); 378 379 const bool AddStartFiles = 380 !Relocatable && 381 !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib); 382 383 auto AddCRTObject = [&](const char *Name) { 384 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(Name))); 385 }; 386 387 if (AddStartFiles) { 388 if (!Shared) 389 AddCRTObject("crt1.o"); 390 AddCRTObject("crti.o"); 391 AddCRTObject(Shared ? "crtbeginS.o" 392 : Static ? "crtbeginT.o" 393 : "crtbegin.o"); 394 } 395 396 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 397 398 if (!Relocatable && 399 !Args.hasArg(options::OPT_nodefaultlibs, options::OPT_nostdlib)) { 400 401 if (UseJMC) { 402 CmdArgs.push_back("--push-state"); 403 CmdArgs.push_back("--whole-archive"); 404 CmdArgs.push_back("-lSceJmc_nosubmission"); 405 CmdArgs.push_back("--pop-state"); 406 } 407 408 if (Args.hasArg(options::OPT_pthread)) 409 CmdArgs.push_back("-lpthread"); 410 411 if (Static) { 412 if (!Args.hasArg(options::OPT_nostdlibxx)) 413 CmdArgs.push_back("-lstdc++"); 414 if (!Args.hasArg(options::OPT_nolibc)) { 415 CmdArgs.push_back("-lm"); 416 CmdArgs.push_back("-lc"); 417 } 418 419 CmdArgs.push_back("-lcompiler_rt"); 420 CmdArgs.push_back("-lkernel"); 421 } else { 422 // The C and C++ libraries are combined. 423 if (!Args.hasArg(options::OPT_nolibc, options::OPT_nostdlibxx)) 424 CmdArgs.push_back("-lc_stub_weak"); 425 426 CmdArgs.push_back("-lkernel_stub_weak"); 427 } 428 } 429 if (AddStartFiles) { 430 AddCRTObject(Shared ? "crtendS.o" : "crtend.o"); 431 AddCRTObject("crtn.o"); 432 } 433 434 if (Args.hasArg(options::OPT_fuse_ld_EQ)) { 435 D.Diag(diag::err_drv_unsupported_opt_for_target) 436 << "-fuse-ld" << TC.getTriple().str(); 437 } 438 439 std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName()); 440 const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str())); 441 442 C.addCommand(std::make_unique<Command>(JA, *this, 443 ResponseFileSupport::AtFileUTF8(), 444 Exec, CmdArgs, Inputs, Output)); 445 } 446 447 toolchains::PS4PS5Base::PS4PS5Base(const Driver &D, const llvm::Triple &Triple, 448 const ArgList &Args, StringRef Platform, 449 const char *EnvVar) 450 : Generic_ELF(D, Triple, Args) { 451 // Determine the baseline SDK directory from the environment, else 452 // the driver's location, which should be <SDK_DIR>/host_tools/bin. 453 SmallString<128> SDKRootDir; 454 SmallString<80> Whence; 455 if (const char *EnvValue = getenv(EnvVar)) { 456 SDKRootDir = EnvValue; 457 Whence = {"environment variable '", EnvVar, "'"}; 458 } else { 459 SDKRootDir = D.Dir + "/../../"; 460 Whence = "compiler's location"; 461 } 462 463 // Allow --sysroot= to override the root directory for header and library 464 // search, and -isysroot to override header search. If both are specified, 465 // -isysroot overrides --sysroot for header search. 466 auto OverrideRoot = [&](const options::ID &Opt, std::string &Root, 467 StringRef Default) { 468 if (const Arg *A = Args.getLastArg(Opt)) { 469 Root = A->getValue(); 470 if (!llvm::sys::fs::exists(Root)) 471 D.Diag(clang::diag::warn_missing_sysroot) << Root; 472 return true; 473 } 474 Root = Default.str(); 475 return false; 476 }; 477 478 bool CustomSysroot = 479 OverrideRoot(options::OPT__sysroot_EQ, SDKLibraryRootDir, SDKRootDir); 480 bool CustomISysroot = 481 OverrideRoot(options::OPT_isysroot, SDKHeaderRootDir, SDKLibraryRootDir); 482 483 // Emit warnings if parts of the SDK are missing, unless the user has taken 484 // control of header or library search. If we're not linking, don't check 485 // for missing libraries. 486 auto CheckSDKPartExists = [&](StringRef Dir, StringRef Desc) { 487 if (llvm::sys::fs::exists(Dir)) 488 return true; 489 D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected) 490 << (Twine(Platform) + " " + Desc).str() << Dir << Whence; 491 return false; 492 }; 493 494 bool Linking = !Args.hasArg(options::OPT_E, options::OPT_c, options::OPT_S, 495 options::OPT_emit_ast); 496 if (Linking) { 497 SmallString<128> Dir(SDKLibraryRootDir); 498 llvm::sys::path::append(Dir, "target/lib"); 499 if (CheckSDKPartExists(Dir, "system libraries")) 500 getFilePaths().push_back(std::string(Dir)); 501 } 502 if (!CustomSysroot && !CustomISysroot && 503 !Args.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc)) { 504 SmallString<128> Dir(SDKHeaderRootDir); 505 llvm::sys::path::append(Dir, "target/include"); 506 CheckSDKPartExists(Dir, "system headers"); 507 } 508 509 getFilePaths().push_back("."); 510 } 511 512 void toolchains::PS4PS5Base::AddClangSystemIncludeArgs( 513 const ArgList &DriverArgs, ArgStringList &CC1Args) const { 514 const Driver &D = getDriver(); 515 516 if (DriverArgs.hasArg(options::OPT_nostdinc)) 517 return; 518 519 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 520 SmallString<128> Dir(D.ResourceDir); 521 llvm::sys::path::append(Dir, "include"); 522 addSystemInclude(DriverArgs, CC1Args, Dir.str()); 523 } 524 525 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 526 return; 527 528 addExternCSystemInclude(DriverArgs, CC1Args, 529 SDKHeaderRootDir + "/target/include"); 530 addExternCSystemInclude(DriverArgs, CC1Args, 531 SDKHeaderRootDir + "/target/include_common"); 532 } 533 534 Tool *toolchains::PS4CPU::buildAssembler() const { 535 return new tools::PScpu::Assembler(*this); 536 } 537 538 Tool *toolchains::PS4CPU::buildLinker() const { 539 return new tools::PS4cpu::Linker(*this); 540 } 541 542 Tool *toolchains::PS5CPU::buildAssembler() const { 543 // PS5 does not support an external assembler. 544 getDriver().Diag(clang::diag::err_no_external_assembler); 545 return nullptr; 546 } 547 548 Tool *toolchains::PS5CPU::buildLinker() const { 549 return new tools::PS5cpu::Linker(*this); 550 } 551 552 SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers() const { 553 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 554 Res |= SanitizerKind::Address; 555 Res |= SanitizerKind::PointerCompare; 556 Res |= SanitizerKind::PointerSubtract; 557 Res |= SanitizerKind::Vptr; 558 return Res; 559 } 560 561 SanitizerMask toolchains::PS5CPU::getSupportedSanitizers() const { 562 SanitizerMask Res = PS4PS5Base::getSupportedSanitizers(); 563 Res |= SanitizerKind::Thread; 564 return Res; 565 } 566 567 void toolchains::PS4PS5Base::addClangTargetOptions( 568 const ArgList &DriverArgs, ArgStringList &CC1Args, 569 Action::OffloadKind DeviceOffloadingKind) const { 570 // PS4/PS5 do not use init arrays. 571 if (DriverArgs.hasArg(options::OPT_fuse_init_array)) { 572 Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array); 573 getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target) 574 << A->getAsString(DriverArgs) << getTriple().str(); 575 } 576 577 CC1Args.push_back("-fno-use-init-array"); 578 579 // Default to `hidden` visibility for PS5. 580 if (getTriple().isPS5() && 581 !DriverArgs.hasArg(options::OPT_fvisibility_EQ, 582 options::OPT_fvisibility_ms_compat)) 583 CC1Args.push_back("-fvisibility=hidden"); 584 585 // Default to -fvisibility-global-new-delete=source for PS5. 586 if (getTriple().isPS5() && 587 !DriverArgs.hasArg(options::OPT_fvisibility_global_new_delete_EQ, 588 options::OPT_fvisibility_global_new_delete_hidden)) 589 CC1Args.push_back("-fvisibility-global-new-delete=source"); 590 591 const Arg *A = 592 DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass, 593 options::OPT_fno_visibility_from_dllstorageclass); 594 if (!A || 595 A->getOption().matches(options::OPT_fvisibility_from_dllstorageclass)) { 596 CC1Args.push_back("-fvisibility-from-dllstorageclass"); 597 598 if (DriverArgs.hasArg(options::OPT_fvisibility_dllexport_EQ)) 599 DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_dllexport_EQ); 600 else 601 CC1Args.push_back("-fvisibility-dllexport=protected"); 602 603 // For PS4 we override the visibilty of globals definitions without 604 // dllimport or dllexport annotations. 605 if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ)) 606 DriverArgs.AddLastArg(CC1Args, 607 options::OPT_fvisibility_nodllstorageclass_EQ); 608 else if (getTriple().isPS4()) 609 CC1Args.push_back("-fvisibility-nodllstorageclass=hidden"); 610 else 611 CC1Args.push_back("-fvisibility-nodllstorageclass=keep"); 612 613 if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ)) 614 DriverArgs.AddLastArg(CC1Args, 615 options::OPT_fvisibility_externs_dllimport_EQ); 616 else 617 CC1Args.push_back("-fvisibility-externs-dllimport=default"); 618 619 // For PS4 we override the visibilty of external globals without 620 // dllimport or dllexport annotations. 621 if (DriverArgs.hasArg( 622 options::OPT_fvisibility_externs_nodllstorageclass_EQ)) 623 DriverArgs.AddLastArg( 624 CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ); 625 else if (getTriple().isPS4()) 626 CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default"); 627 else 628 CC1Args.push_back("-fvisibility-externs-nodllstorageclass=keep"); 629 } 630 631 // Enable jump table sizes section for PS5. 632 if (getTriple().isPS5()) { 633 CC1Args.push_back("-mllvm"); 634 CC1Args.push_back("-emit-jump-table-sizes-section"); 635 } 636 } 637 638 // PS4 toolchain. 639 toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple, 640 const llvm::opt::ArgList &Args) 641 : PS4PS5Base(D, Triple, Args, "PS4", "SCE_ORBIS_SDK_DIR") {} 642 643 // PS5 toolchain. 644 toolchains::PS5CPU::PS5CPU(const Driver &D, const llvm::Triple &Triple, 645 const llvm::opt::ArgList &Args) 646 : PS4PS5Base(D, Triple, Args, "PS5", "SCE_PROSPERO_SDK_DIR") {} 647