Coverage Report

Created: 2020-09-22 08:39

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Hexagon.cpp - Hexagon 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 "Hexagon.h"
10
#include "CommonArgs.h"
11
#include "InputInfo.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 "llvm/ADT/StringExtras.h"
17
#include "llvm/Option/ArgList.h"
18
#include "llvm/Support/FileSystem.h"
19
#include "llvm/Support/Path.h"
20
#include "llvm/Support/VirtualFileSystem.h"
21
22
using namespace clang::driver;
23
using namespace clang::driver::tools;
24
using namespace clang::driver::toolchains;
25
using namespace clang;
26
using namespace llvm::opt;
27
28
// Default hvx-length for various versions.
29
10
static StringRef getDefaultHvxLength(StringRef Cpu) {
30
10
  return llvm::StringSwitch<StringRef>(Cpu)
31
10
      .Case("v60", "64b")
32
10
      .Case("v62", "64b")
33
10
      .Case("v65", "64b")
34
10
      .Default("128b");
35
10
}
36
37
96
static void handleHVXWarnings(const Driver &D, const ArgList &Args) {
38
  // Handle the unsupported values passed to mhvx-length.
39
96
  if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
40
10
    StringRef Val = A->getValue();
41
10
    if (!Val.equals_lower("64b") && 
!Val.equals_lower("128b")7
)
42
2
      D.Diag(diag::err_drv_unsupported_option_argument)
43
2
          << A->getOption().getName() << Val;
44
10
  }
45
96
}
46
47
// Handle hvx target features explicitly.
48
static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
49
                                    std::vector<StringRef> &Features,
50
96
                                    StringRef Cpu, bool &HasHVX) {
51
  // Handle HVX warnings.
52
96
  handleHVXWarnings(D, Args);
53
54
  // Add the +hvx* features based on commandline flags.
55
96
  StringRef HVXFeature, HVXLength;
56
57
  // Handle -mhvx, -mhvx=, -mno-hvx.
58
96
  if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx,
59
20
                               options::OPT_mhexagon_hvx,
60
20
                               options::OPT_mhexagon_hvx_EQ)) {
61
20
    if (A->getOption().matches(options::OPT_mno_hexagon_hvx))
62
2
      return;
63
18
    if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ)) {
64
2
      HasHVX = true;
65
2
      HVXFeature = Cpu = A->getValue();
66
2
      HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + HVXFeature.lower());
67
16
    } else if (A->getOption().matches(options::OPT_mhexagon_hvx)) {
68
16
      HasHVX = true;
69
16
      HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + Cpu);
70
16
    }
71
18
    Features.push_back(HVXFeature);
72
18
  }
73
74
  // Handle -mhvx-length=.
75
94
  if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
76
    // These flags are valid only if HVX in enabled.
77
10
    if (!HasHVX)
78
2
      D.Diag(diag::err_drv_invalid_hvx_length);
79
8
    else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))
80
8
      HVXLength = A->getValue();
81
10
  }
82
  // Default hvx-length based on Cpu.
83
84
  else if (HasHVX)
84
10
    HVXLength = getDefaultHvxLength(Cpu);
85
86
94
  if (!HVXLength.empty()) {
87
18
    HVXFeature =
88
18
        Args.MakeArgString(llvm::Twine("+hvx-length") + HVXLength.lower());
89
18
    Features.push_back(HVXFeature);
90
18
  }
91
94
}
92
93
// Hexagon target features.
94
void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
95
96
                                       std::vector<StringRef> &Features) {
96
96
  handleTargetFeaturesGroup(Args, Features,
97
96
                            options::OPT_m_hexagon_Features_Group);
98
99
96
  bool UseLongCalls = false;
100
96
  if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
101
2
                               options::OPT_mno_long_calls)) {
102
2
    if (A->getOption().matches(options::OPT_mlong_calls))
103
1
      UseLongCalls = true;
104
2
  }
105
106
95
  Features.push_back(UseLongCalls ? 
"+long-calls"1
: "-long-calls");
107
108
96
  bool HasHVX = false;
109
96
  StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));
110
  // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors
111
  // have no dependency on micro-architecture.
112
96
  const bool TinyCore = Cpu.contains('t');
113
114
96
  if (TinyCore)
115
1
    Cpu = Cpu.take_front(Cpu.size() - 1);
116
117
96
  handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);
118
119
96
  if (HexagonToolChain::isAutoHVXEnabled(Args) && 
!HasHVX2
)
120
2
    D.Diag(diag::warn_drv_vectorize_needs_hvx);
121
96
}
122
123
// Hexagon tools start.
124
void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
125
5
                                             ArgStringList &CmdArgs) const {
126
5
}
127
128
void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
129
                                      const InputInfo &Output,
130
                                      const InputInfoList &Inputs,
131
                                      const ArgList &Args,
132
5
                                      const char *LinkingOutput) const {
133
5
  claimNoWarnArgs(Args);
134
135
5
  auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
136
5
  const Driver &D = HTC.getDriver();
137
5
  ArgStringList CmdArgs;
138
139
5
  CmdArgs.push_back("--arch=hexagon");
140
141
5
  RenderExtraToolArgs(JA, CmdArgs);
142
143
5
  const char *AsName = "llvm-mc";
144
5
  CmdArgs.push_back("-filetype=obj");
145
5
  CmdArgs.push_back(Args.MakeArgString(
146
5
      "-mcpu=hexagon" +
147
5
      toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));
148
149
5
  if (Output.isFilename()) {
150
5
    CmdArgs.push_back("-o");
151
5
    CmdArgs.push_back(Output.getFilename());
152
0
  } else {
153
0
    assert(Output.isNothing() && "Unexpected output");
154
0
    CmdArgs.push_back("-fsyntax-only");
155
0
  }
156
157
5
  if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
158
3
    CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(G.getValue())));
159
3
  }
160
161
5
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
162
163
  // Only pass -x if gcc will understand it; otherwise hope gcc
164
  // understands the suffix correctly. The main use case this would go
165
  // wrong in is for linker inputs if they happened to have an odd
166
  // suffix; really the only way to get this to happen is a command
167
  // like '-x foobar a.c' which will treat a.c like a linker input.
168
  //
169
  // FIXME: For the linker case specifically, can we safely convert
170
  // inputs into '-Wl,' options?
171
5
  for (const auto &II : Inputs) {
172
    // Don't try to pass LLVM or AST inputs to a generic gcc.
173
5
    if (types::isLLVMIR(II.getType()))
174
0
      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
175
0
          << HTC.getTripleString();
176
5
    else if (II.getType() == types::TY_AST)
177
0
      D.Diag(clang::diag::err_drv_no_ast_support)
178
0
          << HTC.getTripleString();
179
5
    else if (II.getType() == types::TY_ModuleFile)
180
0
      D.Diag(diag::err_drv_no_module_support)
181
0
          << HTC.getTripleString();
182
183
5
    if (II.isFilename())
184
5
      CmdArgs.push_back(II.getFilename());
185
0
    else
186
      // Don't render as input, we need gcc to do the translations.
187
      // FIXME: What is this?
188
0
      II.getInputArg().render(Args, CmdArgs);
189
5
  }
190
191
5
  auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName));
192
5
  C.addCommand(std::make_unique<Command>(
193
5
      JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
194
5
}
195
196
void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
197
0
                                          ArgStringList &CmdArgs) const {
198
0
}
199
200
static void
201
constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
202
                         const toolchains::HexagonToolChain &HTC,
203
                         const InputInfo &Output, const InputInfoList &Inputs,
204
                         const ArgList &Args, ArgStringList &CmdArgs,
205
70
                         const char *LinkingOutput) {
206
207
70
  const Driver &D = HTC.getDriver();
208
209
  //----------------------------------------------------------------------------
210
  //
211
  //----------------------------------------------------------------------------
212
70
  bool IsStatic = Args.hasArg(options::OPT_static);
213
70
  bool IsShared = Args.hasArg(options::OPT_shared);
214
70
  bool IsPIE = Args.hasArg(options::OPT_pie);
215
70
  bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
216
70
  bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
217
70
  bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
218
70
  bool UseG0 = false;
219
70
  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
220
70
  bool UseLLD = (llvm::sys::path::filename(Exec).equals_lower("ld.lld") ||
221
62
                 llvm::sys::path::stem(Exec).equals_lower("ld.lld"));
222
70
  bool UseShared = IsShared && 
!IsStatic4
;
223
70
  StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
224
225
  //----------------------------------------------------------------------------
226
  // Silence warnings for various options
227
  //----------------------------------------------------------------------------
228
70
  Args.ClaimAllArgs(options::OPT_g_Group);
229
70
  Args.ClaimAllArgs(options::OPT_emit_llvm);
230
70
  Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
231
                                     // handled somewhere else.
232
70
  Args.ClaimAllArgs(options::OPT_static_libgcc);
233
234
  //----------------------------------------------------------------------------
235
  //
236
  //----------------------------------------------------------------------------
237
70
  if (Args.hasArg(options::OPT_s))
238
1
    CmdArgs.push_back("-s");
239
240
70
  if (Args.hasArg(options::OPT_r))
241
0
    CmdArgs.push_back("-r");
242
243
70
  for (const auto &Opt : HTC.ExtraOpts)
244
0
    CmdArgs.push_back(Opt.c_str());
245
246
70
  if (!UseLLD) {
247
62
    CmdArgs.push_back("-march=hexagon");
248
62
    CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));
249
62
  }
250
251
70
  if (IsShared) {
252
4
    CmdArgs.push_back("-shared");
253
    // The following should be the default, but doing as hexagon-gcc does.
254
4
    CmdArgs.push_back("-call_shared");
255
4
  }
256
257
70
  if (IsStatic)
258
2
    CmdArgs.push_back("-static");
259
260
70
  if (IsPIE && 
!IsShared2
)
261
1
    CmdArgs.push_back("-pie");
262
263
70
  if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
264
9
    CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue())));
265
9
    UseG0 = G.getValue() == 0;
266
9
  }
267
268
70
  CmdArgs.push_back("-o");
269
70
  CmdArgs.push_back(Output.getFilename());
270
271
70
  if (HTC.getTriple().isMusl()) {
272
7
    if (!Args.hasArg(options::OPT_shared, options::OPT_static))
273
6
      CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");
274
275
7
    if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,
276
7
                     options::OPT_nostdlib))
277
4
      CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));
278
3
    else if (Args.hasArg(options::OPT_shared) &&
279
1
             !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib))
280
1
      CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));
281
282
7
    CmdArgs.push_back(
283
7
        Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));
284
7
    Args.AddAllArgs(CmdArgs,
285
7
                    {options::OPT_T_Group, options::OPT_e, options::OPT_s,
286
7
                     options::OPT_t, options::OPT_u_Group});
287
7
    AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
288
289
7
    if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
290
5
      CmdArgs.push_back("-lclang_rt.builtins-hexagon");
291
5
      CmdArgs.push_back("-lc");
292
5
    }
293
7
    if (D.CCCIsCXX()) {
294
1
      if (HTC.ShouldLinkCXXStdlib(Args))
295
1
        HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
296
1
    }
297
7
    return;
298
7
  }
299
300
  //----------------------------------------------------------------------------
301
  // moslib
302
  //----------------------------------------------------------------------------
303
63
  std::vector<std::string> OsLibs;
304
63
  bool HasStandalone = false;
305
5
  for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
306
5
    A->claim();
307
5
    OsLibs.emplace_back(A->getValue());
308
5
    HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
309
5
  }
310
63
  if (OsLibs.empty()) {
311
61
    OsLibs.push_back("standalone");
312
61
    HasStandalone = true;
313
61
  }
314
315
  //----------------------------------------------------------------------------
316
  // Start Files
317
  //----------------------------------------------------------------------------
318
63
  const std::string MCpuSuffix = "/" + CpuVer.str();
319
63
  const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
320
63
  const std::string RootDir =
321
63
      HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
322
63
  const std::string StartSubDir =
323
58
      "hexagon/lib" + (UseG0 ? 
MCpuG0Suffix5
: MCpuSuffix);
324
325
63
  auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
326
237
                      const char *Name) -> std::string {
327
237
    std::string RelName = SubDir + Name;
328
237
    std::string P = HTC.GetFilePath(RelName.c_str());
329
237
    if (llvm::sys::fs::exists(P))
330
0
      return P;
331
237
    return RootDir + RelName;
332
237
  };
333
334
63
  if (IncStdLib && 
IncStartFiles62
) {
335
61
    if (!IsShared) {
336
58
      if (HasStandalone) {
337
57
        std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
338
57
        CmdArgs.push_back(Args.MakeArgString(Crt0SA));
339
57
      }
340
58
      std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
341
58
      CmdArgs.push_back(Args.MakeArgString(Crt0));
342
58
    }
343
61
    std::string Init = UseShared
344
2
          ? Find(RootDir, StartSubDir + "/pic", "/initS.o")
345
59
          : Find(RootDir, StartSubDir, "/init.o");
346
61
    CmdArgs.push_back(Args.MakeArgString(Init));
347
61
  }
348
349
  //----------------------------------------------------------------------------
350
  // Library Search Paths
351
  //----------------------------------------------------------------------------
352
63
  const ToolChain::path_list &LibPaths = HTC.getFilePaths();
353
63
  for (const auto &LibPath : LibPaths)
354
136
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
355
356
  //----------------------------------------------------------------------------
357
  //
358
  //----------------------------------------------------------------------------
359
63
  Args.AddAllArgs(CmdArgs,
360
63
                  {options::OPT_T_Group, options::OPT_e, options::OPT_s,
361
63
                   options::OPT_t, options::OPT_u_Group});
362
363
63
  AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
364
365
  //----------------------------------------------------------------------------
366
  // Libraries
367
  //----------------------------------------------------------------------------
368
63
  if (IncStdLib && 
IncDefLibs62
) {
369
61
    if (D.CCCIsCXX()) {
370
7
      if (HTC.ShouldLinkCXXStdlib(Args))
371
7
        HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
372
7
      CmdArgs.push_back("-lm");
373
7
    }
374
375
61
    CmdArgs.push_back("--start-group");
376
377
61
    if (!IsShared) {
378
58
      for (StringRef Lib : OsLibs)
379
61
        CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
380
58
      CmdArgs.push_back("-lc");
381
58
    }
382
61
    CmdArgs.push_back("-lgcc");
383
384
61
    CmdArgs.push_back("--end-group");
385
61
  }
386
387
  //----------------------------------------------------------------------------
388
  // End files
389
  //----------------------------------------------------------------------------
390
63
  if (IncStdLib && 
IncStartFiles62
) {
391
61
    std::string Fini = UseShared
392
2
          ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")
393
59
          : Find(RootDir, StartSubDir, "/fini.o");
394
61
    CmdArgs.push_back(Args.MakeArgString(Fini));
395
61
  }
396
63
}
397
398
void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
399
                                   const InputInfo &Output,
400
                                   const InputInfoList &Inputs,
401
                                   const ArgList &Args,
402
70
                                   const char *LinkingOutput) const {
403
70
  auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
404
405
70
  ArgStringList CmdArgs;
406
70
  constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
407
70
                           LinkingOutput);
408
409
70
  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
410
70
  C.addCommand(std::make_unique<Command>(
411
70
      JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
412
70
}
413
// Hexagon tools end.
414
415
/// Hexagon Toolchain
416
417
std::string HexagonToolChain::getHexagonTargetDir(
418
      const std::string &InstalledDir,
419
349
      const SmallVectorImpl<std::string> &PrefixDirs) const {
420
349
  std::string InstallRelDir;
421
349
  const Driver &D = getDriver();
422
423
  // Locate the rest of the toolchain ...
424
349
  for (auto &I : PrefixDirs)
425
0
    if (D.getVFS().exists(I))
426
0
      return I;
427
428
349
  if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
429
195
    return InstallRelDir;
430
431
154
  return InstalledDir;
432
154
}
433
434
Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
435
267
      const ArgList &Args) {
436
267
  StringRef Gn = "";
437
267
  if (Arg *A = Args.getLastArg(options::OPT_G)) {
438
12
    Gn = A->getValue();
439
255
  } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
440
18
                             options::OPT_fPIC)) {
441
18
    Gn = "0";
442
18
  }
443
444
267
  unsigned G;
445
267
  if (!Gn.getAsInteger(10, G))
446
30
    return G;
447
448
237
  return None;
449
237
}
450
451
void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
452
96
      ToolChain::path_list &LibPaths) const {
453
96
  const Driver &D = getDriver();
454
455
  //----------------------------------------------------------------------------
456
  // -L Args
457
  //----------------------------------------------------------------------------
458
96
  for (Arg *A : Args.filtered(options::OPT_L))
459
3
    for (const char *Value : A->getValues())
460
3
      LibPaths.push_back(Value);
461
462
  //----------------------------------------------------------------------------
463
  // Other standard paths
464
  //----------------------------------------------------------------------------
465
96
  std::vector<std::string> RootDirs;
466
96
  std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
467
96
            std::back_inserter(RootDirs));
468
469
96
  std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
470
96
                                              D.PrefixDirs);
471
96
  if (llvm::find(RootDirs, TargetDir) == RootDirs.end())
472
96
    RootDirs.push_back(TargetDir);
473
474
96
  bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);
475
  // Assume G0 with -shared.
476
96
  bool HasG0 = Args.hasArg(options::OPT_shared);
477
96
  if (auto G = getSmallDataThreshold(Args))
478
9
    HasG0 = G.getValue() == 0;
479
480
96
  const std::string CpuVer = GetTargetCPUVersion(Args).str();
481
96
  for (auto &Dir : RootDirs) {
482
96
    std::string LibDir = Dir + "/hexagon/lib";
483
96
    std::string LibDirCpu = LibDir + '/' + CpuVer;
484
96
    if (HasG0) {
485
6
      if (HasPIC)
486
2
        LibPaths.push_back(LibDirCpu + "/G0/pic");
487
6
      LibPaths.push_back(LibDirCpu + "/G0");
488
6
    }
489
96
    LibPaths.push_back(LibDirCpu);
490
96
    LibPaths.push_back(LibDir);
491
96
  }
492
96
}
493
494
HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
495
                                   const llvm::opt::ArgList &Args)
496
96
    : Linux(D, Triple, Args) {
497
96
  const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
498
96
                                                    D.PrefixDirs);
499
500
  // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
501
  // program paths
502
96
  const std::string BinDir(TargetDir + "/bin");
503
96
  if (D.getVFS().exists(BinDir))
504
0
    getProgramPaths().push_back(BinDir);
505
506
96
  ToolChain::path_list &LibPaths = getFilePaths();
507
508
  // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
509
  // 'elf' OS type, so the Linux paths are not appropriate. When we actually
510
  // support 'linux' we'll need to fix this up
511
96
  LibPaths.clear();
512
96
  getHexagonLibraryPaths(Args, LibPaths);
513
96
}
514
515
96
HexagonToolChain::~HexagonToolChain() {}
516
517
void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
518
8
                                           ArgStringList &CmdArgs) const {
519
8
  CXXStdlibType Type = GetCXXStdlibType(Args);
520
8
  switch (Type) {
521
2
  case ToolChain::CST_Libcxx:
522
2
    CmdArgs.push_back("-lc++");
523
2
    CmdArgs.push_back("-lc++abi");
524
2
    CmdArgs.push_back("-lunwind");
525
2
    break;
526
527
6
  case ToolChain::CST_Libstdcxx:
528
6
    CmdArgs.push_back("-lstdc++");
529
6
    break;
530
8
  }
531
8
}
532
533
5
Tool *HexagonToolChain::buildAssembler() const {
534
5
  return new tools::hexagon::Assembler(*this);
535
5
}
536
537
70
Tool *HexagonToolChain::buildLinker() const {
538
70
  return new tools::hexagon::Linker(*this);
539
70
}
540
541
unsigned HexagonToolChain::getOptimizationLevel(
542
0
    const llvm::opt::ArgList &DriverArgs) const {
543
  // Copied in large part from lib/Frontend/CompilerInvocation.cpp.
544
0
  Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);
545
0
  if (!A)
546
0
    return 0;
547
548
0
  if (A->getOption().matches(options::OPT_O0))
549
0
    return 0;
550
0
  if (A->getOption().matches(options::OPT_Ofast) ||
551
0
      A->getOption().matches(options::OPT_O4))
552
0
    return 3;
553
0
  assert(A->getNumValues() != 0);
554
0
  StringRef S(A->getValue());
555
0
  if (S == "s" || S == "z" || S.empty())
556
0
    return 2;
557
0
  if (S == "g")
558
0
    return 1;
559
560
0
  unsigned OptLevel;
561
0
  if (S.getAsInteger(10, OptLevel))
562
0
    return 0;
563
0
  return OptLevel;
564
0
}
565
566
void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
567
                                             ArgStringList &CC1Args,
568
97
                                             Action::OffloadKind) const {
569
570
97
  bool UseInitArrayDefault = getTriple().isMusl();
571
572
97
  if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
573
97
                          options::OPT_fno_use_init_array,
574
97
                          UseInitArrayDefault))
575
90
    CC1Args.push_back("-fno-use-init-array");
576
577
97
  if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
578
3
    CC1Args.push_back("-target-feature");
579
3
    CC1Args.push_back("+reserved-r19");
580
3
  }
581
97
  if (isAutoHVXEnabled(DriverArgs)) {
582
2
    CC1Args.push_back("-mllvm");
583
2
    CC1Args.push_back("-hexagon-autohvx");
584
2
  }
585
97
}
586
587
void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
588
96
                                                 ArgStringList &CC1Args) const {
589
96
  if (DriverArgs.hasArg(options::OPT_nostdinc) ||
590
95
      DriverArgs.hasArg(options::OPT_nostdlibinc))
591
3
    return;
592
593
93
  const Driver &D = getDriver();
594
93
  if (!D.SysRoot.empty()) {
595
7
    SmallString<128> P(D.SysRoot);
596
7
    if (getTriple().isMusl())
597
6
      llvm::sys::path::append(P, "usr/include");
598
1
    else
599
1
      llvm::sys::path::append(P, "include");
600
7
    addExternCSystemInclude(DriverArgs, CC1Args, P.str());
601
7
    return;
602
7
  }
603
604
86
  std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
605
86
                                              D.PrefixDirs);
606
86
  addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
607
86
}
608
609
void HexagonToolChain::addLibCxxIncludePaths(
610
    const llvm::opt::ArgList &DriverArgs,
611
2
    llvm::opt::ArgStringList &CC1Args) const {
612
2
  const Driver &D = getDriver();
613
2
  if (!D.SysRoot.empty() && 
getTriple().isMusl()1
)
614
1
    addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "", "", "",
615
1
                             "", DriverArgs, CC1Args);
616
1
  else if (getTriple().isMusl())
617
0
    addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", "", "", "",
618
0
                             DriverArgs, CC1Args);
619
1
  else {
620
1
    std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
621
1
    addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++/v1", "", "", "",
622
1
                             "", DriverArgs, CC1Args);
623
1
  }
624
2
}
625
void HexagonToolChain::addLibStdCxxIncludePaths(
626
    const llvm::opt::ArgList &DriverArgs,
627
7
    llvm::opt::ArgStringList &CC1Args) const {
628
7
  const Driver &D = getDriver();
629
7
  std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
630
7
  addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++", "", "", "", "",
631
7
                           DriverArgs, CC1Args);
632
7
}
633
634
ToolChain::CXXStdlibType
635
17
HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
636
17
  Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
637
17
  if (!A) {
638
15
    if (getTriple().isMusl())
639
2
      return ToolChain::CST_Libcxx;
640
13
    else
641
13
      return ToolChain::CST_Libstdcxx;
642
2
  }
643
2
  StringRef Value = A->getValue();
644
2
  if (Value != "libstdc++" && Value != "libc++")
645
0
    getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
646
647
2
  if (Value == "libstdc++")
648
0
    return ToolChain::CST_Libstdcxx;
649
2
  else if (Value == "libc++")
650
2
    return ToolChain::CST_Libcxx;
651
0
  else
652
0
    return ToolChain::CST_Libstdcxx;
653
2
}
654
655
193
bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {
656
193
  if (Arg *A = Args.getLastArg(options::OPT_fvectorize,
657
6
                               options::OPT_fno_vectorize))
658
6
    return A->getOption().matches(options::OPT_fvectorize);
659
187
  return false;
660
187
}
661
662
//
663
// Returns the default CPU for Hexagon. This is the default compilation target
664
// if no Hexagon processor is selected at the command-line.
665
//
666
123
const StringRef HexagonToolChain::GetDefaultCPU() {
667
123
  return "hexagonv60";
668
123
}
669
670
363
const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
671
363
  Arg *CpuArg = nullptr;
672
363
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
673
240
    CpuArg = A;
674
675
240
  StringRef CPU = CpuArg ? CpuArg->getValue() : 
GetDefaultCPU()123
;
676
363
  if (CPU.startswith("hexagon"))
677
363
    return CPU.substr(sizeof("hexagon") - 1);
678
0
  return CPU;
679
0
}