1317019Sdim//===--- Gnu.h - Gnu Tool and ToolChain Implementations ---------*- C++ -*-===//
2317019Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6317019Sdim//
7317019Sdim//===----------------------------------------------------------------------===//
8317019Sdim
9317019Sdim#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
10317019Sdim#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
11317019Sdim
12317019Sdim#include "Cuda.h"
13317019Sdim#include "clang/Driver/Tool.h"
14317019Sdim#include "clang/Driver/ToolChain.h"
15317019Sdim#include <set>
16317019Sdim
17317019Sdimnamespace clang {
18317019Sdimnamespace driver {
19317019Sdim
20317019Sdimstruct DetectedMultilibs {
21317019Sdim  /// The set of multilibs that the detected installation supports.
22317019Sdim  MultilibSet Multilibs;
23317019Sdim
24317019Sdim  /// The primary multilib appropriate for the given flags.
25317019Sdim  Multilib SelectedMultilib;
26317019Sdim
27317019Sdim  /// On Biarch systems, this corresponds to the default multilib when
28317019Sdim  /// targeting the non-default multilib. Otherwise, it is empty.
29317019Sdim  llvm::Optional<Multilib> BiarchSibling;
30317019Sdim};
31317019Sdim
32317019Sdimbool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
33317019Sdim                       StringRef Path, const llvm::opt::ArgList &Args,
34317019Sdim                       DetectedMultilibs &Result);
35317019Sdim
36317019Sdimnamespace tools {
37317019Sdim
38341825Sdim/// Base class for all GNU tools that provide the same behavior when
39317019Sdim/// it comes to response files support
40317019Sdimclass LLVM_LIBRARY_VISIBILITY GnuTool : public Tool {
41317019Sdim  virtual void anchor();
42317019Sdim
43317019Sdimpublic:
44317019Sdim  GnuTool(const char *Name, const char *ShortName, const ToolChain &TC)
45317019Sdim      : Tool(Name, ShortName, TC, RF_Full, llvm::sys::WEM_CurrentCodePage) {}
46317019Sdim};
47317019Sdim
48317019Sdim/// Directly call GNU Binutils' assembler and linker.
49317019Sdimnamespace gnutools {
50317019Sdimclass LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
51317019Sdimpublic:
52317019Sdim  Assembler(const ToolChain &TC) : GnuTool("GNU::Assembler", "assembler", TC) {}
53317019Sdim
54317019Sdim  bool hasIntegratedCPP() const override { return false; }
55317019Sdim
56317019Sdim  void ConstructJob(Compilation &C, const JobAction &JA,
57317019Sdim                    const InputInfo &Output, const InputInfoList &Inputs,
58317019Sdim                    const llvm::opt::ArgList &TCArgs,
59317019Sdim                    const char *LinkingOutput) const override;
60317019Sdim};
61317019Sdim
62317019Sdimclass LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
63317019Sdimpublic:
64317019Sdim  Linker(const ToolChain &TC) : GnuTool("GNU::Linker", "linker", TC) {}
65317019Sdim
66317019Sdim  bool hasIntegratedCPP() const override { return false; }
67317019Sdim  bool isLinkJob() const override { return true; }
68317019Sdim
69317019Sdim  void ConstructJob(Compilation &C, const JobAction &JA,
70317019Sdim                    const InputInfo &Output, const InputInfoList &Inputs,
71317019Sdim                    const llvm::opt::ArgList &TCArgs,
72317019Sdim                    const char *LinkingOutput) const override;
73317019Sdim};
74317019Sdim} // end namespace gnutools
75317019Sdim
76317019Sdim/// gcc - Generic GCC tool implementations.
77317019Sdimnamespace gcc {
78317019Sdimclass LLVM_LIBRARY_VISIBILITY Common : public GnuTool {
79317019Sdimpublic:
80317019Sdim  Common(const char *Name, const char *ShortName, const ToolChain &TC)
81317019Sdim      : GnuTool(Name, ShortName, TC) {}
82317019Sdim
83317019Sdim  // A gcc tool has an "integrated" assembler that it will call to produce an
84317019Sdim  // object. Let it use that assembler so that we don't have to deal with
85317019Sdim  // assembly syntax incompatibilities.
86317019Sdim  bool hasIntegratedAssembler() const override { return true; }
87317019Sdim  void ConstructJob(Compilation &C, const JobAction &JA,
88317019Sdim                    const InputInfo &Output, const InputInfoList &Inputs,
89317019Sdim                    const llvm::opt::ArgList &TCArgs,
90317019Sdim                    const char *LinkingOutput) const override;
91317019Sdim
92317019Sdim  /// RenderExtraToolArgs - Render any arguments necessary to force
93317019Sdim  /// the particular tool mode.
94317019Sdim  virtual void RenderExtraToolArgs(const JobAction &JA,
95317019Sdim                                   llvm::opt::ArgStringList &CmdArgs) const = 0;
96317019Sdim};
97317019Sdim
98317019Sdimclass LLVM_LIBRARY_VISIBILITY Preprocessor : public Common {
99317019Sdimpublic:
100317019Sdim  Preprocessor(const ToolChain &TC)
101317019Sdim      : Common("gcc::Preprocessor", "gcc preprocessor", TC) {}
102317019Sdim
103317019Sdim  bool hasGoodDiagnostics() const override { return true; }
104317019Sdim  bool hasIntegratedCPP() const override { return false; }
105317019Sdim
106317019Sdim  void RenderExtraToolArgs(const JobAction &JA,
107317019Sdim                           llvm::opt::ArgStringList &CmdArgs) const override;
108317019Sdim};
109317019Sdim
110317019Sdimclass LLVM_LIBRARY_VISIBILITY Compiler : public Common {
111317019Sdimpublic:
112317019Sdim  Compiler(const ToolChain &TC) : Common("gcc::Compiler", "gcc frontend", TC) {}
113317019Sdim
114317019Sdim  bool hasGoodDiagnostics() const override { return true; }
115317019Sdim  bool hasIntegratedCPP() const override { return true; }
116317019Sdim
117317019Sdim  void RenderExtraToolArgs(const JobAction &JA,
118317019Sdim                           llvm::opt::ArgStringList &CmdArgs) const override;
119317019Sdim};
120317019Sdim
121317019Sdimclass LLVM_LIBRARY_VISIBILITY Linker : public Common {
122317019Sdimpublic:
123317019Sdim  Linker(const ToolChain &TC) : Common("gcc::Linker", "linker (via gcc)", TC) {}
124317019Sdim
125317019Sdim  bool hasIntegratedCPP() const override { return false; }
126317019Sdim  bool isLinkJob() const override { return true; }
127317019Sdim
128317019Sdim  void RenderExtraToolArgs(const JobAction &JA,
129317019Sdim                           llvm::opt::ArgStringList &CmdArgs) const override;
130317019Sdim};
131317019Sdim} // end namespace gcc
132317019Sdim} // end namespace tools
133317019Sdim
134317019Sdimnamespace toolchains {
135317019Sdim
136317019Sdim/// Generic_GCC - A tool chain using the 'gcc' command to perform
137317019Sdim/// all subcommands; this relies on gcc translating the majority of
138317019Sdim/// command line options.
139317019Sdimclass LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain {
140317019Sdimpublic:
141341825Sdim  /// Struct to store and manipulate GCC versions.
142317019Sdim  ///
143317019Sdim  /// We rely on assumptions about the form and structure of GCC version
144317019Sdim  /// numbers: they consist of at most three '.'-separated components, and each
145317019Sdim  /// component is a non-negative integer except for the last component. For
146317019Sdim  /// the last component we are very flexible in order to tolerate release
147317019Sdim  /// candidates or 'x' wildcards.
148317019Sdim  ///
149317019Sdim  /// Note that the ordering established among GCCVersions is based on the
150317019Sdim  /// preferred version string to use. For example we prefer versions without
151317019Sdim  /// a hard-coded patch number to those with a hard coded patch number.
152317019Sdim  ///
153317019Sdim  /// Currently this doesn't provide any logic for textual suffixes to patches
154317019Sdim  /// in the way that (for example) Debian's version format does. If that ever
155317019Sdim  /// becomes necessary, it can be added.
156317019Sdim  struct GCCVersion {
157341825Sdim    /// The unparsed text of the version.
158317019Sdim    std::string Text;
159317019Sdim
160341825Sdim    /// The parsed major, minor, and patch numbers.
161317019Sdim    int Major, Minor, Patch;
162317019Sdim
163341825Sdim    /// The text of the parsed major, and major+minor versions.
164317019Sdim    std::string MajorStr, MinorStr;
165317019Sdim
166341825Sdim    /// Any textual suffix on the patch number.
167317019Sdim    std::string PatchSuffix;
168317019Sdim
169317019Sdim    static GCCVersion Parse(StringRef VersionText);
170317019Sdim    bool isOlderThan(int RHSMajor, int RHSMinor, int RHSPatch,
171317019Sdim                     StringRef RHSPatchSuffix = StringRef()) const;
172317019Sdim    bool operator<(const GCCVersion &RHS) const {
173317019Sdim      return isOlderThan(RHS.Major, RHS.Minor, RHS.Patch, RHS.PatchSuffix);
174317019Sdim    }
175317019Sdim    bool operator>(const GCCVersion &RHS) const { return RHS < *this; }
176317019Sdim    bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); }
177317019Sdim    bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
178317019Sdim  };
179317019Sdim
180341825Sdim  /// This is a class to find a viable GCC installation for Clang to
181317019Sdim  /// use.
182317019Sdim  ///
183317019Sdim  /// This class tries to find a GCC installation on the system, and report
184317019Sdim  /// information about it. It starts from the host information provided to the
185317019Sdim  /// Driver, and has logic for fuzzing that where appropriate.
186317019Sdim  class GCCInstallationDetector {
187317019Sdim    bool IsValid;
188317019Sdim    llvm::Triple GCCTriple;
189317019Sdim    const Driver &D;
190317019Sdim
191317019Sdim    // FIXME: These might be better as path objects.
192317019Sdim    std::string GCCInstallPath;
193317019Sdim    std::string GCCParentLibPath;
194317019Sdim
195317019Sdim    /// The primary multilib appropriate for the given flags.
196317019Sdim    Multilib SelectedMultilib;
197317019Sdim    /// On Biarch systems, this corresponds to the default multilib when
198317019Sdim    /// targeting the non-default multilib. Otherwise, it is empty.
199317019Sdim    llvm::Optional<Multilib> BiarchSibling;
200317019Sdim
201317019Sdim    GCCVersion Version;
202317019Sdim
203317019Sdim    // We retain the list of install paths that were considered and rejected in
204317019Sdim    // order to print out detailed information in verbose mode.
205317019Sdim    std::set<std::string> CandidateGCCInstallPaths;
206317019Sdim
207317019Sdim    /// The set of multilibs that the detected installation supports.
208317019Sdim    MultilibSet Multilibs;
209317019Sdim
210317019Sdim  public:
211317019Sdim    explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
212317019Sdim    void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args,
213317019Sdim              ArrayRef<std::string> ExtraTripleAliases = None);
214317019Sdim
215341825Sdim    /// Check whether we detected a valid GCC install.
216317019Sdim    bool isValid() const { return IsValid; }
217317019Sdim
218341825Sdim    /// Get the GCC triple for the detected install.
219317019Sdim    const llvm::Triple &getTriple() const { return GCCTriple; }
220317019Sdim
221341825Sdim    /// Get the detected GCC installation path.
222317019Sdim    StringRef getInstallPath() const { return GCCInstallPath; }
223317019Sdim
224341825Sdim    /// Get the detected GCC parent lib path.
225317019Sdim    StringRef getParentLibPath() const { return GCCParentLibPath; }
226317019Sdim
227341825Sdim    /// Get the detected Multilib
228317019Sdim    const Multilib &getMultilib() const { return SelectedMultilib; }
229317019Sdim
230341825Sdim    /// Get the whole MultilibSet
231317019Sdim    const MultilibSet &getMultilibs() const { return Multilibs; }
232317019Sdim
233317019Sdim    /// Get the biarch sibling multilib (if it exists).
234317019Sdim    /// \return true iff such a sibling exists
235317019Sdim    bool getBiarchSibling(Multilib &M) const;
236317019Sdim
237341825Sdim    /// Get the detected GCC version string.
238317019Sdim    const GCCVersion &getVersion() const { return Version; }
239317019Sdim
240341825Sdim    /// Print information about the detected GCC installation.
241317019Sdim    void print(raw_ostream &OS) const;
242317019Sdim
243317019Sdim  private:
244317019Sdim    static void
245317019Sdim    CollectLibDirsAndTriples(const llvm::Triple &TargetTriple,
246317019Sdim                             const llvm::Triple &BiarchTriple,
247317019Sdim                             SmallVectorImpl<StringRef> &LibDirs,
248317019Sdim                             SmallVectorImpl<StringRef> &TripleAliases,
249317019Sdim                             SmallVectorImpl<StringRef> &BiarchLibDirs,
250317019Sdim                             SmallVectorImpl<StringRef> &BiarchTripleAliases);
251317019Sdim
252341825Sdim    void AddDefaultGCCPrefixes(const llvm::Triple &TargetTriple,
253341825Sdim                               SmallVectorImpl<std::string> &Prefixes,
254341825Sdim                               StringRef SysRoot);
255341825Sdim
256317019Sdim    bool ScanGCCForMultilibs(const llvm::Triple &TargetTriple,
257317019Sdim                             const llvm::opt::ArgList &Args,
258317019Sdim                             StringRef Path,
259317019Sdim                             bool NeedsBiarchSuffix = false);
260317019Sdim
261317019Sdim    void ScanLibDirForGCCTriple(const llvm::Triple &TargetArch,
262317019Sdim                                const llvm::opt::ArgList &Args,
263317019Sdim                                const std::string &LibDir,
264317019Sdim                                StringRef CandidateTriple,
265317019Sdim                                bool NeedsBiarchSuffix = false);
266317019Sdim
267341825Sdim    bool ScanGentooConfigs(const llvm::Triple &TargetTriple,
268341825Sdim                           const llvm::opt::ArgList &Args,
269341825Sdim                           const SmallVectorImpl<StringRef> &CandidateTriples,
270341825Sdim                           const SmallVectorImpl<StringRef> &BiarchTriples);
271317019Sdim
272317019Sdim    bool ScanGentooGccConfig(const llvm::Triple &TargetTriple,
273317019Sdim                             const llvm::opt::ArgList &Args,
274317019Sdim                             StringRef CandidateTriple,
275317019Sdim                             bool NeedsBiarchSuffix = false);
276317019Sdim  };
277317019Sdim
278317019Sdimprotected:
279317019Sdim  GCCInstallationDetector GCCInstallation;
280317019Sdim  CudaInstallationDetector CudaInstallation;
281317019Sdim
282317019Sdimpublic:
283317019Sdim  Generic_GCC(const Driver &D, const llvm::Triple &Triple,
284317019Sdim              const llvm::opt::ArgList &Args);
285317019Sdim  ~Generic_GCC() override;
286317019Sdim
287317019Sdim  void printVerboseInfo(raw_ostream &OS) const override;
288317019Sdim
289322740Sdim  bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
290317019Sdim  bool isPICDefault() const override;
291317019Sdim  bool isPIEDefault() const override;
292317019Sdim  bool isPICDefaultForced() const override;
293317019Sdim  bool IsIntegratedAssemblerDefault() const override;
294317019Sdim  llvm::opt::DerivedArgList *
295317019Sdim  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
296317019Sdim                Action::OffloadKind DeviceOffloadKind) const override;
297317019Sdim
298317019Sdimprotected:
299317019Sdim  Tool *getTool(Action::ActionClass AC) const override;
300317019Sdim  Tool *buildAssembler() const override;
301317019Sdim  Tool *buildLinker() const override;
302317019Sdim
303360784Sdim  virtual std::string getMultiarchTriple(const Driver &D,
304360784Sdim                                         const llvm::Triple &TargetTriple,
305360784Sdim                                         StringRef SysRoot) const
306360784Sdim  { return TargetTriple.str(); }
307360784Sdim
308317019Sdim  /// \name ToolChain Implementation Helper Functions
309317019Sdim  /// @{
310317019Sdim
311341825Sdim  /// Check whether the target triple's architecture is 64-bits.
312317019Sdim  bool isTarget64Bit() const { return getTriple().isArch64Bit(); }
313317019Sdim
314341825Sdim  /// Check whether the target triple's architecture is 32-bits.
315317019Sdim  bool isTarget32Bit() const { return getTriple().isArch32Bit(); }
316317019Sdim
317341825Sdim  // FIXME: This should be final, but the CrossWindows toolchain does weird
318341825Sdim  // things that can't be easily generalized.
319317019Sdim  void AddClangCXXStdlibIncludeArgs(
320317019Sdim      const llvm::opt::ArgList &DriverArgs,
321317019Sdim      llvm::opt::ArgStringList &CC1Args) const override;
322317019Sdim
323317019Sdim  virtual void
324341825Sdim  addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
325341825Sdim                        llvm::opt::ArgStringList &CC1Args) const;
326341825Sdim  virtual void
327317019Sdim  addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
328317019Sdim                           llvm::opt::ArgStringList &CC1Args) const;
329317019Sdim
330360784Sdim  bool
331360784Sdim  addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
332360784Sdim                           llvm::opt::ArgStringList &CC1Args) const;
333360784Sdim
334317019Sdim  bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple,
335317019Sdim                                StringRef GCCMultiarchTriple,
336317019Sdim                                StringRef TargetMultiarchTriple,
337317019Sdim                                Twine IncludeSuffix,
338317019Sdim                                const llvm::opt::ArgList &DriverArgs,
339317019Sdim                                llvm::opt::ArgStringList &CC1Args) const;
340317019Sdim
341317019Sdim  /// @}
342317019Sdim
343317019Sdimprivate:
344317019Sdim  mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocess;
345317019Sdim  mutable std::unique_ptr<tools::gcc::Compiler> Compile;
346317019Sdim};
347317019Sdim
348317019Sdimclass LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
349317019Sdim  virtual void anchor();
350317019Sdim
351317019Sdimpublic:
352317019Sdim  Generic_ELF(const Driver &D, const llvm::Triple &Triple,
353317019Sdim              const llvm::opt::ArgList &Args)
354317019Sdim      : Generic_GCC(D, Triple, Args) {}
355317019Sdim
356317019Sdim  void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
357320970Sdim                             llvm::opt::ArgStringList &CC1Args,
358320970Sdim                             Action::OffloadKind DeviceOffloadKind) const override;
359363496Sdim
360363496Sdim  virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const {
361363496Sdim    return {};
362363496Sdim  }
363363496Sdim
364363496Sdim  virtual void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {}
365317019Sdim};
366317019Sdim
367317019Sdim} // end namespace toolchains
368317019Sdim} // end namespace driver
369317019Sdim} // end namespace clang
370317019Sdim
371317019Sdim#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
372