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 17 namespace clang { 18 namespace driver { 19 20 struct 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 32 bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple, 33 StringRef Path, const llvm::opt::ArgList &Args, 34 DetectedMultilibs &Result); 35 36 namespace tools { 37 38 /// Base class for all GNU tools that provide the same behavior when 39 /// it comes to response files support 40 class LLVM_LIBRARY_VISIBILITY GnuTool : public Tool { 41 virtual void anchor(); 42 43 public: 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. 49 namespace gnutools { 50 class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool { 51 public: 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 62 class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool { 63 public: 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. 77 namespace gcc { 78 class LLVM_LIBRARY_VISIBILITY Common : public GnuTool { 79 public: 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 98 class LLVM_LIBRARY_VISIBILITY Preprocessor : public Common { 99 public: 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 110 class LLVM_LIBRARY_VISIBILITY Compiler : public Common { 111 public: 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 121 class LLVM_LIBRARY_VISIBILITY Linker : public Common { 122 public: 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 134 namespace 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. 139 class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain { 140 public: 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 278 protected: 279 GCCInstallationDetector GCCInstallation; 280 CudaInstallationDetector CudaInstallation; 281 282 public: 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 298 protected: 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 343 private: 344 mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocess; 345 mutable std::unique_ptr<tools::gcc::Compiler> Compile; 346 }; 347 348 class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC { 349 virtual void anchor(); 350 351 public: 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