1 //===--- RISCVToolchain.cpp - RISCV ToolChain Implementations ---*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "RISCVToolchain.h" 10 #include "CommonArgs.h" 11 #include "InputInfo.h" 12 #include "clang/Driver/Compilation.h" 13 #include "clang/Driver/Options.h" 14 #include "llvm/Option/ArgList.h" 15 #include "llvm/Support/FileSystem.h" 16 #include "llvm/Support/Path.h" 17 #include "llvm/Support/raw_ostream.h" 18 19 using namespace clang::driver; 20 using namespace clang::driver::toolchains; 21 using namespace clang::driver::tools; 22 using namespace clang; 23 using namespace llvm::opt; 24 25 /// RISCV Toolchain 26 RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple, 27 const ArgList &Args) 28 : Generic_ELF(D, Triple, Args) { 29 GCCInstallation.init(Triple, Args); 30 getFilePaths().push_back(computeSysRoot() + "/lib"); 31 if (GCCInstallation.isValid()) { 32 getFilePaths().push_back(GCCInstallation.getInstallPath().str()); 33 getProgramPaths().push_back( 34 (GCCInstallation.getParentLibPath() + "/../bin").str()); 35 } 36 } 37 38 Tool *RISCVToolChain::buildLinker() const { 39 return new tools::RISCV::Linker(*this); 40 } 41 42 void RISCVToolChain::addClangTargetOptions( 43 const llvm::opt::ArgList &DriverArgs, 44 llvm::opt::ArgStringList &CC1Args, 45 Action::OffloadKind) const { 46 CC1Args.push_back("-nostdsysteminc"); 47 CC1Args.push_back("-fuse-init-array"); 48 } 49 50 void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 51 ArgStringList &CC1Args) const { 52 if (DriverArgs.hasArg(options::OPT_nostdinc)) 53 return; 54 55 if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) { 56 SmallString<128> Dir(computeSysRoot()); 57 llvm::sys::path::append(Dir, "include"); 58 addSystemInclude(DriverArgs, CC1Args, Dir.str()); 59 } 60 } 61 62 void RISCVToolChain::addLibStdCxxIncludePaths( 63 const llvm::opt::ArgList &DriverArgs, 64 llvm::opt::ArgStringList &CC1Args) const { 65 const GCCVersion &Version = GCCInstallation.getVersion(); 66 StringRef TripleStr = GCCInstallation.getTriple().str(); 67 const Multilib &Multilib = GCCInstallation.getMultilib(); 68 addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text, 69 "", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args); 70 } 71 72 std::string RISCVToolChain::computeSysRoot() const { 73 if (!getDriver().SysRoot.empty()) 74 return getDriver().SysRoot; 75 76 if (!GCCInstallation.isValid()) 77 return std::string(); 78 79 StringRef LibDir = GCCInstallation.getParentLibPath(); 80 StringRef TripleStr = GCCInstallation.getTriple().str(); 81 std::string SysRootDir = LibDir.str() + "/../" + TripleStr.str(); 82 83 if (!llvm::sys::fs::exists(SysRootDir)) 84 return std::string(); 85 86 return SysRootDir; 87 } 88 89 void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, 90 const InputInfo &Output, 91 const InputInfoList &Inputs, 92 const ArgList &Args, 93 const char *LinkingOutput) const { 94 const ToolChain &ToolChain = getToolChain(); 95 const Driver &D = ToolChain.getDriver(); 96 ArgStringList CmdArgs; 97 98 if (!D.SysRoot.empty()) 99 CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 100 101 std::string Linker = getToolChain().GetProgramPath(getShortName()); 102 103 bool WantCRTs = 104 !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles); 105 106 if (WantCRTs) { 107 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); 108 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o"))); 109 } 110 111 Args.AddAllArgs(CmdArgs, options::OPT_L); 112 ToolChain.AddFilePathLibArgs(Args, CmdArgs); 113 Args.AddAllArgs(CmdArgs, 114 {options::OPT_T_Group, options::OPT_e, options::OPT_s, 115 options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); 116 117 AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 118 119 // TODO: add C++ includes and libs if compiling C++. 120 121 if (!Args.hasArg(options::OPT_nostdlib) && 122 !Args.hasArg(options::OPT_nodefaultlibs)) { 123 if (ToolChain.ShouldLinkCXXStdlib(Args)) 124 ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); 125 CmdArgs.push_back("--start-group"); 126 CmdArgs.push_back("-lc"); 127 CmdArgs.push_back("-lgloss"); 128 CmdArgs.push_back("--end-group"); 129 CmdArgs.push_back("-lgcc"); 130 } 131 132 if (WantCRTs) 133 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); 134 135 CmdArgs.push_back("-o"); 136 CmdArgs.push_back(Output.getFilename()); 137 C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), 138 CmdArgs, Inputs)); 139 } 140 // RISCV tools end. 141