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