clang  6.0.0svn
NetBSD.cpp
Go to the documentation of this file.
1 //===--- NetBSD.cpp - NetBSD ToolChain Implementations ----------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "NetBSD.h"
11 #include "Arch/ARM.h"
12 #include "Arch/Mips.h"
13 #include "Arch/Sparc.h"
14 #include "CommonArgs.h"
16 #include "clang/Driver/Driver.h"
17 #include "clang/Driver/Options.h"
19 #include "llvm/Option/ArgList.h"
20 
21 using namespace clang::driver;
22 using namespace clang::driver::tools;
23 using namespace clang::driver::toolchains;
24 using namespace clang;
25 using namespace llvm::opt;
26 
28  const InputInfo &Output,
29  const InputInfoList &Inputs,
30  const ArgList &Args,
31  const char *LinkingOutput) const {
32  claimNoWarnArgs(Args);
33  ArgStringList CmdArgs;
34 
35  // GNU as needs different flags for creating the correct output format
36  // on architectures with different ABIs or optional feature sets.
37  switch (getToolChain().getArch()) {
38  case llvm::Triple::x86:
39  CmdArgs.push_back("--32");
40  break;
41  case llvm::Triple::arm:
42  case llvm::Triple::armeb:
43  case llvm::Triple::thumb:
44  case llvm::Triple::thumbeb: {
45  StringRef MArch, MCPU;
46  arm::getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true);
47  std::string Arch =
48  arm::getARMTargetCPU(MCPU, MArch, getToolChain().getTriple());
49  CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch));
50  break;
51  }
52 
53  case llvm::Triple::mips:
54  case llvm::Triple::mipsel:
55  case llvm::Triple::mips64:
56  case llvm::Triple::mips64el: {
57  StringRef CPUName;
58  StringRef ABIName;
59  mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
60 
61  CmdArgs.push_back("-march");
62  CmdArgs.push_back(CPUName.data());
63 
64  CmdArgs.push_back("-mabi");
65  CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
66 
67  if (getToolChain().getArch() == llvm::Triple::mips ||
68  getToolChain().getArch() == llvm::Triple::mips64)
69  CmdArgs.push_back("-EB");
70  else
71  CmdArgs.push_back("-EL");
72 
73  AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
74  break;
75  }
76 
77  case llvm::Triple::sparc:
78  case llvm::Triple::sparcel: {
79  CmdArgs.push_back("-32");
80  std::string CPU = getCPUName(Args, getToolChain().getTriple());
81  CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
82  AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
83  break;
84  }
85 
86  case llvm::Triple::sparcv9: {
87  CmdArgs.push_back("-64");
88  std::string CPU = getCPUName(Args, getToolChain().getTriple());
89  CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
90  AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
91  break;
92  }
93 
94  default:
95  break;
96  }
97 
98  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
99 
100  CmdArgs.push_back("-o");
101  CmdArgs.push_back(Output.getFilename());
102 
103  for (const auto &II : Inputs)
104  CmdArgs.push_back(II.getFilename());
105 
106  const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as")));
107  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
108 }
109 
111  const InputInfo &Output,
112  const InputInfoList &Inputs,
113  const ArgList &Args,
114  const char *LinkingOutput) const {
115  const Driver &D = getToolChain().getDriver();
116  ArgStringList CmdArgs;
117 
118  if (!D.SysRoot.empty())
119  CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
120 
121  CmdArgs.push_back("--eh-frame-hdr");
122  if (Args.hasArg(options::OPT_static)) {
123  CmdArgs.push_back("-Bstatic");
124  } else {
125  if (Args.hasArg(options::OPT_rdynamic))
126  CmdArgs.push_back("-export-dynamic");
127  if (Args.hasArg(options::OPT_shared)) {
128  CmdArgs.push_back("-Bshareable");
129  } else {
130  Args.AddAllArgs(CmdArgs, options::OPT_pie);
131  CmdArgs.push_back("-dynamic-linker");
132  CmdArgs.push_back("/libexec/ld.elf_so");
133  }
134  }
135 
136  // Many NetBSD architectures support more than one ABI.
137  // Determine the correct emulation for ld.
138  switch (getToolChain().getArch()) {
139  case llvm::Triple::x86:
140  CmdArgs.push_back("-m");
141  CmdArgs.push_back("elf_i386");
142  break;
143  case llvm::Triple::arm:
144  case llvm::Triple::thumb:
145  CmdArgs.push_back("-m");
146  switch (getToolChain().getTriple().getEnvironment()) {
147  case llvm::Triple::EABI:
148  case llvm::Triple::GNUEABI:
149  CmdArgs.push_back("armelf_nbsd_eabi");
150  break;
151  case llvm::Triple::EABIHF:
152  case llvm::Triple::GNUEABIHF:
153  CmdArgs.push_back("armelf_nbsd_eabihf");
154  break;
155  default:
156  CmdArgs.push_back("armelf_nbsd");
157  break;
158  }
159  break;
160  case llvm::Triple::armeb:
161  case llvm::Triple::thumbeb:
162  arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getEffectiveTriple());
163  CmdArgs.push_back("-m");
164  switch (getToolChain().getTriple().getEnvironment()) {
165  case llvm::Triple::EABI:
166  case llvm::Triple::GNUEABI:
167  CmdArgs.push_back("armelfb_nbsd_eabi");
168  break;
169  case llvm::Triple::EABIHF:
170  case llvm::Triple::GNUEABIHF:
171  CmdArgs.push_back("armelfb_nbsd_eabihf");
172  break;
173  default:
174  CmdArgs.push_back("armelfb_nbsd");
175  break;
176  }
177  break;
178  case llvm::Triple::mips64:
179  case llvm::Triple::mips64el:
180  if (mips::hasMipsAbiArg(Args, "32")) {
181  CmdArgs.push_back("-m");
182  if (getToolChain().getArch() == llvm::Triple::mips64)
183  CmdArgs.push_back("elf32btsmip");
184  else
185  CmdArgs.push_back("elf32ltsmip");
186  } else if (mips::hasMipsAbiArg(Args, "64")) {
187  CmdArgs.push_back("-m");
188  if (getToolChain().getArch() == llvm::Triple::mips64)
189  CmdArgs.push_back("elf64btsmip");
190  else
191  CmdArgs.push_back("elf64ltsmip");
192  }
193  break;
194  case llvm::Triple::ppc:
195  CmdArgs.push_back("-m");
196  CmdArgs.push_back("elf32ppc_nbsd");
197  break;
198 
199  case llvm::Triple::ppc64:
200  case llvm::Triple::ppc64le:
201  CmdArgs.push_back("-m");
202  CmdArgs.push_back("elf64ppc");
203  break;
204 
205  case llvm::Triple::sparc:
206  CmdArgs.push_back("-m");
207  CmdArgs.push_back("elf32_sparc");
208  break;
209 
210  case llvm::Triple::sparcv9:
211  CmdArgs.push_back("-m");
212  CmdArgs.push_back("elf64_sparc");
213  break;
214 
215  default:
216  break;
217  }
218 
219  if (Output.isFilename()) {
220  CmdArgs.push_back("-o");
221  CmdArgs.push_back(Output.getFilename());
222  } else {
223  assert(Output.isNothing() && "Invalid output.");
224  }
225 
226  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
227  if (!Args.hasArg(options::OPT_shared)) {
228  CmdArgs.push_back(
229  Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
230  }
231  CmdArgs.push_back(
232  Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
233  if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) {
234  CmdArgs.push_back(
235  Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
236  } else {
237  CmdArgs.push_back(
238  Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
239  }
240  }
241 
242  Args.AddAllArgs(CmdArgs, options::OPT_L);
243  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
244  Args.AddAllArgs(CmdArgs, options::OPT_e);
245  Args.AddAllArgs(CmdArgs, options::OPT_s);
246  Args.AddAllArgs(CmdArgs, options::OPT_t);
247  Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
248  Args.AddAllArgs(CmdArgs, options::OPT_r);
249 
250  bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
251  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
252 
253  unsigned Major, Minor, Micro;
254  getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
255  bool useLibgcc = true;
256  if (Major >= 7 || Major == 0) {
257  switch (getToolChain().getArch()) {
258  case llvm::Triple::aarch64:
259  case llvm::Triple::aarch64_be:
260  case llvm::Triple::arm:
261  case llvm::Triple::armeb:
262  case llvm::Triple::thumb:
263  case llvm::Triple::thumbeb:
264  case llvm::Triple::ppc:
265  case llvm::Triple::ppc64:
266  case llvm::Triple::ppc64le:
267  case llvm::Triple::sparc:
268  case llvm::Triple::sparcv9:
269  case llvm::Triple::x86:
270  case llvm::Triple::x86_64:
271  useLibgcc = false;
272  break;
273  default:
274  break;
275  }
276  }
277 
278  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
279  addOpenMPRuntime(CmdArgs, getToolChain(), Args);
280  if (D.CCCIsCXX()) {
281  if (getToolChain().ShouldLinkCXXStdlib(Args))
282  getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
283  CmdArgs.push_back("-lm");
284  }
285  if (NeedsSanitizerDeps)
286  linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
287  if (Args.hasArg(options::OPT_pthread))
288  CmdArgs.push_back("-lpthread");
289  CmdArgs.push_back("-lc");
290 
291  if (useLibgcc) {
292  if (Args.hasArg(options::OPT_static)) {
293  // libgcc_eh depends on libc, so resolve as much as possible,
294  // pull in any new requirements from libc and then get the rest
295  // of libgcc.
296  CmdArgs.push_back("-lgcc_eh");
297  CmdArgs.push_back("-lc");
298  CmdArgs.push_back("-lgcc");
299  } else {
300  CmdArgs.push_back("-lgcc");
301  CmdArgs.push_back("--as-needed");
302  CmdArgs.push_back("-lgcc_s");
303  CmdArgs.push_back("--no-as-needed");
304  }
305  }
306  }
307 
308  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
309  if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
310  CmdArgs.push_back(
311  Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
312  else
313  CmdArgs.push_back(
314  Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
315  CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
316  }
317 
318  getToolChain().addProfileRTLibs(Args, CmdArgs);
319 
320  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
321  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
322 }
323 
324 /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
325 
326 NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
327  : Generic_ELF(D, Triple, Args) {
328  if (!Args.hasArg(options::OPT_nostdlib)) {
329  // When targeting a 32-bit platform, try the special directory used on
330  // 64-bit hosts, and only fall back to the main library directory if that
331  // doesn't work.
332  // FIXME: It'd be nicer to test if this directory exists, but I'm not sure
333  // what all logic is needed to emulate the '=' prefix here.
334  switch (Triple.getArch()) {
335  case llvm::Triple::x86:
336  getFilePaths().push_back("=/usr/lib/i386");
337  break;
338  case llvm::Triple::arm:
339  case llvm::Triple::armeb:
340  case llvm::Triple::thumb:
341  case llvm::Triple::thumbeb:
342  switch (Triple.getEnvironment()) {
343  case llvm::Triple::EABI:
344  case llvm::Triple::GNUEABI:
345  getFilePaths().push_back("=/usr/lib/eabi");
346  break;
347  case llvm::Triple::EABIHF:
348  case llvm::Triple::GNUEABIHF:
349  getFilePaths().push_back("=/usr/lib/eabihf");
350  break;
351  default:
352  getFilePaths().push_back("=/usr/lib/oabi");
353  break;
354  }
355  break;
356  case llvm::Triple::mips64:
357  case llvm::Triple::mips64el:
358  if (tools::mips::hasMipsAbiArg(Args, "o32"))
359  getFilePaths().push_back("=/usr/lib/o32");
360  else if (tools::mips::hasMipsAbiArg(Args, "64"))
361  getFilePaths().push_back("=/usr/lib/64");
362  break;
363  case llvm::Triple::ppc:
364  getFilePaths().push_back("=/usr/lib/powerpc");
365  break;
366  case llvm::Triple::sparc:
367  getFilePaths().push_back("=/usr/lib/sparc");
368  break;
369  default:
370  break;
371  }
372 
373  getFilePaths().push_back("=/usr/lib");
374  }
375 }
376 
378  return new tools::netbsd::Assembler(*this);
379 }
380 
381 Tool *NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); }
382 
384  unsigned Major, Minor, Micro;
385  getTriple().getOSVersion(Major, Minor, Micro);
386  if (Major >= 7 || Major == 0) {
387  switch (getArch()) {
388  case llvm::Triple::aarch64:
389  case llvm::Triple::aarch64_be:
390  case llvm::Triple::arm:
391  case llvm::Triple::armeb:
392  case llvm::Triple::thumb:
393  case llvm::Triple::thumbeb:
394  case llvm::Triple::ppc:
395  case llvm::Triple::ppc64:
396  case llvm::Triple::ppc64le:
397  case llvm::Triple::sparc:
398  case llvm::Triple::sparcv9:
399  case llvm::Triple::x86:
400  case llvm::Triple::x86_64:
401  return ToolChain::CST_Libcxx;
402  default:
403  break;
404  }
405  }
407 }
408 
409 std::string NetBSD::findLibCxxIncludePath() const {
410  return getDriver().SysRoot + "/usr/include/c++/";
411 }
412 
413 void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
414  llvm::opt::ArgStringList &CC1Args) const {
415  addLibStdCXXIncludePaths(getDriver().SysRoot, "/usr/include/g++", "", "", "",
416  "", DriverArgs, CC1Args);
417 }
418 
419 llvm::ExceptionHandling NetBSD::GetExceptionModel(const ArgList &Args) const {
420  // NetBSD uses Dwarf exceptions on ARM.
421  llvm::Triple::ArchType TArch = getTriple().getArch();
422  if (TArch == llvm::Triple::arm || TArch == llvm::Triple::armeb ||
423  TArch == llvm::Triple::thumb || TArch == llvm::Triple::thumbeb)
424  return llvm::ExceptionHandling::DwarfCFI;
426 }
427 
429  const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
430  const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
432  if (IsX86 || IsX86_64) {
433  Res |= SanitizerKind::Address;
434  Res |= SanitizerKind::Function;
435  Res |= SanitizerKind::Leak;
436  Res |= SanitizerKind::SafeStack;
437  Res |= SanitizerKind::Scudo;
438  Res |= SanitizerKind::Vptr;
439  }
440  if (IsX86_64) {
441  Res |= SanitizerKind::Efficiency;
442  Res |= SanitizerKind::Fuzzer;
443  Res |= SanitizerKind::FuzzerNoLink;
444  Res |= SanitizerKind::KernelAddress;
445  Res |= SanitizerKind::Memory;
446  Res |= SanitizerKind::Thread;
447  }
448  return Res;
449 }
const char * getSparcAsmModeForCPU(llvm::StringRef Name, const llvm::Triple &Triple)
std::string getCPUName(const llvm::opt::ArgList &Args, const llvm::Triple &T, bool FromAs=false)
const char * getFilename() const
Definition: InputInfo.h:84
void linkSanitizerRuntimeDeps(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs)
Tool * buildAssembler() const override
Definition: NetBSD.cpp:377
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs...
Definition: NetBSD.cpp:27
bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs)
InputInfo - Wrapper for information about an input source.
Definition: InputInfo.h:23
path_list & getFilePaths()
Definition: ToolChain.h:202
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:65
bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value)
CXXStdlibType GetDefaultCXXStdlibType() const override
Definition: NetBSD.cpp:383
bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC, const llvm::opt::ArgList &Args, bool IsOffloadingHost=false, bool GompNeedsRT=false)
Returns true, if an OpenMP runtime has been added.
Tool * buildLinker() const override
Definition: NetBSD.cpp:381
SanitizerMask getSupportedSanitizers() const override
Return sanitizers which are available in this toolchain.
Definition: NetBSD.cpp:428
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs...
Definition: NetBSD.cpp:110
void addCommand(std::unique_ptr< Command > C)
Definition: Compilation.h:189
void AddAssemblerKPIC(const ToolChain &ToolChain, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs)
llvm::Triple::ArchType getArch() const
Definition: ToolChain.h:183
const Driver & getDriver() const
Definition: ToolChain.h:167
bool CCCIsCXX() const
Whether the driver should follow g++ like behavior.
Definition: Driver.h:174
void addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override
Definition: NetBSD.cpp:413
llvm::ExceptionHandling GetExceptionModel(const llvm::opt::ArgList &Args) const override
GetExceptionModel - Return the tool chain exception model.
Definition: NetBSD.cpp:419
void appendEBLinkFlags(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const llvm::Triple &Triple)
std::string getARMTargetCPU(StringRef CPU, llvm::StringRef Arch, const llvm::Triple &Triple)
Dataflow Directional Tag Classes.
uint64_t SanitizerMask
Definition: Sanitizers.h:24
void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const JobAction &JA)
std::string SysRoot
sysroot, if present
Definition: Driver.h:149
Tool - Information on a specific compilation tool.
Definition: Tool.h:34
void getARMArchCPUFromArgs(const llvm::opt::ArgList &Args, llvm::StringRef &Arch, llvm::StringRef &CPU, bool FromAs=false)
std::string findLibCxxIncludePath() const override
Definition: NetBSD.cpp:409
void claimNoWarnArgs(const llvm::opt::ArgList &Args)
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:34
const llvm::Triple & getTriple() const
Definition: ToolChain.h:169
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:776
StringRef getGnuCompatibleMipsABIName(StringRef ABI)
Definition: Mips.cpp:138
bool isNothing() const
Definition: InputInfo.h:75
bool isFilename() const
Definition: InputInfo.h:76
bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple, StringRef GCCMultiarchTriple, StringRef TargetMultiarchTriple, Twine IncludeSuffix, const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const
Helper to add the variant paths of a libstdc++ installation.
Definition: Gnu.cpp:2294
void getMipsCPUAndABI(const llvm::opt::ArgList &Args, const llvm::Triple &Triple, StringRef &CPUName, StringRef &ABIName)