Skip to content

[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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion clang/lib/Driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ add_clang_library(clangDriver
ToolChains/OHOS.cpp
ToolChains/OpenBSD.cpp
ToolChains/PS4CPU.cpp
ToolChains/RISCVToolchain.cpp
ToolChains/Solaris.cpp
ToolChains/SPIRV.cpp
ToolChains/TCE.cpp
Expand Down
7 changes: 1 addition & 6 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
#include "ToolChains/PPCFreeBSD.h"
#include "ToolChains/PPCLinux.h"
#include "ToolChains/PS4CPU.h"
#include "ToolChains/RISCVToolchain.h"
#include "ToolChains/SPIRV.h"
#include "ToolChains/Solaris.h"
#include "ToolChains/TCE.h"
Expand Down Expand Up @@ -6557,11 +6556,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
break;
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
if (toolchains::RISCVToolChain::hasGCCToolchain(*this, Args))
TC =
std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);
else
TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args);
TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args);
break;
case llvm::Triple::ve:
TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);
Expand Down
247 changes: 197 additions & 50 deletions clang/lib/Driver/ToolChains/BareMetal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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");
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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));
}
}
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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())
Expand All @@ -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))
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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
Expand Down
Loading
Loading