10b57cec5SDimitry Andric //===--- RISCVToolchain.cpp - RISCV ToolChain Implementations ---*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "RISCVToolchain.h" 10*a7dea167SDimitry Andric #include "Arch/RISCV.h" 110b57cec5SDimitry Andric #include "CommonArgs.h" 120b57cec5SDimitry Andric #include "InputInfo.h" 130b57cec5SDimitry Andric #include "clang/Driver/Compilation.h" 140b57cec5SDimitry Andric #include "clang/Driver/Options.h" 150b57cec5SDimitry Andric #include "llvm/Option/ArgList.h" 160b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 170b57cec5SDimitry Andric #include "llvm/Support/Path.h" 180b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric using namespace clang::driver; 210b57cec5SDimitry Andric using namespace clang::driver::toolchains; 220b57cec5SDimitry Andric using namespace clang::driver::tools; 230b57cec5SDimitry Andric using namespace clang; 240b57cec5SDimitry Andric using namespace llvm::opt; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric /// RISCV Toolchain 270b57cec5SDimitry Andric RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple, 280b57cec5SDimitry Andric const ArgList &Args) 290b57cec5SDimitry Andric : Generic_ELF(D, Triple, Args) { 300b57cec5SDimitry Andric GCCInstallation.init(Triple, Args); 310b57cec5SDimitry Andric getFilePaths().push_back(computeSysRoot() + "/lib"); 320b57cec5SDimitry Andric if (GCCInstallation.isValid()) { 330b57cec5SDimitry Andric getFilePaths().push_back(GCCInstallation.getInstallPath().str()); 340b57cec5SDimitry Andric getProgramPaths().push_back( 350b57cec5SDimitry Andric (GCCInstallation.getParentLibPath() + "/../bin").str()); 360b57cec5SDimitry Andric } 370b57cec5SDimitry Andric } 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric Tool *RISCVToolChain::buildLinker() const { 400b57cec5SDimitry Andric return new tools::RISCV::Linker(*this); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric void RISCVToolChain::addClangTargetOptions( 440b57cec5SDimitry Andric const llvm::opt::ArgList &DriverArgs, 450b57cec5SDimitry Andric llvm::opt::ArgStringList &CC1Args, 460b57cec5SDimitry Andric Action::OffloadKind) const { 470b57cec5SDimitry Andric CC1Args.push_back("-nostdsysteminc"); 480b57cec5SDimitry Andric CC1Args.push_back("-fuse-init-array"); 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 520b57cec5SDimitry Andric ArgStringList &CC1Args) const { 530b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) 540b57cec5SDimitry Andric return; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) { 570b57cec5SDimitry Andric SmallString<128> Dir(computeSysRoot()); 580b57cec5SDimitry Andric llvm::sys::path::append(Dir, "include"); 590b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, Dir.str()); 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric void RISCVToolChain::addLibStdCxxIncludePaths( 640b57cec5SDimitry Andric const llvm::opt::ArgList &DriverArgs, 650b57cec5SDimitry Andric llvm::opt::ArgStringList &CC1Args) const { 660b57cec5SDimitry Andric const GCCVersion &Version = GCCInstallation.getVersion(); 670b57cec5SDimitry Andric StringRef TripleStr = GCCInstallation.getTriple().str(); 680b57cec5SDimitry Andric const Multilib &Multilib = GCCInstallation.getMultilib(); 690b57cec5SDimitry Andric addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text, 700b57cec5SDimitry Andric "", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args); 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric std::string RISCVToolChain::computeSysRoot() const { 740b57cec5SDimitry Andric if (!getDriver().SysRoot.empty()) 750b57cec5SDimitry Andric return getDriver().SysRoot; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric if (!GCCInstallation.isValid()) 780b57cec5SDimitry Andric return std::string(); 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric StringRef LibDir = GCCInstallation.getParentLibPath(); 810b57cec5SDimitry Andric StringRef TripleStr = GCCInstallation.getTriple().str(); 820b57cec5SDimitry Andric std::string SysRootDir = LibDir.str() + "/../" + TripleStr.str(); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric if (!llvm::sys::fs::exists(SysRootDir)) 850b57cec5SDimitry Andric return std::string(); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric return SysRootDir; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, 910b57cec5SDimitry Andric const InputInfo &Output, 920b57cec5SDimitry Andric const InputInfoList &Inputs, 930b57cec5SDimitry Andric const ArgList &Args, 940b57cec5SDimitry Andric const char *LinkingOutput) const { 950b57cec5SDimitry Andric const ToolChain &ToolChain = getToolChain(); 960b57cec5SDimitry Andric const Driver &D = ToolChain.getDriver(); 970b57cec5SDimitry Andric ArgStringList CmdArgs; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric if (!D.SysRoot.empty()) 1000b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric std::string Linker = getToolChain().GetProgramPath(getShortName()); 1030b57cec5SDimitry Andric 104*a7dea167SDimitry Andric if (D.isUsingLTO()) { 105*a7dea167SDimitry Andric assert(!Inputs.empty() && "Must have at least one input."); 106*a7dea167SDimitry Andric AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0], 107*a7dea167SDimitry Andric D.getLTOMode() == LTOK_Thin); 108*a7dea167SDimitry Andric } 109*a7dea167SDimitry Andric 1100b57cec5SDimitry Andric bool WantCRTs = 1110b57cec5SDimitry Andric !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric if (WantCRTs) { 1140b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); 1150b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o"))); 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L); 1190b57cec5SDimitry Andric ToolChain.AddFilePathLibArgs(Args, CmdArgs); 1200b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, 1210b57cec5SDimitry Andric {options::OPT_T_Group, options::OPT_e, options::OPT_s, 1220b57cec5SDimitry Andric options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric // TODO: add C++ includes and libs if compiling C++. 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib) && 1290b57cec5SDimitry Andric !Args.hasArg(options::OPT_nodefaultlibs)) { 1300b57cec5SDimitry Andric if (ToolChain.ShouldLinkCXXStdlib(Args)) 1310b57cec5SDimitry Andric ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); 1320b57cec5SDimitry Andric CmdArgs.push_back("--start-group"); 1330b57cec5SDimitry Andric CmdArgs.push_back("-lc"); 1340b57cec5SDimitry Andric CmdArgs.push_back("-lgloss"); 1350b57cec5SDimitry Andric CmdArgs.push_back("--end-group"); 1360b57cec5SDimitry Andric CmdArgs.push_back("-lgcc"); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric if (WantCRTs) 1400b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric CmdArgs.push_back("-o"); 1430b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 144*a7dea167SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), 1450b57cec5SDimitry Andric CmdArgs, Inputs)); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric // RISCV tools end. 148