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