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(RHSMajor: RHS.Major, RHSMinor: RHS.Minor, RHSPatch: RHS.Patch, RHSPatchSuffix: 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 |
Definitions
- DetectedMultilibs
- Assembler
- Assembler
- hasIntegratedCPP
- Linker
- Linker
- hasIntegratedCPP
- isLinkJob
- StaticLibTool
- StaticLibTool
- hasIntegratedCPP
- isLinkJob
- Common
- Common
- hasIntegratedAssembler
- Preprocessor
- Preprocessor
- hasGoodDiagnostics
- hasIntegratedCPP
- Compiler
- Compiler
- hasGoodDiagnostics
- hasIntegratedCPP
- Linker
- Linker
- hasIntegratedCPP
- isLinkJob
- Generic_GCC
- GCCVersion
- operator<
- operator>
- operator<=
- operator>=
- GCCInstallationDetector
- GCCInstallationDetector
- isValid
- getTriple
- getInstallPath
- getParentLibPath
- getMultilib
- getMultilibs
- getVersion
- isTarget64Bit
- isTarget32Bit
- Generic_ELF
- Generic_ELF
- getDynamicLinker
Improve your Profiling and Debugging skills
Find out more