@@ -97,7 +97,8 @@ static bool findRISCVMultilibs(const Driver &D,
97
97
return false ;
98
98
}
99
99
100
- static std::string computeBaseSysRoot (const Driver &D, bool IncludeTriple) {
100
+ static std::string computeInstalledToolchainSysRoot (const Driver &D,
101
+ bool IncludeTriple) {
101
102
if (!D.SysRoot .empty ())
102
103
return D.SysRoot ;
103
104
@@ -110,20 +111,95 @@ static std::string computeBaseSysRoot(const Driver &D, bool IncludeTriple) {
110
111
return std::string (SysRootDir);
111
112
}
112
113
114
+ // GCC sysroot here means form sysroot from either --gcc-install-dir, or from
115
+ // --gcc-toolchain or if the toolchain is installed alongside clang in
116
+ // bin/../<TargetTriple> directory if it is not explicitly specified on the
117
+ // command line through `--sysroot` option. libc here will be newlib.
118
+ std::string BareMetal::computeGCCSysRoot () const {
119
+ if (!getDriver ().SysRoot .empty ())
120
+ return getDriver ().SysRoot ;
121
+
122
+ SmallString<128 > SysRootDir;
123
+ if (GCCInstallation.isValid ()) {
124
+ StringRef LibDir = GCCInstallation.getParentLibPath ();
125
+ StringRef TripleStr = GCCInstallation.getTriple ().str ();
126
+ llvm::sys::path::append (SysRootDir, LibDir, " .." , TripleStr);
127
+ } else {
128
+ // Use the triple as provided to the driver. Unlike the parsed triple
129
+ // this has not been normalized to always contain every field.
130
+ llvm::sys::path::append (SysRootDir, getDriver ().Dir , " .." ,
131
+ getDriver ().getTargetTriple ());
132
+ }
133
+
134
+ if (!llvm::sys::fs::exists (SysRootDir))
135
+ return std::string ();
136
+
137
+ return std::string (SysRootDir);
138
+ }
139
+
140
+ std::string BareMetal::computeSysRoot () const {
141
+ if (!SysRoot.empty ())
142
+ return SysRoot;
143
+
144
+ std::string SysRoot = getDriver ().SysRoot ;
145
+ if (!SysRoot.empty () && llvm::sys::fs::exists (SysRoot))
146
+ return SysRoot;
147
+
148
+ // Verify the GCC installation from -gcc-install-dir, --gcc-toolchain, or
149
+ // alongside clang. If valid, form the sysroot. Otherwise, check
150
+ // lib/clang-runtimes above the driver.
151
+ SysRoot = computeGCCSysRoot ();
152
+ if (!SysRoot.empty ())
153
+ return SysRoot;
154
+
155
+ SysRoot =
156
+ computeInstalledToolchainSysRoot (getDriver (), /* IncludeTriple*/ true );
157
+
158
+ return SysRoot;
159
+ }
160
+
161
+ static void addMultilibsFilePaths (const Driver &D, const MultilibSet &Multilibs,
162
+ const Multilib &Multilib,
163
+ StringRef InstallPath,
164
+ ToolChain::path_list &Paths) {
165
+ if (const auto &PathsCallback = Multilibs.filePathsCallback ())
166
+ for (const auto &Path : PathsCallback (Multilib))
167
+ addPathIfExists (D, InstallPath + Path, Paths);
168
+ }
169
+
113
170
BareMetal::BareMetal (const Driver &D, const llvm::Triple &Triple,
114
171
const ArgList &Args)
115
- : ToolChain(D, Triple, Args),
116
- SysRoot(computeBaseSysRoot(D, /* IncludeTriple=*/ true )) {
117
- getProgramPaths ().push_back (getDriver ().Dir );
118
-
119
- findMultilibs (D, Triple, Args);
120
- SmallString<128 > SysRoot (computeSysRoot ());
121
- if (!SysRoot.empty ()) {
122
- for (const Multilib &M : getOrderedMultilibs ()) {
123
- SmallString<128 > Dir (SysRoot);
124
- llvm::sys::path::append (Dir, M.osSuffix (), " lib" );
125
- getFilePaths ().push_back (std::string (Dir));
126
- getLibraryPaths ().push_back (std::string (Dir));
172
+ : Generic_ELF(D, Triple, Args) {
173
+ GCCInstallation.init (Triple, Args);
174
+ SysRoot = computeSysRoot ();
175
+ UseLD =
176
+ Args.getLastArgValue (options::OPT_fuse_ld_EQ).equals_insensitive (" ld" );
177
+ if (GCCInstallation.isValid ()) {
178
+ Multilibs = GCCInstallation.getMultilibs ();
179
+ SelectedMultilibs.assign ({GCCInstallation.getMultilib ()});
180
+ path_list &Paths = getFilePaths ();
181
+ // Add toolchain/multilib specific file paths.
182
+ addMultilibsFilePaths (D, Multilibs, SelectedMultilibs.back (),
183
+ GCCInstallation.getInstallPath (), Paths);
184
+ getFilePaths ().push_back (GCCInstallation.getInstallPath ().str ());
185
+ ToolChain::path_list &PPaths = getProgramPaths ();
186
+ // Multilib cross-compiler GCC installations put ld in a triple-prefixed
187
+ // directory off of the parent of the GCC installation.
188
+ PPaths.push_back (Twine (GCCInstallation.getParentLibPath () + " /../" +
189
+ GCCInstallation.getTriple ().str () + " /bin" )
190
+ .str ());
191
+ PPaths.push_back ((GCCInstallation.getParentLibPath () + " /../bin" ).str ());
192
+ getFilePaths ().push_back (computeSysRoot () + " /lib" );
193
+ } else {
194
+ getProgramPaths ().push_back (getDriver ().Dir );
195
+ findMultilibs (D, Triple, Args);
196
+ if (!SysRoot.empty ()) {
197
+ for (const Multilib &M : getOrderedMultilibs ()) {
198
+ SmallString<128 > Dir (SysRoot);
199
+ llvm::sys::path::append (Dir, M.osSuffix (), " lib" );
200
+ getFilePaths ().push_back (std::string (Dir));
201
+ getLibraryPaths ().push_back (std::string (Dir));
202
+ }
127
203
}
128
204
}
129
205
}
@@ -215,7 +291,7 @@ getMultilibConfigPath(const Driver &D, const llvm::Triple &Triple,
215
291
return {};
216
292
}
217
293
} else {
218
- MultilibPath = computeBaseSysRoot (D, /* IncludeTriple=*/ false );
294
+ MultilibPath = computeInstalledToolchainSysRoot (D, /* IncludeTriple=*/ false );
219
295
llvm::sys::path::append (MultilibPath, MultilibFilename);
220
296
}
221
297
return MultilibPath;
@@ -233,7 +309,7 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
233
309
if (D.getVFS ().exists (*MultilibPath)) {
234
310
// If multilib.yaml is found, update sysroot so it doesn't use a target
235
311
// specific suffix
236
- SysRoot = computeBaseSysRoot (D, /* IncludeTriple=*/ false );
312
+ SysRoot = computeInstalledToolchainSysRoot (D, /* IncludeTriple=*/ false );
237
313
findMultilibsFromYAML (*this , D, *MultilibPath, Args, Result);
238
314
SelectedMultilibs = Result.SelectedMultilibs ;
239
315
Multilibs = Result.Multilibs ;
@@ -258,8 +334,6 @@ Tool *BareMetal::buildStaticLibTool() const {
258
334
return new tools::baremetal::StaticLibTool (*this );
259
335
}
260
336
261
- std::string BareMetal::computeSysRoot () const { return SysRoot; }
262
-
263
337
BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs () const {
264
338
// Get multilibs in reverse order because they're ordered most-specific last.
265
339
if (!SelectedMultilibs.empty ())
@@ -270,6 +344,32 @@ BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
270
344
return llvm::reverse (Default);
271
345
}
272
346
347
+ ToolChain::CXXStdlibType BareMetal::GetDefaultCXXStdlibType () const {
348
+ if (getTriple ().isRISCV () && GCCInstallation.isValid ())
349
+ return ToolChain::CST_Libstdcxx;
350
+ return ToolChain::CST_Libcxx;
351
+ }
352
+
353
+ ToolChain::RuntimeLibType BareMetal::GetDefaultRuntimeLibType () const {
354
+ if (getTriple ().isRISCV () && GCCInstallation.isValid ())
355
+ return ToolChain::RLT_Libgcc;
356
+ return ToolChain::RLT_CompilerRT;
357
+ }
358
+
359
+ ToolChain::UnwindLibType
360
+ BareMetal::GetUnwindLibType (const llvm::opt::ArgList &Args) const {
361
+ if (getTriple ().isRISCV ())
362
+ return ToolChain::UNW_None;
363
+
364
+ return ToolChain::GetUnwindLibType (Args);
365
+ }
366
+
367
+ const char *BareMetal::getDefaultLinker () const {
368
+ if (isUsingLD ())
369
+ return " ld" ;
370
+ return " ld.lld" ;
371
+ }
372
+
273
373
void BareMetal::AddClangSystemIncludeArgs (const ArgList &DriverArgs,
274
374
ArgStringList &CC1Args) const {
275
375
if (DriverArgs.hasArg (options::OPT_nostdinc))
@@ -304,6 +404,19 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
304
404
CC1Args.push_back (" -nostdsysteminc" );
305
405
}
306
406
407
+ void BareMetal::addLibStdCxxIncludePaths (
408
+ const llvm::opt::ArgList &DriverArgs,
409
+ llvm::opt::ArgStringList &CC1Args) const {
410
+ if (!GCCInstallation.isValid ())
411
+ return ;
412
+ const GCCVersion &Version = GCCInstallation.getVersion ();
413
+ StringRef TripleStr = GCCInstallation.getTriple ().str ();
414
+ const Multilib &Multilib = GCCInstallation.getMultilib ();
415
+ addLibStdCXXIncludePaths (computeSysRoot () + " /include/c++/" + Version.Text ,
416
+ TripleStr, Multilib.includeSuffix (), DriverArgs,
417
+ CC1Args);
418
+ }
419
+
307
420
void BareMetal::AddClangCXXStdlibIncludeArgs (const ArgList &DriverArgs,
308
421
ArgStringList &CC1Args) const {
309
422
if (DriverArgs.hasArg (options::OPT_nostdinc, options::OPT_nostdlibinc,
@@ -334,15 +447,15 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
334
447
};
335
448
336
449
switch (GetCXXStdlibType (DriverArgs)) {
337
- case ToolChain::CST_Libcxx: {
338
- SmallString<128 > P (D.Dir );
339
- llvm::sys::path::append (P, " .." , " include" );
340
- AddCXXIncludePath (P);
341
- break ;
342
- }
343
- case ToolChain::CST_Libstdcxx:
344
- // We only support libc++ toolchain installation.
345
- break ;
450
+ case ToolChain::CST_Libcxx: {
451
+ SmallString<128 > P (D.Dir );
452
+ llvm::sys::path::append (P, " .." , " include" );
453
+ AddCXXIncludePath (P);
454
+ break ;
455
+ }
456
+ case ToolChain::CST_Libstdcxx:
457
+ addLibStdCxxIncludePaths (DriverArgs, CC1Args);
458
+ break ;
346
459
}
347
460
348
461
std::string SysRoot (computeSysRoot ());
@@ -450,12 +563,21 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
450
563
const llvm::Triple::ArchType Arch = TC.getArch ();
451
564
const llvm::Triple &Triple = getToolChain ().getEffectiveTriple ();
452
565
453
- AddLinkerInputs (TC, Inputs, Args, CmdArgs, JA);
566
+ if (!D.SysRoot .empty ())
567
+ CmdArgs.push_back (Args.MakeArgString (" --sysroot=" + D.SysRoot ));
454
568
455
569
CmdArgs.push_back (" -Bstatic" );
456
570
457
- if (TC.getTriple ().isRISCV () && Args.hasArg (options::OPT_mno_relax))
458
- CmdArgs.push_back (" --no-relax" );
571
+ if (Triple.isRISCV ()) {
572
+ if (Args.hasArg (options::OPT_mno_relax))
573
+ CmdArgs.push_back (" --no-relax" );
574
+ if (TC.isUsingLD ()) {
575
+ CmdArgs.push_back (" -m" );
576
+ CmdArgs.push_back (Arch == llvm::Triple::riscv64 ? " elf64lriscv"
577
+ : " elf32lriscv" );
578
+ }
579
+ CmdArgs.push_back (" -X" );
580
+ }
459
581
460
582
if (Triple.isARM () || Triple.isThumb ()) {
461
583
bool IsBigEndian = arm::isARMBigEndian (Triple, Args);
@@ -466,19 +588,54 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
466
588
CmdArgs.push_back (Arch == llvm::Triple::aarch64_be ? " -EB" : " -EL" );
467
589
}
468
590
469
- if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nostartfiles,
470
- options::OPT_r)) {
471
- CmdArgs.push_back (Args.MakeArgString (TC.GetFilePath (" crt0.o" )));
591
+ bool WantCRTs =
592
+ !Args.hasArg (options::OPT_nostdlib, options::OPT_nostartfiles);
593
+
594
+ const char *crtbegin, *crtend;
595
+ if (WantCRTs) {
596
+ if (!Args.hasArg (options::OPT_r))
597
+ CmdArgs.push_back (Args.MakeArgString (TC.GetFilePath (" crt0.o" )));
598
+ if (TC.isUsingLD ()) {
599
+ auto RuntimeLib = TC.GetRuntimeLibType (Args);
600
+ if (RuntimeLib == ToolChain::RLT_Libgcc) {
601
+ crtbegin = " crtbegin.o" ;
602
+ crtend = " crtend.o" ;
603
+ } else {
604
+ assert (RuntimeLib == ToolChain::RLT_CompilerRT);
605
+ crtbegin =
606
+ TC.getCompilerRTArgString (Args, " crtbegin" , ToolChain::FT_Object);
607
+ crtend =
608
+ TC.getCompilerRTArgString (Args, " crtend" , ToolChain::FT_Object);
609
+ }
610
+ CmdArgs.push_back (Args.MakeArgString (TC.GetFilePath (crtbegin)));
611
+ }
472
612
}
473
613
474
- Args.addAllArgs (CmdArgs, {options::OPT_L, options::OPT_T_Group,
475
- options::OPT_s, options::OPT_t, options::OPT_r});
614
+ Args.addAllArgs (CmdArgs,
615
+ {options::OPT_L, options::OPT_u, options::OPT_T_Group,
616
+ options::OPT_s, options::OPT_t, options::OPT_r});
476
617
477
618
TC.AddFilePathLibArgs (Args, CmdArgs);
478
619
479
620
for (const auto &LibPath : TC.getLibraryPaths ())
480
621
CmdArgs.push_back (Args.MakeArgString (llvm::Twine (" -L" , LibPath)));
481
622
623
+ if (D.isUsingLTO ()) {
624
+ assert (!Inputs.empty () && " Must have at least one input." );
625
+ // Find the first filename InputInfo object.
626
+ auto Input = llvm::find_if (
627
+ Inputs, [](const InputInfo &II) -> bool { return II.isFilename (); });
628
+ if (Input == Inputs.end ())
629
+ // For a very rare case, all of the inputs to the linker are
630
+ // InputArg. If that happens, just use the first InputInfo.
631
+ Input = Inputs.begin ();
632
+
633
+ addLTOOptions (TC, Args, CmdArgs, Output, *Input,
634
+ D.getLTOMode () == LTOK_Thin);
635
+ }
636
+
637
+ AddLinkerInputs (TC, Inputs, Args, CmdArgs, JA);
638
+
482
639
if (TC.ShouldLinkCXXStdlib (Args)) {
483
640
bool OnlyLibstdcxxStatic = Args.hasArg (options::OPT_static_libstdcxx) &&
484
641
!Args.hasArg (options::OPT_static);
@@ -491,26 +648,16 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
491
648
}
492
649
493
650
if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
651
+ CmdArgs.push_back (" --start-group" );
494
652
AddRunTimeLibs (TC, D, CmdArgs, Args);
495
-
496
653
CmdArgs.push_back (" -lc" );
654
+ if (TC.isUsingLD ())
655
+ CmdArgs.push_back (" -lgloss" );
656
+ CmdArgs.push_back (" --end-group" );
497
657
}
498
658
499
- if (D.isUsingLTO ()) {
500
- assert (!Inputs.empty () && " Must have at least one input." );
501
- // Find the first filename InputInfo object.
502
- auto Input = llvm::find_if (
503
- Inputs, [](const InputInfo &II) -> bool { return II.isFilename (); });
504
- if (Input == Inputs.end ())
505
- // For a very rare case, all of the inputs to the linker are
506
- // InputArg. If that happens, just use the first InputInfo.
507
- Input = Inputs.begin ();
508
-
509
- addLTOOptions (TC, Args, CmdArgs, Output, *Input,
510
- D.getLTOMode () == LTOK_Thin);
511
- }
512
- if (TC.getTriple ().isRISCV ())
513
- CmdArgs.push_back (" -X" );
659
+ if (TC.isUsingLD () && WantCRTs)
660
+ CmdArgs.push_back (Args.MakeArgString (TC.GetFilePath (crtend)));
514
661
515
662
// The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
516
663
// and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
0 commit comments