xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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 
12181ad6265SDimitry Andric void tools::PScpu::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 
149*5f757f3fSDimitry 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   const bool IsPS4 = TC.getTriple().isPS4();
159bdd1243dSDimitry Andric 
16006c3fb27SDimitry Andric   const char *PS4LTOArgs = "";
161bdd1243dSDimitry Andric   auto AddCodeGenFlag = [&](Twine Flag) {
16206c3fb27SDimitry Andric     if (IsPS4)
16306c3fb27SDimitry Andric       PS4LTOArgs = Args.MakeArgString(Twine(PS4LTOArgs) + " " + Flag);
164*5f757f3fSDimitry Andric     else
16506c3fb27SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=") + Flag));
166bdd1243dSDimitry Andric   };
167bdd1243dSDimitry Andric 
168bdd1243dSDimitry Andric   if (UseLTO) {
169bdd1243dSDimitry Andric     // We default to creating the arange section, but LTO does not. Enable it
170bdd1243dSDimitry Andric     // here.
171bdd1243dSDimitry Andric     AddCodeGenFlag("-generate-arange-section");
172bdd1243dSDimitry Andric 
173bdd1243dSDimitry Andric     // This tells LTO to perform JustMyCode instrumentation.
174bdd1243dSDimitry Andric     if (UseJMC)
175bdd1243dSDimitry Andric       AddCodeGenFlag("-enable-jmc-instrument");
176bdd1243dSDimitry Andric 
177bdd1243dSDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir))
178bdd1243dSDimitry Andric       AddCodeGenFlag(Twine("-crash-diagnostics-dir=") + A->getValue());
17906c3fb27SDimitry Andric 
18006c3fb27SDimitry Andric     StringRef Parallelism = getLTOParallelism(Args, D);
18106c3fb27SDimitry Andric     if (!Parallelism.empty()) {
18206c3fb27SDimitry Andric       if (IsPS4)
18306c3fb27SDimitry Andric         AddCodeGenFlag(Twine("-threads=") + Parallelism);
18406c3fb27SDimitry Andric       else
18506c3fb27SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") + Parallelism));
18606c3fb27SDimitry Andric     }
18706c3fb27SDimitry Andric 
18806c3fb27SDimitry Andric     if (IsPS4) {
18906c3fb27SDimitry Andric       const char *Prefix = nullptr;
19006c3fb27SDimitry Andric       if (D.getLTOMode() == LTOK_Thin)
19106c3fb27SDimitry Andric         Prefix = "-lto-thin-debug-options=";
19206c3fb27SDimitry Andric       else if (D.getLTOMode() == LTOK_Full)
19306c3fb27SDimitry Andric         Prefix = "-lto-debug-options=";
19406c3fb27SDimitry Andric       else
19506c3fb27SDimitry Andric         llvm_unreachable("new LTO mode?");
19606c3fb27SDimitry Andric 
19706c3fb27SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine(Prefix) + PS4LTOArgs));
19806c3fb27SDimitry Andric     }
199bdd1243dSDimitry Andric   }
200bdd1243dSDimitry Andric 
2010b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
20281ad6265SDimitry Andric     TC.addSanitizerArgs(Args, CmdArgs, "-l", "");
2030b57cec5SDimitry Andric 
20406c3fb27SDimitry Andric   if (D.isUsingLTO() && Args.hasArg(options::OPT_funified_lto)) {
20506c3fb27SDimitry Andric     if (D.getLTOMode() == LTOK_Thin)
20606c3fb27SDimitry Andric       CmdArgs.push_back("--lto=thin");
20706c3fb27SDimitry Andric     else if (D.getLTOMode() == LTOK_Full)
20806c3fb27SDimitry Andric       CmdArgs.push_back("--lto=full");
20906c3fb27SDimitry Andric   }
21006c3fb27SDimitry Andric 
211*5f757f3fSDimitry Andric   Args.addAllArgs(CmdArgs,
212*5f757f3fSDimitry Andric                   {options::OPT_L, options::OPT_T_Group, options::OPT_s,
213*5f757f3fSDimitry Andric                    options::OPT_t, options::OPT_r});
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
2160b57cec5SDimitry Andric     CmdArgs.push_back("--no-demangle");
2170b57cec5SDimitry Andric 
21881ad6265SDimitry Andric   AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_pthread)) {
2210b57cec5SDimitry Andric     CmdArgs.push_back("-lpthread");
2220b57cec5SDimitry Andric   }
2230b57cec5SDimitry Andric 
224bdd1243dSDimitry Andric   if (UseJMC) {
225bdd1243dSDimitry Andric     CmdArgs.push_back("--whole-archive");
226bdd1243dSDimitry Andric     if (IsPS4)
227bdd1243dSDimitry Andric       CmdArgs.push_back("-lSceDbgJmc");
228bdd1243dSDimitry Andric     else
229bdd1243dSDimitry Andric       CmdArgs.push_back("-lSceJmc_nosubmission");
230bdd1243dSDimitry Andric     CmdArgs.push_back("--no-whole-archive");
231bdd1243dSDimitry Andric   }
232bdd1243dSDimitry Andric 
2335ffd83dbSDimitry Andric   if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
2345ffd83dbSDimitry Andric     D.Diag(diag::err_drv_unsupported_opt_for_target)
23581ad6265SDimitry Andric         << "-fuse-ld" << TC.getTriple().str();
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric 
23881ad6265SDimitry Andric   std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName());
23981ad6265SDimitry Andric   const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str()));
2400b57cec5SDimitry Andric 
241e8d8bef9SDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this,
242e8d8bef9SDimitry Andric                                          ResponseFileSupport::AtFileUTF8(),
243e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
24681ad6265SDimitry Andric toolchains::PS4PS5Base::PS4PS5Base(const Driver &D, const llvm::Triple &Triple,
24781ad6265SDimitry Andric                                    const ArgList &Args, StringRef Platform,
24881ad6265SDimitry Andric                                    const char *EnvVar)
2490b57cec5SDimitry Andric     : Generic_ELF(D, Triple, Args) {
2500b57cec5SDimitry Andric   if (Args.hasArg(clang::driver::options::OPT_static))
25181ad6265SDimitry Andric     D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
25281ad6265SDimitry Andric         << "-static" << Platform;
2530b57cec5SDimitry Andric 
25406c3fb27SDimitry Andric   // Determine where to find the PS4/PS5 libraries.
25506c3fb27SDimitry Andric   // If -isysroot was passed, use that as the SDK base path.
25606c3fb27SDimitry Andric   // If not, we use the EnvVar if it exists; otherwise use the driver's
25706c3fb27SDimitry Andric   // installation path, which should be <SDK_DIR>/host_tools/bin.
25806c3fb27SDimitry Andric   SmallString<80> Whence;
25906c3fb27SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
26006c3fb27SDimitry Andric     SDKRootDir = A->getValue();
26106c3fb27SDimitry Andric     if (!llvm::sys::fs::exists(SDKRootDir))
26206c3fb27SDimitry Andric       D.Diag(clang::diag::warn_missing_sysroot) << SDKRootDir;
26306c3fb27SDimitry Andric     Whence = A->getSpelling();
26406c3fb27SDimitry Andric   } else if (const char *EnvValue = getenv(EnvVar)) {
26506c3fb27SDimitry Andric     SDKRootDir = EnvValue;
26606c3fb27SDimitry Andric     Whence = { "environment variable '", EnvVar, "'" };
2670b57cec5SDimitry Andric   } else {
26806c3fb27SDimitry Andric     SDKRootDir = D.Dir + "/../../";
26906c3fb27SDimitry Andric     Whence = "compiler's location";
2700b57cec5SDimitry Andric   }
2710b57cec5SDimitry Andric 
27206c3fb27SDimitry Andric   SmallString<512> SDKIncludeDir(SDKRootDir);
27381ad6265SDimitry Andric   llvm::sys::path::append(SDKIncludeDir, "target/include");
2740b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdinc) &&
2750b57cec5SDimitry Andric       !Args.hasArg(options::OPT_nostdlibinc) &&
2760b57cec5SDimitry Andric       !Args.hasArg(options::OPT_isysroot) &&
2770b57cec5SDimitry Andric       !Args.hasArg(options::OPT__sysroot_EQ) &&
27881ad6265SDimitry Andric       !llvm::sys::fs::exists(SDKIncludeDir)) {
27981ad6265SDimitry Andric     D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
28006c3fb27SDimitry Andric         << Twine(Platform, " system headers").str() << SDKIncludeDir << Whence;
2810b57cec5SDimitry Andric   }
2820b57cec5SDimitry Andric 
28306c3fb27SDimitry Andric   SmallString<512> SDKLibDir(SDKRootDir);
28481ad6265SDimitry Andric   llvm::sys::path::append(SDKLibDir, "target/lib");
2850b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib) &&
2860b57cec5SDimitry Andric       !Args.hasArg(options::OPT_nodefaultlibs) &&
2870b57cec5SDimitry Andric       !Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) &&
2880b57cec5SDimitry Andric       !Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) &&
2890b57cec5SDimitry Andric       !Args.hasArg(options::OPT_emit_ast) &&
29081ad6265SDimitry Andric       !llvm::sys::fs::exists(SDKLibDir)) {
29181ad6265SDimitry Andric     D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
29206c3fb27SDimitry Andric         << Twine(Platform, " system libraries").str() << SDKLibDir << Whence;
2930b57cec5SDimitry Andric     return;
2940b57cec5SDimitry Andric   }
29581ad6265SDimitry Andric   getFilePaths().push_back(std::string(SDKLibDir.str()));
2960b57cec5SDimitry Andric }
2970b57cec5SDimitry Andric 
29806c3fb27SDimitry Andric void toolchains::PS4PS5Base::AddClangSystemIncludeArgs(
29906c3fb27SDimitry Andric     const ArgList &DriverArgs,
30006c3fb27SDimitry Andric     ArgStringList &CC1Args) const {
30106c3fb27SDimitry Andric   const Driver &D = getDriver();
30206c3fb27SDimitry Andric 
30306c3fb27SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdinc))
30406c3fb27SDimitry Andric     return;
30506c3fb27SDimitry Andric 
30606c3fb27SDimitry Andric   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
30706c3fb27SDimitry Andric     SmallString<128> Dir(D.ResourceDir);
30806c3fb27SDimitry Andric     llvm::sys::path::append(Dir, "include");
30906c3fb27SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, Dir.str());
31006c3fb27SDimitry Andric   }
31106c3fb27SDimitry Andric 
31206c3fb27SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
31306c3fb27SDimitry Andric     return;
31406c3fb27SDimitry Andric 
31506c3fb27SDimitry Andric   addExternCSystemInclude(DriverArgs, CC1Args,
31606c3fb27SDimitry Andric                           SDKRootDir + "/target/include");
31706c3fb27SDimitry Andric   addExternCSystemInclude(DriverArgs, CC1Args,
31806c3fb27SDimitry Andric                           SDKRootDir + "/target/include_common");
31906c3fb27SDimitry Andric }
32006c3fb27SDimitry Andric 
3210b57cec5SDimitry Andric Tool *toolchains::PS4CPU::buildAssembler() const {
32281ad6265SDimitry Andric   return new tools::PScpu::Assembler(*this);
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric 
32581ad6265SDimitry Andric Tool *toolchains::PS5CPU::buildAssembler() const {
32681ad6265SDimitry Andric   // PS5 does not support an external assembler.
32781ad6265SDimitry Andric   getDriver().Diag(clang::diag::err_no_external_assembler);
32881ad6265SDimitry Andric   return nullptr;
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric 
33181ad6265SDimitry Andric Tool *toolchains::PS4PS5Base::buildLinker() const {
33281ad6265SDimitry Andric   return new tools::PScpu::Linker(*this);
33381ad6265SDimitry Andric }
3340b57cec5SDimitry Andric 
33581ad6265SDimitry Andric SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers() const {
3360b57cec5SDimitry Andric   SanitizerMask Res = ToolChain::getSupportedSanitizers();
3370b57cec5SDimitry Andric   Res |= SanitizerKind::Address;
3380b57cec5SDimitry Andric   Res |= SanitizerKind::PointerCompare;
3390b57cec5SDimitry Andric   Res |= SanitizerKind::PointerSubtract;
3400b57cec5SDimitry Andric   Res |= SanitizerKind::Vptr;
3410b57cec5SDimitry Andric   return Res;
3420b57cec5SDimitry Andric }
3435ffd83dbSDimitry Andric 
34481ad6265SDimitry Andric SanitizerMask toolchains::PS5CPU::getSupportedSanitizers() const {
34581ad6265SDimitry Andric   SanitizerMask Res = PS4PS5Base::getSupportedSanitizers();
34681ad6265SDimitry Andric   Res |= SanitizerKind::Thread;
34781ad6265SDimitry Andric   return Res;
34881ad6265SDimitry Andric }
34981ad6265SDimitry Andric 
35081ad6265SDimitry Andric void toolchains::PS4PS5Base::addClangTargetOptions(
351e8d8bef9SDimitry Andric     const ArgList &DriverArgs, ArgStringList &CC1Args,
3525ffd83dbSDimitry Andric     Action::OffloadKind DeviceOffloadingKind) const {
35381ad6265SDimitry Andric   // PS4/PS5 do not use init arrays.
3545ffd83dbSDimitry Andric   if (DriverArgs.hasArg(options::OPT_fuse_init_array)) {
3555ffd83dbSDimitry Andric     Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array);
3565ffd83dbSDimitry Andric     getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target)
3575ffd83dbSDimitry Andric         << A->getAsString(DriverArgs) << getTriple().str();
3585ffd83dbSDimitry Andric   }
3595ffd83dbSDimitry Andric 
3605ffd83dbSDimitry Andric   CC1Args.push_back("-fno-use-init-array");
361e8d8bef9SDimitry Andric 
362e8d8bef9SDimitry Andric   const Arg *A =
363e8d8bef9SDimitry Andric       DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass,
364e8d8bef9SDimitry Andric                             options::OPT_fno_visibility_from_dllstorageclass);
365e8d8bef9SDimitry Andric   if (!A ||
366e8d8bef9SDimitry Andric       A->getOption().matches(options::OPT_fvisibility_from_dllstorageclass)) {
367e8d8bef9SDimitry Andric     CC1Args.push_back("-fvisibility-from-dllstorageclass");
368e8d8bef9SDimitry Andric 
369e8d8bef9SDimitry Andric     if (DriverArgs.hasArg(options::OPT_fvisibility_dllexport_EQ))
370e8d8bef9SDimitry Andric       DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_dllexport_EQ);
371e8d8bef9SDimitry Andric     else
372e8d8bef9SDimitry Andric       CC1Args.push_back("-fvisibility-dllexport=protected");
373e8d8bef9SDimitry Andric 
374e8d8bef9SDimitry Andric     if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ))
375e8d8bef9SDimitry Andric       DriverArgs.AddLastArg(CC1Args,
376e8d8bef9SDimitry Andric                             options::OPT_fvisibility_nodllstorageclass_EQ);
377e8d8bef9SDimitry Andric     else
378e8d8bef9SDimitry Andric       CC1Args.push_back("-fvisibility-nodllstorageclass=hidden");
379e8d8bef9SDimitry Andric 
380e8d8bef9SDimitry Andric     if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ))
381e8d8bef9SDimitry Andric       DriverArgs.AddLastArg(CC1Args,
382e8d8bef9SDimitry Andric                             options::OPT_fvisibility_externs_dllimport_EQ);
383e8d8bef9SDimitry Andric     else
384e8d8bef9SDimitry Andric       CC1Args.push_back("-fvisibility-externs-dllimport=default");
385e8d8bef9SDimitry Andric 
386e8d8bef9SDimitry Andric     if (DriverArgs.hasArg(
387e8d8bef9SDimitry Andric             options::OPT_fvisibility_externs_nodllstorageclass_EQ))
388e8d8bef9SDimitry Andric       DriverArgs.AddLastArg(
389e8d8bef9SDimitry Andric           CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ);
390e8d8bef9SDimitry Andric     else
391e8d8bef9SDimitry Andric       CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default");
392e8d8bef9SDimitry Andric   }
3935ffd83dbSDimitry Andric }
39481ad6265SDimitry Andric 
39581ad6265SDimitry Andric // PS4 toolchain.
39681ad6265SDimitry Andric toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
39781ad6265SDimitry Andric                            const llvm::opt::ArgList &Args)
39881ad6265SDimitry Andric     : PS4PS5Base(D, Triple, Args, "PS4", "SCE_ORBIS_SDK_DIR") {}
39981ad6265SDimitry Andric 
40081ad6265SDimitry Andric // PS5 toolchain.
40181ad6265SDimitry Andric toolchains::PS5CPU::PS5CPU(const Driver &D, const llvm::Triple &Triple,
40281ad6265SDimitry Andric                            const llvm::opt::ArgList &Args)
40381ad6265SDimitry Andric     : PS4PS5Base(D, Triple, Args, "PS5", "SCE_PROSPERO_SDK_DIR") {}
404