@@ -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
}
@@ -236,7 +312,7 @@ getMultilibConfigPath(const Driver &D, const llvm::Triple &Triple,
236
312
return {};
237
313
}
238
314
} else {
239
- MultilibPath = computeBaseSysRoot (D, /* IncludeTriple=*/ false );
315
+ MultilibPath = computeInstalledToolchainSysRoot (D, /* IncludeTriple=*/ false );
240
316
llvm::sys::path::append (MultilibPath, MultilibFilename);
241
317
}
242
318
return MultilibPath;
@@ -254,7 +330,7 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
254
330
if (D.getVFS ().exists (*MultilibPath)) {
255
331
// If multilib.yaml is found, update sysroot so it doesn't use a target
256
332
// specific suffix
257
- SysRoot = computeBaseSysRoot (D, /* IncludeTriple=*/ false );
333
+ SysRoot = computeInstalledToolchainSysRoot (D, /* IncludeTriple=*/ false );
258
334
findMultilibsFromYAML (*this , D, *MultilibPath, Args, Result);
259
335
SelectedMultilibs = Result.SelectedMultilibs ;
260
336
Multilibs = Result.Multilibs ;
@@ -279,8 +355,6 @@ Tool *BareMetal::buildStaticLibTool() const {
279
355
return new tools::baremetal::StaticLibTool (*this );
280
356
}
281
357
282
- std::string BareMetal::computeSysRoot () const { return SysRoot; }
283
-
284
358
BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs () const {
285
359
// Get multilibs in reverse order because they're ordered most-specific last.
286
360
if (!SelectedMultilibs.empty ())
@@ -291,6 +365,36 @@ BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
291
365
return llvm::reverse (Default);
292
366
}
293
367
368
+ ToolChain::CXXStdlibType BareMetal::GetDefaultCXXStdlibType () const {
369
+ if (getTriple ().isRISCV ()) {
370
+ return GCCInstallation.isValid () ? ToolChain::CST_Libstdcxx
371
+ : ToolChain::CST_Libcxx;
372
+ }
373
+ return ToolChain::CST_Libcxx;
374
+ }
375
+
376
+ ToolChain::RuntimeLibType BareMetal::GetDefaultRuntimeLibType () const {
377
+ if (getTriple ().isRISCV ()) {
378
+ return GCCInstallation.isValid () ? ToolChain::RLT_Libgcc
379
+ : ToolChain::RLT_CompilerRT;
380
+ }
381
+ return ToolChain::RLT_CompilerRT;
382
+ }
383
+
384
+ ToolChain::UnwindLibType
385
+ BareMetal::GetUnwindLibType (const llvm::opt::ArgList &Args) const {
386
+ if (getTriple ().isRISCV ())
387
+ return ToolChain::UNW_None;
388
+
389
+ return ToolChain::GetUnwindLibType (Args);
390
+ }
391
+
392
+ const char *BareMetal::getDefaultLinker () const {
393
+ if (isUsingLD ())
394
+ return " ld" ;
395
+ return " ld.lld" ;
396
+ }
397
+
294
398
void BareMetal::AddClangSystemIncludeArgs (const ArgList &DriverArgs,
295
399
ArgStringList &CC1Args) const {
296
400
if (DriverArgs.hasArg (options::OPT_nostdinc))
@@ -325,6 +429,19 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
325
429
CC1Args.push_back (" -nostdsysteminc" );
326
430
}
327
431
432
+ void BareMetal::addLibStdCxxIncludePaths (
433
+ const llvm::opt::ArgList &DriverArgs,
434
+ llvm::opt::ArgStringList &CC1Args) const {
435
+ if (GCCInstallation.isValid ()) {
436
+ const GCCVersion &Version = GCCInstallation.getVersion ();
437
+ StringRef TripleStr = GCCInstallation.getTriple ().str ();
438
+ const Multilib &Multilib = GCCInstallation.getMultilib ();
439
+ addLibStdCXXIncludePaths (computeSysRoot () + " /include/c++/" + Version.Text ,
440
+ TripleStr, Multilib.includeSuffix (), DriverArgs,
441
+ CC1Args);
442
+ }
443
+ }
444
+
328
445
void BareMetal::AddClangCXXStdlibIncludeArgs (const ArgList &DriverArgs,
329
446
ArgStringList &CC1Args) const {
330
447
if (DriverArgs.hasArg (options::OPT_nostdinc, options::OPT_nostdlibinc,
@@ -355,15 +472,15 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
355
472
};
356
473
357
474
switch (GetCXXStdlibType (DriverArgs)) {
358
- case ToolChain::CST_Libcxx: {
359
- SmallString<128 > P (D.Dir );
360
- llvm::sys::path::append (P, " .." , " include" );
361
- AddCXXIncludePath (P);
362
- break ;
363
- }
364
- case ToolChain::CST_Libstdcxx:
365
- // We only support libc++ toolchain installation.
366
- break ;
475
+ case ToolChain::CST_Libcxx: {
476
+ SmallString<128 > P (D.Dir );
477
+ llvm::sys::path::append (P, " .." , " include" );
478
+ AddCXXIncludePath (P);
479
+ break ;
480
+ }
481
+ case ToolChain::CST_Libstdcxx:
482
+ addLibStdCxxIncludePaths (DriverArgs, CC1Args);
483
+ break ;
367
484
}
368
485
369
486
std::string SysRoot (computeSysRoot ());
@@ -428,6 +545,10 @@ void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
428
545
CmdArgs.push_back (" -lsupc++" );
429
546
break ;
430
547
}
548
+
549
+ if (getTriple ().isRISCV () && GCCInstallation.isValid ())
550
+ return ;
551
+
431
552
CmdArgs.push_back (" -lunwind" );
432
553
}
433
554
@@ -503,12 +624,22 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
503
624
const llvm::Triple::ArchType Arch = TC.getArch ();
504
625
const llvm::Triple &Triple = getToolChain ().getEffectiveTriple ();
505
626
506
- AddLinkerInputs (TC, Inputs, Args, CmdArgs, JA);
627
+ if (!D.SysRoot .empty ())
628
+ CmdArgs.push_back (Args.MakeArgString (" --sysroot=" + D.SysRoot ));
507
629
630
+ Args.addAllArgs (CmdArgs, {options::OPT_u});
508
631
CmdArgs.push_back (" -Bstatic" );
509
632
510
- if (TC.getTriple ().isRISCV () && Args.hasArg (options::OPT_mno_relax))
511
- CmdArgs.push_back (" --no-relax" );
633
+ if (TC.getTriple ().isRISCV ()) {
634
+ if (Args.hasArg (options::OPT_mno_relax))
635
+ CmdArgs.push_back (" --no-relax" );
636
+ if (TC.isUsingLD ()) {
637
+ CmdArgs.push_back (" -m" );
638
+ CmdArgs.push_back (TC.getArch () == llvm::Triple::riscv64 ? " elf64lriscv"
639
+ : " elf32lriscv" );
640
+ }
641
+ CmdArgs.push_back (" -X" );
642
+ }
512
643
513
644
if (Triple.isARM () || Triple.isThumb ()) {
514
645
bool IsBigEndian = arm::isARMBigEndian (Triple, Args);
@@ -519,9 +650,24 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
519
650
CmdArgs.push_back (Arch == llvm::Triple::aarch64_be ? " -EB" : " -EL" );
520
651
}
521
652
522
- if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nostartfiles,
523
- options::OPT_r)) {
524
- CmdArgs.push_back (Args.MakeArgString (TC.GetFilePath (" crt0.o" )));
653
+ bool WantCRTs =
654
+ !Args.hasArg (options::OPT_nostdlib, options::OPT_nostartfiles);
655
+
656
+ const char *crtbegin, *crtend;
657
+ if (WantCRTs) {
658
+ if (!Args.hasArg (options::OPT_r))
659
+ CmdArgs.push_back (Args.MakeArgString (TC.GetFilePath (" crt0.o" )));
660
+ auto RuntimeLib = TC.GetRuntimeLibType (Args);
661
+ if (RuntimeLib == ToolChain::RLT_Libgcc) {
662
+ crtbegin = " crtbegin.o" ;
663
+ crtend = " crtend.o" ;
664
+ } else {
665
+ assert (RuntimeLib == ToolChain::RLT_CompilerRT);
666
+ crtbegin =
667
+ TC.getCompilerRTArgString (Args, " crtbegin" , ToolChain::FT_Object);
668
+ crtend = TC.getCompilerRTArgString (Args, " crtend" , ToolChain::FT_Object);
669
+ }
670
+ CmdArgs.push_back (Args.MakeArgString (TC.GetFilePath (crtbegin)));
525
671
}
526
672
527
673
Args.addAllArgs (CmdArgs, {options::OPT_L, options::OPT_T_Group,
@@ -536,12 +682,20 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
536
682
TC.AddCXXStdlibLibArgs (Args, CmdArgs);
537
683
538
684
if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
539
- CmdArgs.push_back (" -lc" );
540
685
CmdArgs.push_back (" -lm" );
541
-
686
+ if (TC.isUsingLD ())
687
+ CmdArgs.push_back (" --start-group" );
688
+ CmdArgs.push_back (" -lc" );
689
+ if (TC.isUsingLD ()) {
690
+ CmdArgs.push_back (" -lgloss" );
691
+ CmdArgs.push_back (" --end-group" );
692
+ }
542
693
TC.AddLinkRuntimeLib (Args, CmdArgs);
543
694
}
544
695
696
+ if (WantCRTs)
697
+ CmdArgs.push_back (Args.MakeArgString (TC.GetFilePath (crtend)));
698
+
545
699
if (D.isUsingLTO ()) {
546
700
assert (!Inputs.empty () && " Must have at least one input." );
547
701
// Find the first filename InputInfo object.
@@ -555,8 +709,8 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
555
709
addLTOOptions (TC, Args, CmdArgs, Output, *Input,
556
710
D.getLTOMode () == LTOK_Thin);
557
711
}
558
- if (TC. getTriple (). isRISCV ())
559
- CmdArgs. push_back ( " -X " );
712
+
713
+ AddLinkerInputs (TC, Inputs, Args, CmdArgs, JA );
560
714
561
715
// The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
562
716
// and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
0 commit comments