@@ -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}
@@ -236,7 +312,7 @@ getMultilibConfigPath(const Driver &D, const llvm::Triple &Triple,
236312 return {};
237313 }
238314 } else {
239- MultilibPath = computeBaseSysRoot (D, /* IncludeTriple=*/ false );
315+ MultilibPath = computeInstalledToolchainSysRoot (D, /* IncludeTriple=*/ false );
240316 llvm::sys::path::append (MultilibPath, MultilibFilename);
241317 }
242318 return MultilibPath;
@@ -254,7 +330,7 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
254330 if (D.getVFS ().exists (*MultilibPath)) {
255331 // If multilib.yaml is found, update sysroot so it doesn't use a target
256332 // specific suffix
257- SysRoot = computeBaseSysRoot (D, /* IncludeTriple=*/ false );
333+ SysRoot = computeInstalledToolchainSysRoot (D, /* IncludeTriple=*/ false );
258334 findMultilibsFromYAML (*this , D, *MultilibPath, Args, Result);
259335 SelectedMultilibs = Result.SelectedMultilibs ;
260336 Multilibs = Result.Multilibs ;
@@ -279,8 +355,6 @@ Tool *BareMetal::buildStaticLibTool() const {
279355 return new tools::baremetal::StaticLibTool (*this );
280356}
281357
282- std::string BareMetal::computeSysRoot () const { return SysRoot; }
283-
284358BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs () const {
285359 // Get multilibs in reverse order because they're ordered most-specific last.
286360 if (!SelectedMultilibs.empty ())
@@ -291,6 +365,36 @@ BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
291365 return llvm::reverse (Default);
292366}
293367
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+
294398void BareMetal::AddClangSystemIncludeArgs (const ArgList &DriverArgs,
295399 ArgStringList &CC1Args) const {
296400 if (DriverArgs.hasArg (options::OPT_nostdinc))
@@ -325,6 +429,19 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
325429 CC1Args.push_back (" -nostdsysteminc" );
326430}
327431
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+
328445void BareMetal::AddClangCXXStdlibIncludeArgs (const ArgList &DriverArgs,
329446 ArgStringList &CC1Args) const {
330447 if (DriverArgs.hasArg (options::OPT_nostdinc, options::OPT_nostdlibinc,
@@ -355,15 +472,15 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
355472 };
356473
357474 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 ;
367484 }
368485
369486 std::string SysRoot (computeSysRoot ());
@@ -428,6 +545,10 @@ void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
428545 CmdArgs.push_back (" -lsupc++" );
429546 break ;
430547 }
548+
549+ if (getTriple ().isRISCV () && GCCInstallation.isValid ())
550+ return ;
551+
431552 CmdArgs.push_back (" -lunwind" );
432553}
433554
@@ -503,12 +624,22 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
503624 const llvm::Triple::ArchType Arch = TC.getArch ();
504625 const llvm::Triple &Triple = getToolChain ().getEffectiveTriple ();
505626
506- AddLinkerInputs (TC, Inputs, Args, CmdArgs, JA);
627+ if (!D.SysRoot .empty ())
628+ CmdArgs.push_back (Args.MakeArgString (" --sysroot=" + D.SysRoot ));
507629
630+ Args.addAllArgs (CmdArgs, {options::OPT_u});
508631 CmdArgs.push_back (" -Bstatic" );
509632
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+ }
512643
513644 if (Triple.isARM () || Triple.isThumb ()) {
514645 bool IsBigEndian = arm::isARMBigEndian (Triple, Args);
@@ -519,9 +650,24 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
519650 CmdArgs.push_back (Arch == llvm::Triple::aarch64_be ? " -EB" : " -EL" );
520651 }
521652
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)));
525671 }
526672
527673 Args.addAllArgs (CmdArgs, {options::OPT_L, options::OPT_T_Group,
@@ -536,12 +682,20 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
536682 TC.AddCXXStdlibLibArgs (Args, CmdArgs);
537683
538684 if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
539- CmdArgs.push_back (" -lc" );
540685 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+ }
542693 TC.AddLinkRuntimeLib (Args, CmdArgs);
543694 }
544695
696+ if (WantCRTs)
697+ CmdArgs.push_back (Args.MakeArgString (TC.GetFilePath (crtend)));
698+
545699 if (D.isUsingLTO ()) {
546700 assert (!Inputs.empty () && " Must have at least one input." );
547701 // Find the first filename InputInfo object.
@@ -555,8 +709,8 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
555709 addLTOOptions (TC, Args, CmdArgs, Output, *Input,
556710 D.getLTOMode () == LTOK_Thin);
557711 }
558- if (TC. getTriple (). isRISCV ())
559- CmdArgs. push_back ( " -X " );
712+
713+ AddLinkerInputs (TC, Inputs, Args, CmdArgs, JA );
560714
561715 // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
562716 // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
0 commit comments