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)CudaArch::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(CudaArch 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(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 : 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 : public Tool { 112 public: 113 Linker(const ToolChain &TC) : Tool("NVPTX::Linker", "fatbinary", 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, 136 const llvm::opt::ArgList &Args); 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 // Never try to use the integrated assembler with CUDA; always fork out to 146 // ptxas. 147 bool useIntegratedAs() const override { return false; } 148 bool isCrossCompiling() const override { return true; } 149 bool isPICDefault() const override { return false; } 150 bool isPIEDefault(const llvm::opt::ArgList &Args) const override { 151 return false; 152 } 153 bool isPICDefaultForced() const override { return false; } 154 bool SupportsProfiling() const override { return false; } 155 156 bool IsMathErrnoDefault() const override { return false; } 157 158 bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override; 159 void adjustDebugInfoKind(codegenoptions::DebugInfoKind &DebugInfoKind, 160 const llvm::opt::ArgList &Args) const override; 161 162 // NVPTX supports only DWARF2. 163 unsigned GetDefaultDwarfVersion() const override { return 2; } 164 unsigned getMaxDwarfVersion() const override { return 2; } 165 166 CudaInstallationDetector CudaInstallation; 167 168 protected: 169 Tool *buildAssembler() const override; // ptxas. 170 Tool *buildLinker() const override; // nvlink. 171 }; 172 173 class LLVM_LIBRARY_VISIBILITY CudaToolChain : public NVPTXToolChain { 174 public: 175 CudaToolChain(const Driver &D, const llvm::Triple &Triple, 176 const ToolChain &HostTC, const llvm::opt::ArgList &Args); 177 178 const llvm::Triple *getAuxTriple() const override { 179 return &HostTC.getTriple(); 180 } 181 182 std::string getInputFilename(const InputInfo &Input) const override; 183 184 llvm::opt::DerivedArgList * 185 TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 186 Action::OffloadKind DeviceOffloadKind) const override; 187 void 188 addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, 189 llvm::opt::ArgStringList &CC1Args, 190 Action::OffloadKind DeviceOffloadKind) const override; 191 192 llvm::DenormalMode getDefaultDenormalModeForType( 193 const llvm::opt::ArgList &DriverArgs, const JobAction &JA, 194 const llvm::fltSemantics *FPType = nullptr) const override; 195 196 void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, 197 llvm::opt::ArgStringList &CC1Args) const override; 198 199 void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override; 200 CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; 201 void 202 AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, 203 llvm::opt::ArgStringList &CC1Args) const override; 204 void AddClangCXXStdlibIncludeArgs( 205 const llvm::opt::ArgList &Args, 206 llvm::opt::ArgStringList &CC1Args) const override; 207 void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs, 208 llvm::opt::ArgStringList &CC1Args) const override; 209 210 SanitizerMask getSupportedSanitizers() const override; 211 212 VersionTuple 213 computeMSVCVersion(const Driver *D, 214 const llvm::opt::ArgList &Args) const override; 215 216 const ToolChain &HostTC; 217 218 /// Uses nvptx-arch tool to get arch of the system GPU. Will return error 219 /// if unable to find one. 220 virtual Expected<SmallVector<std::string>> 221 getSystemGPUArchs(const llvm::opt::ArgList &Args) const override; 222 223 protected: 224 Tool *buildAssembler() const override; // ptxas 225 Tool *buildLinker() const override; // fatbinary (ok, not really a linker) 226 }; 227 228 } // end namespace toolchains 229 } // end namespace driver 230 } // end namespace clang 231 232 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CUDA_H 233