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