Coverage Report

Created: 2021-01-23 06:44

/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>(JA, *this,
193
5
                                         ResponseFileSupport::AtFileCurCP(),
194
5
                                         Exec, CmdArgs, Inputs, Output));
195
5
}
196
197
void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
198
0
                                          ArgStringList &CmdArgs) const {
199
0
}
200
201
static void
202
constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
203
                         const toolchains::HexagonToolChain &HTC,
204
                         const InputInfo &Output, const InputInfoList &Inputs,
205
                         const ArgList &Args, ArgStringList &CmdArgs,
206
70
                         const char *LinkingOutput) {
207
208
70
  const Driver &D = HTC.getDriver();
209
210
  //----------------------------------------------------------------------------
211
  //
212
  //----------------------------------------------------------------------------
213
70
  bool IsStatic = Args.hasArg(options::OPT_static);
214
70
  bool IsShared = Args.hasArg(options::OPT_shared);
215
70
  bool IsPIE = Args.hasArg(options::OPT_pie);
216
70
  bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
217
70
  bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
218
70
  bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
219
70
  bool UseG0 = false;
220
70
  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
221
70
  bool UseLLD = (llvm::sys::path::filename(Exec).equals_lower("ld.lld") ||
222
62
                 llvm::sys::path::stem(Exec).equals_lower("ld.lld"));
223
70
  bool UseShared = IsShared && 
!IsStatic4
;
224
70
  StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
225
226
  //----------------------------------------------------------------------------
227
  // Silence warnings for various options
228
  //----------------------------------------------------------------------------
229
70
  Args.ClaimAllArgs(options::OPT_g_Group);
230
70
  Args.ClaimAllArgs(options::OPT_emit_llvm);
231
70
  Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
232
                                     // handled somewhere else.
233
70
  Args.ClaimAllArgs(options::OPT_static_libgcc);
234
235
  //----------------------------------------------------------------------------
236
  //
237
  //----------------------------------------------------------------------------
238
70
  if (Args.hasArg(options::OPT_s))
239
1
    CmdArgs.push_back("-s");
240
241
70
  if (Args.hasArg(options::OPT_r))
242
0
    CmdArgs.push_back("-r");
243
244
70
  for (const auto &Opt : HTC.ExtraOpts)
245
0
    CmdArgs.push_back(Opt.c_str());
246
247
70
  if (!UseLLD) {
248
62
    CmdArgs.push_back("-march=hexagon");
249
62
    CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));
250
62
  }
251
252
70
  if (IsShared) {
253
4
    CmdArgs.push_back("-shared");
254
    // The following should be the default, but doing as hexagon-gcc does.
255
4
    CmdArgs.push_back("-call_shared");
256
4
  }
257
258
70
  if (IsStatic)
259
2
    CmdArgs.push_back("-static");
260
261
70
  if (IsPIE && 
!IsShared2
)
262
1
    CmdArgs.push_back("-pie");
263
264
70
  if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
265
9
    CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue())));
266
9
    UseG0 = G.getValue() == 0;
267
9
  }
268
269
70
  CmdArgs.push_back("-o");
270
70
  CmdArgs.push_back(Output.getFilename());
271
272
70
  if (HTC.getTriple().isMusl()) {
273
7
    if (!Args.hasArg(options::OPT_shared, options::OPT_static))
274
6
      CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");
275
276
7
    if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,
277
7
                     options::OPT_nostdlib))
278
4
      CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));
279
3
    else if (Args.hasArg(options::OPT_shared) &&
280
1
             !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib))
281
1
      CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));
282
283
7
    CmdArgs.push_back(
284
7
        Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));
285
7
    Args.AddAllArgs(CmdArgs,
286
7
                    {options::OPT_T_Group, options::OPT_e, options::OPT_s,
287
7
                     options::OPT_t, options::OPT_u_Group});
288
7
    AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
289
290
7
    if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
291
5
      CmdArgs.push_back("-lclang_rt.builtins-hexagon");
292
5
      CmdArgs.push_back("-lc");
293
5
    }
294
7
    if (D.CCCIsCXX()) {
295
1
      if (HTC.ShouldLinkCXXStdlib(Args))
296
1
        HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
297
1
    }
298
7
    return;
299
7
  }
300
301
  //----------------------------------------------------------------------------
302
  // moslib
303
  //----------------------------------------------------------------------------
304
63
  std::vector<std::string> OsLibs;
305
63
  bool HasStandalone = false;
306
5
  for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
307
5
    A->claim();
308
5
    OsLibs.emplace_back(A->getValue());
309
5
    HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
310
5
  }
311
63
  if (OsLibs.empty()) {
312
61
    OsLibs.push_back("standalone");
313
61
    HasStandalone = true;
314
61
  }
315
316
  //----------------------------------------------------------------------------
317
  // Start Files
318
  //----------------------------------------------------------------------------
319
63
  const std::string MCpuSuffix = "/" + CpuVer.str();
320
63
  const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
321
63
  const std::string RootDir =
322
63
      HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
323
63
  const std::string StartSubDir =
324
58
      "hexagon/lib" + (UseG0 ? 
MCpuG0Suffix5
: MCpuSuffix);
325
326
63
  auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
327
237
                      const char *Name) -> std::string {
328
237
    std::string RelName = SubDir + Name;
329
237
    std::string P = HTC.GetFilePath(RelName.c_str());
330
237
    if (llvm::sys::fs::exists(P))
331
0
      return P;
332
237
    return RootDir + RelName;
333
237
  };
334
335
63
  if (IncStdLib && 
IncStartFiles62
) {
336
61
    if (!IsShared) {
337
58
      if (HasStandalone) {
338
57
        std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
339
57
        CmdArgs.push_back(Args.MakeArgString(Crt0SA));
340
57
      }
341
58
      std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
342
58
      CmdArgs.push_back(Args.MakeArgString(Crt0));
343
58
    }
344
61
    std::string Init = UseShared
345
2
          ? Find(RootDir, StartSubDir + "/pic", "/initS.o")
346
59
          : Find(RootDir, StartSubDir, "/init.o");
347
61
    CmdArgs.push_back(Args.MakeArgString(Init));
348
61
  }
349
350
  //----------------------------------------------------------------------------
351
  // Library Search Paths
352
  //----------------------------------------------------------------------------
353
63
  const ToolChain::path_list &LibPaths = HTC.getFilePaths();
354
63
  for (const auto &LibPath : LibPaths)
355
136
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
356
357
  //----------------------------------------------------------------------------
358
  //
359
  //----------------------------------------------------------------------------
360
63
  Args.AddAllArgs(CmdArgs,
361
63
                  {options::OPT_T_Group, options::OPT_e, options::OPT_s,
362
63
                   options::OPT_t, options::OPT_u_Group});
363
364
63
  AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
365
366
  //----------------------------------------------------------------------------
367
  // Libraries
368
  //----------------------------------------------------------------------------
369
63
  if (IncStdLib && 
IncDefLibs62
) {
370
61
    if (D.CCCIsCXX()) {
371
7
      if (HTC.ShouldLinkCXXStdlib(Args))
372
7
        HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
373
7
      CmdArgs.push_back("-lm");
374
7
    }
375
376
61
    CmdArgs.push_back("--start-group");
377
378
61
    if (!IsShared) {
379
58
      for (StringRef Lib : OsLibs)
380
61
        CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
381
58
      CmdArgs.push_back("-lc");
382
58
    }
383
61
    CmdArgs.push_back("-lgcc");
384
385
61
    CmdArgs.push_back("--end-group");
386
61
  }
387
388
  //----------------------------------------------------------------------------
389
  // End files
390
  //----------------------------------------------------------------------------
391
63
  if (IncStdLib && 
IncStartFiles62
) {
392
61
    std::string Fini = UseShared
393
2
          ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")
394
59
          : Find(RootDir, StartSubDir, "/fini.o");
395
61
    CmdArgs.push_back(Args.MakeArgString(Fini));
396
61
  }
397
63
}
398
399
void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
400
                                   const InputInfo &Output,
401
                                   const InputInfoList &Inputs,
402
                                   const ArgList &Args,
403
70
                                   const char *LinkingOutput) const {
404
70
  auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
405
406
70
  ArgStringList CmdArgs;
407
70
  constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
408
70
                           LinkingOutput);
409
410
70
  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
411
70
  C.addCommand(std::make_unique<Command>(JA, *this,
412
70
                                         ResponseFileSupport::AtFileCurCP(),
413
70
                                         Exec, CmdArgs, Inputs, Output));
414
70
}
415
// Hexagon tools end.
416
417
/// Hexagon Toolchain
418
419
std::string HexagonToolChain::getHexagonTargetDir(
420
      const std::string &InstalledDir,
421
349
      const SmallVectorImpl<std::string> &PrefixDirs) const {
422
349
  std::string InstallRelDir;
423
349
  const Driver &D = getDriver();
424
425
  // Locate the rest of the toolchain ...
426
349
  for (auto &I : PrefixDirs)
427
0
    if (D.getVFS().exists(I))
428
0
      return I;
429
430
349
  if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
431
195
    return InstallRelDir;
432
433
154
  return InstalledDir;
434
154
}
435
436
Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
437
267
      const ArgList &Args) {
438
267
  StringRef Gn = "";
439
267
  if (Arg *A = Args.getLastArg(options::OPT_G)) {
440
12
    Gn = A->getValue();
441
255
  } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
442
18
                             options::OPT_fPIC)) {
443
18
    Gn = "0";
444
18
  }
445
446
267
  unsigned G;
447
267
  if (!Gn.getAsInteger(10, G))
448
30
    return G;
449
450
237
  return None;
451
237
}
452
453
void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
454
96
      ToolChain::path_list &LibPaths) const {
455
96
  const Driver &D = getDriver();
456
457
  //----------------------------------------------------------------------------
458
  // -L Args
459
  //----------------------------------------------------------------------------
460
96
  for (Arg *A : Args.filtered(options::OPT_L))
461
3
    for (const char *Value : A->getValues())
462
3
      LibPaths.push_back(Value);
463
464
  //----------------------------------------------------------------------------
465
  // Other standard paths
466
  //----------------------------------------------------------------------------
467
96
  std::vector<std::string> RootDirs;
468
96
  std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
469
96
            std::back_inserter(RootDirs));
470
471
96
  std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
472
96
                                              D.PrefixDirs);
473
96
  if (llvm::find(RootDirs, TargetDir) == RootDirs.end())
474
96
    RootDirs.push_back(TargetDir);
475
476
96
  bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);
477
  // Assume G0 with -shared.
478
96
  bool HasG0 = Args.hasArg(options::OPT_shared);
479
96
  if (auto G = getSmallDataThreshold(Args))
480
9
    HasG0 = G.getValue() == 0;
481
482
96
  const std::string CpuVer = GetTargetCPUVersion(Args).str();
483
96
  for (auto &Dir : RootDirs) {
484
96
    std::string LibDir = Dir + "/hexagon/lib";
485
96
    std::string LibDirCpu = LibDir + '/' + CpuVer;
486
96
    if (HasG0) {
487
6
      if (HasPIC)
488
2
        LibPaths.push_back(LibDirCpu + "/G0/pic");
489
6
      LibPaths.push_back(LibDirCpu + "/G0");
490
6
    }
491
96
    LibPaths.push_back(LibDirCpu);
492
96
    LibPaths.push_back(LibDir);
493
96
  }
494
96
}
495
496
HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
497
                                   const llvm::opt::ArgList &Args)
498
96
    : Linux(D, Triple, Args) {
499
96
  const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
500
96
                                                    D.PrefixDirs);
501
502
  // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
503
  // program paths
504
96
  const std::string BinDir(TargetDir + "/bin");
505
96
  if (D.getVFS().exists(BinDir))
506
0
    getProgramPaths().push_back(BinDir);
507
508
96
  ToolChain::path_list &LibPaths = getFilePaths();
509
510
  // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
511
  // 'elf' OS type, so the Linux paths are not appropriate. When we actually
512
  // support 'linux' we'll need to fix this up
513
96
  LibPaths.clear();
514
96
  getHexagonLibraryPaths(Args, LibPaths);
515
96
}
516
517
96
HexagonToolChain::~HexagonToolChain() {}
518
519
void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
520
8
                                           ArgStringList &CmdArgs) const {
521
8
  CXXStdlibType Type = GetCXXStdlibType(Args);
522
8
  switch (Type) {
523
2
  case ToolChain::CST_Libcxx:
524
2
    CmdArgs.push_back("-lc++");
525
2
    CmdArgs.push_back("-lc++abi");
526
2
    CmdArgs.push_back("-lunwind");
527
2
    break;
528
529
6
  case ToolChain::CST_Libstdcxx:
530
6
    CmdArgs.push_back("-lstdc++");
531
6
    break;
532
8
  }
533
8
}
534
535
5
Tool *HexagonToolChain::buildAssembler() const {
536
5
  return new tools::hexagon::Assembler(*this);
537
5
}
538
539
70
Tool *HexagonToolChain::buildLinker() const {
540
70
  return new tools::hexagon::Linker(*this);
541
70
}
542
543
unsigned HexagonToolChain::getOptimizationLevel(
544
0
    const llvm::opt::ArgList &DriverArgs) const {
545
  // Copied in large part from lib/Frontend/CompilerInvocation.cpp.
546
0
  Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);
547
0
  if (!A)
548
0
    return 0;
549
550
0
  if (A->getOption().matches(options::OPT_O0))
551
0
    return 0;
552
0
  if (A->getOption().matches(options::OPT_Ofast) ||
553
0
      A->getOption().matches(options::OPT_O4))
554
0
    return 3;
555
0
  assert(A->getNumValues() != 0);
556
0
  StringRef S(A->getValue());
557
0
  if (S == "s" || S == "z" || S.empty())
558
0
    return 2;
559
0
  if (S == "g")
560
0
    return 1;
561
562
0
  unsigned OptLevel;
563
0
  if (S.getAsInteger(10, OptLevel))
564
0
    return 0;
565
0
  return OptLevel;
566
0
}
567
568
void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
569
                                             ArgStringList &CC1Args,
570
97
                                             Action::OffloadKind) const {
571
572
97
  bool UseInitArrayDefault = getTriple().isMusl();
573
574
97
  if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
575
97
                          options::OPT_fno_use_init_array,
576
97
                          UseInitArrayDefault))
577
90
    CC1Args.push_back("-fno-use-init-array");
578
579
97
  if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
580
3
    CC1Args.push_back("-target-feature");
581
3
    CC1Args.push_back("+reserved-r19");
582
3
  }
583
97
  if (isAutoHVXEnabled(DriverArgs)) {
584
2
    CC1Args.push_back("-mllvm");
585
2
    CC1Args.push_back("-hexagon-autohvx");
586
2
  }
587
97
}
588
589
void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
590
96
                                                 ArgStringList &CC1Args) const {
591
96
  if (DriverArgs.hasArg(options::OPT_nostdinc) ||
592
95
      DriverArgs.hasArg(options::OPT_nostdlibinc))
593
3
    return;
594
595
93
  const Driver &D = getDriver();
596
93
  if (!D.SysRoot.empty()) {
597
7
    SmallString<128> P(D.SysRoot);
598
7
    if (getTriple().isMusl())
599
6
      llvm::sys::path::append(P, "usr/include");
600
1
    else
601
1
      llvm::sys::path::append(P, "include");
602
7
    addExternCSystemInclude(DriverArgs, CC1Args, P.str());
603
7
    return;
604
7
  }
605
606
86
  std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
607
86
                                              D.PrefixDirs);
608
86
  addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
609
86
}
610
611
void HexagonToolChain::addLibCxxIncludePaths(
612
    const llvm::opt::ArgList &DriverArgs,
613
2
    llvm::opt::ArgStringList &CC1Args) const {
614
2
  const Driver &D = getDriver();
615
2
  if (!D.SysRoot.empty() && 
getTriple().isMusl()1
)
616
1
    addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "", "", "",
617
1
                             "", DriverArgs, CC1Args);
618
1
  else if (getTriple().isMusl())
619
0
    addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", "", "", "",
620
0
                             DriverArgs, CC1Args);
621
1
  else {
622
1
    std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
623
1
    addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++/v1", "", "", "",
624
1
                             "", DriverArgs, CC1Args);
625
1
  }
626
2
}
627
void HexagonToolChain::addLibStdCxxIncludePaths(
628
    const llvm::opt::ArgList &DriverArgs,
629
7
    llvm::opt::ArgStringList &CC1Args) const {
630
7
  const Driver &D = getDriver();
631
7
  std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
632
7
  addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++", "", "", "", "",
633
7
                           DriverArgs, CC1Args);
634
7
}
635
636
ToolChain::CXXStdlibType
637
17
HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
638
17
  Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
639
17
  if (!A) {
640
15
    if (getTriple().isMusl())
641
2
      return ToolChain::CST_Libcxx;
642
13
    else
643
13
      return ToolChain::CST_Libstdcxx;
644
2
  }
645
2
  StringRef Value = A->getValue();
646
2
  if (Value != "libstdc++" && Value != "libc++")
647
0
    getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
648
649
2
  if (Value == "libstdc++")
650
0
    return ToolChain::CST_Libstdcxx;
651
2
  else if (Value == "libc++")
652
2
    return ToolChain::CST_Libcxx;
653
0
  else
654
0
    return ToolChain::CST_Libstdcxx;
655
2
}
656
657
193
bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {
658
193
  if (Arg *A = Args.getLastArg(options::OPT_fvectorize,
659
6
                               options::OPT_fno_vectorize))
660
6
    return A->getOption().matches(options::OPT_fvectorize);
661
187
  return false;
662
187
}
663
664
//
665
// Returns the default CPU for Hexagon. This is the default compilation target
666
// if no Hexagon processor is selected at the command-line.
667
//
668
123
const StringRef HexagonToolChain::GetDefaultCPU() {
669
123
  return "hexagonv60";
670
123
}
671
672
363
const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
673
363
  Arg *CpuArg = nullptr;
674
363
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
675
240
    CpuArg = A;
676
677
240
  StringRef CPU = CpuArg ? CpuArg->getValue() : 
GetDefaultCPU()123
;
678
363
  if (CPU.startswith("hexagon"))
679
363
    return CPU.substr(sizeof("hexagon") - 1);
680
0
  return CPU;
681
0
}