xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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"
11*06c3fb27SDimitry 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 
1490b57cec5SDimitry Andric   if (Output.isFilename()) {
1500b57cec5SDimitry Andric     CmdArgs.push_back("-o");
1510b57cec5SDimitry Andric     CmdArgs.push_back(Output.getFilename());
1520b57cec5SDimitry Andric   } else {
1530b57cec5SDimitry Andric     assert(Output.isNothing() && "Invalid output.");
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric 
156bdd1243dSDimitry Andric   const bool UseLTO = D.isUsingLTO();
157bdd1243dSDimitry Andric   const bool UseJMC =
158bdd1243dSDimitry Andric       Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false);
159bdd1243dSDimitry Andric   const bool IsPS4 = TC.getTriple().isPS4();
160bdd1243dSDimitry Andric   const bool IsPS5 = TC.getTriple().isPS5();
161bdd1243dSDimitry Andric   assert(IsPS4 || IsPS5);
162bdd1243dSDimitry Andric 
163*06c3fb27SDimitry Andric   const char *PS4LTOArgs = "";
164bdd1243dSDimitry Andric   auto AddCodeGenFlag = [&](Twine Flag) {
165*06c3fb27SDimitry Andric     if (IsPS4)
166*06c3fb27SDimitry Andric       PS4LTOArgs = Args.MakeArgString(Twine(PS4LTOArgs) + " " + Flag);
167bdd1243dSDimitry Andric     else if (IsPS5)
168*06c3fb27SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=") + Flag));
169bdd1243dSDimitry Andric   };
170bdd1243dSDimitry Andric 
171bdd1243dSDimitry Andric   if (UseLTO) {
172bdd1243dSDimitry Andric     // We default to creating the arange section, but LTO does not. Enable it
173bdd1243dSDimitry Andric     // here.
174bdd1243dSDimitry Andric     AddCodeGenFlag("-generate-arange-section");
175bdd1243dSDimitry Andric 
176bdd1243dSDimitry Andric     // This tells LTO to perform JustMyCode instrumentation.
177bdd1243dSDimitry Andric     if (UseJMC)
178bdd1243dSDimitry Andric       AddCodeGenFlag("-enable-jmc-instrument");
179bdd1243dSDimitry Andric 
180bdd1243dSDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir))
181bdd1243dSDimitry Andric       AddCodeGenFlag(Twine("-crash-diagnostics-dir=") + A->getValue());
182*06c3fb27SDimitry Andric 
183*06c3fb27SDimitry Andric     StringRef Parallelism = getLTOParallelism(Args, D);
184*06c3fb27SDimitry Andric     if (!Parallelism.empty()) {
185*06c3fb27SDimitry Andric       if (IsPS4)
186*06c3fb27SDimitry Andric         AddCodeGenFlag(Twine("-threads=") + Parallelism);
187*06c3fb27SDimitry Andric       else
188*06c3fb27SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") + Parallelism));
189*06c3fb27SDimitry Andric     }
190*06c3fb27SDimitry Andric 
191*06c3fb27SDimitry Andric     if (IsPS4) {
192*06c3fb27SDimitry Andric       const char *Prefix = nullptr;
193*06c3fb27SDimitry Andric       if (D.getLTOMode() == LTOK_Thin)
194*06c3fb27SDimitry Andric         Prefix = "-lto-thin-debug-options=";
195*06c3fb27SDimitry Andric       else if (D.getLTOMode() == LTOK_Full)
196*06c3fb27SDimitry Andric         Prefix = "-lto-debug-options=";
197*06c3fb27SDimitry Andric       else
198*06c3fb27SDimitry Andric         llvm_unreachable("new LTO mode?");
199*06c3fb27SDimitry Andric 
200*06c3fb27SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine(Prefix) + PS4LTOArgs));
201*06c3fb27SDimitry Andric     }
202bdd1243dSDimitry Andric   }
203bdd1243dSDimitry Andric 
2040b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
20581ad6265SDimitry Andric     TC.addSanitizerArgs(Args, CmdArgs, "-l", "");
2060b57cec5SDimitry Andric 
207*06c3fb27SDimitry Andric   if (D.isUsingLTO() && Args.hasArg(options::OPT_funified_lto)) {
208*06c3fb27SDimitry Andric     if (D.getLTOMode() == LTOK_Thin)
209*06c3fb27SDimitry Andric       CmdArgs.push_back("--lto=thin");
210*06c3fb27SDimitry Andric     else if (D.getLTOMode() == LTOK_Full)
211*06c3fb27SDimitry Andric       CmdArgs.push_back("--lto=full");
212*06c3fb27SDimitry Andric   }
213*06c3fb27SDimitry Andric 
2140b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_L);
2150b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
2160b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_s);
2170b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_t);
2180b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_r);
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
2210b57cec5SDimitry Andric     CmdArgs.push_back("--no-demangle");
2220b57cec5SDimitry Andric 
22381ad6265SDimitry Andric   AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_pthread)) {
2260b57cec5SDimitry Andric     CmdArgs.push_back("-lpthread");
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
229bdd1243dSDimitry Andric   if (UseJMC) {
230bdd1243dSDimitry Andric     CmdArgs.push_back("--whole-archive");
231bdd1243dSDimitry Andric     if (IsPS4)
232bdd1243dSDimitry Andric       CmdArgs.push_back("-lSceDbgJmc");
233bdd1243dSDimitry Andric     else
234bdd1243dSDimitry Andric       CmdArgs.push_back("-lSceJmc_nosubmission");
235bdd1243dSDimitry Andric     CmdArgs.push_back("--no-whole-archive");
236bdd1243dSDimitry Andric   }
237bdd1243dSDimitry Andric 
2385ffd83dbSDimitry Andric   if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
2395ffd83dbSDimitry Andric     D.Diag(diag::err_drv_unsupported_opt_for_target)
24081ad6265SDimitry Andric         << "-fuse-ld" << TC.getTriple().str();
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric 
24381ad6265SDimitry Andric   std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName());
24481ad6265SDimitry Andric   const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str()));
2450b57cec5SDimitry Andric 
246e8d8bef9SDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this,
247e8d8bef9SDimitry Andric                                          ResponseFileSupport::AtFileUTF8(),
248e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
25181ad6265SDimitry Andric toolchains::PS4PS5Base::PS4PS5Base(const Driver &D, const llvm::Triple &Triple,
25281ad6265SDimitry Andric                                    const ArgList &Args, StringRef Platform,
25381ad6265SDimitry Andric                                    const char *EnvVar)
2540b57cec5SDimitry Andric     : Generic_ELF(D, Triple, Args) {
2550b57cec5SDimitry Andric   if (Args.hasArg(clang::driver::options::OPT_static))
25681ad6265SDimitry Andric     D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
25781ad6265SDimitry Andric         << "-static" << Platform;
2580b57cec5SDimitry Andric 
259*06c3fb27SDimitry Andric   // Determine where to find the PS4/PS5 libraries.
260*06c3fb27SDimitry Andric   // If -isysroot was passed, use that as the SDK base path.
261*06c3fb27SDimitry Andric   // If not, we use the EnvVar if it exists; otherwise use the driver's
262*06c3fb27SDimitry Andric   // installation path, which should be <SDK_DIR>/host_tools/bin.
263*06c3fb27SDimitry Andric   SmallString<80> Whence;
264*06c3fb27SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
265*06c3fb27SDimitry Andric     SDKRootDir = A->getValue();
266*06c3fb27SDimitry Andric     if (!llvm::sys::fs::exists(SDKRootDir))
267*06c3fb27SDimitry Andric       D.Diag(clang::diag::warn_missing_sysroot) << SDKRootDir;
268*06c3fb27SDimitry Andric     Whence = A->getSpelling();
269*06c3fb27SDimitry Andric   } else if (const char *EnvValue = getenv(EnvVar)) {
270*06c3fb27SDimitry Andric     SDKRootDir = EnvValue;
271*06c3fb27SDimitry Andric     Whence = { "environment variable '", EnvVar, "'" };
2720b57cec5SDimitry Andric   } else {
273*06c3fb27SDimitry Andric     SDKRootDir = D.Dir + "/../../";
274*06c3fb27SDimitry Andric     Whence = "compiler's location";
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric 
277*06c3fb27SDimitry Andric   SmallString<512> SDKIncludeDir(SDKRootDir);
27881ad6265SDimitry Andric   llvm::sys::path::append(SDKIncludeDir, "target/include");
2790b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdinc) &&
2800b57cec5SDimitry Andric       !Args.hasArg(options::OPT_nostdlibinc) &&
2810b57cec5SDimitry Andric       !Args.hasArg(options::OPT_isysroot) &&
2820b57cec5SDimitry Andric       !Args.hasArg(options::OPT__sysroot_EQ) &&
28381ad6265SDimitry Andric       !llvm::sys::fs::exists(SDKIncludeDir)) {
28481ad6265SDimitry Andric     D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
285*06c3fb27SDimitry Andric         << Twine(Platform, " system headers").str() << SDKIncludeDir << Whence;
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric 
288*06c3fb27SDimitry Andric   SmallString<512> SDKLibDir(SDKRootDir);
28981ad6265SDimitry Andric   llvm::sys::path::append(SDKLibDir, "target/lib");
2900b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib) &&
2910b57cec5SDimitry Andric       !Args.hasArg(options::OPT_nodefaultlibs) &&
2920b57cec5SDimitry Andric       !Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) &&
2930b57cec5SDimitry Andric       !Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) &&
2940b57cec5SDimitry Andric       !Args.hasArg(options::OPT_emit_ast) &&
29581ad6265SDimitry Andric       !llvm::sys::fs::exists(SDKLibDir)) {
29681ad6265SDimitry Andric     D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
297*06c3fb27SDimitry Andric         << Twine(Platform, " system libraries").str() << SDKLibDir << Whence;
2980b57cec5SDimitry Andric     return;
2990b57cec5SDimitry Andric   }
30081ad6265SDimitry Andric   getFilePaths().push_back(std::string(SDKLibDir.str()));
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric 
303*06c3fb27SDimitry Andric void toolchains::PS4PS5Base::AddClangSystemIncludeArgs(
304*06c3fb27SDimitry Andric     const ArgList &DriverArgs,
305*06c3fb27SDimitry Andric     ArgStringList &CC1Args) const {
306*06c3fb27SDimitry Andric   const Driver &D = getDriver();
307*06c3fb27SDimitry Andric 
308*06c3fb27SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdinc))
309*06c3fb27SDimitry Andric     return;
310*06c3fb27SDimitry Andric 
311*06c3fb27SDimitry Andric   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
312*06c3fb27SDimitry Andric     SmallString<128> Dir(D.ResourceDir);
313*06c3fb27SDimitry Andric     llvm::sys::path::append(Dir, "include");
314*06c3fb27SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, Dir.str());
315*06c3fb27SDimitry Andric   }
316*06c3fb27SDimitry Andric 
317*06c3fb27SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
318*06c3fb27SDimitry Andric     return;
319*06c3fb27SDimitry Andric 
320*06c3fb27SDimitry Andric   addExternCSystemInclude(DriverArgs, CC1Args,
321*06c3fb27SDimitry Andric                           SDKRootDir + "/target/include");
322*06c3fb27SDimitry Andric   addExternCSystemInclude(DriverArgs, CC1Args,
323*06c3fb27SDimitry Andric                           SDKRootDir + "/target/include_common");
324*06c3fb27SDimitry Andric }
325*06c3fb27SDimitry Andric 
3260b57cec5SDimitry Andric Tool *toolchains::PS4CPU::buildAssembler() const {
32781ad6265SDimitry Andric   return new tools::PScpu::Assembler(*this);
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric 
33081ad6265SDimitry Andric Tool *toolchains::PS5CPU::buildAssembler() const {
33181ad6265SDimitry Andric   // PS5 does not support an external assembler.
33281ad6265SDimitry Andric   getDriver().Diag(clang::diag::err_no_external_assembler);
33381ad6265SDimitry Andric   return nullptr;
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
33681ad6265SDimitry Andric Tool *toolchains::PS4PS5Base::buildLinker() const {
33781ad6265SDimitry Andric   return new tools::PScpu::Linker(*this);
33881ad6265SDimitry Andric }
3390b57cec5SDimitry Andric 
34081ad6265SDimitry Andric SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers() const {
3410b57cec5SDimitry Andric   SanitizerMask Res = ToolChain::getSupportedSanitizers();
3420b57cec5SDimitry Andric   Res |= SanitizerKind::Address;
3430b57cec5SDimitry Andric   Res |= SanitizerKind::PointerCompare;
3440b57cec5SDimitry Andric   Res |= SanitizerKind::PointerSubtract;
3450b57cec5SDimitry Andric   Res |= SanitizerKind::Vptr;
3460b57cec5SDimitry Andric   return Res;
3470b57cec5SDimitry Andric }
3485ffd83dbSDimitry Andric 
34981ad6265SDimitry Andric SanitizerMask toolchains::PS5CPU::getSupportedSanitizers() const {
35081ad6265SDimitry Andric   SanitizerMask Res = PS4PS5Base::getSupportedSanitizers();
35181ad6265SDimitry Andric   Res |= SanitizerKind::Thread;
35281ad6265SDimitry Andric   return Res;
35381ad6265SDimitry Andric }
35481ad6265SDimitry Andric 
35581ad6265SDimitry Andric void toolchains::PS4PS5Base::addClangTargetOptions(
356e8d8bef9SDimitry Andric     const ArgList &DriverArgs, ArgStringList &CC1Args,
3575ffd83dbSDimitry Andric     Action::OffloadKind DeviceOffloadingKind) const {
35881ad6265SDimitry Andric   // PS4/PS5 do not use init arrays.
3595ffd83dbSDimitry Andric   if (DriverArgs.hasArg(options::OPT_fuse_init_array)) {
3605ffd83dbSDimitry Andric     Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array);
3615ffd83dbSDimitry Andric     getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target)
3625ffd83dbSDimitry Andric         << A->getAsString(DriverArgs) << getTriple().str();
3635ffd83dbSDimitry Andric   }
3645ffd83dbSDimitry Andric 
3655ffd83dbSDimitry Andric   CC1Args.push_back("-fno-use-init-array");
366e8d8bef9SDimitry Andric 
367e8d8bef9SDimitry Andric   const Arg *A =
368e8d8bef9SDimitry Andric       DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass,
369e8d8bef9SDimitry Andric                             options::OPT_fno_visibility_from_dllstorageclass);
370e8d8bef9SDimitry Andric   if (!A ||
371e8d8bef9SDimitry Andric       A->getOption().matches(options::OPT_fvisibility_from_dllstorageclass)) {
372e8d8bef9SDimitry Andric     CC1Args.push_back("-fvisibility-from-dllstorageclass");
373e8d8bef9SDimitry Andric 
374e8d8bef9SDimitry Andric     if (DriverArgs.hasArg(options::OPT_fvisibility_dllexport_EQ))
375e8d8bef9SDimitry Andric       DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_dllexport_EQ);
376e8d8bef9SDimitry Andric     else
377e8d8bef9SDimitry Andric       CC1Args.push_back("-fvisibility-dllexport=protected");
378e8d8bef9SDimitry Andric 
379e8d8bef9SDimitry Andric     if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ))
380e8d8bef9SDimitry Andric       DriverArgs.AddLastArg(CC1Args,
381e8d8bef9SDimitry Andric                             options::OPT_fvisibility_nodllstorageclass_EQ);
382e8d8bef9SDimitry Andric     else
383e8d8bef9SDimitry Andric       CC1Args.push_back("-fvisibility-nodllstorageclass=hidden");
384e8d8bef9SDimitry Andric 
385e8d8bef9SDimitry Andric     if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ))
386e8d8bef9SDimitry Andric       DriverArgs.AddLastArg(CC1Args,
387e8d8bef9SDimitry Andric                             options::OPT_fvisibility_externs_dllimport_EQ);
388e8d8bef9SDimitry Andric     else
389e8d8bef9SDimitry Andric       CC1Args.push_back("-fvisibility-externs-dllimport=default");
390e8d8bef9SDimitry Andric 
391e8d8bef9SDimitry Andric     if (DriverArgs.hasArg(
392e8d8bef9SDimitry Andric             options::OPT_fvisibility_externs_nodllstorageclass_EQ))
393e8d8bef9SDimitry Andric       DriverArgs.AddLastArg(
394e8d8bef9SDimitry Andric           CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ);
395e8d8bef9SDimitry Andric     else
396e8d8bef9SDimitry Andric       CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default");
397e8d8bef9SDimitry Andric   }
3985ffd83dbSDimitry Andric }
39981ad6265SDimitry Andric 
40081ad6265SDimitry Andric // PS4 toolchain.
40181ad6265SDimitry Andric toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
40281ad6265SDimitry Andric                            const llvm::opt::ArgList &Args)
40381ad6265SDimitry Andric     : PS4PS5Base(D, Triple, Args, "PS4", "SCE_ORBIS_SDK_DIR") {}
40481ad6265SDimitry Andric 
40581ad6265SDimitry Andric // PS5 toolchain.
40681ad6265SDimitry Andric toolchains::PS5CPU::PS5CPU(const Driver &D, const llvm::Triple &Triple,
40781ad6265SDimitry Andric                            const llvm::opt::ArgList &Args)
40881ad6265SDimitry Andric     : PS4PS5Base(D, Triple, Args, "PS5", "SCE_PROSPERO_SDK_DIR") {}
409