Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.cpp
Line
Count
Source (jump to first uncovered line)
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
44
                                 const char *Base, const char *Suffix) {
29
  // Basically "Prefix + Base + Suffix" all converted to Twine then saved.
30
44
  return Args.MakeArgString(Twine(StringRef(Prefix), Base) + Suffix);
31
44
}
32
33
void tools::PScpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
34
269
                                    ArgStringList &CmdArgs) {
35
269
  assert(TC.getTriple().isPS());
36
269
  auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC);
37
38
269
  if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
39
269
                    false) ||
40
269
       Args.hasFlag(options::OPT_fprofile_generate,
41
265
                    options::OPT_fno_profile_generate, false) ||
42
269
       Args.hasFlag(options::OPT_fprofile_generate_EQ,
43
261
                    options::OPT_fno_profile_generate, false) ||
44
269
       Args.hasFlag(options::OPT_fprofile_instr_generate,
45
259
                    options::OPT_fno_profile_instr_generate, false) ||
46
269
       Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
47
257
                    options::OPT_fno_profile_instr_generate, false) ||
48
269
       Args.hasFlag(options::OPT_fcs_profile_generate,
49
255
                    options::OPT_fno_profile_generate, false) ||
50
269
       Args.hasFlag(options::OPT_fcs_profile_generate_EQ,
51
253
                    options::OPT_fno_profile_generate, false) ||
52
269
       
Args.hasArg(options::OPT_fcreate_profile)253
||
53
269
       
Args.hasArg(options::OPT_coverage)253
))
54
18
    CmdArgs.push_back(makeArgString(
55
18
        Args, "--dependent-lib=", PSTC.getProfileRTLibName(), ""));
56
269
}
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
0
                                           const char *LinkingOutput) const {
63
0
  auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
64
0
  claimNoWarnArgs(Args);
65
0
  ArgStringList CmdArgs;
66
67
0
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
68
69
0
  CmdArgs.push_back("-o");
70
0
  CmdArgs.push_back(Output.getFilename());
71
72
0
  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
73
0
  const InputInfo &Input = Inputs[0];
74
0
  assert(Input.isFilename() && "Invalid input.");
75
0
  CmdArgs.push_back(Input.getFilename());
76
77
0
  std::string AsName = TC.qualifyPSCmdName("as");
78
0
  const char *Exec = Args.MakeArgString(TC.GetProgramPath(AsName.c_str()));
79
0
  C.addCommand(std::make_unique<Command>(JA, *this,
80
0
                                         ResponseFileSupport::AtFileUTF8(),
81
0
                                         Exec, CmdArgs, Inputs, Output));
82
0
}
83
84
void tools::PScpu::addSanitizerArgs(const ToolChain &TC, const ArgList &Args,
85
269
                                    ArgStringList &CmdArgs) {
86
269
  assert(TC.getTriple().isPS());
87
269
  auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC);
88
269
  PSTC.addSanitizerArgs(Args, CmdArgs, "--dependent-lib=lib", ".a");
89
269
}
90
91
void toolchains::PS4CPU::addSanitizerArgs(const ArgList &Args,
92
                                          ArgStringList &CmdArgs,
93
                                          const char *Prefix,
94
225
                                          const char *Suffix) const {
95
225
  auto arg = [&](const char *Name) -> const char * {
96
10
    return makeArgString(Args, Prefix, Name, Suffix);
97
10
  };
98
225
  const SanitizerArgs &SanArgs = getSanitizerArgs(Args);
99
225
  if (SanArgs.needsUbsanRt())
100
2
    CmdArgs.push_back(arg("SceDbgUBSanitizer_stub_weak"));
101
225
  if (SanArgs.needsAsanRt())
102
8
    CmdArgs.push_back(arg("SceDbgAddressSanitizer_stub_weak"));
103
225
}
104
105
void toolchains::PS5CPU::addSanitizerArgs(const ArgList &Args,
106
                                          ArgStringList &CmdArgs,
107
                                          const char *Prefix,
108
172
                                          const char *Suffix) const {
109
172
  auto arg = [&](const char *Name) -> const char * {
110
16
    return makeArgString(Args, Prefix, Name, Suffix);
111
16
  };
112
172
  const SanitizerArgs &SanArgs = getSanitizerArgs(Args);
113
172
  if (SanArgs.needsUbsanRt())
114
6
    CmdArgs.push_back(arg("SceUBSanitizer_nosubmission_stub_weak"));
115
172
  if (SanArgs.needsAsanRt())
116
8
    CmdArgs.push_back(arg("SceAddressSanitizer_nosubmission_stub_weak"));
117
172
  if (SanArgs.needsTsanRt())
118
2
    CmdArgs.push_back(arg("SceThreadSanitizer_nosubmission_stub_weak"));
119
172
}
120
121
void tools::PScpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
122
                                        const InputInfo &Output,
123
                                        const InputInfoList &Inputs,
124
                                        const ArgList &Args,
125
143
                                        const char *LinkingOutput) const {
126
143
  auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
127
143
  const Driver &D = TC.getDriver();
128
143
  ArgStringList CmdArgs;
129
130
  // Silence warning for "clang -g foo.o -o foo"
131
143
  Args.ClaimAllArgs(options::OPT_g_Group);
132
  // and "clang -emit-llvm foo.o -o foo"
133
143
  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
143
  Args.ClaimAllArgs(options::OPT_w);
137
138
143
  if (!D.SysRoot.empty())
139
2
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
140
141
143
  if (Args.hasArg(options::OPT_pie))
142
0
    CmdArgs.push_back("-pie");
143
144
143
  if (Args.hasArg(options::OPT_rdynamic))
145
0
    CmdArgs.push_back("-export-dynamic");
146
143
  if (Args.hasArg(options::OPT_shared))
147
10
    CmdArgs.push_back("--shared");
148
149
143
  if (Output.isFilename()) {
150
143
    CmdArgs.push_back("-o");
151
143
    CmdArgs.push_back(Output.getFilename());
152
143
  } else {
153
0
    assert(Output.isNothing() && "Invalid output.");
154
0
  }
155
156
143
  const bool UseLTO = D.isUsingLTO();
157
143
  const bool UseJMC =
158
143
      Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false);
159
143
  const bool IsPS4 = TC.getTriple().isPS4();
160
161
143
  const char *PS4LTOArgs = "";
162
143
  auto AddCodeGenFlag = [&](Twine Flag) {
163
30
    if (IsPS4)
164
21
      PS4LTOArgs = Args.MakeArgString(Twine(PS4LTOArgs) + " " + Flag);
165
9
    else
166
9
      CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=") + Flag));
167
30
  };
168
169
143
  if (UseLTO) {
170
    // We default to creating the arange section, but LTO does not. Enable it
171
    // here.
172
23
    AddCodeGenFlag("-generate-arange-section");
173
174
    // This tells LTO to perform JustMyCode instrumentation.
175
23
    if (UseJMC)
176
3
      AddCodeGenFlag("-enable-jmc-instrument");
177
178
23
    if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir))
179
3
      AddCodeGenFlag(Twine("-crash-diagnostics-dir=") + A->getValue());
180
181
23
    StringRef Parallelism = getLTOParallelism(Args, D);
182
23
    if (!Parallelism.empty()) {
183
2
      if (IsPS4)
184
1
        AddCodeGenFlag(Twine("-threads=") + Parallelism);
185
1
      else
186
1
        CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") + Parallelism));
187
2
    }
188
189
23
    if (IsPS4) {
190
16
      const char *Prefix = nullptr;
191
16
      if (D.getLTOMode() == LTOK_Thin)
192
8
        Prefix = "-lto-thin-debug-options=";
193
8
      else if (D.getLTOMode() == LTOK_Full)
194
8
        Prefix = "-lto-debug-options=";
195
0
      else
196
0
        llvm_unreachable("new LTO mode?");
197
198
16
      CmdArgs.push_back(Args.MakeArgString(Twine(Prefix) + PS4LTOArgs));
199
16
    }
200
23
  }
201
202
143
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
203
128
    TC.addSanitizerArgs(Args, CmdArgs, "-l", "");
204
205
143
  if (D.isUsingLTO() && 
Args.hasArg(options::OPT_funified_lto)23
) {
206
4
    if (D.getLTOMode() == LTOK_Thin)
207
2
      CmdArgs.push_back("--lto=thin");
208
2
    else if (D.getLTOMode() == LTOK_Full)
209
2
      CmdArgs.push_back("--lto=full");
210
4
  }
211
212
143
  Args.AddAllArgs(CmdArgs, options::OPT_L);
213
143
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
214
143
  Args.AddAllArgs(CmdArgs, options::OPT_s);
215
143
  Args.AddAllArgs(CmdArgs, options::OPT_t);
216
143
  Args.AddAllArgs(CmdArgs, options::OPT_r);
217
218
143
  if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
219
0
    CmdArgs.push_back("--no-demangle");
220
221
143
  AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
222
223
143
  if (Args.hasArg(options::OPT_pthread)) {
224
0
    CmdArgs.push_back("-lpthread");
225
0
  }
226
227
143
  if (UseJMC) {
228
5
    CmdArgs.push_back("--whole-archive");
229
5
    if (IsPS4)
230
3
      CmdArgs.push_back("-lSceDbgJmc");
231
2
    else
232
2
      CmdArgs.push_back("-lSceJmc_nosubmission");
233
5
    CmdArgs.push_back("--no-whole-archive");
234
5
  }
235
236
143
  if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
237
10
    D.Diag(diag::err_drv_unsupported_opt_for_target)
238
10
        << "-fuse-ld" << TC.getTriple().str();
239
10
  }
240
241
143
  std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName());
242
143
  const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str()));
243
244
143
  C.addCommand(std::make_unique<Command>(JA, *this,
245
143
                                         ResponseFileSupport::AtFileUTF8(),
246
143
                                         Exec, CmdArgs, Inputs, Output));
247
143
}
248
249
toolchains::PS4PS5Base::PS4PS5Base(const Driver &D, const llvm::Triple &Triple,
250
                                   const ArgList &Args, StringRef Platform,
251
                                   const char *EnvVar)
252
292
    : Generic_ELF(D, Triple, Args) {
253
292
  if (Args.hasArg(clang::driver::options::OPT_static))
254
2
    D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
255
2
        << "-static" << Platform;
256
257
  // Determine where to find the PS4/PS5 libraries.
258
  // If -isysroot was passed, use that as the SDK base path.
259
  // If not, we use the EnvVar if it exists; otherwise use the driver's
260
  // installation path, which should be <SDK_DIR>/host_tools/bin.
261
292
  SmallString<80> Whence;
262
292
  if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
263
14
    SDKRootDir = A->getValue();
264
14
    if (!llvm::sys::fs::exists(SDKRootDir))
265
12
      D.Diag(clang::diag::warn_missing_sysroot) << SDKRootDir;
266
14
    Whence = A->getSpelling();
267
278
  } else if (const char *EnvValue = getenv(EnvVar)) {
268
32
    SDKRootDir = EnvValue;
269
32
    Whence = { "environment variable '", EnvVar, "'" };
270
246
  } else {
271
246
    SDKRootDir = D.Dir + "/../../";
272
246
    Whence = "compiler's location";
273
246
  }
274
275
292
  SmallString<512> SDKIncludeDir(SDKRootDir);
276
292
  llvm::sys::path::append(SDKIncludeDir, "target/include");
277
292
  if (!Args.hasArg(options::OPT_nostdinc) &&
278
292
      
!Args.hasArg(options::OPT_nostdlibinc)284
&&
279
292
      
!Args.hasArg(options::OPT_isysroot)284
&&
280
292
      
!Args.hasArg(options::OPT__sysroot_EQ)270
&&
281
292
      
!llvm::sys::fs::exists(SDKIncludeDir)260
) {
282
260
    D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
283
260
        << Twine(Platform, " system headers").str() << SDKIncludeDir << Whence;
284
260
  }
285
286
292
  SmallString<512> SDKLibDir(SDKRootDir);
287
292
  llvm::sys::path::append(SDKLibDir, "target/lib");
288
292
  if (!Args.hasArg(options::OPT_nostdlib) &&
289
292
      
!Args.hasArg(options::OPT_nodefaultlibs)282
&&
290
292
      
!Args.hasArg(options::OPT__sysroot_EQ)277
&&
!Args.hasArg(options::OPT_E)265
&&
291
292
      
!Args.hasArg(options::OPT_c)257
&&
!Args.hasArg(options::OPT_S)161
&&
292
292
      
!Args.hasArg(options::OPT_emit_ast)149
&&
293
292
      
!llvm::sys::fs::exists(SDKLibDir)143
) {
294
143
    D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
295
143
        << Twine(Platform, " system libraries").str() << SDKLibDir << Whence;
296
143
    return;
297
143
  }
298
149
  getFilePaths().push_back(std::string(SDKLibDir.str()));
299
149
}
300
301
void toolchains::PS4PS5Base::AddClangSystemIncludeArgs(
302
    const ArgList &DriverArgs,
303
282
    ArgStringList &CC1Args) const {
304
282
  const Driver &D = getDriver();
305
306
282
  if (DriverArgs.hasArg(options::OPT_nostdinc))
307
8
    return;
308
309
274
  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
310
274
    SmallString<128> Dir(D.ResourceDir);
311
274
    llvm::sys::path::append(Dir, "include");
312
274
    addSystemInclude(DriverArgs, CC1Args, Dir.str());
313
274
  }
314
315
274
  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
316
0
    return;
317
318
274
  addExternCSystemInclude(DriverArgs, CC1Args,
319
274
                          SDKRootDir + "/target/include");
320
274
  addExternCSystemInclude(DriverArgs, CC1Args,
321
274
                          SDKRootDir + "/target/include_common");
322
274
}
323
324
0
Tool *toolchains::PS4CPU::buildAssembler() const {
325
0
  return new tools::PScpu::Assembler(*this);
326
0
}
327
328
2
Tool *toolchains::PS5CPU::buildAssembler() const {
329
  // PS5 does not support an external assembler.
330
2
  getDriver().Diag(clang::diag::err_no_external_assembler);
331
2
  return nullptr;
332
2
}
333
334
143
Tool *toolchains::PS4PS5Base::buildLinker() const {
335
143
  return new tools::PScpu::Linker(*this);
336
143
}
337
338
681
SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers() const {
339
681
  SanitizerMask Res = ToolChain::getSupportedSanitizers();
340
681
  Res |= SanitizerKind::Address;
341
681
  Res |= SanitizerKind::PointerCompare;
342
681
  Res |= SanitizerKind::PointerSubtract;
343
681
  Res |= SanitizerKind::Vptr;
344
681
  return Res;
345
681
}
346
347
297
SanitizerMask toolchains::PS5CPU::getSupportedSanitizers() const {
348
297
  SanitizerMask Res = PS4PS5Base::getSupportedSanitizers();
349
297
  Res |= SanitizerKind::Thread;
350
297
  return Res;
351
297
}
352
353
void toolchains::PS4PS5Base::addClangTargetOptions(
354
    const ArgList &DriverArgs, ArgStringList &CC1Args,
355
284
    Action::OffloadKind DeviceOffloadingKind) const {
356
  // PS4/PS5 do not use init arrays.
357
284
  if (DriverArgs.hasArg(options::OPT_fuse_init_array)) {
358
2
    Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array);
359
2
    getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target)
360
2
        << A->getAsString(DriverArgs) << getTriple().str();
361
2
  }
362
363
284
  CC1Args.push_back("-fno-use-init-array");
364
365
284
  const Arg *A =
366
284
      DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass,
367
284
                            options::OPT_fno_visibility_from_dllstorageclass);
368
284
  if (!A ||
369
284
      
A->getOption().matches(options::OPT_fvisibility_from_dllstorageclass)8
) {
370
282
    CC1Args.push_back("-fvisibility-from-dllstorageclass");
371
372
282
    if (DriverArgs.hasArg(options::OPT_fvisibility_dllexport_EQ))
373
4
      DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_dllexport_EQ);
374
278
    else
375
278
      CC1Args.push_back("-fvisibility-dllexport=protected");
376
377
282
    if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ))
378
8
      DriverArgs.AddLastArg(CC1Args,
379
8
                            options::OPT_fvisibility_nodllstorageclass_EQ);
380
274
    else
381
274
      CC1Args.push_back("-fvisibility-nodllstorageclass=hidden");
382
383
282
    if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ))
384
8
      DriverArgs.AddLastArg(CC1Args,
385
8
                            options::OPT_fvisibility_externs_dllimport_EQ);
386
274
    else
387
274
      CC1Args.push_back("-fvisibility-externs-dllimport=default");
388
389
282
    if (DriverArgs.hasArg(
390
282
            options::OPT_fvisibility_externs_nodllstorageclass_EQ))
391
4
      DriverArgs.AddLastArg(
392
4
          CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ);
393
278
    else
394
278
      CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default");
395
282
  }
396
284
}
397
398
// PS4 toolchain.
399
toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
400
                           const llvm::opt::ArgList &Args)
401
162
    : PS4PS5Base(D, Triple, Args, "PS4", "SCE_ORBIS_SDK_DIR") {}
402
403
// PS5 toolchain.
404
toolchains::PS5CPU::PS5CPU(const Driver &D, const llvm::Triple &Triple,
405
                           const llvm::opt::ArgList &Args)
406
130
    : PS4PS5Base(D, Triple, Args, "PS5", "SCE_PROSPERO_SDK_DIR") {}