clang  15.0.0git
PS4CPU.cpp
Go to the documentation of this file.
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"
12 #include "clang/Driver/Driver.h"
14 #include "clang/Driver/Options.h"
16 #include "llvm/Option/ArgList.h"
17 #include "llvm/Support/FileSystem.h"
18 #include "llvm/Support/Path.h"
19 #include <cstdlib> // ::getenv
20 
21 using namespace clang::driver;
22 using namespace clang;
23 using namespace llvm::opt;
24 
25 // Helper to paste bits of an option together and return a saved string.
26 static const char *makeArgString(const ArgList &Args, const char *Prefix,
27  const char *Base, const char *Suffix) {
28  // Basically "Prefix + Base + Suffix" all converted to Twine then saved.
29  return Args.MakeArgString(Twine(StringRef(Prefix), Base) + Suffix);
30 }
31 
32 void tools::PScpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
33  ArgStringList &CmdArgs) {
34  assert(TC.getTriple().isPS());
35  auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC);
36 
37  if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
38  false) ||
39  Args.hasFlag(options::OPT_fprofile_generate,
40  options::OPT_fno_profile_generate, false) ||
41  Args.hasFlag(options::OPT_fprofile_generate_EQ,
42  options::OPT_fno_profile_generate, false) ||
43  Args.hasFlag(options::OPT_fprofile_instr_generate,
44  options::OPT_fno_profile_instr_generate, false) ||
45  Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
46  options::OPT_fno_profile_instr_generate, false) ||
47  Args.hasFlag(options::OPT_fcs_profile_generate,
48  options::OPT_fno_profile_generate, false) ||
49  Args.hasFlag(options::OPT_fcs_profile_generate_EQ,
50  options::OPT_fno_profile_generate, false) ||
51  Args.hasArg(options::OPT_fcreate_profile) ||
52  Args.hasArg(options::OPT_coverage)))
53  CmdArgs.push_back(makeArgString(
54  Args, "--dependent-lib=", PSTC.getProfileRTLibName(), ""));
55 }
56 
58  const InputInfo &Output,
59  const InputInfoList &Inputs,
60  const ArgList &Args,
61  const char *LinkingOutput) const {
62  auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
63  claimNoWarnArgs(Args);
64  ArgStringList CmdArgs;
65 
66  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
67 
68  CmdArgs.push_back("-o");
69  CmdArgs.push_back(Output.getFilename());
70 
71  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
72  const InputInfo &Input = Inputs[0];
73  assert(Input.isFilename() && "Invalid input.");
74  CmdArgs.push_back(Input.getFilename());
75 
76  std::string AsName = TC.qualifyPSCmdName("as");
77  const char *Exec = Args.MakeArgString(TC.GetProgramPath(AsName.c_str()));
78  C.addCommand(std::make_unique<Command>(JA, *this,
80  Exec, CmdArgs, Inputs, Output));
81 }
82 
83 void tools::PScpu::addSanitizerArgs(const ToolChain &TC, const ArgList &Args,
84  ArgStringList &CmdArgs) {
85  assert(TC.getTriple().isPS());
86  auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC);
87  PSTC.addSanitizerArgs(Args, CmdArgs, "--dependent-lib=lib", ".a");
88 }
89 
90 void toolchains::PS4CPU::addSanitizerArgs(const ArgList &Args,
91  ArgStringList &CmdArgs,
92  const char *Prefix,
93  const char *Suffix) const {
94  auto arg = [&](const char *Name) -> const char * {
95  return makeArgString(Args, Prefix, Name, Suffix);
96  };
97  const SanitizerArgs &SanArgs = getSanitizerArgs(Args);
98  if (SanArgs.needsUbsanRt())
99  CmdArgs.push_back(arg("SceDbgUBSanitizer_stub_weak"));
100  if (SanArgs.needsAsanRt())
101  CmdArgs.push_back(arg("SceDbgAddressSanitizer_stub_weak"));
102 }
103 
104 void toolchains::PS5CPU::addSanitizerArgs(const ArgList &Args,
105  ArgStringList &CmdArgs,
106  const char *Prefix,
107  const char *Suffix) const {
108  auto arg = [&](const char *Name) -> const char * {
109  return makeArgString(Args, Prefix, Name, Suffix);
110  };
111  const SanitizerArgs &SanArgs = getSanitizerArgs(Args);
112  if (SanArgs.needsUbsanRt())
113  CmdArgs.push_back(arg("SceUBSanitizer_nosubmission_stub_weak"));
114  if (SanArgs.needsAsanRt())
115  CmdArgs.push_back(arg("SceAddressSanitizer_nosubmission_stub_weak"));
116  if (SanArgs.needsTsanRt())
117  CmdArgs.push_back(arg("SceThreadSanitizer_nosubmission_stub_weak"));
118 }
119 
121  const InputInfo &Output,
122  const InputInfoList &Inputs,
123  const ArgList &Args,
124  const char *LinkingOutput) const {
125  auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
126  const Driver &D = TC.getDriver();
127  ArgStringList CmdArgs;
128 
129  // Silence warning for "clang -g foo.o -o foo"
130  Args.ClaimAllArgs(options::OPT_g_Group);
131  // and "clang -emit-llvm foo.o -o foo"
132  Args.ClaimAllArgs(options::OPT_emit_llvm);
133  // and for "clang -w foo.o -o foo". Other warning options are already
134  // handled somewhere else.
135  Args.ClaimAllArgs(options::OPT_w);
136 
137  if (!D.SysRoot.empty())
138  CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
139 
140  if (Args.hasArg(options::OPT_pie))
141  CmdArgs.push_back("-pie");
142 
143  if (Args.hasArg(options::OPT_rdynamic))
144  CmdArgs.push_back("-export-dynamic");
145  if (Args.hasArg(options::OPT_shared))
146  CmdArgs.push_back("--shared");
147 
148  if (Output.isFilename()) {
149  CmdArgs.push_back("-o");
150  CmdArgs.push_back(Output.getFilename());
151  } else {
152  assert(Output.isNothing() && "Invalid output.");
153  }
154 
155  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
156  TC.addSanitizerArgs(Args, CmdArgs, "-l", "");
157 
158  Args.AddAllArgs(CmdArgs, options::OPT_L);
159  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
160  Args.AddAllArgs(CmdArgs, options::OPT_e);
161  Args.AddAllArgs(CmdArgs, options::OPT_s);
162  Args.AddAllArgs(CmdArgs, options::OPT_t);
163  Args.AddAllArgs(CmdArgs, options::OPT_r);
164 
165  if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
166  CmdArgs.push_back("--no-demangle");
167 
168  AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
169 
170  if (Args.hasArg(options::OPT_pthread)) {
171  CmdArgs.push_back("-lpthread");
172  }
173 
174  if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
175  D.Diag(diag::err_drv_unsupported_opt_for_target)
176  << "-fuse-ld" << TC.getTriple().str();
177  }
178 
179  std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName());
180  const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str()));
181 
182  C.addCommand(std::make_unique<Command>(JA, *this,
184  Exec, CmdArgs, Inputs, Output));
185 }
186 
187 toolchains::PS4PS5Base::PS4PS5Base(const Driver &D, const llvm::Triple &Triple,
188  const ArgList &Args, StringRef Platform,
189  const char *EnvVar)
190  : Generic_ELF(D, Triple, Args) {
191  if (Args.hasArg(clang::driver::options::OPT_static))
192  D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
193  << "-static" << Platform;
194 
195  // Determine where to find the PS4/PS5 libraries. We use the EnvVar
196  // if it exists; otherwise use the driver's installation path, which
197  // should be <SDK_DIR>/host_tools/bin.
198 
199  SmallString<512> SDKDir;
200  if (const char *EnvValue = getenv(EnvVar)) {
201  if (!llvm::sys::fs::exists(EnvValue))
202  D.Diag(clang::diag::warn_drv_ps_sdk_dir) << EnvVar << EnvValue;
203  SDKDir = EnvValue;
204  } else {
205  SDKDir = D.Dir;
206  llvm::sys::path::append(SDKDir, "/../../");
207  }
208 
209  // By default, the driver won't report a warning if it can't find the
210  // SDK include or lib directories. This behavior could be changed if
211  // -Weverything or -Winvalid-or-nonexistent-directory options are passed.
212  // If -isysroot was passed, use that as the SDK base path.
213  std::string PrefixDir;
214  if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
215  PrefixDir = A->getValue();
216  if (!llvm::sys::fs::exists(PrefixDir))
217  D.Diag(clang::diag::warn_missing_sysroot) << PrefixDir;
218  } else
219  PrefixDir = std::string(SDKDir.str());
220 
221  SmallString<512> SDKIncludeDir(PrefixDir);
222  llvm::sys::path::append(SDKIncludeDir, "target/include");
223  if (!Args.hasArg(options::OPT_nostdinc) &&
224  !Args.hasArg(options::OPT_nostdlibinc) &&
225  !Args.hasArg(options::OPT_isysroot) &&
226  !Args.hasArg(options::OPT__sysroot_EQ) &&
227  !llvm::sys::fs::exists(SDKIncludeDir)) {
228  D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
229  << Twine(Platform, " system headers").str() << SDKIncludeDir;
230  }
231 
232  SmallString<512> SDKLibDir(SDKDir);
233  llvm::sys::path::append(SDKLibDir, "target/lib");
234  if (!Args.hasArg(options::OPT_nostdlib) &&
235  !Args.hasArg(options::OPT_nodefaultlibs) &&
236  !Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) &&
237  !Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) &&
238  !Args.hasArg(options::OPT_emit_ast) &&
239  !llvm::sys::fs::exists(SDKLibDir)) {
240  D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
241  << Twine(Platform, " system libraries").str() << SDKLibDir;
242  return;
243  }
244  getFilePaths().push_back(std::string(SDKLibDir.str()));
245 }
246 
248  return new tools::PScpu::Assembler(*this);
249 }
250 
252  // PS5 does not support an external assembler.
253  getDriver().Diag(clang::diag::err_no_external_assembler);
254  return nullptr;
255 }
256 
258  return new tools::PScpu::Linker(*this);
259 }
260 
263  Res |= SanitizerKind::Address;
264  Res |= SanitizerKind::PointerCompare;
265  Res |= SanitizerKind::PointerSubtract;
266  Res |= SanitizerKind::Vptr;
267  return Res;
268 }
269 
272  Res |= SanitizerKind::Thread;
273  return Res;
274 }
275 
277  const ArgList &DriverArgs, ArgStringList &CC1Args,
278  Action::OffloadKind DeviceOffloadingKind) const {
279  // PS4/PS5 do not use init arrays.
280  if (DriverArgs.hasArg(options::OPT_fuse_init_array)) {
281  Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array);
282  getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target)
283  << A->getAsString(DriverArgs) << getTriple().str();
284  }
285 
286  CC1Args.push_back("-fno-use-init-array");
287 
288  const Arg *A =
289  DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass,
290  options::OPT_fno_visibility_from_dllstorageclass);
291  if (!A ||
292  A->getOption().matches(options::OPT_fvisibility_from_dllstorageclass)) {
293  CC1Args.push_back("-fvisibility-from-dllstorageclass");
294 
295  if (DriverArgs.hasArg(options::OPT_fvisibility_dllexport_EQ))
296  DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_dllexport_EQ);
297  else
298  CC1Args.push_back("-fvisibility-dllexport=protected");
299 
300  if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ))
301  DriverArgs.AddLastArg(CC1Args,
302  options::OPT_fvisibility_nodllstorageclass_EQ);
303  else
304  CC1Args.push_back("-fvisibility-nodllstorageclass=hidden");
305 
306  if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ))
307  DriverArgs.AddLastArg(CC1Args,
308  options::OPT_fvisibility_externs_dllimport_EQ);
309  else
310  CC1Args.push_back("-fvisibility-externs-dllimport=default");
311 
312  if (DriverArgs.hasArg(
313  options::OPT_fvisibility_externs_nodllstorageclass_EQ))
314  DriverArgs.AddLastArg(
315  CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ);
316  else
317  CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default");
318  }
319 }
320 
321 // PS4 toolchain.
322 toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
323  const llvm::opt::ArgList &Args)
324  : PS4PS5Base(D, Triple, Args, "PS4", "SCE_ORBIS_SDK_DIR") {}
325 
326 // PS5 toolchain.
327 toolchains::PS5CPU::PS5CPU(const Driver &D, const llvm::Triple &Triple,
328  const llvm::opt::ArgList &Args)
329  : PS4PS5Base(D, Triple, Args, "PS5", "SCE_PROSPERO_SDK_DIR") {}
clang::driver::toolchains::PS4PS5Base::addSanitizerArgs
virtual void addSanitizerArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const char *Prefix, const char *Suffix) const =0
Driver.h
clang::driver::toolchains::PS5CPU::addSanitizerArgs
void addSanitizerArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const char *Prefix, const char *Suffix) const override
Definition: PS4CPU.cpp:104
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::driver::Driver::Dir
std::string Dir
The path the driver executable was in, as invoked from the command line.
Definition: Driver.h:143
clang::driver::ResponseFileSupport::AtFileUTF8
static constexpr ResponseFileSupport AtFileUTF8()
Definition: Job.h:85
llvm::SmallVector
Definition: LLVM.h:38
clang::driver::ToolChain::GetProgramPath
std::string GetProgramPath(const char *Name) const
Definition: ToolChain.cpp:581
clang::driver::toolchains::PS5CPU::PS5CPU
PS5CPU(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
Definition: PS4CPU.cpp:327
clang::driver::ToolChain::getDriver
const Driver & getDriver() const
Definition: ToolChain.h:225
clang::driver::SanitizerArgs::needsTsanRt
bool needsTsanRt() const
Definition: SanitizerArgs.h:84
clang::driver::tools::PScpu::Linker
Definition: PS4CPU.h:42
clang::driver::toolchains::PS4CPU::buildAssembler
Tool * buildAssembler() const override
Definition: PS4CPU.cpp:247
clang::driver::InputInfo
InputInfo - Wrapper for information about an input source.
Definition: InputInfo.h:22
clang::driver::toolchains::PS4PS5Base
Definition: PS4CPU.h:60
clang::driver::tools::AddLinkerInputs
void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const JobAction &JA)
clang::driver::toolchains::PS4PS5Base::addClangTargetOptions
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadingKind) const override
Add options that need to be passed to cc1 for this target.
Definition: PS4CPU.cpp:276
clang::driver::ToolChain::getFilePaths
path_list & getFilePaths()
Definition: ToolChain.h:263
clang::driver::Driver::Diag
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:132
clang::driver::Tool
Tool - Information on a specific compilation tool.
Definition: Tool.h:32
clang::driver::toolchains::Generic_ELF
Definition: Gnu.h:362
clang::driver::tools::claimNoWarnArgs
void claimNoWarnArgs(const llvm::opt::ArgList &Args)
Options.h
clang::driver::InputInfo::isFilename
bool isFilename() const
Definition: InputInfo.h:75
PS4CPU.h
llvm::opt
Definition: DiagnosticOptions.h:19
DriverDiagnostic.h
clang::driver::toolchains::PS4PS5Base::getSupportedSanitizers
SanitizerMask getSupportedSanitizers() const override
Return sanitizers which are available in this toolchain.
Definition: PS4CPU.cpp:261
clang::driver::InputInfo::isNothing
bool isNothing() const
Definition: InputInfo.h:74
clang::driver::tools::PScpu::Linker::ConstructJob
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs,...
Definition: PS4CPU.cpp:120
llvm::SmallString< 512 >
clang::driver::ToolChain::getTriple
const llvm::Triple & getTriple() const
Definition: ToolChain.h:227
clang::driver::Driver::SysRoot
std::string SysRoot
sysroot, if present
Definition: Driver.h:171
clang::driver::SanitizerArgs::needsAsanRt
bool needsAsanRt() const
Definition: SanitizerArgs.h:77
clang::driver::toolchains::PS5CPU::buildAssembler
Tool * buildAssembler() const override
Definition: PS4CPU.cpp:251
Base
clang::driver::SanitizerArgs
Definition: SanitizerArgs.h:24
SanitizerArgs.h
clang::driver::tools::PScpu::Assembler
Definition: PS4CPU.h:30
makeArgString
static const char * makeArgString(const ArgList &Args, const char *Prefix, const char *Base, const char *Suffix)
Definition: PS4CPU.cpp:26
clang::driver::tools::PScpu::Assembler::ConstructJob
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs,...
Definition: PS4CPU.cpp:57
clang::driver::tools::PScpu::addProfileRTArgs
void addProfileRTArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs)
clang::driver::ToolChain::getSupportedSanitizers
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:1031
Compilation.h
clang::driver::ToolChain
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:91
clang::driver::tools::PScpu::addSanitizerArgs
void addSanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs)
clang::driver::Compilation
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
clang::driver::toolchains::PS5CPU::getSupportedSanitizers
SanitizerMask getSupportedSanitizers() const override
Return sanitizers which are available in this toolchain.
Definition: PS4CPU.cpp:270
clang::driver::toolchains::PS4CPU::addSanitizerArgs
void addSanitizerArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const char *Prefix, const char *Suffix) const override
Definition: PS4CPU.cpp:90
clang::driver::InputInfo::getFilename
const char * getFilename() const
Definition: InputInfo.h:83
CommonArgs.h
clang
Definition: CalledOnceCheck.h:17
clang::driver::Driver
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:71
clang::driver::toolchains::PS4CPU::PS4CPU
PS4CPU(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
Definition: PS4CPU.cpp:322
clang::driver::toolchains::PS4PS5Base::buildLinker
Tool * buildLinker() const override
Definition: PS4CPU.cpp:257
std::arg
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
Definition: complex_cmath.h:40
clang::driver::SanitizerArgs::needsUbsanRt
bool needsUbsanRt() const
Definition: SanitizerArgs.cpp:257
clang::driver::Action::OffloadKind
OffloadKind
Definition: Action.h:88
clang::driver
Definition: Action.h:31
clang::driver::toolchains::PS4PS5Base::PS4PS5Base
PS4PS5Base(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args, StringRef Platform, const char *EnvVar)
Definition: PS4CPU.cpp:187
clang::driver::JobAction
Definition: Action.h:395
clang::SanitizerMask
Definition: Sanitizers.h:30