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
16using namespace clang::driver;
17using namespace clang::driver::tools;
18using namespace clang::driver::toolchains;
19using namespace clang;
20using 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.
26void 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
53void 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 if (!Args.hasArg(options::OPT_r)) {
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
184DragonFly::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
198Tool *DragonFly::buildAssembler() const {
199  return new tools::dragonfly::Assembler(*this);
200}
201
202Tool *DragonFly::buildLinker() const {
203  return new tools::dragonfly::Linker(*this);
204}
205