]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Driver/ToolChains/Hexagon.cpp
Merge clang trunk r300422 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Driver / ToolChains / Hexagon.cpp
1 //===--- Hexagon.cpp - Hexagon 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 "Hexagon.h"
11 #include "InputInfo.h"
12 #include "CommonArgs.h"
13 #include "clang/Basic/VirtualFileSystem.h"
14 #include "clang/Config/config.h"
15 #include "clang/Driver/Compilation.h"
16 #include "clang/Driver/Driver.h"
17 #include "clang/Driver/DriverDiagnostic.h"
18 #include "clang/Driver/Options.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/Option/ArgList.h"
21 #include "llvm/Support/FileSystem.h"
22 #include "llvm/Support/Path.h"
23
24 using namespace clang::driver;
25 using namespace clang::driver::tools;
26 using namespace clang::driver::toolchains;
27 using namespace clang;
28 using namespace llvm::opt;
29
30 // Hexagon tools start.
31 void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
32                                              ArgStringList &CmdArgs) const {
33 }
34
35 void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
36                                       const InputInfo &Output,
37                                       const InputInfoList &Inputs,
38                                       const ArgList &Args,
39                                       const char *LinkingOutput) const {
40   claimNoWarnArgs(Args);
41
42   auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
43   const Driver &D = HTC.getDriver();
44   ArgStringList CmdArgs;
45
46   std::string MArchString = "-march=hexagon";
47   CmdArgs.push_back(Args.MakeArgString(MArchString));
48
49   RenderExtraToolArgs(JA, CmdArgs);
50
51   std::string AsName = "hexagon-llvm-mc";
52   std::string MCpuString = "-mcpu=hexagon" +
53         toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
54   CmdArgs.push_back("-filetype=obj");
55   CmdArgs.push_back(Args.MakeArgString(MCpuString));
56
57   if (Output.isFilename()) {
58     CmdArgs.push_back("-o");
59     CmdArgs.push_back(Output.getFilename());
60   } else {
61     assert(Output.isNothing() && "Unexpected output");
62     CmdArgs.push_back("-fsyntax-only");
63   }
64
65   if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
66     std::string N = llvm::utostr(G.getValue());
67     CmdArgs.push_back(Args.MakeArgString(std::string("-gpsize=") + N));
68   }
69
70   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
71
72   // Only pass -x if gcc will understand it; otherwise hope gcc
73   // understands the suffix correctly. The main use case this would go
74   // wrong in is for linker inputs if they happened to have an odd
75   // suffix; really the only way to get this to happen is a command
76   // like '-x foobar a.c' which will treat a.c like a linker input.
77   //
78   // FIXME: For the linker case specifically, can we safely convert
79   // inputs into '-Wl,' options?
80   for (const auto &II : Inputs) {
81     // Don't try to pass LLVM or AST inputs to a generic gcc.
82     if (types::isLLVMIR(II.getType()))
83       D.Diag(clang::diag::err_drv_no_linker_llvm_support)
84           << HTC.getTripleString();
85     else if (II.getType() == types::TY_AST)
86       D.Diag(clang::diag::err_drv_no_ast_support)
87           << HTC.getTripleString();
88     else if (II.getType() == types::TY_ModuleFile)
89       D.Diag(diag::err_drv_no_module_support)
90           << HTC.getTripleString();
91
92     if (II.isFilename())
93       CmdArgs.push_back(II.getFilename());
94     else
95       // Don't render as input, we need gcc to do the translations.
96       // FIXME: What is this?
97       II.getInputArg().render(Args, CmdArgs);
98   }
99
100   auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName.c_str()));
101   C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
102 }
103
104 void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
105                                           ArgStringList &CmdArgs) const {
106 }
107
108 static void
109 constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
110                          const toolchains::HexagonToolChain &HTC,
111                          const InputInfo &Output, const InputInfoList &Inputs,
112                          const ArgList &Args, ArgStringList &CmdArgs,
113                          const char *LinkingOutput) {
114
115   const Driver &D = HTC.getDriver();
116
117   //----------------------------------------------------------------------------
118   //
119   //----------------------------------------------------------------------------
120   bool IsStatic = Args.hasArg(options::OPT_static);
121   bool IsShared = Args.hasArg(options::OPT_shared);
122   bool IsPIE = Args.hasArg(options::OPT_pie);
123   bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
124   bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
125   bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
126   bool UseG0 = false;
127   bool UseShared = IsShared && !IsStatic;
128
129   //----------------------------------------------------------------------------
130   // Silence warnings for various options
131   //----------------------------------------------------------------------------
132   Args.ClaimAllArgs(options::OPT_g_Group);
133   Args.ClaimAllArgs(options::OPT_emit_llvm);
134   Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
135                                      // handled somewhere else.
136   Args.ClaimAllArgs(options::OPT_static_libgcc);
137
138   //----------------------------------------------------------------------------
139   //
140   //----------------------------------------------------------------------------
141   if (Args.hasArg(options::OPT_s))
142     CmdArgs.push_back("-s");
143
144   if (Args.hasArg(options::OPT_r))
145     CmdArgs.push_back("-r");
146
147   for (const auto &Opt : HTC.ExtraOpts)
148     CmdArgs.push_back(Opt.c_str());
149
150   CmdArgs.push_back("-march=hexagon");
151   std::string CpuVer =
152         toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
153   std::string MCpuString = "-mcpu=hexagon" + CpuVer;
154   CmdArgs.push_back(Args.MakeArgString(MCpuString));
155
156   if (IsShared) {
157     CmdArgs.push_back("-shared");
158     // The following should be the default, but doing as hexagon-gcc does.
159     CmdArgs.push_back("-call_shared");
160   }
161
162   if (IsStatic)
163     CmdArgs.push_back("-static");
164
165   if (IsPIE && !IsShared)
166     CmdArgs.push_back("-pie");
167
168   if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
169     std::string N = llvm::utostr(G.getValue());
170     CmdArgs.push_back(Args.MakeArgString(std::string("-G") + N));
171     UseG0 = G.getValue() == 0;
172   }
173
174   //----------------------------------------------------------------------------
175   //
176   //----------------------------------------------------------------------------
177   CmdArgs.push_back("-o");
178   CmdArgs.push_back(Output.getFilename());
179
180   //----------------------------------------------------------------------------
181   // moslib
182   //----------------------------------------------------------------------------
183   std::vector<std::string> OsLibs;
184   bool HasStandalone = false;
185
186   for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
187     A->claim();
188     OsLibs.emplace_back(A->getValue());
189     HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
190   }
191   if (OsLibs.empty()) {
192     OsLibs.push_back("standalone");
193     HasStandalone = true;
194   }
195
196   //----------------------------------------------------------------------------
197   // Start Files
198   //----------------------------------------------------------------------------
199   const std::string MCpuSuffix = "/" + CpuVer;
200   const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
201   const std::string RootDir =
202       HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
203   const std::string StartSubDir =
204       "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);
205
206   auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
207                       const char *Name) -> std::string {
208     std::string RelName = SubDir + Name;
209     std::string P = HTC.GetFilePath(RelName.c_str());
210     if (llvm::sys::fs::exists(P))
211       return P;
212     return RootDir + RelName;
213   };
214
215   if (IncStdLib && IncStartFiles) {
216     if (!IsShared) {
217       if (HasStandalone) {
218         std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
219         CmdArgs.push_back(Args.MakeArgString(Crt0SA));
220       }
221       std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
222       CmdArgs.push_back(Args.MakeArgString(Crt0));
223     }
224     std::string Init = UseShared
225           ? Find(RootDir, StartSubDir + "/pic", "/initS.o")
226           : Find(RootDir, StartSubDir, "/init.o");
227     CmdArgs.push_back(Args.MakeArgString(Init));
228   }
229
230   //----------------------------------------------------------------------------
231   // Library Search Paths
232   //----------------------------------------------------------------------------
233   const ToolChain::path_list &LibPaths = HTC.getFilePaths();
234   for (const auto &LibPath : LibPaths)
235     CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
236
237   //----------------------------------------------------------------------------
238   //
239   //----------------------------------------------------------------------------
240   Args.AddAllArgs(CmdArgs,
241                   {options::OPT_T_Group, options::OPT_e, options::OPT_s,
242                    options::OPT_t, options::OPT_u_Group});
243
244   AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
245
246   //----------------------------------------------------------------------------
247   // Libraries
248   //----------------------------------------------------------------------------
249   if (IncStdLib && IncDefLibs) {
250     if (D.CCCIsCXX()) {
251       HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
252       CmdArgs.push_back("-lm");
253     }
254
255     CmdArgs.push_back("--start-group");
256
257     if (!IsShared) {
258       for (const std::string &Lib : OsLibs)
259         CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
260       CmdArgs.push_back("-lc");
261     }
262     CmdArgs.push_back("-lgcc");
263
264     CmdArgs.push_back("--end-group");
265   }
266
267   //----------------------------------------------------------------------------
268   // End files
269   //----------------------------------------------------------------------------
270   if (IncStdLib && IncStartFiles) {
271     std::string Fini = UseShared
272           ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")
273           : Find(RootDir, StartSubDir, "/fini.o");
274     CmdArgs.push_back(Args.MakeArgString(Fini));
275   }
276 }
277
278 void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
279                                    const InputInfo &Output,
280                                    const InputInfoList &Inputs,
281                                    const ArgList &Args,
282                                    const char *LinkingOutput) const {
283   auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
284
285   ArgStringList CmdArgs;
286   constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
287                            LinkingOutput);
288
289   std::string Linker = HTC.GetProgramPath("hexagon-link");
290   C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
291                                           CmdArgs, Inputs));
292 }
293 // Hexagon tools end.
294
295 /// Hexagon Toolchain
296
297 std::string HexagonToolChain::getHexagonTargetDir(
298       const std::string &InstalledDir,
299       const SmallVectorImpl<std::string> &PrefixDirs) const {
300   std::string InstallRelDir;
301   const Driver &D = getDriver();
302
303   // Locate the rest of the toolchain ...
304   for (auto &I : PrefixDirs)
305     if (D.getVFS().exists(I))
306       return I;
307
308   if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
309     return InstallRelDir;
310
311   return InstalledDir;
312 }
313
314 Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
315       const ArgList &Args) {
316   StringRef Gn = "";
317   if (Arg *A = Args.getLastArg(options::OPT_G)) {
318     Gn = A->getValue();
319   } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
320                              options::OPT_fPIC)) {
321     Gn = "0";
322   }
323
324   unsigned G;
325   if (!Gn.getAsInteger(10, G))
326     return G;
327
328   return None;
329 }
330
331 void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
332       ToolChain::path_list &LibPaths) const {
333   const Driver &D = getDriver();
334
335   //----------------------------------------------------------------------------
336   // -L Args
337   //----------------------------------------------------------------------------
338   for (Arg *A : Args.filtered(options::OPT_L))
339     for (const char *Value : A->getValues())
340       LibPaths.push_back(Value);
341
342   //----------------------------------------------------------------------------
343   // Other standard paths
344   //----------------------------------------------------------------------------
345   std::vector<std::string> RootDirs;
346   std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
347             std::back_inserter(RootDirs));
348
349   std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
350                                               D.PrefixDirs);
351   if (std::find(RootDirs.begin(), RootDirs.end(), TargetDir) == RootDirs.end())
352     RootDirs.push_back(TargetDir);
353
354   bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);
355   // Assume G0 with -shared.
356   bool HasG0 = Args.hasArg(options::OPT_shared);
357   if (auto G = getSmallDataThreshold(Args))
358     HasG0 = G.getValue() == 0;
359
360   const std::string CpuVer = GetTargetCPUVersion(Args).str();
361   for (auto &Dir : RootDirs) {
362     std::string LibDir = Dir + "/hexagon/lib";
363     std::string LibDirCpu = LibDir + '/' + CpuVer;
364     if (HasG0) {
365       if (HasPIC)
366         LibPaths.push_back(LibDirCpu + "/G0/pic");
367       LibPaths.push_back(LibDirCpu + "/G0");
368     }
369     LibPaths.push_back(LibDirCpu);
370     LibPaths.push_back(LibDir);
371   }
372 }
373
374 HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
375                                    const llvm::opt::ArgList &Args)
376     : Linux(D, Triple, Args) {
377   const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
378                                                     D.PrefixDirs);
379
380   // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
381   // program paths
382   const std::string BinDir(TargetDir + "/bin");
383   if (D.getVFS().exists(BinDir))
384     getProgramPaths().push_back(BinDir);
385
386   ToolChain::path_list &LibPaths = getFilePaths();
387
388   // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
389   // 'elf' OS type, so the Linux paths are not appropriate. When we actually
390   // support 'linux' we'll need to fix this up
391   LibPaths.clear();
392   getHexagonLibraryPaths(Args, LibPaths);
393 }
394
395 HexagonToolChain::~HexagonToolChain() {}
396
397 Tool *HexagonToolChain::buildAssembler() const {
398   return new tools::hexagon::Assembler(*this);
399 }
400
401 Tool *HexagonToolChain::buildLinker() const {
402   return new tools::hexagon::Linker(*this);
403 }
404
405 void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
406                                                  ArgStringList &CC1Args) const {
407   if (DriverArgs.hasArg(options::OPT_nostdinc) ||
408       DriverArgs.hasArg(options::OPT_nostdlibinc))
409     return;
410
411   const Driver &D = getDriver();
412   std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
413                                               D.PrefixDirs);
414   addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
415 }
416
417
418 void HexagonToolChain::addLibStdCxxIncludePaths(
419     const llvm::opt::ArgList &DriverArgs,
420     llvm::opt::ArgStringList &CC1Args) const {
421   const Driver &D = getDriver();
422   std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
423   addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++", "", "", "", "",
424                            DriverArgs, CC1Args);
425 }
426
427 ToolChain::CXXStdlibType
428 HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
429   Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
430   if (!A)
431     return ToolChain::CST_Libstdcxx;
432
433   StringRef Value = A->getValue();
434   if (Value != "libstdc++")
435     getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
436
437   return ToolChain::CST_Libstdcxx;
438 }
439
440 //
441 // Returns the default CPU for Hexagon. This is the default compilation target
442 // if no Hexagon processor is selected at the command-line.
443 //
444 const StringRef HexagonToolChain::GetDefaultCPU() {
445   return "hexagonv60";
446 }
447
448 const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
449   Arg *CpuArg = nullptr;
450   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ, options::OPT_march_EQ))
451     CpuArg = A;
452
453   StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
454   if (CPU.startswith("hexagon"))
455     return CPU.substr(sizeof("hexagon") - 1);
456   return CPU;
457 }