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