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