Gnu.h revision 363496
1//===--- Gnu.h - Gnu Tool and 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#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
10#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
11
12#include "Cuda.h"
13#include "clang/Driver/Tool.h"
14#include "clang/Driver/ToolChain.h"
15#include <set>
16
17namespace clang {
18namespace driver {
19
20struct DetectedMultilibs {
21  /// The set of multilibs that the detected installation supports.
22  MultilibSet Multilibs;
23
24  /// The primary multilib appropriate for the given flags.
25  Multilib SelectedMultilib;
26
27  /// On Biarch systems, this corresponds to the default multilib when
28  /// targeting the non-default multilib. Otherwise, it is empty.
29  llvm::Optional<Multilib> BiarchSibling;
30};
31
32bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
33                       StringRef Path, const llvm::opt::ArgList &Args,
34                       DetectedMultilibs &Result);
35
36namespace tools {
37
38/// Base class for all GNU tools that provide the same behavior when
39/// it comes to response files support
40class LLVM_LIBRARY_VISIBILITY GnuTool : public Tool {
41  virtual void anchor();
42
43public:
44  GnuTool(const char *Name, const char *ShortName, const ToolChain &TC)
45      : Tool(Name, ShortName, TC, RF_Full, llvm::sys::WEM_CurrentCodePage) {}
46};
47
48/// Directly call GNU Binutils' assembler and linker.
49namespace gnutools {
50class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
51public:
52  Assembler(const ToolChain &TC) : GnuTool("GNU::Assembler", "assembler", TC) {}
53
54  bool hasIntegratedCPP() const override { return false; }
55
56  void ConstructJob(Compilation &C, const JobAction &JA,
57                    const InputInfo &Output, const InputInfoList &Inputs,
58                    const llvm::opt::ArgList &TCArgs,
59                    const char *LinkingOutput) const override;
60};
61
62class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
63public:
64  Linker(const ToolChain &TC) : GnuTool("GNU::Linker", "linker", TC) {}
65
66  bool hasIntegratedCPP() const override { return false; }
67  bool isLinkJob() const override { return true; }
68
69  void ConstructJob(Compilation &C, const JobAction &JA,
70                    const InputInfo &Output, const InputInfoList &Inputs,
71                    const llvm::opt::ArgList &TCArgs,
72                    const char *LinkingOutput) const override;
73};
74} // end namespace gnutools
75
76/// gcc - Generic GCC tool implementations.
77namespace gcc {
78class LLVM_LIBRARY_VISIBILITY Common : public GnuTool {
79public:
80  Common(const char *Name, const char *ShortName, const ToolChain &TC)
81      : GnuTool(Name, ShortName, TC) {}
82
83  // A gcc tool has an "integrated" assembler that it will call to produce an
84  // object. Let it use that assembler so that we don't have to deal with
85  // assembly syntax incompatibilities.
86  bool hasIntegratedAssembler() const override { return true; }
87  void ConstructJob(Compilation &C, const JobAction &JA,
88                    const InputInfo &Output, const InputInfoList &Inputs,
89                    const llvm::opt::ArgList &TCArgs,
90                    const char *LinkingOutput) const override;
91
92  /// RenderExtraToolArgs - Render any arguments necessary to force
93  /// the particular tool mode.
94  virtual void RenderExtraToolArgs(const JobAction &JA,
95                                   llvm::opt::ArgStringList &CmdArgs) const = 0;
96};
97
98class LLVM_LIBRARY_VISIBILITY Preprocessor : public Common {
99public:
100  Preprocessor(const ToolChain &TC)
101      : Common("gcc::Preprocessor", "gcc preprocessor", TC) {}
102
103  bool hasGoodDiagnostics() const override { return true; }
104  bool hasIntegratedCPP() const override { return false; }
105
106  void RenderExtraToolArgs(const JobAction &JA,
107                           llvm::opt::ArgStringList &CmdArgs) const override;
108};
109
110class LLVM_LIBRARY_VISIBILITY Compiler : public Common {
111public:
112  Compiler(const ToolChain &TC) : Common("gcc::Compiler", "gcc frontend", TC) {}
113
114  bool hasGoodDiagnostics() const override { return true; }
115  bool hasIntegratedCPP() const override { return true; }
116
117  void RenderExtraToolArgs(const JobAction &JA,
118                           llvm::opt::ArgStringList &CmdArgs) const override;
119};
120
121class LLVM_LIBRARY_VISIBILITY Linker : public Common {
122public:
123  Linker(const ToolChain &TC) : Common("gcc::Linker", "linker (via gcc)", TC) {}
124
125  bool hasIntegratedCPP() const override { return false; }
126  bool isLinkJob() const override { return true; }
127
128  void RenderExtraToolArgs(const JobAction &JA,
129                           llvm::opt::ArgStringList &CmdArgs) const override;
130};
131} // end namespace gcc
132} // end namespace tools
133
134namespace toolchains {
135
136/// Generic_GCC - A tool chain using the 'gcc' command to perform
137/// all subcommands; this relies on gcc translating the majority of
138/// command line options.
139class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain {
140public:
141  /// Struct to store and manipulate GCC versions.
142  ///
143  /// We rely on assumptions about the form and structure of GCC version
144  /// numbers: they consist of at most three '.'-separated components, and each
145  /// component is a non-negative integer except for the last component. For
146  /// the last component we are very flexible in order to tolerate release
147  /// candidates or 'x' wildcards.
148  ///
149  /// Note that the ordering established among GCCVersions is based on the
150  /// preferred version string to use. For example we prefer versions without
151  /// a hard-coded patch number to those with a hard coded patch number.
152  ///
153  /// Currently this doesn't provide any logic for textual suffixes to patches
154  /// in the way that (for example) Debian's version format does. If that ever
155  /// becomes necessary, it can be added.
156  struct GCCVersion {
157    /// The unparsed text of the version.
158    std::string Text;
159
160    /// The parsed major, minor, and patch numbers.
161    int Major, Minor, Patch;
162
163    /// The text of the parsed major, and major+minor versions.
164    std::string MajorStr, MinorStr;
165
166    /// Any textual suffix on the patch number.
167    std::string PatchSuffix;
168
169    static GCCVersion Parse(StringRef VersionText);
170    bool isOlderThan(int RHSMajor, int RHSMinor, int RHSPatch,
171                     StringRef RHSPatchSuffix = StringRef()) const;
172    bool operator<(const GCCVersion &RHS) const {
173      return isOlderThan(RHS.Major, RHS.Minor, RHS.Patch, RHS.PatchSuffix);
174    }
175    bool operator>(const GCCVersion &RHS) const { return RHS < *this; }
176    bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); }
177    bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
178  };
179
180  /// This is a class to find a viable GCC installation for Clang to
181  /// use.
182  ///
183  /// This class tries to find a GCC installation on the system, and report
184  /// information about it. It starts from the host information provided to the
185  /// Driver, and has logic for fuzzing that where appropriate.
186  class GCCInstallationDetector {
187    bool IsValid;
188    llvm::Triple GCCTriple;
189    const Driver &D;
190
191    // FIXME: These might be better as path objects.
192    std::string GCCInstallPath;
193    std::string GCCParentLibPath;
194
195    /// The primary multilib appropriate for the given flags.
196    Multilib SelectedMultilib;
197    /// On Biarch systems, this corresponds to the default multilib when
198    /// targeting the non-default multilib. Otherwise, it is empty.
199    llvm::Optional<Multilib> BiarchSibling;
200
201    GCCVersion Version;
202
203    // We retain the list of install paths that were considered and rejected in
204    // order to print out detailed information in verbose mode.
205    std::set<std::string> CandidateGCCInstallPaths;
206
207    /// The set of multilibs that the detected installation supports.
208    MultilibSet Multilibs;
209
210  public:
211    explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
212    void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args,
213              ArrayRef<std::string> ExtraTripleAliases = None);
214
215    /// Check whether we detected a valid GCC install.
216    bool isValid() const { return IsValid; }
217
218    /// Get the GCC triple for the detected install.
219    const llvm::Triple &getTriple() const { return GCCTriple; }
220
221    /// Get the detected GCC installation path.
222    StringRef getInstallPath() const { return GCCInstallPath; }
223
224    /// Get the detected GCC parent lib path.
225    StringRef getParentLibPath() const { return GCCParentLibPath; }
226
227    /// Get the detected Multilib
228    const Multilib &getMultilib() const { return SelectedMultilib; }
229
230    /// Get the whole MultilibSet
231    const MultilibSet &getMultilibs() const { return Multilibs; }
232
233    /// Get the biarch sibling multilib (if it exists).
234    /// \return true iff such a sibling exists
235    bool getBiarchSibling(Multilib &M) const;
236
237    /// Get the detected GCC version string.
238    const GCCVersion &getVersion() const { return Version; }
239
240    /// Print information about the detected GCC installation.
241    void print(raw_ostream &OS) const;
242
243  private:
244    static void
245    CollectLibDirsAndTriples(const llvm::Triple &TargetTriple,
246                             const llvm::Triple &BiarchTriple,
247                             SmallVectorImpl<StringRef> &LibDirs,
248                             SmallVectorImpl<StringRef> &TripleAliases,
249                             SmallVectorImpl<StringRef> &BiarchLibDirs,
250                             SmallVectorImpl<StringRef> &BiarchTripleAliases);
251
252    void AddDefaultGCCPrefixes(const llvm::Triple &TargetTriple,
253                               SmallVectorImpl<std::string> &Prefixes,
254                               StringRef SysRoot);
255
256    bool ScanGCCForMultilibs(const llvm::Triple &TargetTriple,
257                             const llvm::opt::ArgList &Args,
258                             StringRef Path,
259                             bool NeedsBiarchSuffix = false);
260
261    void ScanLibDirForGCCTriple(const llvm::Triple &TargetArch,
262                                const llvm::opt::ArgList &Args,
263                                const std::string &LibDir,
264                                StringRef CandidateTriple,
265                                bool NeedsBiarchSuffix = false);
266
267    bool ScanGentooConfigs(const llvm::Triple &TargetTriple,
268                           const llvm::opt::ArgList &Args,
269                           const SmallVectorImpl<StringRef> &CandidateTriples,
270                           const SmallVectorImpl<StringRef> &BiarchTriples);
271
272    bool ScanGentooGccConfig(const llvm::Triple &TargetTriple,
273                             const llvm::opt::ArgList &Args,
274                             StringRef CandidateTriple,
275                             bool NeedsBiarchSuffix = false);
276  };
277
278protected:
279  GCCInstallationDetector GCCInstallation;
280  CudaInstallationDetector CudaInstallation;
281
282public:
283  Generic_GCC(const Driver &D, const llvm::Triple &Triple,
284              const llvm::opt::ArgList &Args);
285  ~Generic_GCC() override;
286
287  void printVerboseInfo(raw_ostream &OS) const override;
288
289  bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
290  bool isPICDefault() const override;
291  bool isPIEDefault() const override;
292  bool isPICDefaultForced() const override;
293  bool IsIntegratedAssemblerDefault() const override;
294  llvm::opt::DerivedArgList *
295  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
296                Action::OffloadKind DeviceOffloadKind) const override;
297
298protected:
299  Tool *getTool(Action::ActionClass AC) const override;
300  Tool *buildAssembler() const override;
301  Tool *buildLinker() const override;
302
303  virtual std::string getMultiarchTriple(const Driver &D,
304                                         const llvm::Triple &TargetTriple,
305                                         StringRef SysRoot) const
306  { return TargetTriple.str(); }
307
308  /// \name ToolChain Implementation Helper Functions
309  /// @{
310
311  /// Check whether the target triple's architecture is 64-bits.
312  bool isTarget64Bit() const { return getTriple().isArch64Bit(); }
313
314  /// Check whether the target triple's architecture is 32-bits.
315  bool isTarget32Bit() const { return getTriple().isArch32Bit(); }
316
317  // FIXME: This should be final, but the CrossWindows toolchain does weird
318  // things that can't be easily generalized.
319  void AddClangCXXStdlibIncludeArgs(
320      const llvm::opt::ArgList &DriverArgs,
321      llvm::opt::ArgStringList &CC1Args) const override;
322
323  virtual void
324  addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
325                        llvm::opt::ArgStringList &CC1Args) const;
326  virtual void
327  addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
328                           llvm::opt::ArgStringList &CC1Args) const;
329
330  bool
331  addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
332                           llvm::opt::ArgStringList &CC1Args) const;
333
334  bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple,
335                                StringRef GCCMultiarchTriple,
336                                StringRef TargetMultiarchTriple,
337                                Twine IncludeSuffix,
338                                const llvm::opt::ArgList &DriverArgs,
339                                llvm::opt::ArgStringList &CC1Args) const;
340
341  /// @}
342
343private:
344  mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocess;
345  mutable std::unique_ptr<tools::gcc::Compiler> Compile;
346};
347
348class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
349  virtual void anchor();
350
351public:
352  Generic_ELF(const Driver &D, const llvm::Triple &Triple,
353              const llvm::opt::ArgList &Args)
354      : Generic_GCC(D, Triple, Args) {}
355
356  void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
357                             llvm::opt::ArgStringList &CC1Args,
358                             Action::OffloadKind DeviceOffloadKind) const override;
359
360  virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const {
361    return {};
362  }
363
364  virtual void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {}
365};
366
367} // end namespace toolchains
368} // end namespace driver
369} // end namespace clang
370
371#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
372