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/ADT/Optional.h"
18 #include "llvm/ADT/SmallSet.h"
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/VersionTuple.h"
21 #include <set>
22 #include <vector>
23 
24 namespace clang {
25 namespace driver {
26 
27 /// A class to find a viable CUDA installation
28 class CudaInstallationDetector {
29 private:
30   const Driver &D;
31   bool IsValid = false;
32   CudaVersion Version = CudaVersion::UNKNOWN;
33   std::string InstallPath;
34   std::string BinPath;
35   std::string LibPath;
36   std::string LibDevicePath;
37   std::string IncludePath;
38   llvm::StringMap<std::string> LibDeviceMap;
39 
40   // CUDA architectures for which we have raised an error in
41   // CheckCudaVersionSupportsArch.
42   mutable llvm::SmallSet<CudaArch, 4> ArchsWithBadVersion;
43 
44 public:
45   CudaInstallationDetector(const Driver &D, const llvm::Triple &HostTriple,
46                            const llvm::opt::ArgList &Args);
47 
48   void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
49                           llvm::opt::ArgStringList &CC1Args) const;
50 
51   /// Emit an error if Version does not support the given Arch.
52   ///
53   /// If either Version or Arch is unknown, does not emit an error.  Emits at
54   /// most one error per Arch.
55   void CheckCudaVersionSupportsArch(CudaArch Arch) const;
56 
57   /// Check whether we detected a valid Cuda install.
isValid()58   bool isValid() const { return IsValid; }
59   /// Print information about the detected CUDA installation.
60   void print(raw_ostream &OS) const;
61 
62   /// Get the detected Cuda install's version.
version()63   CudaVersion version() const { return Version; }
64   /// Get the detected Cuda installation path.
getInstallPath()65   StringRef getInstallPath() const { return InstallPath; }
66   /// Get the detected path to Cuda's bin directory.
getBinPath()67   StringRef getBinPath() const { return BinPath; }
68   /// Get the detected Cuda Include path.
getIncludePath()69   StringRef getIncludePath() const { return IncludePath; }
70   /// Get the detected Cuda library path.
getLibPath()71   StringRef getLibPath() const { return LibPath; }
72   /// Get the detected Cuda device library path.
getLibDevicePath()73   StringRef getLibDevicePath() const { return LibDevicePath; }
74   /// Get libdevice file for given architecture
getLibDeviceFile(StringRef Gpu)75   std::string getLibDeviceFile(StringRef Gpu) const {
76     return LibDeviceMap.lookup(Gpu);
77   }
78 };
79 
80 namespace tools {
81 namespace NVPTX {
82 
83 // Run ptxas, the NVPTX assembler.
84 class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
85  public:
Assembler(const ToolChain & TC)86    Assembler(const ToolChain &TC)
87        : Tool("NVPTX::Assembler", "ptxas", TC, RF_Full, llvm::sys::WEM_UTF8,
88               "--options-file") {}
89 
hasIntegratedCPP()90    bool hasIntegratedCPP() const override { return false; }
91 
92    void ConstructJob(Compilation &C, const JobAction &JA,
93                      const InputInfo &Output, const InputInfoList &Inputs,
94                      const llvm::opt::ArgList &TCArgs,
95                      const char *LinkingOutput) const override;
96 };
97 
98 // Runs fatbinary, which combines GPU object files ("cubin" files) and/or PTX
99 // assembly into a single output file.
100 class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
101  public:
Linker(const ToolChain & TC)102    Linker(const ToolChain &TC)
103        : Tool("NVPTX::Linker", "fatbinary", TC, RF_Full, llvm::sys::WEM_UTF8,
104               "--options-file") {}
105 
hasIntegratedCPP()106    bool hasIntegratedCPP() const override { return false; }
107 
108    void ConstructJob(Compilation &C, const JobAction &JA,
109                      const InputInfo &Output, const InputInfoList &Inputs,
110                      const llvm::opt::ArgList &TCArgs,
111                      const char *LinkingOutput) const override;
112 };
113 
114 class LLVM_LIBRARY_VISIBILITY OpenMPLinker : public Tool {
115  public:
OpenMPLinker(const ToolChain & TC)116    OpenMPLinker(const ToolChain &TC)
117        : Tool("NVPTX::OpenMPLinker", "nvlink", TC, RF_Full, llvm::sys::WEM_UTF8,
118               "--options-file") {}
119 
hasIntegratedCPP()120    bool hasIntegratedCPP() const override { return false; }
121 
122    void ConstructJob(Compilation &C, const JobAction &JA,
123                      const InputInfo &Output, const InputInfoList &Inputs,
124                      const llvm::opt::ArgList &TCArgs,
125                      const char *LinkingOutput) const override;
126 };
127 
128 } // end namespace NVPTX
129 } // end namespace tools
130 
131 namespace toolchains {
132 
133 class LLVM_LIBRARY_VISIBILITY CudaToolChain : public ToolChain {
134 public:
135   CudaToolChain(const Driver &D, const llvm::Triple &Triple,
136                 const ToolChain &HostTC, const llvm::opt::ArgList &Args,
137                 const Action::OffloadKind OK);
138 
getAuxTriple()139   const llvm::Triple *getAuxTriple() const override {
140     return &HostTC.getTriple();
141   }
142 
143   std::string getInputFilename(const InputInfo &Input) const override;
144 
145   llvm::opt::DerivedArgList *
146   TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
147                 Action::OffloadKind DeviceOffloadKind) const override;
148   void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
149                              llvm::opt::ArgStringList &CC1Args,
150                              Action::OffloadKind DeviceOffloadKind) const override;
151 
152   // Never try to use the integrated assembler with CUDA; always fork out to
153   // ptxas.
useIntegratedAs()154   bool useIntegratedAs() const override { return false; }
isCrossCompiling()155   bool isCrossCompiling() const override { return true; }
isPICDefault()156   bool isPICDefault() const override { return false; }
isPIEDefault()157   bool isPIEDefault() const override { return false; }
isPICDefaultForced()158   bool isPICDefaultForced() const override { return false; }
SupportsProfiling()159   bool SupportsProfiling() const override { return false; }
160   bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override;
161   void adjustDebugInfoKind(codegenoptions::DebugInfoKind &DebugInfoKind,
162                            const llvm::opt::ArgList &Args) const override;
IsMathErrnoDefault()163   bool IsMathErrnoDefault() const override { return false; }
164 
165   void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
166                           llvm::opt::ArgStringList &CC1Args) const override;
167 
168   void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
169   CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
170   void
171   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
172                             llvm::opt::ArgStringList &CC1Args) const override;
173   void AddClangCXXStdlibIncludeArgs(
174       const llvm::opt::ArgList &Args,
175       llvm::opt::ArgStringList &CC1Args) const override;
176   void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
177                            llvm::opt::ArgStringList &CC1Args) const override;
178 
179   SanitizerMask getSupportedSanitizers() const override;
180 
181   VersionTuple
182   computeMSVCVersion(const Driver *D,
183                      const llvm::opt::ArgList &Args) const override;
184 
GetDefaultDwarfVersion()185   unsigned GetDefaultDwarfVersion() const override { return 2; }
186 
187   const ToolChain &HostTC;
188   CudaInstallationDetector CudaInstallation;
189 
190 protected:
191   Tool *buildAssembler() const override;  // ptxas
192   Tool *buildLinker() const override;     // fatbinary (ok, not really a linker)
193 
194 private:
195   const Action::OffloadKind OK;
196 };
197 
198 } // end namespace toolchains
199 } // end namespace driver
200 } // end namespace clang
201 
202 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CUDA_H
203