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