xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp (revision c66ec88fed842fbaad62c30d510644ceb7bd2d71)
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>(
49       JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
50 }
51 
52 void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
53                                      const InputInfo &Output,
54                                      const InputInfoList &Inputs,
55                                      const ArgList &Args,
56                                      const char *LinkingOutput) const {
57   const Driver &D = getToolChain().getDriver();
58   ArgStringList CmdArgs;
59 
60   if (!D.SysRoot.empty())
61     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
62 
63   CmdArgs.push_back("--eh-frame-hdr");
64   if (Args.hasArg(options::OPT_static)) {
65     CmdArgs.push_back("-Bstatic");
66   } else {
67     if (Args.hasArg(options::OPT_rdynamic))
68       CmdArgs.push_back("-export-dynamic");
69     if (Args.hasArg(options::OPT_shared))
70       CmdArgs.push_back("-Bshareable");
71     else {
72       CmdArgs.push_back("-dynamic-linker");
73       CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
74     }
75     CmdArgs.push_back("--hash-style=gnu");
76     CmdArgs.push_back("--enable-new-dtags");
77   }
78 
79   // When building 32-bit code on DragonFly/pc64, we have to explicitly
80   // instruct ld in the base system to link 32-bit code.
81   if (getToolChain().getArch() == llvm::Triple::x86) {
82     CmdArgs.push_back("-m");
83     CmdArgs.push_back("elf_i386");
84   }
85 
86   if (Output.isFilename()) {
87     CmdArgs.push_back("-o");
88     CmdArgs.push_back(Output.getFilename());
89   } else {
90     assert(Output.isNothing() && "Invalid output.");
91   }
92 
93   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
94     if (!Args.hasArg(options::OPT_shared)) {
95       if (Args.hasArg(options::OPT_pg))
96         CmdArgs.push_back(
97             Args.MakeArgString(getToolChain().GetFilePath("gcrt1.o")));
98       else {
99         if (Args.hasArg(options::OPT_pie))
100           CmdArgs.push_back(
101               Args.MakeArgString(getToolChain().GetFilePath("Scrt1.o")));
102         else
103           CmdArgs.push_back(
104               Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
105       }
106     }
107     CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
108     if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
109       CmdArgs.push_back(
110           Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
111     else
112       CmdArgs.push_back(
113           Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
114   }
115 
116   Args.AddAllArgs(CmdArgs,
117                   {options::OPT_L, options::OPT_T_Group, options::OPT_e});
118 
119   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
120 
121   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
122     CmdArgs.push_back("-L/usr/lib/gcc50");
123 
124     if (!Args.hasArg(options::OPT_static)) {
125       CmdArgs.push_back("-rpath");
126       CmdArgs.push_back("/usr/lib/gcc50");
127     }
128 
129     if (D.CCCIsCXX()) {
130       if (getToolChain().ShouldLinkCXXStdlib(Args))
131         getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
132       CmdArgs.push_back("-lm");
133     }
134 
135     if (Args.hasArg(options::OPT_pthread))
136       CmdArgs.push_back("-lpthread");
137 
138     if (!Args.hasArg(options::OPT_nolibc)) {
139       CmdArgs.push_back("-lc");
140     }
141 
142     if (Args.hasArg(options::OPT_static) ||
143         Args.hasArg(options::OPT_static_libgcc)) {
144         CmdArgs.push_back("-lgcc");
145         CmdArgs.push_back("-lgcc_eh");
146     } else {
147       if (Args.hasArg(options::OPT_shared_libgcc)) {
148           CmdArgs.push_back("-lgcc_pic");
149           if (!Args.hasArg(options::OPT_shared))
150             CmdArgs.push_back("-lgcc");
151       } else {
152           CmdArgs.push_back("-lgcc");
153           CmdArgs.push_back("--as-needed");
154           CmdArgs.push_back("-lgcc_pic");
155           CmdArgs.push_back("--no-as-needed");
156       }
157     }
158   }
159 
160   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
161     if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
162       CmdArgs.push_back(
163           Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
164     else
165       CmdArgs.push_back(
166           Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
167     CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
168   }
169 
170   getToolChain().addProfileRTLibs(Args, CmdArgs);
171 
172   const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
173   C.addCommand(std::make_unique<Command>(
174       JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
175 }
176 
177 /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
178 
179 DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,
180                      const ArgList &Args)
181     : Generic_ELF(D, Triple, Args) {
182 
183   // Path mangling to find libexec
184   getProgramPaths().push_back(getDriver().getInstalledDir());
185   if (getDriver().getInstalledDir() != getDriver().Dir)
186     getProgramPaths().push_back(getDriver().Dir);
187 
188   getFilePaths().push_back(getDriver().Dir + "/../lib");
189   getFilePaths().push_back("/usr/lib");
190   getFilePaths().push_back("/usr/lib/gcc50");
191 }
192 
193 Tool *DragonFly::buildAssembler() const {
194   return new tools::dragonfly::Assembler(*this);
195 }
196 
197 Tool *DragonFly::buildLinker() const {
198   return new tools::dragonfly::Linker(*this);
199 }
200