1 | //===--- Cuda.h - Cuda 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_CUDA_H |
10 | #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CUDA_H |
11 | |
12 | #include "clang/Basic/Cuda.h" |
13 | #include "clang/Driver/Action.h" |
14 | #include "clang/Driver/Multilib.h" |
15 | #include "clang/Driver/Tool.h" |
16 | #include "clang/Driver/ToolChain.h" |
17 | #include "llvm/Support/Compiler.h" |
18 | #include "llvm/Support/VersionTuple.h" |
19 | #include <bitset> |
20 | #include <set> |
21 | #include <vector> |
22 | |
23 | namespace clang { |
24 | namespace driver { |
25 | |
26 | /// A class to find a viable CUDA installation |
27 | class CudaInstallationDetector { |
28 | private: |
29 | const Driver &D; |
30 | bool IsValid = false; |
31 | CudaVersion Version = CudaVersion::UNKNOWN; |
32 | std::string InstallPath; |
33 | std::string BinPath; |
34 | std::string LibDevicePath; |
35 | std::string IncludePath; |
36 | llvm::StringMap<std::string> LibDeviceMap; |
37 | |
38 | // CUDA architectures for which we have raised an error in |
39 | // CheckCudaVersionSupportsArch. |
40 | mutable std::bitset<(int)OffloadArch::LAST> ArchsWithBadVersion; |
41 | |
42 | public: |
43 | CudaInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, |
44 | const llvm::opt::ArgList &Args); |
45 | |
46 | void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, |
47 | llvm::opt::ArgStringList &CC1Args) const; |
48 | |
49 | /// Emit an error if Version does not support the given Arch. |
50 | /// |
51 | /// If either Version or Arch is unknown, does not emit an error. Emits at |
52 | /// most one error per Arch. |
53 | void CheckCudaVersionSupportsArch(OffloadArch Arch) const; |
54 | |
55 | /// Check whether we detected a valid Cuda install. |
56 | bool isValid() const { return IsValid; } |
57 | /// Print information about the detected CUDA installation. |
58 | void print(raw_ostream &OS) const; |
59 | |
60 | /// Get the detected Cuda install's version. |
61 | CudaVersion version() const { |
62 | return Version == CudaVersion::NEW ? CudaVersion::PARTIALLY_SUPPORTED |
63 | : Version; |
64 | } |
65 | /// Get the detected Cuda installation path. |
66 | StringRef getInstallPath() const { return InstallPath; } |
67 | /// Get the detected path to Cuda's bin directory. |
68 | StringRef getBinPath() const { return BinPath; } |
69 | /// Get the detected Cuda Include path. |
70 | StringRef getIncludePath() const { return IncludePath; } |
71 | /// Get the detected Cuda device library path. |
72 | StringRef getLibDevicePath() const { return LibDevicePath; } |
73 | /// Get libdevice file for given architecture |
74 | std::string getLibDeviceFile(StringRef Gpu) const { |
75 | return LibDeviceMap.lookup(Key: Gpu); |
76 | } |
77 | void WarnIfUnsupportedVersion(); |
78 | }; |
79 | |
80 | namespace tools { |
81 | namespace NVPTX { |
82 | |
83 | // Run ptxas, the NVPTX assembler. |
84 | class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool { |
85 | public: |
86 | Assembler(const ToolChain &TC) : Tool("NVPTX::Assembler" , "ptxas" , TC) {} |
87 | |
88 | bool hasIntegratedCPP() const override { return false; } |
89 | |
90 | void ConstructJob(Compilation &C, const JobAction &JA, |
91 | const InputInfo &Output, const InputInfoList &Inputs, |
92 | const llvm::opt::ArgList &TCArgs, |
93 | const char *LinkingOutput) const override; |
94 | }; |
95 | |
96 | // Runs fatbinary, which combines GPU object files ("cubin" files) and/or PTX |
97 | // assembly into a single output file. |
98 | class LLVM_LIBRARY_VISIBILITY FatBinary : public Tool { |
99 | public: |
100 | FatBinary(const ToolChain &TC) : Tool("NVPTX::Linker" , "fatbinary" , TC) {} |
101 | |
102 | bool hasIntegratedCPP() const override { return false; } |
103 | |
104 | void ConstructJob(Compilation &C, const JobAction &JA, |
105 | const InputInfo &Output, const InputInfoList &Inputs, |
106 | const llvm::opt::ArgList &TCArgs, |
107 | const char *LinkingOutput) const override; |
108 | }; |
109 | |
110 | // Runs nvlink, which links GPU object files ("cubin" files) into a single file. |
111 | class LLVM_LIBRARY_VISIBILITY Linker final : public Tool { |
112 | public: |
113 | Linker(const ToolChain &TC) : Tool("NVPTX::Linker" , "nvlink" , TC) {} |
114 | |
115 | bool hasIntegratedCPP() const override { return false; } |
116 | |
117 | void ConstructJob(Compilation &C, const JobAction &JA, |
118 | const InputInfo &Output, const InputInfoList &Inputs, |
119 | const llvm::opt::ArgList &TCArgs, |
120 | const char *LinkingOutput) const override; |
121 | }; |
122 | |
123 | void getNVPTXTargetFeatures(const Driver &D, const llvm::Triple &Triple, |
124 | const llvm::opt::ArgList &Args, |
125 | std::vector<StringRef> &Features); |
126 | |
127 | } // end namespace NVPTX |
128 | } // end namespace tools |
129 | |
130 | namespace toolchains { |
131 | |
132 | class LLVM_LIBRARY_VISIBILITY NVPTXToolChain : public ToolChain { |
133 | public: |
134 | NVPTXToolChain(const Driver &D, const llvm::Triple &Triple, |
135 | const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args, |
136 | bool Freestanding); |
137 | |
138 | NVPTXToolChain(const Driver &D, const llvm::Triple &Triple, |
139 | const llvm::opt::ArgList &Args); |
140 | |
141 | llvm::opt::DerivedArgList * |
142 | TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, |
143 | Action::OffloadKind DeviceOffloadKind) const override; |
144 | |
145 | void |
146 | addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, |
147 | llvm::opt::ArgStringList &CC1Args, |
148 | Action::OffloadKind DeviceOffloadKind) const override; |
149 | |
150 | // Never try to use the integrated assembler with CUDA; always fork out to |
151 | // ptxas. |
152 | bool useIntegratedAs() const override { return false; } |
153 | bool isCrossCompiling() const override { return true; } |
154 | bool isPICDefault() const override { return false; } |
155 | bool isPIEDefault(const llvm::opt::ArgList &Args) const override { |
156 | return false; |
157 | } |
158 | bool HasNativeLLVMSupport() const override { return true; } |
159 | bool isPICDefaultForced() const override { return false; } |
160 | bool SupportsProfiling() const override { return false; } |
161 | |
162 | bool IsMathErrnoDefault() const override { return false; } |
163 | |
164 | bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override; |
165 | void adjustDebugInfoKind(llvm::codegenoptions::DebugInfoKind &DebugInfoKind, |
166 | const llvm::opt::ArgList &Args) const override; |
167 | |
168 | // NVPTX supports only DWARF2. |
169 | unsigned GetDefaultDwarfVersion() const override { return 2; } |
170 | unsigned getMaxDwarfVersion() const override { return 2; } |
171 | |
172 | /// Uses nvptx-arch tool to get arch of the system GPU. Will return error |
173 | /// if unable to find one. |
174 | virtual Expected<SmallVector<std::string>> |
175 | getSystemGPUArchs(const llvm::opt::ArgList &Args) const override; |
176 | |
177 | CudaInstallationDetector CudaInstallation; |
178 | |
179 | protected: |
180 | Tool *buildAssembler() const override; // ptxas. |
181 | Tool *buildLinker() const override; // nvlink. |
182 | |
183 | private: |
184 | bool Freestanding = false; |
185 | }; |
186 | |
187 | class LLVM_LIBRARY_VISIBILITY CudaToolChain : public NVPTXToolChain { |
188 | public: |
189 | CudaToolChain(const Driver &D, const llvm::Triple &Triple, |
190 | const ToolChain &HostTC, const llvm::opt::ArgList &Args); |
191 | |
192 | const llvm::Triple *getAuxTriple() const override { |
193 | return &HostTC.getTriple(); |
194 | } |
195 | |
196 | bool HasNativeLLVMSupport() const override { return false; } |
197 | |
198 | std::string getInputFilename(const InputInfo &Input) const override; |
199 | |
200 | llvm::opt::DerivedArgList * |
201 | TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, |
202 | Action::OffloadKind DeviceOffloadKind) const override; |
203 | void |
204 | addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, |
205 | llvm::opt::ArgStringList &CC1Args, |
206 | Action::OffloadKind DeviceOffloadKind) const override; |
207 | |
208 | llvm::DenormalMode getDefaultDenormalModeForType( |
209 | const llvm::opt::ArgList &DriverArgs, const JobAction &JA, |
210 | const llvm::fltSemantics *FPType = nullptr) const override; |
211 | |
212 | void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, |
213 | llvm::opt::ArgStringList &CC1Args) const override; |
214 | |
215 | void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override; |
216 | CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; |
217 | void |
218 | AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, |
219 | llvm::opt::ArgStringList &CC1Args) const override; |
220 | void AddClangCXXStdlibIncludeArgs( |
221 | const llvm::opt::ArgList &Args, |
222 | llvm::opt::ArgStringList &CC1Args) const override; |
223 | void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs, |
224 | llvm::opt::ArgStringList &CC1Args) const override; |
225 | |
226 | SanitizerMask getSupportedSanitizers() const override; |
227 | |
228 | VersionTuple |
229 | computeMSVCVersion(const Driver *D, |
230 | const llvm::opt::ArgList &Args) const override; |
231 | |
232 | const ToolChain &HostTC; |
233 | |
234 | protected: |
235 | Tool *buildAssembler() const override; // ptxas |
236 | Tool *buildLinker() const override; // fatbinary (ok, not really a linker) |
237 | }; |
238 | |
239 | } // end namespace toolchains |
240 | } // end namespace driver |
241 | } // end namespace clang |
242 | |
243 | #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CUDA_H |
244 | |