1 //===--- DragonFly.cpp - DragonFly 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 "DragonFly.h"
10 #include "CommonArgs.h"
11 #include "clang/Driver/Compilation.h"
12 #include "clang/Driver/Driver.h"
13 #include "clang/Driver/Options.h"
14 #include "llvm/Option/ArgList.h"
15 
16 using namespace clang::driver;
17 using namespace clang::driver::tools;
18 using namespace clang::driver::toolchains;
19 using namespace clang;
20 using namespace llvm::opt;
21 
22 /// DragonFly Tools
23 
24 // For now, DragonFly Assemble does just about the same as for
25 // FreeBSD, but this may change soon.
26 void dragonfly::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
27                                         const InputInfo &Output,
28                                         const InputInfoList &Inputs,
29                                         const ArgList &Args,
30                                         const char *LinkingOutput) const {
31   claimNoWarnArgs(Args);
32   ArgStringList CmdArgs;
33 
34   // When building 32-bit code on DragonFly/pc64, we have to explicitly
35   // instruct as in the base system to assemble 32-bit code.
36   if (getToolChain().getArch() == llvm::Triple::x86)
37     CmdArgs.push_back("--32");
38 
39   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
40 
41   CmdArgs.push_back("-o");
42   CmdArgs.push_back(Output.getFilename());
43 
44   for (const auto &II : Inputs)
45     CmdArgs.push_back(II.getFilename());
46 
47   const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
48   C.addCommand(std::make_unique<Command>(JA, *this,
49                                          ResponseFileSupport::AtFileCurCP(),
50                                          Exec, CmdArgs, Inputs, Output));
51 }
52 
53 void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
54                                      const InputInfo &Output,
55                                      const InputInfoList &Inputs,
56                                      const ArgList &Args,
57                                      const char *LinkingOutput) const {
58   const Driver &D = getToolChain().getDriver();
59   ArgStringList CmdArgs;
60 
61   if (!D.SysRoot.empty())
62     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
63 
64   CmdArgs.push_back("--eh-frame-hdr");
65   if (Args.hasArg(options::OPT_static)) {
66     CmdArgs.push_back("-Bstatic");
67   } else {
68     if (Args.hasArg(options::OPT_rdynamic))
69       CmdArgs.push_back("-export-dynamic");
70     if (Args.hasArg(options::OPT_shared))
71       CmdArgs.push_back("-Bshareable");
72     else {
73       CmdArgs.push_back("-dynamic-linker");
74       CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
75     }
76     CmdArgs.push_back("--hash-style=gnu");
77     CmdArgs.push_back("--enable-new-dtags");
78   }
79 
80   // When building 32-bit code on DragonFly/pc64, we have to explicitly
81   // instruct ld in the base system to link 32-bit code.
82   if (getToolChain().getArch() == llvm::Triple::x86) {
83     CmdArgs.push_back("-m");
84     CmdArgs.push_back("elf_i386");
85   }
86 
87   if (Output.isFilename()) {
88     CmdArgs.push_back("-o");
89     CmdArgs.push_back(Output.getFilename());
90   } else {
91     assert(Output.isNothing() && "Invalid output.");
92   }
93 
94   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
95                    options::OPT_r)) {
96     if (!Args.hasArg(options::OPT_shared)) {
97       if (Args.hasArg(options::OPT_pg))
98         CmdArgs.push_back(
99             Args.MakeArgString(getToolChain().GetFilePath("gcrt1.o")));
100       else {
101         if (Args.hasArg(options::OPT_pie))
102           CmdArgs.push_back(
103               Args.MakeArgString(getToolChain().GetFilePath("Scrt1.o")));
104         else
105           CmdArgs.push_back(
106               Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
107       }
108     }
109     CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
110     if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
111       CmdArgs.push_back(
112           Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
113     else
114       CmdArgs.push_back(
115           Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
116   }
117 
118   Args.AddAllArgs(CmdArgs,
119                   {options::OPT_L, options::OPT_T_Group, options::OPT_e});
120 
121   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
122 
123   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
124                    options::OPT_r)) {
125     CmdArgs.push_back("-L/usr/lib/gcc80");
126 
127     if (!Args.hasArg(options::OPT_static)) {
128       CmdArgs.push_back("-rpath");
129       CmdArgs.push_back("/usr/lib/gcc80");
130     }
131 
132     if (D.CCCIsCXX()) {
133       if (getToolChain().ShouldLinkCXXStdlib(Args))
134         getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
135       CmdArgs.push_back("-lm");
136     }
137 
138     if (Args.hasArg(options::OPT_pthread))
139       CmdArgs.push_back("-lpthread");
140 
141     if (!Args.hasArg(options::OPT_nolibc)) {
142       CmdArgs.push_back("-lc");
143     }
144 
145     if (Args.hasArg(options::OPT_static) ||
146         Args.hasArg(options::OPT_static_libgcc)) {
147         CmdArgs.push_back("-lgcc");
148         CmdArgs.push_back("-lgcc_eh");
149     } else {
150       if (Args.hasArg(options::OPT_shared_libgcc)) {
151           CmdArgs.push_back("-lgcc_pic");
152           if (!Args.hasArg(options::OPT_shared))
153             CmdArgs.push_back("-lgcc");
154       } else {
155           CmdArgs.push_back("-lgcc");
156           CmdArgs.push_back("--as-needed");
157           CmdArgs.push_back("-lgcc_pic");
158           CmdArgs.push_back("--no-as-needed");
159       }
160     }
161   }
162 
163   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
164                    options::OPT_r)) {
165     if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
166       CmdArgs.push_back(
167           Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
168     else
169       CmdArgs.push_back(
170           Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
171     CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
172   }
173 
174   getToolChain().addProfileRTLibs(Args, CmdArgs);
175 
176   const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
177   C.addCommand(std::make_unique<Command>(JA, *this,
178                                          ResponseFileSupport::AtFileCurCP(),
179                                          Exec, CmdArgs, Inputs, Output));
180 }
181 
182 /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
183 
184 DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,
185                      const ArgList &Args)
186     : Generic_ELF(D, Triple, Args) {
187 
188   // Path mangling to find libexec
189   getProgramPaths().push_back(getDriver().getInstalledDir());
190   if (getDriver().getInstalledDir() != getDriver().Dir)
191     getProgramPaths().push_back(getDriver().Dir);
192 
193   getFilePaths().push_back(getDriver().Dir + "/../lib");
194   getFilePaths().push_back("/usr/lib");
195   getFilePaths().push_back("/usr/lib/gcc80");
196 }
197 
198 Tool *DragonFly::buildAssembler() const {
199   return new tools::dragonfly::Assembler(*this);
200 }
201 
202 Tool *DragonFly::buildLinker() const {
203   return new tools::dragonfly::Linker(*this);
204 }
205