xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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