Skip to content

Commit b6d7bbf

Browse files
committed
[RISCV] Support mutilib in baremetal environment
Currently only support the set of multilibs same to riscv-gnu-toolchain. Reviewers: espindola, asb, kito-cheng, lenary Reviewed By: lenary Differential Revision: https://reviews.llvm.org/D67508
1 parent 4ef9315 commit b6d7bbf

File tree

29 files changed

+201
-11
lines changed

29 files changed

+201
-11
lines changed

clang/lib/Driver/ToolChains/Gnu.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,9 +1503,65 @@ static bool findMSP430Multilibs(const Driver &D,
15031503
return false;
15041504
}
15051505

1506+
static void findRISCVBareMetalMultilibs(const Driver &D,
1507+
const llvm::Triple &TargetTriple,
1508+
StringRef Path, const ArgList &Args,
1509+
DetectedMultilibs &Result) {
1510+
FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
1511+
struct RiscvMultilib {
1512+
StringRef march;
1513+
StringRef mabi;
1514+
};
1515+
// currently only support the set of multilibs like riscv-gnu-toolchain does.
1516+
// TODO: support MULTILIB_REUSE
1517+
SmallVector<RiscvMultilib, 8> RISCVMultilibSet = {
1518+
{"rv32i", "ilp32"}, {"rv32im", "ilp32"}, {"rv32iac", "ilp32"},
1519+
{"rv32imac", "ilp32"}, {"rv32imafc", "ilp32f"}, {"rv64imac", "lp64"},
1520+
{"rv64imafdc", "lp64d"}};
1521+
1522+
std::vector<Multilib> Ms;
1523+
for (auto Element : RISCVMultilibSet) {
1524+
// multilib path rule is ${march}/${mabi}
1525+
Ms.emplace_back(
1526+
makeMultilib((Twine(Element.march) + "/" + Twine(Element.mabi)).str())
1527+
.flag(Twine("+march=", Element.march).str())
1528+
.flag(Twine("+mabi=", Element.mabi).str()));
1529+
}
1530+
MultilibSet RISCVMultilibs =
1531+
MultilibSet()
1532+
.Either(ArrayRef<Multilib>(Ms))
1533+
.FilterOut(NonExistent)
1534+
.setFilePathsCallback([](const Multilib &M) {
1535+
return std::vector<std::string>(
1536+
{M.gccSuffix(),
1537+
"/../../../../riscv64-unknown-elf/lib" + M.gccSuffix(),
1538+
"/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()});
1539+
});
1540+
1541+
1542+
Multilib::flags_list Flags;
1543+
llvm::StringSet<> Added_ABIs;
1544+
StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
1545+
StringRef MArch = tools::riscv::getRISCVArch(Args, TargetTriple);
1546+
for (auto Element : RISCVMultilibSet) {
1547+
addMultilibFlag(MArch == Element.march,
1548+
Twine("march=", Element.march).str().c_str(), Flags);
1549+
if (!Added_ABIs.count(Element.mabi)) {
1550+
Added_ABIs.insert(Element.mabi);
1551+
addMultilibFlag(ABIName == Element.mabi,
1552+
Twine("mabi=", Element.mabi).str().c_str(), Flags);
1553+
}
1554+
}
1555+
1556+
if (RISCVMultilibs.select(Flags, Result.SelectedMultilib))
1557+
Result.Multilibs = RISCVMultilibs;
1558+
}
1559+
15061560
static void findRISCVMultilibs(const Driver &D,
15071561
const llvm::Triple &TargetTriple, StringRef Path,
15081562
const ArgList &Args, DetectedMultilibs &Result) {
1563+
if (TargetTriple.getOS() == llvm::Triple::UnknownOS)
1564+
return findRISCVBareMetalMultilibs(D, TargetTriple, Path, Args, Result);
15091565

15101566
FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
15111567
Multilib Ilp32 = makeMultilib("lib32/ilp32").flag("+m32").flag("+mabi=ilp32");

clang/lib/Driver/ToolChains/RISCVToolchain.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,39 @@ using namespace clang::driver::tools;
2222
using namespace clang;
2323
using namespace llvm::opt;
2424

25+
static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
26+
const Multilib &Multilib,
27+
StringRef InstallPath,
28+
ToolChain::path_list &Paths) {
29+
if (const auto &PathsCallback = Multilibs.filePathsCallback())
30+
for (const auto &Path : PathsCallback(Multilib))
31+
addPathIfExists(D, InstallPath + Path, Paths);
32+
}
33+
2534
/// RISCV Toolchain
2635
RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
2736
const ArgList &Args)
2837
: Generic_ELF(D, Triple, Args) {
2938
GCCInstallation.init(Triple, Args);
30-
getFilePaths().push_back(computeSysRoot() + "/lib");
3139
if (GCCInstallation.isValid()) {
40+
Multilibs = GCCInstallation.getMultilibs();
41+
SelectedMultilib = GCCInstallation.getMultilib();
42+
path_list &Paths = getFilePaths();
43+
// Add toolchain/multilib specific file paths.
44+
addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
45+
GCCInstallation.getInstallPath(), Paths);
3246
getFilePaths().push_back(GCCInstallation.getInstallPath().str());
33-
getProgramPaths().push_back(
34-
(GCCInstallation.getParentLibPath() + "/../bin").str());
47+
ToolChain::path_list &PPaths = getProgramPaths();
48+
// Multilib cross-compiler GCC installations put ld in a triple-prefixed
49+
// directory off of the parent of the GCC installation.
50+
PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
51+
GCCInstallation.getTriple().str() + "/bin")
52+
.str());
53+
PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str());
3554
} else {
3655
getProgramPaths().push_back(D.Dir);
3756
}
57+
getFilePaths().push_back(computeSysRoot() + "/lib");
3858
}
3959

4060
Tool *RISCVToolChain::buildLinker() const {
@@ -105,6 +125,14 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
105125
if (!D.SysRoot.empty())
106126
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
107127

128+
bool IsRV64 = ToolChain.getArch() == llvm::Triple::riscv64;
129+
CmdArgs.push_back("-m");
130+
if (IsRV64) {
131+
CmdArgs.push_back("elf64lriscv");
132+
} else {
133+
CmdArgs.push_back("elf32lriscv");
134+
}
135+
108136
std::string Linker = getToolChain().GetProgramPath(getShortName());
109137

110138
bool WantCRTs =

clang/test/Driver/Inputs/multilib_riscv_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/crtbegin.o

Whitespace-only changes.

clang/test/Driver/Inputs/multilib_riscv_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/crtend.o

Whitespace-only changes.

clang/test/Driver/Inputs/multilib_riscv_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv32i/ilp32/crtbegin.o

Whitespace-only changes.

clang/test/Driver/Inputs/multilib_riscv_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv32i/ilp32/crtend.o

Whitespace-only changes.

clang/test/Driver/Inputs/multilib_riscv_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv32iac/ilp32/crtbegin.o

Whitespace-only changes.

clang/test/Driver/Inputs/multilib_riscv_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv32iac/ilp32/crtend.o

Whitespace-only changes.

clang/test/Driver/Inputs/multilib_riscv_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv32im/ilp32/crtbegin.o

Whitespace-only changes.

clang/test/Driver/Inputs/multilib_riscv_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv32im/ilp32/crtend.o

Whitespace-only changes.

0 commit comments

Comments
 (0)