clang  14.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 "FreeBSD.h"
11 #include "CommonArgs.h"
13 #include "clang/Driver/Driver.h"
15 #include "clang/Driver/Options.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 
27 
28 void tools::PS4cpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
29  ArgStringList &CmdArgs) {
30  if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
31  false) ||
32  Args.hasFlag(options::OPT_fprofile_generate,
33  options::OPT_fno_profile_generate, false) ||
34  Args.hasFlag(options::OPT_fprofile_generate_EQ,
35  options::OPT_fno_profile_generate, false) ||
36  Args.hasFlag(options::OPT_fprofile_instr_generate,
37  options::OPT_fno_profile_instr_generate, false) ||
38  Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
39  options::OPT_fno_profile_instr_generate, false) ||
40  Args.hasFlag(options::OPT_fcs_profile_generate,
41  options::OPT_fno_profile_generate, false) ||
42  Args.hasFlag(options::OPT_fcs_profile_generate_EQ,
43  options::OPT_fno_profile_generate, false) ||
44  Args.hasArg(options::OPT_fcreate_profile) ||
45  Args.hasArg(options::OPT_coverage)))
46  CmdArgs.push_back("--dependent-lib=libclang_rt.profile-x86_64.a");
47 }
48 
50  const InputInfo &Output,
51  const InputInfoList &Inputs,
52  const ArgList &Args,
53  const char *LinkingOutput) const {
54  claimNoWarnArgs(Args);
55  ArgStringList CmdArgs;
56 
57  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
58 
59  CmdArgs.push_back("-o");
60  CmdArgs.push_back(Output.getFilename());
61 
62  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
63  const InputInfo &Input = Inputs[0];
64  assert(Input.isFilename() && "Invalid input.");
65  CmdArgs.push_back(Input.getFilename());
66 
67  const char *Exec =
68  Args.MakeArgString(getToolChain().GetProgramPath("orbis-as"));
69  C.addCommand(std::make_unique<Command>(JA, *this,
71  Exec, CmdArgs, Inputs, Output));
72 }
73 
74 static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) {
75  const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
76  if (SanArgs.needsUbsanRt()) {
77  CmdArgs.push_back("-lSceDbgUBSanitizer_stub_weak");
78  }
79  if (SanArgs.needsAsanRt()) {
80  CmdArgs.push_back("-lSceDbgAddressSanitizer_stub_weak");
81  }
82 }
83 
85  ArgStringList &CmdArgs) {
86  const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
87  if (SanArgs.needsUbsanRt())
88  CmdArgs.push_back("--dependent-lib=libSceDbgUBSanitizer_stub_weak.a");
89  if (SanArgs.needsAsanRt())
90  CmdArgs.push_back("--dependent-lib=libSceDbgAddressSanitizer_stub_weak.a");
91 }
92 
94  const InputInfo &Output,
95  const InputInfoList &Inputs,
96  const ArgList &Args,
97  const char *LinkingOutput) const {
99  static_cast<const toolchains::FreeBSD &>(getToolChain());
100  const Driver &D = ToolChain.getDriver();
101  ArgStringList CmdArgs;
102 
103  // Silence warning for "clang -g foo.o -o foo"
104  Args.ClaimAllArgs(options::OPT_g_Group);
105  // and "clang -emit-llvm foo.o -o foo"
106  Args.ClaimAllArgs(options::OPT_emit_llvm);
107  // and for "clang -w foo.o -o foo". Other warning options are already
108  // handled somewhere else.
109  Args.ClaimAllArgs(options::OPT_w);
110 
111  if (!D.SysRoot.empty())
112  CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
113 
114  if (Args.hasArg(options::OPT_pie))
115  CmdArgs.push_back("-pie");
116 
117  if (Args.hasArg(options::OPT_rdynamic))
118  CmdArgs.push_back("-export-dynamic");
119  if (Args.hasArg(options::OPT_shared))
120  CmdArgs.push_back("--oformat=so");
121 
122  if (Output.isFilename()) {
123  CmdArgs.push_back("-o");
124  CmdArgs.push_back(Output.getFilename());
125  } else {
126  assert(Output.isNothing() && "Invalid output.");
127  }
128 
129  if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
130  AddPS4SanitizerArgs(ToolChain, CmdArgs);
131 
132  Args.AddAllArgs(CmdArgs, options::OPT_L);
133  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
134  Args.AddAllArgs(CmdArgs, options::OPT_e);
135  Args.AddAllArgs(CmdArgs, options::OPT_s);
136  Args.AddAllArgs(CmdArgs, options::OPT_t);
137  Args.AddAllArgs(CmdArgs, options::OPT_r);
138 
139  if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
140  CmdArgs.push_back("--no-demangle");
141 
142  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
143 
144  if (Args.hasArg(options::OPT_pthread)) {
145  CmdArgs.push_back("-lpthread");
146  }
147 
148  if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
149  D.Diag(diag::err_drv_unsupported_opt_for_target)
150  << "-fuse-ld" << getToolChain().getTriple().str();
151  }
152 
153  const char *Exec =
154  Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld"));
155 
156  C.addCommand(std::make_unique<Command>(JA, *this,
158  Exec, CmdArgs, Inputs, Output));
159 }
160 
161 toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
162  const ArgList &Args)
163  : Generic_ELF(D, Triple, Args) {
164  if (Args.hasArg(clang::driver::options::OPT_static))
165  D.Diag(clang::diag::err_drv_unsupported_opt_for_target) << "-static"
166  << "PS4";
167 
168  // Determine where to find the PS4 libraries. We use SCE_ORBIS_SDK_DIR
169  // if it exists; otherwise use the driver's installation path, which
170  // should be <SDK_DIR>/host_tools/bin.
171 
172  SmallString<512> PS4SDKDir;
173  if (const char *EnvValue = getenv("SCE_ORBIS_SDK_DIR")) {
174  if (!llvm::sys::fs::exists(EnvValue))
175  getDriver().Diag(clang::diag::warn_drv_ps4_sdk_dir) << EnvValue;
176  PS4SDKDir = EnvValue;
177  } else {
178  PS4SDKDir = getDriver().Dir;
179  llvm::sys::path::append(PS4SDKDir, "/../../");
180  }
181 
182  // By default, the driver won't report a warning if it can't find
183  // PS4's include or lib directories. This behavior could be changed if
184  // -Weverything or -Winvalid-or-nonexistent-directory options are passed.
185  // If -isysroot was passed, use that as the SDK base path.
186  std::string PrefixDir;
187  if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
188  PrefixDir = A->getValue();
189  if (!llvm::sys::fs::exists(PrefixDir))
190  getDriver().Diag(clang::diag::warn_missing_sysroot) << PrefixDir;
191  } else
192  PrefixDir = std::string(PS4SDKDir.str());
193 
194  SmallString<512> PS4SDKIncludeDir(PrefixDir);
195  llvm::sys::path::append(PS4SDKIncludeDir, "target/include");
196  if (!Args.hasArg(options::OPT_nostdinc) &&
197  !Args.hasArg(options::OPT_nostdlibinc) &&
198  !Args.hasArg(options::OPT_isysroot) &&
199  !Args.hasArg(options::OPT__sysroot_EQ) &&
200  !llvm::sys::fs::exists(PS4SDKIncludeDir)) {
201  getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
202  << "PS4 system headers" << PS4SDKIncludeDir;
203  }
204 
205  SmallString<512> PS4SDKLibDir(PS4SDKDir);
206  llvm::sys::path::append(PS4SDKLibDir, "target/lib");
207  if (!Args.hasArg(options::OPT_nostdlib) &&
208  !Args.hasArg(options::OPT_nodefaultlibs) &&
209  !Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) &&
210  !Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) &&
211  !Args.hasArg(options::OPT_emit_ast) &&
212  !llvm::sys::fs::exists(PS4SDKLibDir)) {
213  getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
214  << "PS4 system libraries" << PS4SDKLibDir;
215  return;
216  }
217  getFilePaths().push_back(std::string(PS4SDKLibDir.str()));
218 }
219 
221  return new tools::PS4cpu::Assemble(*this);
222 }
223 
225  return new tools::PS4cpu::Link(*this);
226 }
227 
228 bool toolchains::PS4CPU::isPICDefault() const { return true; }
229 
230 bool toolchains::PS4CPU::HasNativeLLVMSupport() const { return true; }
231 
234  Res |= SanitizerKind::Address;
235  Res |= SanitizerKind::PointerCompare;
236  Res |= SanitizerKind::PointerSubtract;
237  Res |= SanitizerKind::Vptr;
238  return Res;
239 }
240 
242  const ArgList &DriverArgs, ArgStringList &CC1Args,
243  Action::OffloadKind DeviceOffloadingKind) const {
244  // PS4 does not use init arrays.
245  if (DriverArgs.hasArg(options::OPT_fuse_init_array)) {
246  Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array);
247  getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target)
248  << A->getAsString(DriverArgs) << getTriple().str();
249  }
250 
251  CC1Args.push_back("-fno-use-init-array");
252 
253  const Arg *A =
254  DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass,
255  options::OPT_fno_visibility_from_dllstorageclass);
256  if (!A ||
257  A->getOption().matches(options::OPT_fvisibility_from_dllstorageclass)) {
258  CC1Args.push_back("-fvisibility-from-dllstorageclass");
259 
260  if (DriverArgs.hasArg(options::OPT_fvisibility_dllexport_EQ))
261  DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_dllexport_EQ);
262  else
263  CC1Args.push_back("-fvisibility-dllexport=protected");
264 
265  if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ))
266  DriverArgs.AddLastArg(CC1Args,
267  options::OPT_fvisibility_nodllstorageclass_EQ);
268  else
269  CC1Args.push_back("-fvisibility-nodllstorageclass=hidden");
270 
271  if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ))
272  DriverArgs.AddLastArg(CC1Args,
273  options::OPT_fvisibility_externs_dllimport_EQ);
274  else
275  CC1Args.push_back("-fvisibility-externs-dllimport=default");
276 
277  if (DriverArgs.hasArg(
278  options::OPT_fvisibility_externs_nodllstorageclass_EQ))
279  DriverArgs.AddLastArg(
280  CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ);
281  else
282  CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default");
283  }
284 }
clang::driver::ToolChain::getSanitizerArgs
const SanitizerArgs & getSanitizerArgs() const
Definition: ToolChain.cpp:117
clang::driver::toolchains::FreeBSD
Definition: FreeBSD.h:52
Driver.h
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:123
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:542
clang::driver::toolchains::PS4CPU::getSupportedSanitizers
SanitizerMask getSupportedSanitizers() const override
Return sanitizers which are available in this toolchain.
Definition: PS4CPU.cpp:232
clang::driver::ToolChain::getDriver
const Driver & getDriver() const
Definition: ToolChain.h:221
clang::driver::tools::PS4cpu::addSanitizerArgs
void addSanitizerArgs(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs)
clang::driver::toolchains::PS4CPU::buildAssembler
Tool * buildAssembler() const override
Definition: PS4CPU.cpp:220
clang::driver::InputInfo
InputInfo - Wrapper for information about an input source.
Definition: InputInfo.h:22
clang::driver::toolchains::PS4CPU::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:241
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::ToolChain::getFilePaths
path_list & getFilePaths()
Definition: ToolChain.h:259
clang::driver::Driver::Diag
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:112
clang::driver::toolchains::PS4CPU::buildLinker
Tool * buildLinker() const override
Definition: PS4CPU.cpp:224
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
clang::driver::tools::PS4cpu::addProfileRTArgs
void addProfileRTArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs)
clang::driver::phases::Assemble
@ Assemble
Definition: Phases.h:22
clang::driver::phases::Link
@ Link
Definition: Phases.h:23
llvm::opt
Definition: DiagnosticOptions.h:19
DriverDiagnostic.h
clang::driver::InputInfo::isNothing
bool isNothing() const
Definition: InputInfo.h:74
llvm::SmallString< 512 >
clang::driver::Driver::SysRoot
std::string SysRoot
sysroot, if present
Definition: Driver.h:151
clang::driver::SanitizerArgs::needsAsanRt
bool needsAsanRt() const
Definition: SanitizerArgs.h:73
clang::driver::SanitizerArgs
Definition: SanitizerArgs.h:24
SanitizerArgs.h
FreeBSD.h
clang::driver::ToolChain::getSupportedSanitizers
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:998
Compilation.h
clang::driver::ToolChain
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:91
clang::driver::toolchains::PS4CPU::isPICDefault
bool isPICDefault() const override
Test whether this toolchain defaults to PIC.
Definition: PS4CPU.cpp:228
clang::driver::tools::PS4cpu::Assemble::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:49
clang::driver::Compilation
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
clang::driver::toolchains::PS4CPU::HasNativeLLVMSupport
bool HasNativeLLVMSupport() const override
HasNativeLTOLinker - Check whether the linker and related tools have native LLVM support.
Definition: PS4CPU.cpp:230
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:59
clang::driver::toolchains::PS4CPU::PS4CPU
PS4CPU(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
Definition: PS4CPU.cpp:161
clang::driver::SanitizerArgs::needsUbsanRt
bool needsUbsanRt() const
Definition: SanitizerArgs.cpp:247
clang::driver::Action::OffloadKind
OffloadKind
Definition: Action.h:85
clang::driver
Definition: Action.h:31
clang::driver::JobAction
Definition: Action.h:380
AddPS4SanitizerArgs
static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs)
Definition: PS4CPU.cpp:74
clang::SanitizerMask
Definition: Sanitizers.h:30