10b57cec5SDimitry Andric //===--- PS4CPU.cpp - PS4CPU ToolChain Implementations ----------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "PS4CPU.h" 100b57cec5SDimitry Andric #include "CommonArgs.h" 1106c3fb27SDimitry Andric #include "clang/Config/config.h" 120b57cec5SDimitry Andric #include "clang/Driver/Compilation.h" 130b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 140b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 150b57cec5SDimitry Andric #include "clang/Driver/Options.h" 160b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h" 170b57cec5SDimitry Andric #include "llvm/Option/ArgList.h" 180b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 190b57cec5SDimitry Andric #include "llvm/Support/Path.h" 200b57cec5SDimitry Andric #include <cstdlib> // ::getenv 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace clang::driver; 230b57cec5SDimitry Andric using namespace clang; 240b57cec5SDimitry Andric using namespace llvm::opt; 250b57cec5SDimitry Andric 2681ad6265SDimitry Andric // Helper to paste bits of an option together and return a saved string. 2781ad6265SDimitry Andric static const char *makeArgString(const ArgList &Args, const char *Prefix, 2881ad6265SDimitry Andric const char *Base, const char *Suffix) { 2981ad6265SDimitry Andric // Basically "Prefix + Base + Suffix" all converted to Twine then saved. 3081ad6265SDimitry Andric return Args.MakeArgString(Twine(StringRef(Prefix), Base) + Suffix); 3181ad6265SDimitry Andric } 3281ad6265SDimitry Andric 3381ad6265SDimitry Andric void tools::PScpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args, 340b57cec5SDimitry Andric ArgStringList &CmdArgs) { 3581ad6265SDimitry Andric assert(TC.getTriple().isPS()); 3681ad6265SDimitry Andric auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC); 3781ad6265SDimitry Andric 380b57cec5SDimitry Andric if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, 390b57cec5SDimitry Andric false) || 400b57cec5SDimitry Andric Args.hasFlag(options::OPT_fprofile_generate, 415ffd83dbSDimitry Andric options::OPT_fno_profile_generate, false) || 420b57cec5SDimitry Andric Args.hasFlag(options::OPT_fprofile_generate_EQ, 435ffd83dbSDimitry Andric options::OPT_fno_profile_generate, false) || 440b57cec5SDimitry Andric Args.hasFlag(options::OPT_fprofile_instr_generate, 450b57cec5SDimitry Andric options::OPT_fno_profile_instr_generate, false) || 460b57cec5SDimitry Andric Args.hasFlag(options::OPT_fprofile_instr_generate_EQ, 470b57cec5SDimitry Andric options::OPT_fno_profile_instr_generate, false) || 485ffd83dbSDimitry Andric Args.hasFlag(options::OPT_fcs_profile_generate, 495ffd83dbSDimitry Andric options::OPT_fno_profile_generate, false) || 505ffd83dbSDimitry Andric Args.hasFlag(options::OPT_fcs_profile_generate_EQ, 515ffd83dbSDimitry Andric options::OPT_fno_profile_generate, false) || 520b57cec5SDimitry Andric Args.hasArg(options::OPT_fcreate_profile) || 530b57cec5SDimitry Andric Args.hasArg(options::OPT_coverage))) 5481ad6265SDimitry Andric CmdArgs.push_back(makeArgString( 5581ad6265SDimitry Andric Args, "--dependent-lib=", PSTC.getProfileRTLibName(), "")); 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 5881ad6265SDimitry Andric void tools::PScpu::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 590b57cec5SDimitry Andric const InputInfo &Output, 600b57cec5SDimitry Andric const InputInfoList &Inputs, 610b57cec5SDimitry Andric const ArgList &Args, 620b57cec5SDimitry Andric const char *LinkingOutput) const { 6381ad6265SDimitry Andric auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain()); 640b57cec5SDimitry Andric claimNoWarnArgs(Args); 650b57cec5SDimitry Andric ArgStringList CmdArgs; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric CmdArgs.push_back("-o"); 700b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric assert(Inputs.size() == 1 && "Unexpected number of inputs."); 730b57cec5SDimitry Andric const InputInfo &Input = Inputs[0]; 740b57cec5SDimitry Andric assert(Input.isFilename() && "Invalid input."); 750b57cec5SDimitry Andric CmdArgs.push_back(Input.getFilename()); 760b57cec5SDimitry Andric 7781ad6265SDimitry Andric std::string AsName = TC.qualifyPSCmdName("as"); 7881ad6265SDimitry Andric const char *Exec = Args.MakeArgString(TC.GetProgramPath(AsName.c_str())); 79e8d8bef9SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, 80e8d8bef9SDimitry Andric ResponseFileSupport::AtFileUTF8(), 81e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 8481ad6265SDimitry Andric void tools::PScpu::addSanitizerArgs(const ToolChain &TC, const ArgList &Args, 85349cc55cSDimitry Andric ArgStringList &CmdArgs) { 8681ad6265SDimitry Andric assert(TC.getTriple().isPS()); 8781ad6265SDimitry Andric auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC); 8881ad6265SDimitry Andric PSTC.addSanitizerArgs(Args, CmdArgs, "--dependent-lib=lib", ".a"); 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 9181ad6265SDimitry Andric void toolchains::PS4CPU::addSanitizerArgs(const ArgList &Args, 9281ad6265SDimitry Andric ArgStringList &CmdArgs, 9381ad6265SDimitry Andric const char *Prefix, 9481ad6265SDimitry Andric const char *Suffix) const { 9581ad6265SDimitry Andric auto arg = [&](const char *Name) -> const char * { 9681ad6265SDimitry Andric return makeArgString(Args, Prefix, Name, Suffix); 9781ad6265SDimitry Andric }; 9881ad6265SDimitry Andric const SanitizerArgs &SanArgs = getSanitizerArgs(Args); 990b57cec5SDimitry Andric if (SanArgs.needsUbsanRt()) 10081ad6265SDimitry Andric CmdArgs.push_back(arg("SceDbgUBSanitizer_stub_weak")); 1010b57cec5SDimitry Andric if (SanArgs.needsAsanRt()) 10281ad6265SDimitry Andric CmdArgs.push_back(arg("SceDbgAddressSanitizer_stub_weak")); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 10581ad6265SDimitry Andric void toolchains::PS5CPU::addSanitizerArgs(const ArgList &Args, 10681ad6265SDimitry Andric ArgStringList &CmdArgs, 10781ad6265SDimitry Andric const char *Prefix, 10881ad6265SDimitry Andric const char *Suffix) const { 10981ad6265SDimitry Andric auto arg = [&](const char *Name) -> const char * { 11081ad6265SDimitry Andric return makeArgString(Args, Prefix, Name, Suffix); 11181ad6265SDimitry Andric }; 11281ad6265SDimitry Andric const SanitizerArgs &SanArgs = getSanitizerArgs(Args); 11381ad6265SDimitry Andric if (SanArgs.needsUbsanRt()) 11481ad6265SDimitry Andric CmdArgs.push_back(arg("SceUBSanitizer_nosubmission_stub_weak")); 11581ad6265SDimitry Andric if (SanArgs.needsAsanRt()) 11681ad6265SDimitry Andric CmdArgs.push_back(arg("SceAddressSanitizer_nosubmission_stub_weak")); 11781ad6265SDimitry Andric if (SanArgs.needsTsanRt()) 11881ad6265SDimitry Andric CmdArgs.push_back(arg("SceThreadSanitizer_nosubmission_stub_weak")); 11981ad6265SDimitry Andric } 12081ad6265SDimitry Andric 121*0fca6ea1SDimitry Andric void tools::PS4cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, 1225ffd83dbSDimitry Andric const InputInfo &Output, 1230b57cec5SDimitry Andric const InputInfoList &Inputs, 1240b57cec5SDimitry Andric const ArgList &Args, 1255ffd83dbSDimitry Andric const char *LinkingOutput) const { 12681ad6265SDimitry Andric auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain()); 12781ad6265SDimitry Andric const Driver &D = TC.getDriver(); 1280b57cec5SDimitry Andric ArgStringList CmdArgs; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric // Silence warning for "clang -g foo.o -o foo" 1310b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_g_Group); 1320b57cec5SDimitry Andric // and "clang -emit-llvm foo.o -o foo" 1330b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_emit_llvm); 1340b57cec5SDimitry Andric // and for "clang -w foo.o -o foo". Other warning options are already 1350b57cec5SDimitry Andric // handled somewhere else. 1360b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_w); 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric if (!D.SysRoot.empty()) 1390b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pie)) 1420b57cec5SDimitry Andric CmdArgs.push_back("-pie"); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric if (Args.hasArg(options::OPT_rdynamic)) 1450b57cec5SDimitry Andric CmdArgs.push_back("-export-dynamic"); 1460b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared)) 14781ad6265SDimitry Andric CmdArgs.push_back("--shared"); 1480b57cec5SDimitry Andric 1495f757f3fSDimitry Andric assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 1500b57cec5SDimitry Andric if (Output.isFilename()) { 1510b57cec5SDimitry Andric CmdArgs.push_back("-o"); 1520b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 155bdd1243dSDimitry Andric const bool UseLTO = D.isUsingLTO(); 156bdd1243dSDimitry Andric const bool UseJMC = 157bdd1243dSDimitry Andric Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false); 158bdd1243dSDimitry Andric 159*0fca6ea1SDimitry Andric const char *LTOArgs = ""; 160bdd1243dSDimitry Andric auto AddCodeGenFlag = [&](Twine Flag) { 161*0fca6ea1SDimitry Andric LTOArgs = Args.MakeArgString(Twine(LTOArgs) + " " + Flag); 162*0fca6ea1SDimitry Andric }; 163*0fca6ea1SDimitry Andric 164*0fca6ea1SDimitry Andric if (UseLTO) { 165*0fca6ea1SDimitry Andric // We default to creating the arange section, but LTO does not. Enable it 166*0fca6ea1SDimitry Andric // here. 167*0fca6ea1SDimitry Andric AddCodeGenFlag("-generate-arange-section"); 168*0fca6ea1SDimitry Andric 169*0fca6ea1SDimitry Andric // This tells LTO to perform JustMyCode instrumentation. 170*0fca6ea1SDimitry Andric if (UseJMC) 171*0fca6ea1SDimitry Andric AddCodeGenFlag("-enable-jmc-instrument"); 172*0fca6ea1SDimitry Andric 173*0fca6ea1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir)) 174*0fca6ea1SDimitry Andric AddCodeGenFlag(Twine("-crash-diagnostics-dir=") + A->getValue()); 175*0fca6ea1SDimitry Andric 176*0fca6ea1SDimitry Andric StringRef Parallelism = getLTOParallelism(Args, D); 177*0fca6ea1SDimitry Andric if (!Parallelism.empty()) 178*0fca6ea1SDimitry Andric AddCodeGenFlag(Twine("-threads=") + Parallelism); 179*0fca6ea1SDimitry Andric 180*0fca6ea1SDimitry Andric const char *Prefix = nullptr; 181*0fca6ea1SDimitry Andric if (D.getLTOMode() == LTOK_Thin) 182*0fca6ea1SDimitry Andric Prefix = "-lto-thin-debug-options="; 183*0fca6ea1SDimitry Andric else if (D.getLTOMode() == LTOK_Full) 184*0fca6ea1SDimitry Andric Prefix = "-lto-debug-options="; 1855f757f3fSDimitry Andric else 186*0fca6ea1SDimitry Andric llvm_unreachable("new LTO mode?"); 187*0fca6ea1SDimitry Andric 188*0fca6ea1SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine(Prefix) + LTOArgs)); 189*0fca6ea1SDimitry Andric } 190*0fca6ea1SDimitry Andric 191*0fca6ea1SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) 192*0fca6ea1SDimitry Andric TC.addSanitizerArgs(Args, CmdArgs, "-l", ""); 193*0fca6ea1SDimitry Andric 194*0fca6ea1SDimitry Andric if (D.isUsingLTO() && Args.hasArg(options::OPT_funified_lto)) { 195*0fca6ea1SDimitry Andric if (D.getLTOMode() == LTOK_Thin) 196*0fca6ea1SDimitry Andric CmdArgs.push_back("--lto=thin"); 197*0fca6ea1SDimitry Andric else if (D.getLTOMode() == LTOK_Full) 198*0fca6ea1SDimitry Andric CmdArgs.push_back("--lto=full"); 199*0fca6ea1SDimitry Andric } 200*0fca6ea1SDimitry Andric 201*0fca6ea1SDimitry Andric Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, 202*0fca6ea1SDimitry Andric options::OPT_s, options::OPT_t}); 203*0fca6ea1SDimitry Andric 204*0fca6ea1SDimitry Andric if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) 205*0fca6ea1SDimitry Andric CmdArgs.push_back("--no-demangle"); 206*0fca6ea1SDimitry Andric 207*0fca6ea1SDimitry Andric AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 208*0fca6ea1SDimitry Andric 209*0fca6ea1SDimitry Andric if (Args.hasArg(options::OPT_pthread)) { 210*0fca6ea1SDimitry Andric CmdArgs.push_back("-lpthread"); 211*0fca6ea1SDimitry Andric } 212*0fca6ea1SDimitry Andric 213*0fca6ea1SDimitry Andric if (UseJMC) { 214*0fca6ea1SDimitry Andric CmdArgs.push_back("--whole-archive"); 215*0fca6ea1SDimitry Andric CmdArgs.push_back("-lSceDbgJmc"); 216*0fca6ea1SDimitry Andric CmdArgs.push_back("--no-whole-archive"); 217*0fca6ea1SDimitry Andric } 218*0fca6ea1SDimitry Andric 219*0fca6ea1SDimitry Andric if (Args.hasArg(options::OPT_fuse_ld_EQ)) { 220*0fca6ea1SDimitry Andric D.Diag(diag::err_drv_unsupported_opt_for_target) 221*0fca6ea1SDimitry Andric << "-fuse-ld" << TC.getTriple().str(); 222*0fca6ea1SDimitry Andric } 223*0fca6ea1SDimitry Andric 224*0fca6ea1SDimitry Andric std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName()); 225*0fca6ea1SDimitry Andric const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str())); 226*0fca6ea1SDimitry Andric 227*0fca6ea1SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, 228*0fca6ea1SDimitry Andric ResponseFileSupport::AtFileUTF8(), 229*0fca6ea1SDimitry Andric Exec, CmdArgs, Inputs, Output)); 230*0fca6ea1SDimitry Andric } 231*0fca6ea1SDimitry Andric 232*0fca6ea1SDimitry Andric void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, 233*0fca6ea1SDimitry Andric const InputInfo &Output, 234*0fca6ea1SDimitry Andric const InputInfoList &Inputs, 235*0fca6ea1SDimitry Andric const ArgList &Args, 236*0fca6ea1SDimitry Andric const char *LinkingOutput) const { 237*0fca6ea1SDimitry Andric auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain()); 238*0fca6ea1SDimitry Andric const Driver &D = TC.getDriver(); 239*0fca6ea1SDimitry Andric ArgStringList CmdArgs; 240*0fca6ea1SDimitry Andric 241*0fca6ea1SDimitry Andric // Silence warning for "clang -g foo.o -o foo" 242*0fca6ea1SDimitry Andric Args.ClaimAllArgs(options::OPT_g_Group); 243*0fca6ea1SDimitry Andric // and "clang -emit-llvm foo.o -o foo" 244*0fca6ea1SDimitry Andric Args.ClaimAllArgs(options::OPT_emit_llvm); 245*0fca6ea1SDimitry Andric // and for "clang -w foo.o -o foo". Other warning options are already 246*0fca6ea1SDimitry Andric // handled somewhere else. 247*0fca6ea1SDimitry Andric Args.ClaimAllArgs(options::OPT_w); 248*0fca6ea1SDimitry Andric 249*0fca6ea1SDimitry Andric if (!D.SysRoot.empty()) 250*0fca6ea1SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 251*0fca6ea1SDimitry Andric 252*0fca6ea1SDimitry Andric if (Args.hasArg(options::OPT_pie)) 253*0fca6ea1SDimitry Andric CmdArgs.push_back("-pie"); 254*0fca6ea1SDimitry Andric 255*0fca6ea1SDimitry Andric if (Args.hasArg(options::OPT_rdynamic)) 256*0fca6ea1SDimitry Andric CmdArgs.push_back("-export-dynamic"); 257*0fca6ea1SDimitry Andric if (Args.hasArg(options::OPT_shared)) 258*0fca6ea1SDimitry Andric CmdArgs.push_back("--shared"); 259*0fca6ea1SDimitry Andric 260*0fca6ea1SDimitry Andric assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 261*0fca6ea1SDimitry Andric if (Output.isFilename()) { 262*0fca6ea1SDimitry Andric CmdArgs.push_back("-o"); 263*0fca6ea1SDimitry Andric CmdArgs.push_back(Output.getFilename()); 264*0fca6ea1SDimitry Andric } 265*0fca6ea1SDimitry Andric 266*0fca6ea1SDimitry Andric const bool UseLTO = D.isUsingLTO(); 267*0fca6ea1SDimitry Andric const bool UseJMC = 268*0fca6ea1SDimitry Andric Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false); 269*0fca6ea1SDimitry Andric 270*0fca6ea1SDimitry Andric auto AddCodeGenFlag = [&](Twine Flag) { 27106c3fb27SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=") + Flag)); 272bdd1243dSDimitry Andric }; 273bdd1243dSDimitry Andric 274bdd1243dSDimitry Andric if (UseLTO) { 275bdd1243dSDimitry Andric // We default to creating the arange section, but LTO does not. Enable it 276bdd1243dSDimitry Andric // here. 277bdd1243dSDimitry Andric AddCodeGenFlag("-generate-arange-section"); 278bdd1243dSDimitry Andric 279bdd1243dSDimitry Andric // This tells LTO to perform JustMyCode instrumentation. 280bdd1243dSDimitry Andric if (UseJMC) 281bdd1243dSDimitry Andric AddCodeGenFlag("-enable-jmc-instrument"); 282bdd1243dSDimitry Andric 283bdd1243dSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir)) 284bdd1243dSDimitry Andric AddCodeGenFlag(Twine("-crash-diagnostics-dir=") + A->getValue()); 28506c3fb27SDimitry Andric 28606c3fb27SDimitry Andric StringRef Parallelism = getLTOParallelism(Args, D); 287*0fca6ea1SDimitry Andric if (!Parallelism.empty()) 28806c3fb27SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") + Parallelism)); 28906c3fb27SDimitry Andric } 29006c3fb27SDimitry Andric 2910b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) 29281ad6265SDimitry Andric TC.addSanitizerArgs(Args, CmdArgs, "-l", ""); 2930b57cec5SDimitry Andric 29406c3fb27SDimitry Andric if (D.isUsingLTO() && Args.hasArg(options::OPT_funified_lto)) { 29506c3fb27SDimitry Andric if (D.getLTOMode() == LTOK_Thin) 29606c3fb27SDimitry Andric CmdArgs.push_back("--lto=thin"); 29706c3fb27SDimitry Andric else if (D.getLTOMode() == LTOK_Full) 29806c3fb27SDimitry Andric CmdArgs.push_back("--lto=full"); 29906c3fb27SDimitry Andric } 30006c3fb27SDimitry Andric 301*0fca6ea1SDimitry Andric Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, 302*0fca6ea1SDimitry Andric options::OPT_s, options::OPT_t}); 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) 3050b57cec5SDimitry Andric CmdArgs.push_back("--no-demangle"); 3060b57cec5SDimitry Andric 30781ad6265SDimitry Andric AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pthread)) { 3100b57cec5SDimitry Andric CmdArgs.push_back("-lpthread"); 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 313bdd1243dSDimitry Andric if (UseJMC) { 314bdd1243dSDimitry Andric CmdArgs.push_back("--whole-archive"); 315bdd1243dSDimitry Andric CmdArgs.push_back("-lSceJmc_nosubmission"); 316bdd1243dSDimitry Andric CmdArgs.push_back("--no-whole-archive"); 317bdd1243dSDimitry Andric } 318bdd1243dSDimitry Andric 3195ffd83dbSDimitry Andric if (Args.hasArg(options::OPT_fuse_ld_EQ)) { 3205ffd83dbSDimitry Andric D.Diag(diag::err_drv_unsupported_opt_for_target) 32181ad6265SDimitry Andric << "-fuse-ld" << TC.getTriple().str(); 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 32481ad6265SDimitry Andric std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName()); 32581ad6265SDimitry Andric const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str())); 3260b57cec5SDimitry Andric 327e8d8bef9SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, 328e8d8bef9SDimitry Andric ResponseFileSupport::AtFileUTF8(), 329e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 33281ad6265SDimitry Andric toolchains::PS4PS5Base::PS4PS5Base(const Driver &D, const llvm::Triple &Triple, 33381ad6265SDimitry Andric const ArgList &Args, StringRef Platform, 33481ad6265SDimitry Andric const char *EnvVar) 3350b57cec5SDimitry Andric : Generic_ELF(D, Triple, Args) { 3360b57cec5SDimitry Andric if (Args.hasArg(clang::driver::options::OPT_static)) 33781ad6265SDimitry Andric D.Diag(clang::diag::err_drv_unsupported_opt_for_target) 33881ad6265SDimitry Andric << "-static" << Platform; 3390b57cec5SDimitry Andric 34006c3fb27SDimitry Andric // Determine where to find the PS4/PS5 libraries. 34106c3fb27SDimitry Andric // If -isysroot was passed, use that as the SDK base path. 34206c3fb27SDimitry Andric // If not, we use the EnvVar if it exists; otherwise use the driver's 34306c3fb27SDimitry Andric // installation path, which should be <SDK_DIR>/host_tools/bin. 34406c3fb27SDimitry Andric SmallString<80> Whence; 34506c3fb27SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { 34606c3fb27SDimitry Andric SDKRootDir = A->getValue(); 34706c3fb27SDimitry Andric if (!llvm::sys::fs::exists(SDKRootDir)) 34806c3fb27SDimitry Andric D.Diag(clang::diag::warn_missing_sysroot) << SDKRootDir; 34906c3fb27SDimitry Andric Whence = A->getSpelling(); 35006c3fb27SDimitry Andric } else if (const char *EnvValue = getenv(EnvVar)) { 35106c3fb27SDimitry Andric SDKRootDir = EnvValue; 35206c3fb27SDimitry Andric Whence = { "environment variable '", EnvVar, "'" }; 3530b57cec5SDimitry Andric } else { 35406c3fb27SDimitry Andric SDKRootDir = D.Dir + "/../../"; 35506c3fb27SDimitry Andric Whence = "compiler's location"; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 35806c3fb27SDimitry Andric SmallString<512> SDKIncludeDir(SDKRootDir); 35981ad6265SDimitry Andric llvm::sys::path::append(SDKIncludeDir, "target/include"); 3600b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdinc) && 3610b57cec5SDimitry Andric !Args.hasArg(options::OPT_nostdlibinc) && 3620b57cec5SDimitry Andric !Args.hasArg(options::OPT_isysroot) && 3630b57cec5SDimitry Andric !Args.hasArg(options::OPT__sysroot_EQ) && 36481ad6265SDimitry Andric !llvm::sys::fs::exists(SDKIncludeDir)) { 36581ad6265SDimitry Andric D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected) 36606c3fb27SDimitry Andric << Twine(Platform, " system headers").str() << SDKIncludeDir << Whence; 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 36906c3fb27SDimitry Andric SmallString<512> SDKLibDir(SDKRootDir); 37081ad6265SDimitry Andric llvm::sys::path::append(SDKLibDir, "target/lib"); 3710b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib) && 3720b57cec5SDimitry Andric !Args.hasArg(options::OPT_nodefaultlibs) && 3730b57cec5SDimitry Andric !Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) && 3740b57cec5SDimitry Andric !Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) && 3750b57cec5SDimitry Andric !Args.hasArg(options::OPT_emit_ast) && 37681ad6265SDimitry Andric !llvm::sys::fs::exists(SDKLibDir)) { 37781ad6265SDimitry Andric D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected) 37806c3fb27SDimitry Andric << Twine(Platform, " system libraries").str() << SDKLibDir << Whence; 3790b57cec5SDimitry Andric return; 3800b57cec5SDimitry Andric } 3817a6dacacSDimitry Andric getFilePaths().push_back(std::string(SDKLibDir)); 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 38406c3fb27SDimitry Andric void toolchains::PS4PS5Base::AddClangSystemIncludeArgs( 38506c3fb27SDimitry Andric const ArgList &DriverArgs, 38606c3fb27SDimitry Andric ArgStringList &CC1Args) const { 38706c3fb27SDimitry Andric const Driver &D = getDriver(); 38806c3fb27SDimitry Andric 38906c3fb27SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) 39006c3fb27SDimitry Andric return; 39106c3fb27SDimitry Andric 39206c3fb27SDimitry Andric if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 39306c3fb27SDimitry Andric SmallString<128> Dir(D.ResourceDir); 39406c3fb27SDimitry Andric llvm::sys::path::append(Dir, "include"); 39506c3fb27SDimitry Andric addSystemInclude(DriverArgs, CC1Args, Dir.str()); 39606c3fb27SDimitry Andric } 39706c3fb27SDimitry Andric 39806c3fb27SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 39906c3fb27SDimitry Andric return; 40006c3fb27SDimitry Andric 40106c3fb27SDimitry Andric addExternCSystemInclude(DriverArgs, CC1Args, 40206c3fb27SDimitry Andric SDKRootDir + "/target/include"); 40306c3fb27SDimitry Andric addExternCSystemInclude(DriverArgs, CC1Args, 40406c3fb27SDimitry Andric SDKRootDir + "/target/include_common"); 40506c3fb27SDimitry Andric } 40606c3fb27SDimitry Andric 4070b57cec5SDimitry Andric Tool *toolchains::PS4CPU::buildAssembler() const { 40881ad6265SDimitry Andric return new tools::PScpu::Assembler(*this); 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric 411*0fca6ea1SDimitry Andric Tool *toolchains::PS4CPU::buildLinker() const { 412*0fca6ea1SDimitry Andric return new tools::PS4cpu::Linker(*this); 413*0fca6ea1SDimitry Andric } 414*0fca6ea1SDimitry Andric 41581ad6265SDimitry Andric Tool *toolchains::PS5CPU::buildAssembler() const { 41681ad6265SDimitry Andric // PS5 does not support an external assembler. 41781ad6265SDimitry Andric getDriver().Diag(clang::diag::err_no_external_assembler); 41881ad6265SDimitry Andric return nullptr; 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric 421*0fca6ea1SDimitry Andric Tool *toolchains::PS5CPU::buildLinker() const { 422*0fca6ea1SDimitry Andric return new tools::PS5cpu::Linker(*this); 42381ad6265SDimitry Andric } 4240b57cec5SDimitry Andric 42581ad6265SDimitry Andric SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers() const { 4260b57cec5SDimitry Andric SanitizerMask Res = ToolChain::getSupportedSanitizers(); 4270b57cec5SDimitry Andric Res |= SanitizerKind::Address; 4280b57cec5SDimitry Andric Res |= SanitizerKind::PointerCompare; 4290b57cec5SDimitry Andric Res |= SanitizerKind::PointerSubtract; 4300b57cec5SDimitry Andric Res |= SanitizerKind::Vptr; 4310b57cec5SDimitry Andric return Res; 4320b57cec5SDimitry Andric } 4335ffd83dbSDimitry Andric 43481ad6265SDimitry Andric SanitizerMask toolchains::PS5CPU::getSupportedSanitizers() const { 43581ad6265SDimitry Andric SanitizerMask Res = PS4PS5Base::getSupportedSanitizers(); 43681ad6265SDimitry Andric Res |= SanitizerKind::Thread; 43781ad6265SDimitry Andric return Res; 43881ad6265SDimitry Andric } 43981ad6265SDimitry Andric 44081ad6265SDimitry Andric void toolchains::PS4PS5Base::addClangTargetOptions( 441e8d8bef9SDimitry Andric const ArgList &DriverArgs, ArgStringList &CC1Args, 4425ffd83dbSDimitry Andric Action::OffloadKind DeviceOffloadingKind) const { 44381ad6265SDimitry Andric // PS4/PS5 do not use init arrays. 4445ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_fuse_init_array)) { 4455ffd83dbSDimitry Andric Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array); 4465ffd83dbSDimitry Andric getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target) 4475ffd83dbSDimitry Andric << A->getAsString(DriverArgs) << getTriple().str(); 4485ffd83dbSDimitry Andric } 4495ffd83dbSDimitry Andric 4505ffd83dbSDimitry Andric CC1Args.push_back("-fno-use-init-array"); 451e8d8bef9SDimitry Andric 452*0fca6ea1SDimitry Andric // Default to `hidden` visibility for PS5. 453*0fca6ea1SDimitry Andric if (getTriple().isPS5() && 454*0fca6ea1SDimitry Andric !DriverArgs.hasArg(options::OPT_fvisibility_EQ, 455*0fca6ea1SDimitry Andric options::OPT_fvisibility_ms_compat)) 456*0fca6ea1SDimitry Andric CC1Args.push_back("-fvisibility=hidden"); 457*0fca6ea1SDimitry Andric 4587a6dacacSDimitry Andric // Default to -fvisibility-global-new-delete=source for PS5. 4597a6dacacSDimitry Andric if (getTriple().isPS5() && 4607a6dacacSDimitry Andric !DriverArgs.hasArg(options::OPT_fvisibility_global_new_delete_EQ, 4617a6dacacSDimitry Andric options::OPT_fvisibility_global_new_delete_hidden)) 4627a6dacacSDimitry Andric CC1Args.push_back("-fvisibility-global-new-delete=source"); 4637a6dacacSDimitry Andric 464e8d8bef9SDimitry Andric const Arg *A = 465e8d8bef9SDimitry Andric DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass, 466e8d8bef9SDimitry Andric options::OPT_fno_visibility_from_dllstorageclass); 467e8d8bef9SDimitry Andric if (!A || 468e8d8bef9SDimitry Andric A->getOption().matches(options::OPT_fvisibility_from_dllstorageclass)) { 469e8d8bef9SDimitry Andric CC1Args.push_back("-fvisibility-from-dllstorageclass"); 470e8d8bef9SDimitry Andric 471e8d8bef9SDimitry Andric if (DriverArgs.hasArg(options::OPT_fvisibility_dllexport_EQ)) 472e8d8bef9SDimitry Andric DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_dllexport_EQ); 473e8d8bef9SDimitry Andric else 474e8d8bef9SDimitry Andric CC1Args.push_back("-fvisibility-dllexport=protected"); 475e8d8bef9SDimitry Andric 476*0fca6ea1SDimitry Andric // For PS4 we override the visibilty of globals definitions without 477*0fca6ea1SDimitry Andric // dllimport or dllexport annotations. 478e8d8bef9SDimitry Andric if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ)) 479e8d8bef9SDimitry Andric DriverArgs.AddLastArg(CC1Args, 480e8d8bef9SDimitry Andric options::OPT_fvisibility_nodllstorageclass_EQ); 481*0fca6ea1SDimitry Andric else if (getTriple().isPS4()) 482e8d8bef9SDimitry Andric CC1Args.push_back("-fvisibility-nodllstorageclass=hidden"); 483*0fca6ea1SDimitry Andric else 484*0fca6ea1SDimitry Andric CC1Args.push_back("-fvisibility-nodllstorageclass=keep"); 485e8d8bef9SDimitry Andric 486e8d8bef9SDimitry Andric if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ)) 487e8d8bef9SDimitry Andric DriverArgs.AddLastArg(CC1Args, 488e8d8bef9SDimitry Andric options::OPT_fvisibility_externs_dllimport_EQ); 489e8d8bef9SDimitry Andric else 490e8d8bef9SDimitry Andric CC1Args.push_back("-fvisibility-externs-dllimport=default"); 491e8d8bef9SDimitry Andric 492*0fca6ea1SDimitry Andric // For PS4 we override the visibilty of external globals without 493*0fca6ea1SDimitry Andric // dllimport or dllexport annotations. 494e8d8bef9SDimitry Andric if (DriverArgs.hasArg( 495e8d8bef9SDimitry Andric options::OPT_fvisibility_externs_nodllstorageclass_EQ)) 496e8d8bef9SDimitry Andric DriverArgs.AddLastArg( 497e8d8bef9SDimitry Andric CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ); 498*0fca6ea1SDimitry Andric else if (getTriple().isPS4()) 499e8d8bef9SDimitry Andric CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default"); 500*0fca6ea1SDimitry Andric else 501*0fca6ea1SDimitry Andric CC1Args.push_back("-fvisibility-externs-nodllstorageclass=keep"); 502e8d8bef9SDimitry Andric } 5035ffd83dbSDimitry Andric } 50481ad6265SDimitry Andric 50581ad6265SDimitry Andric // PS4 toolchain. 50681ad6265SDimitry Andric toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple, 50781ad6265SDimitry Andric const llvm::opt::ArgList &Args) 50881ad6265SDimitry Andric : PS4PS5Base(D, Triple, Args, "PS4", "SCE_ORBIS_SDK_DIR") {} 50981ad6265SDimitry Andric 51081ad6265SDimitry Andric // PS5 toolchain. 51181ad6265SDimitry Andric toolchains::PS5CPU::PS5CPU(const Driver &D, const llvm::Triple &Triple, 51281ad6265SDimitry Andric const llvm::opt::ArgList &Args) 51381ad6265SDimitry Andric : PS4PS5Base(D, Triple, Args, "PS5", "SCE_PROSPERO_SDK_DIR") {} 514