Coverage Report

Created: 2020-09-22 08:39

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