@@ -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,94 @@ 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 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+
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 = 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+ }
127202 }
128203 }
129204}
@@ -236,7 +311,7 @@ getMultilibConfigPath(const Driver &D, const llvm::Triple &Triple,
236311 return {};
237312 }
238313 } else {
239- MultilibPath = computeBaseSysRoot (D, /* IncludeTriple=*/ false );
314+ MultilibPath = computeInstalledToolchainSysRoot (D, /* IncludeTriple=*/ false );
240315 llvm::sys::path::append (MultilibPath, MultilibFilename);
241316 }
242317 return MultilibPath;
@@ -254,7 +329,7 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
254329 if (D.getVFS ().exists (*MultilibPath)) {
255330 // If multilib.yaml is found, update sysroot so it doesn't use a target
256331 // specific suffix
257- SysRoot = computeBaseSysRoot (D, /* IncludeTriple=*/ false );
332+ SysRoot = computeInstalledToolchainSysRoot (D, /* IncludeTriple=*/ false );
258333 findMultilibsFromYAML (*this , D, *MultilibPath, Args, Result);
259334 SelectedMultilibs = Result.SelectedMultilibs ;
260335 Multilibs = Result.Multilibs ;
@@ -279,8 +354,6 @@ Tool *BareMetal::buildStaticLibTool() const {
279354 return new tools::baremetal::StaticLibTool (*this );
280355}
281356
282- std::string BareMetal::computeSysRoot () const { return SysRoot; }
283-
284357BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs () const {
285358 // Get multilibs in reverse order because they're ordered most-specific last.
286359 if (!SelectedMultilibs.empty ())
@@ -291,6 +364,36 @@ BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
291364 return llvm::reverse (Default);
292365}
293366
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+
294397void BareMetal::AddClangSystemIncludeArgs (const ArgList &DriverArgs,
295398 ArgStringList &CC1Args) const {
296399 if (DriverArgs.hasArg (options::OPT_nostdinc))
@@ -325,6 +428,19 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
325428 CC1Args.push_back (" -nostdsysteminc" );
326429}
327430
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+
328444void BareMetal::AddClangCXXStdlibIncludeArgs (const ArgList &DriverArgs,
329445 ArgStringList &CC1Args) const {
330446 if (DriverArgs.hasArg (options::OPT_nostdinc, options::OPT_nostdlibinc,
@@ -355,15 +471,15 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
355471 };
356472
357473 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 ;
367483 }
368484
369485 std::string SysRoot (computeSysRoot ());
@@ -428,6 +544,10 @@ void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
428544 CmdArgs.push_back (" -lsupc++" );
429545 break ;
430546 }
547+
548+ if (getTriple ().isRISCV () && GCCInstallation.isValid ())
549+ return ;
550+
431551 CmdArgs.push_back (" -lunwind" );
432552}
433553
@@ -503,12 +623,22 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
503623 const llvm::Triple::ArchType Arch = TC.getArch ();
504624 const llvm::Triple &Triple = getToolChain ().getEffectiveTriple ();
505625
506- AddLinkerInputs (TC, Inputs, Args, CmdArgs, JA);
626+ if (!D.SysRoot .empty ())
627+ CmdArgs.push_back (Args.MakeArgString (" --sysroot=" + D.SysRoot ));
507628
629+ Args.addAllArgs (CmdArgs, {options::OPT_u});
508630 CmdArgs.push_back (" -Bstatic" );
509631
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+ }
512642
513643 if (Triple.isARM () || Triple.isThumb ()) {
514644 bool IsBigEndian = arm::isARMBigEndian (Triple, Args);
@@ -519,9 +649,24 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
519649 CmdArgs.push_back (Arch == llvm::Triple::aarch64_be ? " -EB" : " -EL" );
520650 }
521651
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)));
525670 }
526671
527672 Args.addAllArgs (CmdArgs, {options::OPT_L, options::OPT_T_Group,
@@ -536,12 +681,20 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
536681 TC.AddCXXStdlibLibArgs (Args, CmdArgs);
537682
538683 if (!Args.hasArg (options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
539- CmdArgs.push_back (" -lc" );
540684 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+ }
542692 TC.AddLinkRuntimeLib (Args, CmdArgs);
543693 }
544694
695+ if (WantCRTs)
696+ CmdArgs.push_back (Args.MakeArgString (TC.GetFilePath (crtend)));
697+
545698 if (D.isUsingLTO ()) {
546699 assert (!Inputs.empty () && " Must have at least one input." );
547700 // Find the first filename InputInfo object.
@@ -555,8 +708,8 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
555708 addLTOOptions (TC, Args, CmdArgs, Output, *Input,
556709 D.getLTOMode () == LTOK_Thin);
557710 }
558- if (TC. getTriple (). isRISCV ())
559- CmdArgs. push_back ( " -X " );
711+
712+ AddLinkerInputs (TC, Inputs, Args, CmdArgs, JA );
560713
561714 // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
562715 // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
0 commit comments