Coverage Report

Created: 2022-01-15 10:30

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