@@ -97,7 +97,8 @@ static bool findRISCVMultilibs(const Driver &D,
9797 return false ;
9898}
9999
100- static std::string computeBaseSysRoot (const Driver &D, bool IncludeTriple) {
100+ static std::string computeInstalledToolchainSysRoot (const Driver &D,
101+ bool IncludeTriple) {
101102 if (!D.SysRoot .empty ())
102103 return D.SysRoot ;
103104
@@ -110,20 +111,95 @@ static std::string computeBaseSysRoot(const Driver &D, bool IncludeTriple) {
110111 return std::string (SysRootDir);
111112}
112113
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+
113170BareMetal::BareMetal (const Driver &D, const llvm::Triple &Triple,
114171 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+ }
127203 }
128204 }
129205}
@@ -215,7 +291,7 @@ getMultilibConfigPath(const Driver &D, const llvm::Triple &Triple,
215291 return {};
216292 }
217293 } else {
218- MultilibPath = computeBaseSysRoot (D, /* IncludeTriple=*/ false );
294+ MultilibPath = computeInstalledToolchainSysRoot (D, /* IncludeTriple=*/ false );
219295 llvm::sys::path::append (MultilibPath, MultilibFilename);
220296 }
221297 return MultilibPath;
@@ -233,7 +309,7 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
233309 if (D.getVFS ().exists (*MultilibPath)) {
234310 // If multilib.yaml is found, update sysroot so it doesn't use a target
235311 // specific suffix
236- SysRoot = computeBaseSysRoot (D, /* IncludeTriple=*/ false );
312+ SysRoot = computeInstalledToolchainSysRoot (D, /* IncludeTriple=*/ false );
237313 findMultilibsFromYAML (*this , D, *MultilibPath, Args, Result);
238314 SelectedMultilibs = Result.SelectedMultilibs ;
239315 Multilibs = Result.Multilibs ;
@@ -258,8 +334,6 @@ Tool *BareMetal::buildStaticLibTool() const {
258334 return new tools::baremetal::StaticLibTool (*this );
259335}
260336
261- std::string BareMetal::computeSysRoot () const { return SysRoot; }
262-
263337BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs () const {
264338 // Get multilibs in reverse order because they're ordered most-specific last.
265339 if (!SelectedMultilibs.empty ())
@@ -270,6 +344,32 @@ BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
270344 return llvm::reverse (Default);
271345}
272346
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+
273373void BareMetal::AddClangSystemIncludeArgs (const ArgList &DriverArgs,
274374 ArgStringList &CC1Args) const {
275375 if (DriverArgs.hasArg (options::OPT_nostdinc))
@@ -304,6 +404,19 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
304404 CC1Args.push_back (" -nostdsysteminc" );
305405}
306406
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+
307420void BareMetal::AddClangCXXStdlibIncludeArgs (const ArgList &DriverArgs,
308421 ArgStringList &CC1Args) const {
309422 if (DriverArgs.hasArg (options::OPT_nostdinc, options::OPT_nostdlibinc,
@@ -334,15 +447,15 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
334447 };
335448
336449 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 ;
346459 }
347460
348461 std::string SysRoot (computeSysRoot ());
@@ -450,12 +563,21 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
450563 const llvm::Triple::ArchType Arch = TC.getArch ();
451564 const llvm::Triple &Triple = getToolChain ().getEffectiveTriple ();
452565
453- AddLinkerInputs (TC, Inputs, Args, CmdArgs, JA);
566+ if (!D.SysRoot .empty ())
567+ CmdArgs.push_back (Args.MakeArgString (" --sysroot=" + D.SysRoot ));
454568
455569 CmdArgs.push_back (" -Bstatic" );
456570
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+ }
459581
460582 if (Triple.isARM () || Triple.isThumb ()) {
461583 bool IsBigEndian = arm::isARMBigEndian (Triple, Args);
@@ -466,19 +588,54 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
466588 CmdArgs.push_back (Arch == llvm::Triple::aarch64_be ? " -EB" : " -EL" );
467589 }
468590
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+ }
472612 }
473613
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});
476617
477618 TC.AddFilePathLibArgs (Args, CmdArgs);
478619
479620 for (const auto &LibPath : TC.getLibraryPaths ())
480621 CmdArgs.push_back (Args.MakeArgString (llvm::Twine (" -L" , LibPath)));
481622
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+
482639 if (TC.ShouldLinkCXXStdlib (Args)) {
483640 bool OnlyLibstdcxxStatic = Args.hasArg (options::OPT_static_libstdcxx) &&
484641 !Args.hasArg (options::OPT_static);
@@ -491,26 +648,16 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
491648 }
492649
493650 if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
651+ CmdArgs.push_back (" --start-group" );
494652 AddRunTimeLibs (TC, D, CmdArgs, Args);
495-
496653 CmdArgs.push_back (" -lc" );
654+ if (TC.isUsingLD ())
655+ CmdArgs.push_back (" -lgloss" );
656+ CmdArgs.push_back (" --end-group" );
497657 }
498658
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)));
514661
515662 // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
516663 // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
0 commit comments