Coverage Report

Created: 2020-02-15 09:57

/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
86
static void handleHVXWarnings(const Driver &D, const ArgList &Args) {
38
86
  // Handle the unsupported values passed to mhvx-length.
39
86
  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
86
}
46
47
// Handle hvx target features explicitly.
48
static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
49
                                    std::vector<StringRef> &Features,
50
86
                                    StringRef Cpu, bool &HasHVX) {
51
86
  // Handle HVX warnings.
52
86
  handleHVXWarnings(D, Args);
53
86
54
86
  // Add the +hvx* features based on commandline flags.
55
86
  StringRef HVXFeature, HVXLength;
56
86
57
86
  // Handle -mhvx, -mhvx=, -mno-hvx.
58
86
  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
86
74
86
  // Handle -mhvx-length=.
75
86
  
if (Arg *84
A84
= Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
76
10
    // 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
74
  // Default hvx-length based on Cpu.
83
74
  else if (HasHVX)
84
10
    HVXLength = getDefaultHvxLength(Cpu);
85
84
86
84
  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
84
}
92
93
// Hexagon target features.
94
void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
95
86
                                       std::vector<StringRef> &Features) {
96
86
  handleTargetFeaturesGroup(Args, Features,
97
86
                            options::OPT_m_hexagon_Features_Group);
98
86
99
86
  bool UseLongCalls = false;
100
86
  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
86
106
86
  Features.push_back(UseLongCalls ? 
"+long-calls"1
:
"-long-calls"85
);
107
86
108
86
  bool HasHVX = false;
109
86
  StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));
110
86
  // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors
111
86
  // have no dependency on micro-architecture.
112
86
  const bool TinyCore = Cpu.contains('t');
113
86
114
86
  if (TinyCore)
115
1
    Cpu = Cpu.take_front(Cpu.size() - 1);
116
86
117
86
  handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);
118
86
119
86
  if (HexagonToolChain::isAutoHVXEnabled(Args) && 
!HasHVX2
)
120
2
    D.Diag(diag::warn_drv_vectorize_needs_hvx);
121
86
}
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
5
135
5
  auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
136
5
  const Driver &D = HTC.getDriver();
137
5
  ArgStringList CmdArgs;
138
5
139
5
  CmdArgs.push_back("--arch=hexagon");
140
5
141
5
  RenderExtraToolArgs(JA, CmdArgs);
142
5
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
5
149
5
  if (Output.isFilename()) {
150
5
    CmdArgs.push_back("-o");
151
5
    CmdArgs.push_back(Output.getFilename());
152
5
  } else {
153
0
    assert(Output.isNothing() && "Unexpected output");
154
0
    CmdArgs.push_back("-fsyntax-only");
155
0
  }
156
5
157
5
  if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
158
3
    CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(G.getValue())));
159
3
  }
160
5
161
5
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
162
5
163
5
  // Only pass -x if gcc will understand it; otherwise hope gcc
164
5
  // understands the suffix correctly. The main use case this would go
165
5
  // wrong in is for linker inputs if they happened to have an odd
166
5
  // suffix; really the only way to get this to happen is a command
167
5
  // like '-x foobar a.c' which will treat a.c like a linker input.
168
5
  //
169
5
  // FIXME: For the linker case specifically, can we safely convert
170
5
  // inputs into '-Wl,' options?
171
5
  for (const auto &II : Inputs) {
172
5
    // 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
5
183
5
    if (II.isFilename())
184
5
      CmdArgs.push_back(II.getFilename());
185
0
    else
186
0
      // Don't render as input, we need gcc to do the translations.
187
0
      // FIXME: What is this?
188
0
      II.getInputArg().render(Args, CmdArgs);
189
5
  }
190
5
191
5
  auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName));
192
5
  C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
193
5
}
194
195
void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
196
0
                                          ArgStringList &CmdArgs) const {
197
0
}
198
199
static void
200
constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
201
                         const toolchains::HexagonToolChain &HTC,
202
                         const InputInfo &Output, const InputInfoList &Inputs,
203
                         const ArgList &Args, ArgStringList &CmdArgs,
204
60
                         const char *LinkingOutput) {
205
60
206
60
  const Driver &D = HTC.getDriver();
207
60
208
60
  //----------------------------------------------------------------------------
209
60
  //
210
60
  //----------------------------------------------------------------------------
211
60
  bool IsStatic = Args.hasArg(options::OPT_static);
212
60
  bool IsShared = Args.hasArg(options::OPT_shared);
213
60
  bool IsPIE = Args.hasArg(options::OPT_pie);
214
60
  bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
215
60
  bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
216
60
  bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
217
60
  bool UseG0 = false;
218
60
  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
219
60
  bool UseLLD = (llvm::sys::path::filename(Exec).equals_lower("ld.lld") ||
220
60
                 
llvm::sys::path::stem(Exec).equals_lower("ld.lld")59
);
221
60
  bool UseShared = IsShared && 
!IsStatic3
;
222
60
  StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
223
60
224
60
  //----------------------------------------------------------------------------
225
60
  // Silence warnings for various options
226
60
  //----------------------------------------------------------------------------
227
60
  Args.ClaimAllArgs(options::OPT_g_Group);
228
60
  Args.ClaimAllArgs(options::OPT_emit_llvm);
229
60
  Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
230
60
                                     // handled somewhere else.
231
60
  Args.ClaimAllArgs(options::OPT_static_libgcc);
232
60
233
60
  //----------------------------------------------------------------------------
234
60
  //
235
60
  //----------------------------------------------------------------------------
236
60
  if (Args.hasArg(options::OPT_s))
237
1
    CmdArgs.push_back("-s");
238
60
239
60
  if (Args.hasArg(options::OPT_r))
240
0
    CmdArgs.push_back("-r");
241
60
242
60
  for (const auto &Opt : HTC.ExtraOpts)
243
0
    CmdArgs.push_back(Opt.c_str());
244
60
245
60
  if (!UseLLD) {
246
59
    CmdArgs.push_back("-march=hexagon");
247
59
    CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));
248
59
  }
249
60
250
60
  if (IsShared) {
251
3
    CmdArgs.push_back("-shared");
252
3
    // The following should be the default, but doing as hexagon-gcc does.
253
3
    CmdArgs.push_back("-call_shared");
254
3
  }
255
60
256
60
  if (IsStatic)
257
2
    CmdArgs.push_back("-static");
258
60
259
60
  if (IsPIE && 
!IsShared2
)
260
1
    CmdArgs.push_back("-pie");
261
60
262
60
  if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
263
8
    CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue())));
264
8
    UseG0 = G.getValue() == 0;
265
8
  }
266
60
267
60
  //----------------------------------------------------------------------------
268
60
  //
269
60
  //----------------------------------------------------------------------------
270
60
  CmdArgs.push_back("-o");
271
60
  CmdArgs.push_back(Output.getFilename());
272
60
273
60
  //----------------------------------------------------------------------------
274
60
  // moslib
275
60
  //----------------------------------------------------------------------------
276
60
  std::vector<std::string> OsLibs;
277
60
  bool HasStandalone = false;
278
60
279
60
  for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
280
5
    A->claim();
281
5
    OsLibs.emplace_back(A->getValue());
282
5
    HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
283
5
  }
284
60
  if (OsLibs.empty()) {
285
58
    OsLibs.push_back("standalone");
286
58
    HasStandalone = true;
287
58
  }
288
60
289
60
  //----------------------------------------------------------------------------
290
60
  // Start Files
291
60
  //----------------------------------------------------------------------------
292
60
  const std::string MCpuSuffix = "/" + CpuVer.str();
293
60
  const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
294
60
  const std::string RootDir =
295
60
      HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
296
60
  const std::string StartSubDir =
297
60
      "hexagon/lib" + (UseG0 ? 
MCpuG0Suffix5
:
MCpuSuffix55
);
298
60
299
60
  auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
300
225
                      const char *Name) -> std::string {
301
225
    std::string RelName = SubDir + Name;
302
225
    std::string P = HTC.GetFilePath(RelName.c_str());
303
225
    if (llvm::sys::fs::exists(P))
304
0
      return P;
305
225
    return RootDir + RelName;
306
225
  };
307
60
308
60
  if (IncStdLib && 
IncStartFiles59
) {
309
58
    if (!IsShared) {
310
55
      if (HasStandalone) {
311
54
        std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
312
54
        CmdArgs.push_back(Args.MakeArgString(Crt0SA));
313
54
      }
314
55
      std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
315
55
      CmdArgs.push_back(Args.MakeArgString(Crt0));
316
55
    }
317
58
    std::string Init = UseShared
318
58
          ? 
Find(RootDir, StartSubDir + "/pic", "/initS.o")2
319
58
          : 
Find(RootDir, StartSubDir, "/init.o")56
;
320
58
    CmdArgs.push_back(Args.MakeArgString(Init));
321
58
  }
322
60
323
60
  //----------------------------------------------------------------------------
324
60
  // Library Search Paths
325
60
  //----------------------------------------------------------------------------
326
60
  const ToolChain::path_list &LibPaths = HTC.getFilePaths();
327
60
  for (const auto &LibPath : LibPaths)
328
130
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
329
60
330
60
  //----------------------------------------------------------------------------
331
60
  //
332
60
  //----------------------------------------------------------------------------
333
60
  Args.AddAllArgs(CmdArgs,
334
60
                  {options::OPT_T_Group, options::OPT_e, options::OPT_s,
335
60
                   options::OPT_t, options::OPT_u_Group});
336
60
337
60
  AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
338
60
339
60
  //----------------------------------------------------------------------------
340
60
  // Libraries
341
60
  //----------------------------------------------------------------------------
342
60
  if (IncStdLib && 
IncDefLibs59
) {
343
58
    if (D.CCCIsCXX()) {
344
6
      if (HTC.ShouldLinkCXXStdlib(Args))
345
6
        HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
346
6
      CmdArgs.push_back("-lm");
347
6
    }
348
58
349
58
    CmdArgs.push_back("--start-group");
350
58
351
58
    if (!IsShared) {
352
55
      for (StringRef Lib : OsLibs)
353
58
        CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
354
55
      CmdArgs.push_back("-lc");
355
55
    }
356
58
    CmdArgs.push_back("-lgcc");
357
58
358
58
    CmdArgs.push_back("--end-group");
359
58
  }
360
60
361
60
  //----------------------------------------------------------------------------
362
60
  // End files
363
60
  //----------------------------------------------------------------------------
364
60
  if (IncStdLib && 
IncStartFiles59
) {
365
58
    std::string Fini = UseShared
366
58
          ? 
Find(RootDir, StartSubDir + "/pic", "/finiS.o")2
367
58
          : 
Find(RootDir, StartSubDir, "/fini.o")56
;
368
58
    CmdArgs.push_back(Args.MakeArgString(Fini));
369
58
  }
370
60
}
371
372
void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
373
                                   const InputInfo &Output,
374
                                   const InputInfoList &Inputs,
375
                                   const ArgList &Args,
376
60
                                   const char *LinkingOutput) const {
377
60
  auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
378
60
379
60
  ArgStringList CmdArgs;
380
60
  constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
381
60
                           LinkingOutput);
382
60
383
60
  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
384
60
  C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
385
60
}
386
// Hexagon tools end.
387
388
/// Hexagon Toolchain
389
390
std::string HexagonToolChain::getHexagonTargetDir(
391
      const std::string &InstalledDir,
392
322
      const SmallVectorImpl<std::string> &PrefixDirs) const {
393
322
  std::string InstallRelDir;
394
322
  const Driver &D = getDriver();
395
322
396
322
  // Locate the rest of the toolchain ...
397
322
  for (auto &I : PrefixDirs)
398
0
    if (D.getVFS().exists(I))
399
0
      return I;
400
322
401
322
  if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
402
168
    return InstallRelDir;
403
154
404
154
  return InstalledDir;
405
154
}
406
407
Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
408
237
      const ArgList &Args) {
409
237
  StringRef Gn = "";
410
237
  if (Arg *A = Args.getLastArg(options::OPT_G)) {
411
12
    Gn = A->getValue();
412
225
  } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
413
225
                             options::OPT_fPIC)) {
414
15
    Gn = "0";
415
15
  }
416
237
417
237
  unsigned G;
418
237
  if (!Gn.getAsInteger(10, G))
419
27
    return G;
420
210
421
210
  return None;
422
210
}
423
424
void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
425
86
      ToolChain::path_list &LibPaths) const {
426
86
  const Driver &D = getDriver();
427
86
428
86
  //----------------------------------------------------------------------------
429
86
  // -L Args
430
86
  //----------------------------------------------------------------------------
431
86
  for (Arg *A : Args.filtered(options::OPT_L))
432
3
    for (const char *Value : A->getValues())
433
3
      LibPaths.push_back(Value);
434
86
435
86
  //----------------------------------------------------------------------------
436
86
  // Other standard paths
437
86
  //----------------------------------------------------------------------------
438
86
  std::vector<std::string> RootDirs;
439
86
  std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
440
86
            std::back_inserter(RootDirs));
441
86
442
86
  std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
443
86
                                              D.PrefixDirs);
444
86
  if (llvm::find(RootDirs, TargetDir) == RootDirs.end())
445
86
    RootDirs.push_back(TargetDir);
446
86
447
86
  bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);
448
86
  // Assume G0 with -shared.
449
86
  bool HasG0 = Args.hasArg(options::OPT_shared);
450
86
  if (auto G = getSmallDataThreshold(Args))
451
8
    HasG0 = G.getValue() == 0;
452
86
453
86
  const std::string CpuVer = GetTargetCPUVersion(Args).str();
454
86
  for (auto &Dir : RootDirs) {
455
86
    std::string LibDir = Dir + "/hexagon/lib";
456
86
    std::string LibDirCpu = LibDir + '/' + CpuVer;
457
86
    if (HasG0) {
458
5
      if (HasPIC)
459
2
        LibPaths.push_back(LibDirCpu + "/G0/pic");
460
5
      LibPaths.push_back(LibDirCpu + "/G0");
461
5
    }
462
86
    LibPaths.push_back(LibDirCpu);
463
86
    LibPaths.push_back(LibDir);
464
86
  }
465
86
}
466
467
HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
468
                                   const llvm::opt::ArgList &Args)
469
86
    : Linux(D, Triple, Args) {
470
86
  const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
471
86
                                                    D.PrefixDirs);
472
86
473
86
  // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
474
86
  // program paths
475
86
  const std::string BinDir(TargetDir + "/bin");
476
86
  if (D.getVFS().exists(BinDir))
477
0
    getProgramPaths().push_back(BinDir);
478
86
479
86
  ToolChain::path_list &LibPaths = getFilePaths();
480
86
481
86
  // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
482
86
  // 'elf' OS type, so the Linux paths are not appropriate. When we actually
483
86
  // support 'linux' we'll need to fix this up
484
86
  LibPaths.clear();
485
86
  getHexagonLibraryPaths(Args, LibPaths);
486
86
}
487
488
86
HexagonToolChain::~HexagonToolChain() {}
489
490
5
Tool *HexagonToolChain::buildAssembler() const {
491
5
  return new tools::hexagon::Assembler(*this);
492
5
}
493
494
60
Tool *HexagonToolChain::buildLinker() const {
495
60
  return new tools::hexagon::Linker(*this);
496
60
}
497
498
unsigned HexagonToolChain::getOptimizationLevel(
499
0
    const llvm::opt::ArgList &DriverArgs) const {
500
0
  // Copied in large part from lib/Frontend/CompilerInvocation.cpp.
501
0
  Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);
502
0
  if (!A)
503
0
    return 0;
504
0
505
0
  if (A->getOption().matches(options::OPT_O0))
506
0
    return 0;
507
0
  if (A->getOption().matches(options::OPT_Ofast) ||
508
0
      A->getOption().matches(options::OPT_O4))
509
0
    return 3;
510
0
  assert(A->getNumValues() != 0);
511
0
  StringRef S(A->getValue());
512
0
  if (S == "s" || S == "z" || S.empty())
513
0
    return 2;
514
0
  if (S == "g")
515
0
    return 1;
516
0
517
0
  unsigned OptLevel;
518
0
  if (S.getAsInteger(10, OptLevel))
519
0
    return 0;
520
0
  return OptLevel;
521
0
}
522
523
void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
524
                                             ArgStringList &CC1Args,
525
87
                                             Action::OffloadKind) const {
526
87
  if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
527
3
    CC1Args.push_back("-target-feature");
528
3
    CC1Args.push_back("+reserved-r19");
529
3
  }
530
87
  if (isAutoHVXEnabled(DriverArgs)) {
531
2
    CC1Args.push_back("-mllvm");
532
2
    CC1Args.push_back("-hexagon-autohvx");
533
2
  }
534
87
}
535
536
void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
537
86
                                                 ArgStringList &CC1Args) const {
538
86
  if (DriverArgs.hasArg(options::OPT_nostdinc) ||
539
86
      
DriverArgs.hasArg(options::OPT_nostdlibinc)85
)
540
3
    return;
541
83
542
83
  const Driver &D = getDriver();
543
83
  std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
544
83
                                              D.PrefixDirs);
545
83
  addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
546
83
}
547
548
549
void HexagonToolChain::addLibStdCxxIncludePaths(
550
    const llvm::opt::ArgList &DriverArgs,
551
7
    llvm::opt::ArgStringList &CC1Args) const {
552
7
  const Driver &D = getDriver();
553
7
  std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
554
7
  addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++", "", "", "", "",
555
7
                           DriverArgs, CC1Args);
556
7
}
557
558
ToolChain::CXXStdlibType
559
13
HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
560
13
  Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
561
13
  if (!A)
562
13
    return ToolChain::CST_Libstdcxx;
563
0
564
0
  StringRef Value = A->getValue();
565
0
  if (Value != "libstdc++")
566
0
    getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
567
0
568
0
  return ToolChain::CST_Libstdcxx;
569
0
}
570
571
173
bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {
572
173
  if (Arg *A = Args.getLastArg(options::OPT_fvectorize,
573
6
                               options::OPT_fno_vectorize))
574
6
    return A->getOption().matches(options::OPT_fvectorize);
575
167
  return false;
576
167
}
577
578
//
579
// Returns the default CPU for Hexagon. This is the default compilation target
580
// if no Hexagon processor is selected at the command-line.
581
//
582
123
const StringRef HexagonToolChain::GetDefaultCPU() {
583
123
  return "hexagonv60";
584
123
}
585
586
323
const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
587
323
  Arg *CpuArg = nullptr;
588
323
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
589
200
    CpuArg = A;
590
323
591
323
  StringRef CPU = CpuArg ? 
CpuArg->getValue()200
:
GetDefaultCPU()123
;
592
323
  if (CPU.startswith("hexagon"))
593
323
    return CPU.substr(sizeof("hexagon") - 1);
594
0
  return CPU;
595
0
}