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