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