-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV] Merging RISCVToolChain and BareMetal toolchains #118809
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,7 +97,8 @@ static bool findRISCVMultilibs(const Driver &D, | |
return false; | ||
} | ||
|
||
static std::string computeBaseSysRoot(const Driver &D, bool IncludeTriple) { | ||
static std::string computeInstalledToolchainSysRoot(const Driver &D, | ||
bool IncludeTriple) { | ||
if (!D.SysRoot.empty()) | ||
return D.SysRoot; | ||
|
||
|
@@ -110,20 +111,95 @@ static std::string computeBaseSysRoot(const Driver &D, bool IncludeTriple) { | |
return std::string(SysRootDir); | ||
} | ||
|
||
// GCC sysroot here means form sysroot from either --gcc-install-dir, or from | ||
// --gcc-toolchain or if the toolchain is installed alongside clang in | ||
// bin/../<TargetTriple> directory if it is not explicitly specified on the | ||
// command line through `--sysroot` option. libc here will be newlib. | ||
std::string BareMetal::computeGCCSysRoot() const { | ||
if (!getDriver().SysRoot.empty()) | ||
return getDriver().SysRoot; | ||
|
||
SmallString<128> SysRootDir; | ||
if (GCCInstallation.isValid()) { | ||
StringRef LibDir = GCCInstallation.getParentLibPath(); | ||
StringRef TripleStr = GCCInstallation.getTriple().str(); | ||
llvm::sys::path::append(SysRootDir, LibDir, "..", TripleStr); | ||
} else { | ||
// Use the triple as provided to the driver. Unlike the parsed triple | ||
// this has not been normalized to always contain every field. | ||
llvm::sys::path::append(SysRootDir, getDriver().Dir, "..", | ||
getDriver().getTargetTriple()); | ||
} | ||
|
||
if (!llvm::sys::fs::exists(SysRootDir)) | ||
return std::string(); | ||
|
||
return std::string(SysRootDir); | ||
} | ||
|
||
std::string BareMetal::computeSysRoot() const { | ||
if (!SysRoot.empty()) | ||
return SysRoot; | ||
|
||
std::string SysRoot = getDriver().SysRoot; | ||
if (!SysRoot.empty() && llvm::sys::fs::exists(SysRoot)) | ||
return SysRoot; | ||
|
||
// Verify the GCC installation from -gcc-install-dir, --gcc-toolchain, or | ||
// alongside clang. If valid, form the sysroot. Otherwise, check | ||
// lib/clang-runtimes above the driver. | ||
SysRoot = computeGCCSysRoot(); | ||
if (!SysRoot.empty()) | ||
return SysRoot; | ||
|
||
SysRoot = | ||
computeInstalledToolchainSysRoot(getDriver(), /*IncludeTriple*/ true); | ||
|
||
return SysRoot; | ||
} | ||
|
||
static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs, | ||
const Multilib &Multilib, | ||
StringRef InstallPath, | ||
ToolChain::path_list &Paths) { | ||
if (const auto &PathsCallback = Multilibs.filePathsCallback()) | ||
for (const auto &Path : PathsCallback(Multilib)) | ||
addPathIfExists(D, InstallPath + Path, Paths); | ||
} | ||
|
||
BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple, | ||
const ArgList &Args) | ||
: ToolChain(D, Triple, Args), | ||
SysRoot(computeBaseSysRoot(D, /*IncludeTriple=*/true)) { | ||
getProgramPaths().push_back(getDriver().Dir); | ||
|
||
findMultilibs(D, Triple, Args); | ||
SmallString<128> SysRoot(computeSysRoot()); | ||
if (!SysRoot.empty()) { | ||
for (const Multilib &M : getOrderedMultilibs()) { | ||
SmallString<128> Dir(SysRoot); | ||
llvm::sys::path::append(Dir, M.osSuffix(), "lib"); | ||
getFilePaths().push_back(std::string(Dir)); | ||
getLibraryPaths().push_back(std::string(Dir)); | ||
: Generic_ELF(D, Triple, Args) { | ||
GCCInstallation.init(Triple, Args); | ||
SysRoot = computeSysRoot(); | ||
UseLD = | ||
Args.getLastArgValue(options::OPT_fuse_ld_EQ).equals_insensitive("ld"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the right hand side value if there are no -fuse-ld= in the argslist? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. value will be "0". The function to decide the default linker is "getDefaultLinker" which calls "isUsingLd". I have made this function virtual which can be overridden in derived classes and can return false for all cases. |
||
if (GCCInstallation.isValid()) { | ||
Multilibs = GCCInstallation.getMultilibs(); | ||
SelectedMultilibs.assign({GCCInstallation.getMultilib()}); | ||
path_list &Paths = getFilePaths(); | ||
// Add toolchain/multilib specific file paths. | ||
addMultilibsFilePaths(D, Multilibs, SelectedMultilibs.back(), | ||
GCCInstallation.getInstallPath(), Paths); | ||
getFilePaths().push_back(GCCInstallation.getInstallPath().str()); | ||
ToolChain::path_list &PPaths = getProgramPaths(); | ||
// Multilib cross-compiler GCC installations put ld in a triple-prefixed | ||
// directory off of the parent of the GCC installation. | ||
PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" + | ||
GCCInstallation.getTriple().str() + "/bin") | ||
.str()); | ||
PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str()); | ||
getFilePaths().push_back(computeSysRoot() + "/lib"); | ||
} else { | ||
getProgramPaths().push_back(getDriver().Dir); | ||
findMultilibs(D, Triple, Args); | ||
if (!SysRoot.empty()) { | ||
for (const Multilib &M : getOrderedMultilibs()) { | ||
SmallString<128> Dir(SysRoot); | ||
llvm::sys::path::append(Dir, M.osSuffix(), "lib"); | ||
getFilePaths().push_back(std::string(Dir)); | ||
getLibraryPaths().push_back(std::string(Dir)); | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -215,7 +291,7 @@ getMultilibConfigPath(const Driver &D, const llvm::Triple &Triple, | |
return {}; | ||
} | ||
} else { | ||
MultilibPath = computeBaseSysRoot(D, /*IncludeTriple=*/false); | ||
MultilibPath = computeInstalledToolchainSysRoot(D, /*IncludeTriple=*/false); | ||
llvm::sys::path::append(MultilibPath, MultilibFilename); | ||
} | ||
return MultilibPath; | ||
|
@@ -233,7 +309,7 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple, | |
if (D.getVFS().exists(*MultilibPath)) { | ||
// If multilib.yaml is found, update sysroot so it doesn't use a target | ||
// specific suffix | ||
SysRoot = computeBaseSysRoot(D, /*IncludeTriple=*/false); | ||
SysRoot = computeInstalledToolchainSysRoot(D, /*IncludeTriple=*/false); | ||
findMultilibsFromYAML(*this, D, *MultilibPath, Args, Result); | ||
SelectedMultilibs = Result.SelectedMultilibs; | ||
Multilibs = Result.Multilibs; | ||
|
@@ -258,8 +334,6 @@ Tool *BareMetal::buildStaticLibTool() const { | |
return new tools::baremetal::StaticLibTool(*this); | ||
} | ||
|
||
std::string BareMetal::computeSysRoot() const { return SysRoot; } | ||
|
||
BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const { | ||
// Get multilibs in reverse order because they're ordered most-specific last. | ||
if (!SelectedMultilibs.empty()) | ||
|
@@ -270,6 +344,32 @@ BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const { | |
return llvm::reverse(Default); | ||
} | ||
|
||
ToolChain::CXXStdlibType BareMetal::GetDefaultCXXStdlibType() const { | ||
if (getTriple().isRISCV() && GCCInstallation.isValid()) | ||
return ToolChain::CST_Libstdcxx; | ||
return ToolChain::CST_Libcxx; | ||
} | ||
|
||
ToolChain::RuntimeLibType BareMetal::GetDefaultRuntimeLibType() const { | ||
if (getTriple().isRISCV() && GCCInstallation.isValid()) | ||
return ToolChain::RLT_Libgcc; | ||
return ToolChain::RLT_CompilerRT; | ||
} | ||
|
||
ToolChain::UnwindLibType | ||
BareMetal::GetUnwindLibType(const llvm::opt::ArgList &Args) const { | ||
if (getTriple().isRISCV()) | ||
return ToolChain::UNW_None; | ||
|
||
return ToolChain::GetUnwindLibType(Args); | ||
} | ||
|
||
const char *BareMetal::getDefaultLinker() const { | ||
if (isUsingLD()) | ||
return "ld"; | ||
return "ld.lld"; | ||
} | ||
|
||
void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs, | ||
ArgStringList &CC1Args) const { | ||
if (DriverArgs.hasArg(options::OPT_nostdinc)) | ||
|
@@ -304,6 +404,19 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs, | |
CC1Args.push_back("-nostdsysteminc"); | ||
} | ||
|
||
void BareMetal::addLibStdCxxIncludePaths( | ||
const llvm::opt::ArgList &DriverArgs, | ||
llvm::opt::ArgStringList &CC1Args) const { | ||
if (!GCCInstallation.isValid()) | ||
return; | ||
const GCCVersion &Version = GCCInstallation.getVersion(); | ||
StringRef TripleStr = GCCInstallation.getTriple().str(); | ||
const Multilib &Multilib = GCCInstallation.getMultilib(); | ||
addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text, | ||
TripleStr, Multilib.includeSuffix(), DriverArgs, | ||
CC1Args); | ||
} | ||
|
||
void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, | ||
ArgStringList &CC1Args) const { | ||
if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, | ||
|
@@ -334,15 +447,15 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, | |
}; | ||
|
||
switch (GetCXXStdlibType(DriverArgs)) { | ||
case ToolChain::CST_Libcxx: { | ||
SmallString<128> P(D.Dir); | ||
llvm::sys::path::append(P, "..", "include"); | ||
AddCXXIncludePath(P); | ||
break; | ||
} | ||
case ToolChain::CST_Libstdcxx: | ||
// We only support libc++ toolchain installation. | ||
break; | ||
case ToolChain::CST_Libcxx: { | ||
SmallString<128> P(D.Dir); | ||
llvm::sys::path::append(P, "..", "include"); | ||
AddCXXIncludePath(P); | ||
break; | ||
} | ||
case ToolChain::CST_Libstdcxx: | ||
addLibStdCxxIncludePaths(DriverArgs, CC1Args); | ||
break; | ||
} | ||
|
||
std::string SysRoot(computeSysRoot()); | ||
|
@@ -450,12 +563,21 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, | |
const llvm::Triple::ArchType Arch = TC.getArch(); | ||
const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); | ||
|
||
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); | ||
if (!D.SysRoot.empty()) | ||
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); | ||
|
||
CmdArgs.push_back("-Bstatic"); | ||
|
||
if (TC.getTriple().isRISCV() && Args.hasArg(options::OPT_mno_relax)) | ||
CmdArgs.push_back("--no-relax"); | ||
if (Triple.isRISCV()) { | ||
if (Args.hasArg(options::OPT_mno_relax)) | ||
CmdArgs.push_back("--no-relax"); | ||
if (TC.isUsingLD()) { | ||
CmdArgs.push_back("-m"); | ||
CmdArgs.push_back(Arch == llvm::Triple::riscv64 ? "elf64lriscv" | ||
: "elf32lriscv"); | ||
} | ||
CmdArgs.push_back("-X"); | ||
} | ||
|
||
if (Triple.isARM() || Triple.isThumb()) { | ||
bool IsBigEndian = arm::isARMBigEndian(Triple, Args); | ||
|
@@ -466,19 +588,54 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, | |
CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL"); | ||
} | ||
|
||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, | ||
options::OPT_r)) { | ||
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt0.o"))); | ||
bool WantCRTs = | ||
!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles); | ||
|
||
const char *crtbegin, *crtend; | ||
if (WantCRTs) { | ||
if (!Args.hasArg(options::OPT_r)) | ||
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt0.o"))); | ||
if (TC.isUsingLD()) { | ||
auto RuntimeLib = TC.GetRuntimeLibType(Args); | ||
if (RuntimeLib == ToolChain::RLT_Libgcc) { | ||
crtbegin = "crtbegin.o"; | ||
crtend = "crtend.o"; | ||
} else { | ||
assert(RuntimeLib == ToolChain::RLT_CompilerRT); | ||
crtbegin = | ||
TC.getCompilerRTArgString(Args, "crtbegin", ToolChain::FT_Object); | ||
crtend = | ||
TC.getCompilerRTArgString(Args, "crtend", ToolChain::FT_Object); | ||
} | ||
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(crtbegin))); | ||
} | ||
} | ||
|
||
Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, | ||
options::OPT_s, options::OPT_t, options::OPT_r}); | ||
Args.addAllArgs(CmdArgs, | ||
{options::OPT_L, options::OPT_u, options::OPT_T_Group, | ||
options::OPT_s, options::OPT_t, options::OPT_r}); | ||
|
||
TC.AddFilePathLibArgs(Args, CmdArgs); | ||
|
||
for (const auto &LibPath : TC.getLibraryPaths()) | ||
CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-L", LibPath))); | ||
|
||
if (D.isUsingLTO()) { | ||
assert(!Inputs.empty() && "Must have at least one input."); | ||
// Find the first filename InputInfo object. | ||
auto Input = llvm::find_if( | ||
Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); }); | ||
if (Input == Inputs.end()) | ||
// For a very rare case, all of the inputs to the linker are | ||
// InputArg. If that happens, just use the first InputInfo. | ||
Input = Inputs.begin(); | ||
|
||
addLTOOptions(TC, Args, CmdArgs, Output, *Input, | ||
D.getLTOMode() == LTOK_Thin); | ||
} | ||
|
||
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); | ||
|
||
if (TC.ShouldLinkCXXStdlib(Args)) { | ||
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && | ||
!Args.hasArg(options::OPT_static); | ||
|
@@ -491,26 +648,16 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, | |
} | ||
|
||
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { | ||
CmdArgs.push_back("--start-group"); | ||
AddRunTimeLibs(TC, D, CmdArgs, Args); | ||
|
||
CmdArgs.push_back("-lc"); | ||
if (TC.isUsingLD()) | ||
CmdArgs.push_back("-lgloss"); | ||
CmdArgs.push_back("--end-group"); | ||
} | ||
|
||
if (D.isUsingLTO()) { | ||
assert(!Inputs.empty() && "Must have at least one input."); | ||
// Find the first filename InputInfo object. | ||
auto Input = llvm::find_if( | ||
Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); }); | ||
if (Input == Inputs.end()) | ||
// For a very rare case, all of the inputs to the linker are | ||
// InputArg. If that happens, just use the first InputInfo. | ||
Input = Inputs.begin(); | ||
|
||
addLTOOptions(TC, Args, CmdArgs, Output, *Input, | ||
D.getLTOMode() == LTOK_Thin); | ||
} | ||
if (TC.getTriple().isRISCV()) | ||
CmdArgs.push_back("-X"); | ||
if (TC.isUsingLD() && WantCRTs) | ||
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(crtend))); | ||
|
||
// The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf | ||
// and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and | ||
|
Uh oh!
There was an error while loading. Please reload this page.