1 //===--- PS4CPU.cpp - PS4CPU ToolChain Implementations ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "PS4CPU.h"
10 #include "CommonArgs.h"
11 #include "clang/Config/config.h"
12 #include "clang/Driver/Compilation.h"
13 #include "clang/Driver/Driver.h"
14 #include "clang/Driver/DriverDiagnostic.h"
15 #include "clang/Driver/Options.h"
16 #include "clang/Driver/SanitizerArgs.h"
17 #include "llvm/Option/ArgList.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/Path.h"
20 #include <cstdlib> // ::getenv
21
22 using namespace clang::driver;
23 using namespace clang;
24 using namespace llvm::opt;
25
26 // Helper to paste bits of an option together and return a saved string.
makeArgString(const ArgList & Args,const char * Prefix,const char * Base,const char * Suffix)27 static const char *makeArgString(const ArgList &Args, const char *Prefix,
28 const char *Base, const char *Suffix) {
29 // Basically "Prefix + Base + Suffix" all converted to Twine then saved.
30 return Args.MakeArgString(Twine(StringRef(Prefix), Base) + Suffix);
31 }
32
addProfileRTArgs(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)33 void tools::PScpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
34 ArgStringList &CmdArgs) {
35 assert(TC.getTriple().isPS());
36 auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC);
37
38 if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
39 false) ||
40 Args.hasFlag(options::OPT_fprofile_generate,
41 options::OPT_fno_profile_generate, false) ||
42 Args.hasFlag(options::OPT_fprofile_generate_EQ,
43 options::OPT_fno_profile_generate, false) ||
44 Args.hasFlag(options::OPT_fprofile_instr_generate,
45 options::OPT_fno_profile_instr_generate, false) ||
46 Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
47 options::OPT_fno_profile_instr_generate, false) ||
48 Args.hasFlag(options::OPT_fcs_profile_generate,
49 options::OPT_fno_profile_generate, false) ||
50 Args.hasFlag(options::OPT_fcs_profile_generate_EQ,
51 options::OPT_fno_profile_generate, false) ||
52 Args.hasArg(options::OPT_fcreate_profile) ||
53 Args.hasArg(options::OPT_coverage)))
54 CmdArgs.push_back(makeArgString(
55 Args, "--dependent-lib=", PSTC.getProfileRTLibName(), ""));
56 }
57
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const58 void tools::PScpu::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
59 const InputInfo &Output,
60 const InputInfoList &Inputs,
61 const ArgList &Args,
62 const char *LinkingOutput) const {
63 auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
64 claimNoWarnArgs(Args);
65 ArgStringList CmdArgs;
66
67 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
68
69 CmdArgs.push_back("-o");
70 CmdArgs.push_back(Output.getFilename());
71
72 assert(Inputs.size() == 1 && "Unexpected number of inputs.");
73 const InputInfo &Input = Inputs[0];
74 assert(Input.isFilename() && "Invalid input.");
75 CmdArgs.push_back(Input.getFilename());
76
77 std::string AsName = TC.qualifyPSCmdName("as");
78 const char *Exec = Args.MakeArgString(TC.GetProgramPath(AsName.c_str()));
79 C.addCommand(std::make_unique<Command>(JA, *this,
80 ResponseFileSupport::AtFileUTF8(),
81 Exec, CmdArgs, Inputs, Output));
82 }
83
addSanitizerArgs(const ToolChain & TC,const ArgList & Args,ArgStringList & CmdArgs)84 void tools::PScpu::addSanitizerArgs(const ToolChain &TC, const ArgList &Args,
85 ArgStringList &CmdArgs) {
86 assert(TC.getTriple().isPS());
87 auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC);
88 PSTC.addSanitizerArgs(Args, CmdArgs, "--dependent-lib=lib", ".a");
89 }
90
addSanitizerArgs(const ArgList & Args,ArgStringList & CmdArgs,const char * Prefix,const char * Suffix) const91 void toolchains::PS4CPU::addSanitizerArgs(const ArgList &Args,
92 ArgStringList &CmdArgs,
93 const char *Prefix,
94 const char *Suffix) const {
95 auto arg = [&](const char *Name) -> const char * {
96 return makeArgString(Args, Prefix, Name, Suffix);
97 };
98 const SanitizerArgs &SanArgs = getSanitizerArgs(Args);
99 if (SanArgs.needsUbsanRt())
100 CmdArgs.push_back(arg("SceDbgUBSanitizer_stub_weak"));
101 if (SanArgs.needsAsanRt())
102 CmdArgs.push_back(arg("SceDbgAddressSanitizer_stub_weak"));
103 }
104
addSanitizerArgs(const ArgList & Args,ArgStringList & CmdArgs,const char * Prefix,const char * Suffix) const105 void toolchains::PS5CPU::addSanitizerArgs(const ArgList &Args,
106 ArgStringList &CmdArgs,
107 const char *Prefix,
108 const char *Suffix) const {
109 auto arg = [&](const char *Name) -> const char * {
110 return makeArgString(Args, Prefix, Name, Suffix);
111 };
112 const SanitizerArgs &SanArgs = getSanitizerArgs(Args);
113 if (SanArgs.needsUbsanRt())
114 CmdArgs.push_back(arg("SceUBSanitizer_nosubmission_stub_weak"));
115 if (SanArgs.needsAsanRt())
116 CmdArgs.push_back(arg("SceAddressSanitizer_nosubmission_stub_weak"));
117 if (SanArgs.needsTsanRt())
118 CmdArgs.push_back(arg("SceThreadSanitizer_nosubmission_stub_weak"));
119 }
120
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const121 void tools::PS4cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
122 const InputInfo &Output,
123 const InputInfoList &Inputs,
124 const ArgList &Args,
125 const char *LinkingOutput) const {
126 auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
127 const Driver &D = TC.getDriver();
128 ArgStringList CmdArgs;
129
130 // Silence warning for "clang -g foo.o -o foo"
131 Args.ClaimAllArgs(options::OPT_g_Group);
132 // and "clang -emit-llvm foo.o -o foo"
133 Args.ClaimAllArgs(options::OPT_emit_llvm);
134 // and for "clang -w foo.o -o foo". Other warning options are already
135 // handled somewhere else.
136 Args.ClaimAllArgs(options::OPT_w);
137
138 if (!D.SysRoot.empty())
139 CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
140
141 if (Args.hasArg(options::OPT_pie))
142 CmdArgs.push_back("-pie");
143
144 if (Args.hasArg(options::OPT_rdynamic))
145 CmdArgs.push_back("-export-dynamic");
146 if (Args.hasArg(options::OPT_shared))
147 CmdArgs.push_back("--shared");
148
149 assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
150 if (Output.isFilename()) {
151 CmdArgs.push_back("-o");
152 CmdArgs.push_back(Output.getFilename());
153 }
154
155 const bool UseLTO = D.isUsingLTO();
156 const bool UseJMC =
157 Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false);
158
159 const char *LTOArgs = "";
160 auto AddCodeGenFlag = [&](Twine Flag) {
161 LTOArgs = Args.MakeArgString(Twine(LTOArgs) + " " + Flag);
162 };
163
164 if (UseLTO) {
165 // We default to creating the arange section, but LTO does not. Enable it
166 // here.
167 AddCodeGenFlag("-generate-arange-section");
168
169 // This tells LTO to perform JustMyCode instrumentation.
170 if (UseJMC)
171 AddCodeGenFlag("-enable-jmc-instrument");
172
173 if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir))
174 AddCodeGenFlag(Twine("-crash-diagnostics-dir=") + A->getValue());
175
176 StringRef Parallelism = getLTOParallelism(Args, D);
177 if (!Parallelism.empty())
178 AddCodeGenFlag(Twine("-threads=") + Parallelism);
179
180 const char *Prefix = nullptr;
181 if (D.getLTOMode() == LTOK_Thin)
182 Prefix = "-lto-thin-debug-options=";
183 else if (D.getLTOMode() == LTOK_Full)
184 Prefix = "-lto-debug-options=";
185 else
186 llvm_unreachable("new LTO mode?");
187
188 CmdArgs.push_back(Args.MakeArgString(Twine(Prefix) + LTOArgs));
189 }
190
191 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
192 TC.addSanitizerArgs(Args, CmdArgs, "-l", "");
193
194 if (D.isUsingLTO() && Args.hasArg(options::OPT_funified_lto)) {
195 if (D.getLTOMode() == LTOK_Thin)
196 CmdArgs.push_back("--lto=thin");
197 else if (D.getLTOMode() == LTOK_Full)
198 CmdArgs.push_back("--lto=full");
199 }
200
201 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
202 options::OPT_s, options::OPT_t});
203
204 if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
205 CmdArgs.push_back("--no-demangle");
206
207 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
208
209 if (Args.hasArg(options::OPT_pthread)) {
210 CmdArgs.push_back("-lpthread");
211 }
212
213 if (UseJMC) {
214 CmdArgs.push_back("--whole-archive");
215 CmdArgs.push_back("-lSceDbgJmc");
216 CmdArgs.push_back("--no-whole-archive");
217 }
218
219 if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
220 D.Diag(diag::err_drv_unsupported_opt_for_target)
221 << "-fuse-ld" << TC.getTriple().str();
222 }
223
224 std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName());
225 const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str()));
226
227 C.addCommand(std::make_unique<Command>(JA, *this,
228 ResponseFileSupport::AtFileUTF8(),
229 Exec, CmdArgs, Inputs, Output));
230 }
231
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const232 void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
233 const InputInfo &Output,
234 const InputInfoList &Inputs,
235 const ArgList &Args,
236 const char *LinkingOutput) const {
237 auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
238 const Driver &D = TC.getDriver();
239 ArgStringList CmdArgs;
240
241 // Silence warning for "clang -g foo.o -o foo"
242 Args.ClaimAllArgs(options::OPT_g_Group);
243 // and "clang -emit-llvm foo.o -o foo"
244 Args.ClaimAllArgs(options::OPT_emit_llvm);
245 // and for "clang -w foo.o -o foo". Other warning options are already
246 // handled somewhere else.
247 Args.ClaimAllArgs(options::OPT_w);
248
249 if (!D.SysRoot.empty())
250 CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
251
252 if (Args.hasArg(options::OPT_pie))
253 CmdArgs.push_back("-pie");
254
255 if (Args.hasArg(options::OPT_rdynamic))
256 CmdArgs.push_back("-export-dynamic");
257 if (Args.hasArg(options::OPT_shared))
258 CmdArgs.push_back("--shared");
259
260 assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
261 if (Output.isFilename()) {
262 CmdArgs.push_back("-o");
263 CmdArgs.push_back(Output.getFilename());
264 }
265
266 const bool UseLTO = D.isUsingLTO();
267 const bool UseJMC =
268 Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false);
269
270 auto AddCodeGenFlag = [&](Twine Flag) {
271 CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=") + Flag));
272 };
273
274 if (UseLTO) {
275 // We default to creating the arange section, but LTO does not. Enable it
276 // here.
277 AddCodeGenFlag("-generate-arange-section");
278
279 // This tells LTO to perform JustMyCode instrumentation.
280 if (UseJMC)
281 AddCodeGenFlag("-enable-jmc-instrument");
282
283 if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir))
284 AddCodeGenFlag(Twine("-crash-diagnostics-dir=") + A->getValue());
285
286 StringRef Parallelism = getLTOParallelism(Args, D);
287 if (!Parallelism.empty())
288 CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") + Parallelism));
289 }
290
291 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
292 TC.addSanitizerArgs(Args, CmdArgs, "-l", "");
293
294 if (D.isUsingLTO() && Args.hasArg(options::OPT_funified_lto)) {
295 if (D.getLTOMode() == LTOK_Thin)
296 CmdArgs.push_back("--lto=thin");
297 else if (D.getLTOMode() == LTOK_Full)
298 CmdArgs.push_back("--lto=full");
299 }
300
301 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
302 options::OPT_s, options::OPT_t});
303
304 if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
305 CmdArgs.push_back("--no-demangle");
306
307 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
308
309 if (Args.hasArg(options::OPT_pthread)) {
310 CmdArgs.push_back("-lpthread");
311 }
312
313 if (UseJMC) {
314 CmdArgs.push_back("--whole-archive");
315 CmdArgs.push_back("-lSceJmc_nosubmission");
316 CmdArgs.push_back("--no-whole-archive");
317 }
318
319 if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
320 D.Diag(diag::err_drv_unsupported_opt_for_target)
321 << "-fuse-ld" << TC.getTriple().str();
322 }
323
324 std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName());
325 const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str()));
326
327 C.addCommand(std::make_unique<Command>(JA, *this,
328 ResponseFileSupport::AtFileUTF8(),
329 Exec, CmdArgs, Inputs, Output));
330 }
331
PS4PS5Base(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,StringRef Platform,const char * EnvVar)332 toolchains::PS4PS5Base::PS4PS5Base(const Driver &D, const llvm::Triple &Triple,
333 const ArgList &Args, StringRef Platform,
334 const char *EnvVar)
335 : Generic_ELF(D, Triple, Args) {
336 if (Args.hasArg(clang::driver::options::OPT_static))
337 D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
338 << "-static" << Platform;
339
340 // Determine where to find the PS4/PS5 libraries.
341 // If -isysroot was passed, use that as the SDK base path.
342 // If not, we use the EnvVar if it exists; otherwise use the driver's
343 // installation path, which should be <SDK_DIR>/host_tools/bin.
344 SmallString<80> Whence;
345 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
346 SDKRootDir = A->getValue();
347 if (!llvm::sys::fs::exists(SDKRootDir))
348 D.Diag(clang::diag::warn_missing_sysroot) << SDKRootDir;
349 Whence = A->getSpelling();
350 } else if (const char *EnvValue = getenv(EnvVar)) {
351 SDKRootDir = EnvValue;
352 Whence = { "environment variable '", EnvVar, "'" };
353 } else {
354 SDKRootDir = D.Dir + "/../../";
355 Whence = "compiler's location";
356 }
357
358 SmallString<512> SDKIncludeDir(SDKRootDir);
359 llvm::sys::path::append(SDKIncludeDir, "target/include");
360 if (!Args.hasArg(options::OPT_nostdinc) &&
361 !Args.hasArg(options::OPT_nostdlibinc) &&
362 !Args.hasArg(options::OPT_isysroot) &&
363 !Args.hasArg(options::OPT__sysroot_EQ) &&
364 !llvm::sys::fs::exists(SDKIncludeDir)) {
365 D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
366 << Twine(Platform, " system headers").str() << SDKIncludeDir << Whence;
367 }
368
369 SmallString<512> SDKLibDir(SDKRootDir);
370 llvm::sys::path::append(SDKLibDir, "target/lib");
371 if (!Args.hasArg(options::OPT_nostdlib) &&
372 !Args.hasArg(options::OPT_nodefaultlibs) &&
373 !Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) &&
374 !Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) &&
375 !Args.hasArg(options::OPT_emit_ast) &&
376 !llvm::sys::fs::exists(SDKLibDir)) {
377 D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
378 << Twine(Platform, " system libraries").str() << SDKLibDir << Whence;
379 return;
380 }
381 getFilePaths().push_back(std::string(SDKLibDir));
382 }
383
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const384 void toolchains::PS4PS5Base::AddClangSystemIncludeArgs(
385 const ArgList &DriverArgs,
386 ArgStringList &CC1Args) const {
387 const Driver &D = getDriver();
388
389 if (DriverArgs.hasArg(options::OPT_nostdinc))
390 return;
391
392 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
393 SmallString<128> Dir(D.ResourceDir);
394 llvm::sys::path::append(Dir, "include");
395 addSystemInclude(DriverArgs, CC1Args, Dir.str());
396 }
397
398 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
399 return;
400
401 addExternCSystemInclude(DriverArgs, CC1Args,
402 SDKRootDir + "/target/include");
403 addExternCSystemInclude(DriverArgs, CC1Args,
404 SDKRootDir + "/target/include_common");
405 }
406
buildAssembler() const407 Tool *toolchains::PS4CPU::buildAssembler() const {
408 return new tools::PScpu::Assembler(*this);
409 }
410
buildLinker() const411 Tool *toolchains::PS4CPU::buildLinker() const {
412 return new tools::PS4cpu::Linker(*this);
413 }
414
buildAssembler() const415 Tool *toolchains::PS5CPU::buildAssembler() const {
416 // PS5 does not support an external assembler.
417 getDriver().Diag(clang::diag::err_no_external_assembler);
418 return nullptr;
419 }
420
buildLinker() const421 Tool *toolchains::PS5CPU::buildLinker() const {
422 return new tools::PS5cpu::Linker(*this);
423 }
424
getSupportedSanitizers() const425 SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers() const {
426 SanitizerMask Res = ToolChain::getSupportedSanitizers();
427 Res |= SanitizerKind::Address;
428 Res |= SanitizerKind::PointerCompare;
429 Res |= SanitizerKind::PointerSubtract;
430 Res |= SanitizerKind::Vptr;
431 return Res;
432 }
433
getSupportedSanitizers() const434 SanitizerMask toolchains::PS5CPU::getSupportedSanitizers() const {
435 SanitizerMask Res = PS4PS5Base::getSupportedSanitizers();
436 Res |= SanitizerKind::Thread;
437 return Res;
438 }
439
addClangTargetOptions(const ArgList & DriverArgs,ArgStringList & CC1Args,Action::OffloadKind DeviceOffloadingKind) const440 void toolchains::PS4PS5Base::addClangTargetOptions(
441 const ArgList &DriverArgs, ArgStringList &CC1Args,
442 Action::OffloadKind DeviceOffloadingKind) const {
443 // PS4/PS5 do not use init arrays.
444 if (DriverArgs.hasArg(options::OPT_fuse_init_array)) {
445 Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array);
446 getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target)
447 << A->getAsString(DriverArgs) << getTriple().str();
448 }
449
450 CC1Args.push_back("-fno-use-init-array");
451
452 // Default to `hidden` visibility for PS5.
453 if (getTriple().isPS5() &&
454 !DriverArgs.hasArg(options::OPT_fvisibility_EQ,
455 options::OPT_fvisibility_ms_compat))
456 CC1Args.push_back("-fvisibility=hidden");
457
458 // Default to -fvisibility-global-new-delete=source for PS5.
459 if (getTriple().isPS5() &&
460 !DriverArgs.hasArg(options::OPT_fvisibility_global_new_delete_EQ,
461 options::OPT_fvisibility_global_new_delete_hidden))
462 CC1Args.push_back("-fvisibility-global-new-delete=source");
463
464 const Arg *A =
465 DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass,
466 options::OPT_fno_visibility_from_dllstorageclass);
467 if (!A ||
468 A->getOption().matches(options::OPT_fvisibility_from_dllstorageclass)) {
469 CC1Args.push_back("-fvisibility-from-dllstorageclass");
470
471 if (DriverArgs.hasArg(options::OPT_fvisibility_dllexport_EQ))
472 DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_dllexport_EQ);
473 else
474 CC1Args.push_back("-fvisibility-dllexport=protected");
475
476 // For PS4 we override the visibilty of globals definitions without
477 // dllimport or dllexport annotations.
478 if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ))
479 DriverArgs.AddLastArg(CC1Args,
480 options::OPT_fvisibility_nodllstorageclass_EQ);
481 else if (getTriple().isPS4())
482 CC1Args.push_back("-fvisibility-nodllstorageclass=hidden");
483 else
484 CC1Args.push_back("-fvisibility-nodllstorageclass=keep");
485
486 if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ))
487 DriverArgs.AddLastArg(CC1Args,
488 options::OPT_fvisibility_externs_dllimport_EQ);
489 else
490 CC1Args.push_back("-fvisibility-externs-dllimport=default");
491
492 // For PS4 we override the visibilty of external globals without
493 // dllimport or dllexport annotations.
494 if (DriverArgs.hasArg(
495 options::OPT_fvisibility_externs_nodllstorageclass_EQ))
496 DriverArgs.AddLastArg(
497 CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ);
498 else if (getTriple().isPS4())
499 CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default");
500 else
501 CC1Args.push_back("-fvisibility-externs-nodllstorageclass=keep");
502 }
503 }
504
505 // PS4 toolchain.
PS4CPU(const Driver & D,const llvm::Triple & Triple,const llvm::opt::ArgList & Args)506 toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
507 const llvm::opt::ArgList &Args)
508 : PS4PS5Base(D, Triple, Args, "PS4", "SCE_ORBIS_SDK_DIR") {}
509
510 // PS5 toolchain.
PS5CPU(const Driver & D,const llvm::Triple & Triple,const llvm::opt::ArgList & Args)511 toolchains::PS5CPU::PS5CPU(const Driver &D, const llvm::Triple &Triple,
512 const llvm::opt::ArgList &Args)
513 : PS4PS5Base(D, Triple, Args, "PS5", "SCE_PROSPERO_SDK_DIR") {}
514