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. |
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(Str: Twine(StringRef(Prefix), Base) + Suffix); |
31 | } |
32 | |
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(Pos: options::OPT_fprofile_arcs, Neg: options::OPT_fno_profile_arcs, |
39 | Default: false) || |
40 | Args.hasFlag(Pos: options::OPT_fprofile_generate, |
41 | Neg: options::OPT_fno_profile_generate, Default: false) || |
42 | Args.hasFlag(Pos: options::OPT_fprofile_generate_EQ, |
43 | Neg: options::OPT_fno_profile_generate, Default: false) || |
44 | Args.hasFlag(Pos: options::OPT_fprofile_instr_generate, |
45 | Neg: options::OPT_fno_profile_instr_generate, Default: false) || |
46 | Args.hasFlag(Pos: options::OPT_fprofile_instr_generate_EQ, |
47 | Neg: options::OPT_fno_profile_instr_generate, Default: false) || |
48 | Args.hasFlag(Pos: options::OPT_fcs_profile_generate, |
49 | Neg: options::OPT_fno_profile_generate, Default: false) || |
50 | Args.hasFlag(Pos: options::OPT_fcs_profile_generate_EQ, |
51 | Neg: options::OPT_fno_profile_generate, Default: false) || |
52 | Args.hasArg(Ids: options::OPT_fcreate_profile) || |
53 | Args.hasArg(Ids: options::OPT_coverage))) |
54 | CmdArgs.push_back(Elt: makeArgString( |
55 | Args, Prefix: "--dependent-lib=" , Base: PSTC.getProfileRTLibName(), Suffix: "" )); |
56 | } |
57 | |
58 | 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(Output&: CmdArgs, Id0: options::OPT_Wa_COMMA, Id1: options::OPT_Xassembler); |
68 | |
69 | CmdArgs.push_back(Elt: "-o" ); |
70 | CmdArgs.push_back(Elt: 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(Elt: Input.getFilename()); |
76 | |
77 | std::string AsName = TC.qualifyPSCmdName(CmdName: "as" ); |
78 | const char *Exec = Args.MakeArgString(Str: TC.GetProgramPath(Name: AsName.c_str())); |
79 | C.addCommand(C: std::make_unique<Command>(args: JA, args: *this, |
80 | args: ResponseFileSupport::AtFileUTF8(), |
81 | args&: Exec, args&: CmdArgs, args: Inputs, args: Output)); |
82 | } |
83 | |
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, Prefix: "--dependent-lib=lib" , Suffix: ".a" ); |
89 | } |
90 | |
91 | 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, Base: Name, Suffix); |
97 | }; |
98 | const SanitizerArgs &SanArgs = getSanitizerArgs(JobArgs: Args); |
99 | if (SanArgs.needsUbsanRt()) |
100 | CmdArgs.push_back(Elt: arg("SceDbgUBSanitizer_stub_weak" )); |
101 | if (SanArgs.needsAsanRt()) |
102 | CmdArgs.push_back(Elt: arg("SceDbgAddressSanitizer_stub_weak" )); |
103 | } |
104 | |
105 | 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, Base: Name, Suffix); |
111 | }; |
112 | const SanitizerArgs &SanArgs = getSanitizerArgs(JobArgs: Args); |
113 | if (SanArgs.needsUbsanRt()) |
114 | CmdArgs.push_back(Elt: arg("SceUBSanitizer_nosubmission_stub_weak" )); |
115 | if (SanArgs.needsAsanRt()) |
116 | CmdArgs.push_back(Elt: arg("SceAddressSanitizer_nosubmission_stub_weak" )); |
117 | if (SanArgs.needsTsanRt()) |
118 | CmdArgs.push_back(Elt: arg("SceThreadSanitizer_nosubmission_stub_weak" )); |
119 | } |
120 | |
121 | 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(Id0: options::OPT_g_Group); |
132 | // and "clang -emit-llvm foo.o -o foo" |
133 | Args.ClaimAllArgs(Id0: 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(Id0: options::OPT_w); |
137 | |
138 | if (!D.SysRoot.empty()) |
139 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: "--sysroot=" + D.SysRoot)); |
140 | |
141 | if (Args.hasArg(Ids: options::OPT_pie)) |
142 | CmdArgs.push_back(Elt: "-pie" ); |
143 | |
144 | if (Args.hasArg(Ids: options::OPT_rdynamic)) |
145 | CmdArgs.push_back(Elt: "-export-dynamic" ); |
146 | if (Args.hasArg(Ids: options::OPT_shared)) |
147 | CmdArgs.push_back(Elt: "--shared" ); |
148 | |
149 | assert((Output.isFilename() || Output.isNothing()) && "Invalid output." ); |
150 | if (Output.isFilename()) { |
151 | CmdArgs.push_back(Elt: "-o" ); |
152 | CmdArgs.push_back(Elt: Output.getFilename()); |
153 | } |
154 | |
155 | const bool UseLTO = D.isUsingLTO(); |
156 | const bool UseJMC = |
157 | Args.hasFlag(Pos: options::OPT_fjmc, Neg: options::OPT_fno_jmc, Default: false); |
158 | |
159 | const char *LTOArgs = "" ; |
160 | auto AddCodeGenFlag = [&](Twine Flag) { |
161 | LTOArgs = Args.MakeArgString(Str: 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(Ids: 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(Elt: Args.MakeArgString(Str: Twine(Prefix) + LTOArgs)); |
189 | } |
190 | |
191 | if (!Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nodefaultlibs)) |
192 | TC.addSanitizerArgs(Args, CmdArgs, Prefix: "-l" , Suffix: "" ); |
193 | |
194 | if (D.isUsingLTO() && Args.hasArg(Ids: options::OPT_funified_lto)) { |
195 | if (D.getLTOMode() == LTOK_Thin) |
196 | CmdArgs.push_back(Elt: "--lto=thin" ); |
197 | else if (D.getLTOMode() == LTOK_Full) |
198 | CmdArgs.push_back(Elt: "--lto=full" ); |
199 | } |
200 | |
201 | Args.addAllArgs(Output&: CmdArgs, Ids: {options::OPT_L, options::OPT_T_Group, |
202 | options::OPT_s, options::OPT_t}); |
203 | |
204 | if (Args.hasArg(Ids: options::OPT_Z_Xlinker__no_demangle)) |
205 | CmdArgs.push_back(Elt: "--no-demangle" ); |
206 | |
207 | AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); |
208 | |
209 | if (Args.hasArg(Ids: options::OPT_pthread)) { |
210 | CmdArgs.push_back(Elt: "-lpthread" ); |
211 | } |
212 | |
213 | if (UseJMC) { |
214 | CmdArgs.push_back(Elt: "--whole-archive" ); |
215 | CmdArgs.push_back(Elt: "-lSceDbgJmc" ); |
216 | CmdArgs.push_back(Elt: "--no-whole-archive" ); |
217 | } |
218 | |
219 | if (Args.hasArg(Ids: options::OPT_fuse_ld_EQ)) { |
220 | D.Diag(DiagID: diag::err_drv_unsupported_opt_for_target) |
221 | << "-fuse-ld" << TC.getTriple().str(); |
222 | } |
223 | |
224 | std::string LdName = TC.qualifyPSCmdName(CmdName: TC.getLinkerBaseName()); |
225 | const char *Exec = Args.MakeArgString(Str: TC.GetProgramPath(Name: LdName.c_str())); |
226 | |
227 | C.addCommand(C: std::make_unique<Command>(args: JA, args: *this, |
228 | args: ResponseFileSupport::AtFileUTF8(), |
229 | args&: Exec, args&: CmdArgs, args: Inputs, args: Output)); |
230 | } |
231 | |
232 | 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(Id0: options::OPT_g_Group); |
243 | // and "clang -emit-llvm foo.o -o foo" |
244 | Args.ClaimAllArgs(Id0: 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(Id0: options::OPT_w); |
248 | |
249 | if (!D.SysRoot.empty()) |
250 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: "--sysroot=" + D.SysRoot)); |
251 | |
252 | if (Args.hasArg(Ids: options::OPT_pie)) |
253 | CmdArgs.push_back(Elt: "-pie" ); |
254 | |
255 | if (Args.hasArg(Ids: options::OPT_rdynamic)) |
256 | CmdArgs.push_back(Elt: "-export-dynamic" ); |
257 | if (Args.hasArg(Ids: options::OPT_shared)) |
258 | CmdArgs.push_back(Elt: "--shared" ); |
259 | |
260 | assert((Output.isFilename() || Output.isNothing()) && "Invalid output." ); |
261 | if (Output.isFilename()) { |
262 | CmdArgs.push_back(Elt: "-o" ); |
263 | CmdArgs.push_back(Elt: Output.getFilename()); |
264 | } |
265 | |
266 | const bool UseLTO = D.isUsingLTO(); |
267 | const bool UseJMC = |
268 | Args.hasFlag(Pos: options::OPT_fjmc, Neg: options::OPT_fno_jmc, Default: false); |
269 | |
270 | auto AddCodeGenFlag = [&](Twine Flag) { |
271 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: 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(Ids: 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(Elt: Args.MakeArgString(Str: Twine("-plugin-opt=jobs=" ) + Parallelism)); |
289 | } |
290 | |
291 | if (!Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nodefaultlibs)) |
292 | TC.addSanitizerArgs(Args, CmdArgs, Prefix: "-l" , Suffix: "" ); |
293 | |
294 | if (D.isUsingLTO() && Args.hasArg(Ids: options::OPT_funified_lto)) { |
295 | if (D.getLTOMode() == LTOK_Thin) |
296 | CmdArgs.push_back(Elt: "--lto=thin" ); |
297 | else if (D.getLTOMode() == LTOK_Full) |
298 | CmdArgs.push_back(Elt: "--lto=full" ); |
299 | } |
300 | |
301 | Args.addAllArgs(Output&: CmdArgs, Ids: {options::OPT_L, options::OPT_T_Group, |
302 | options::OPT_s, options::OPT_t}); |
303 | |
304 | if (Args.hasArg(Ids: options::OPT_Z_Xlinker__no_demangle)) |
305 | CmdArgs.push_back(Elt: "--no-demangle" ); |
306 | |
307 | AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); |
308 | |
309 | if (Args.hasArg(Ids: options::OPT_pthread)) { |
310 | CmdArgs.push_back(Elt: "-lpthread" ); |
311 | } |
312 | |
313 | if (UseJMC) { |
314 | CmdArgs.push_back(Elt: "--whole-archive" ); |
315 | CmdArgs.push_back(Elt: "-lSceJmc_nosubmission" ); |
316 | CmdArgs.push_back(Elt: "--no-whole-archive" ); |
317 | } |
318 | |
319 | if (Args.hasArg(Ids: options::OPT_fuse_ld_EQ)) { |
320 | D.Diag(DiagID: diag::err_drv_unsupported_opt_for_target) |
321 | << "-fuse-ld" << TC.getTriple().str(); |
322 | } |
323 | |
324 | std::string LdName = TC.qualifyPSCmdName(CmdName: TC.getLinkerBaseName()); |
325 | const char *Exec = Args.MakeArgString(Str: TC.GetProgramPath(Name: LdName.c_str())); |
326 | |
327 | C.addCommand(C: std::make_unique<Command>(args: JA, args: *this, |
328 | args: ResponseFileSupport::AtFileUTF8(), |
329 | args&: Exec, args&: CmdArgs, args: Inputs, args: Output)); |
330 | } |
331 | |
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(Ids: clang::driver::options::OPT_static)) |
337 | D.Diag(DiagID: 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(Ids: options::OPT_isysroot)) { |
346 | SDKRootDir = A->getValue(); |
347 | if (!llvm::sys::fs::exists(Path: SDKRootDir)) |
348 | D.Diag(DiagID: clang::diag::warn_missing_sysroot) << SDKRootDir; |
349 | Whence = A->getSpelling(); |
350 | } else if (const char *EnvValue = getenv(name: 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(path&: SDKIncludeDir, a: "target/include" ); |
360 | if (!Args.hasArg(Ids: options::OPT_nostdinc) && |
361 | !Args.hasArg(Ids: options::OPT_nostdlibinc) && |
362 | !Args.hasArg(Ids: options::OPT_isysroot) && |
363 | !Args.hasArg(Ids: options::OPT__sysroot_EQ) && |
364 | !llvm::sys::fs::exists(Path: SDKIncludeDir)) { |
365 | D.Diag(DiagID: 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(path&: SDKLibDir, a: "target/lib" ); |
371 | if (!Args.hasArg(Ids: options::OPT_nostdlib) && |
372 | !Args.hasArg(Ids: options::OPT_nodefaultlibs) && |
373 | !Args.hasArg(Ids: options::OPT__sysroot_EQ) && !Args.hasArg(Ids: options::OPT_E) && |
374 | !Args.hasArg(Ids: options::OPT_c) && !Args.hasArg(Ids: options::OPT_S) && |
375 | !Args.hasArg(Ids: options::OPT_emit_ast) && |
376 | !llvm::sys::fs::exists(Path: SDKLibDir)) { |
377 | D.Diag(DiagID: clang::diag::warn_drv_unable_to_find_directory_expected) |
378 | << Twine(Platform, " system libraries" ).str() << SDKLibDir << Whence; |
379 | return; |
380 | } |
381 | getFilePaths().push_back(Elt: std::string(SDKLibDir)); |
382 | } |
383 | |
384 | void toolchains::PS4PS5Base::AddClangSystemIncludeArgs( |
385 | const ArgList &DriverArgs, |
386 | ArgStringList &CC1Args) const { |
387 | const Driver &D = getDriver(); |
388 | |
389 | if (DriverArgs.hasArg(Ids: options::OPT_nostdinc)) |
390 | return; |
391 | |
392 | if (!DriverArgs.hasArg(Ids: options::OPT_nobuiltininc)) { |
393 | SmallString<128> Dir(D.ResourceDir); |
394 | llvm::sys::path::append(path&: Dir, a: "include" ); |
395 | addSystemInclude(DriverArgs, CC1Args, Path: Dir.str()); |
396 | } |
397 | |
398 | if (DriverArgs.hasArg(Ids: options::OPT_nostdlibinc)) |
399 | return; |
400 | |
401 | addExternCSystemInclude(DriverArgs, CC1Args, |
402 | Path: SDKRootDir + "/target/include" ); |
403 | addExternCSystemInclude(DriverArgs, CC1Args, |
404 | Path: SDKRootDir + "/target/include_common" ); |
405 | } |
406 | |
407 | Tool *toolchains::PS4CPU::buildAssembler() const { |
408 | return new tools::PScpu::Assembler(*this); |
409 | } |
410 | |
411 | Tool *toolchains::PS4CPU::buildLinker() const { |
412 | return new tools::PS4cpu::Linker(*this); |
413 | } |
414 | |
415 | Tool *toolchains::PS5CPU::buildAssembler() const { |
416 | // PS5 does not support an external assembler. |
417 | getDriver().Diag(DiagID: clang::diag::err_no_external_assembler); |
418 | return nullptr; |
419 | } |
420 | |
421 | Tool *toolchains::PS5CPU::buildLinker() const { |
422 | return new tools::PS5cpu::Linker(*this); |
423 | } |
424 | |
425 | 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 | |
434 | SanitizerMask toolchains::PS5CPU::getSupportedSanitizers() const { |
435 | SanitizerMask Res = PS4PS5Base::getSupportedSanitizers(); |
436 | Res |= SanitizerKind::Thread; |
437 | return Res; |
438 | } |
439 | |
440 | 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(Ids: options::OPT_fuse_init_array)) { |
445 | Arg *A = DriverArgs.getLastArg(Ids: options::OPT_fuse_init_array); |
446 | getDriver().Diag(DiagID: clang::diag::err_drv_unsupported_opt_for_target) |
447 | << A->getAsString(Args: DriverArgs) << getTriple().str(); |
448 | } |
449 | |
450 | CC1Args.push_back(Elt: "-fno-use-init-array" ); |
451 | |
452 | // Default to `hidden` visibility for PS5. |
453 | if (getTriple().isPS5() && |
454 | !DriverArgs.hasArg(Ids: options::OPT_fvisibility_EQ, |
455 | Ids: options::OPT_fvisibility_ms_compat)) |
456 | CC1Args.push_back(Elt: "-fvisibility=hidden" ); |
457 | |
458 | // Default to -fvisibility-global-new-delete=source for PS5. |
459 | if (getTriple().isPS5() && |
460 | !DriverArgs.hasArg(Ids: options::OPT_fvisibility_global_new_delete_EQ, |
461 | Ids: options::OPT_fvisibility_global_new_delete_hidden)) |
462 | CC1Args.push_back(Elt: "-fvisibility-global-new-delete=source" ); |
463 | |
464 | const Arg *A = |
465 | DriverArgs.getLastArg(Ids: options::OPT_fvisibility_from_dllstorageclass, |
466 | Ids: options::OPT_fno_visibility_from_dllstorageclass); |
467 | if (!A || |
468 | A->getOption().matches(ID: options::OPT_fvisibility_from_dllstorageclass)) { |
469 | CC1Args.push_back(Elt: "-fvisibility-from-dllstorageclass" ); |
470 | |
471 | if (DriverArgs.hasArg(Ids: options::OPT_fvisibility_dllexport_EQ)) |
472 | DriverArgs.AddLastArg(Output&: CC1Args, Ids: options::OPT_fvisibility_dllexport_EQ); |
473 | else |
474 | CC1Args.push_back(Elt: "-fvisibility-dllexport=protected" ); |
475 | |
476 | // For PS4 we override the visibilty of globals definitions without |
477 | // dllimport or dllexport annotations. |
478 | if (DriverArgs.hasArg(Ids: options::OPT_fvisibility_nodllstorageclass_EQ)) |
479 | DriverArgs.AddLastArg(Output&: CC1Args, |
480 | Ids: options::OPT_fvisibility_nodllstorageclass_EQ); |
481 | else if (getTriple().isPS4()) |
482 | CC1Args.push_back(Elt: "-fvisibility-nodllstorageclass=hidden" ); |
483 | else |
484 | CC1Args.push_back(Elt: "-fvisibility-nodllstorageclass=keep" ); |
485 | |
486 | if (DriverArgs.hasArg(Ids: options::OPT_fvisibility_externs_dllimport_EQ)) |
487 | DriverArgs.AddLastArg(Output&: CC1Args, |
488 | Ids: options::OPT_fvisibility_externs_dllimport_EQ); |
489 | else |
490 | CC1Args.push_back(Elt: "-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 | Ids: options::OPT_fvisibility_externs_nodllstorageclass_EQ)) |
496 | DriverArgs.AddLastArg( |
497 | Output&: CC1Args, Ids: options::OPT_fvisibility_externs_nodllstorageclass_EQ); |
498 | else if (getTriple().isPS4()) |
499 | CC1Args.push_back(Elt: "-fvisibility-externs-nodllstorageclass=default" ); |
500 | else |
501 | CC1Args.push_back(Elt: "-fvisibility-externs-nodllstorageclass=keep" ); |
502 | } |
503 | } |
504 | |
505 | // PS4 toolchain. |
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. |
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 | |