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. isValid()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. version()61 CudaVersion version() const { 62 return Version == CudaVersion::NEW ? CudaVersion::PARTIALLY_SUPPORTED 63 : Version; 64 } 65 /// Get the detected Cuda installation path. getInstallPath()66 StringRef getInstallPath() const { return InstallPath; } 67 /// Get the detected path to Cuda's bin directory. getBinPath()68 StringRef getBinPath() const { return BinPath; } 69 /// Get the detected Cuda Include path. getIncludePath()70 StringRef getIncludePath() const { return IncludePath; } 71 /// Get the detected Cuda device library path. getLibDevicePath()72 StringRef getLibDevicePath() const { return LibDevicePath; } 73 /// Get libdevice file for given architecture getLibDeviceFile(StringRef Gpu)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 final : public Tool { 85 public: Assembler(const ToolChain & TC)86 Assembler(const ToolChain &TC) : Tool("NVPTX::Assembler", "ptxas", TC) {} 87 hasIntegratedCPP()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: FatBinary(const ToolChain & TC)100 FatBinary(const ToolChain &TC) : Tool("NVPTX::Linker", "fatbinary", TC) {} 101 hasIntegratedCPP()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: Linker(const ToolChain & TC)113 Linker(const ToolChain &TC) : Tool("NVPTX::Linker", "nvlink", TC) {} 114 hasIntegratedCPP()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. useIntegratedAs()152 bool useIntegratedAs() const override { return false; } isCrossCompiling()153 bool isCrossCompiling() const override { return true; } isPICDefault()154 bool isPICDefault() const override { return false; } isPIEDefault(const llvm::opt::ArgList & Args)155 bool isPIEDefault(const llvm::opt::ArgList &Args) const override { 156 return false; 157 } HasNativeLLVMSupport()158 bool HasNativeLLVMSupport() const override { return true; } isPICDefaultForced()159 bool isPICDefaultForced() const override { return false; } SupportsProfiling()160 bool SupportsProfiling() const override { return false; } 161 IsMathErrnoDefault()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. GetDefaultDwarfVersion()169 unsigned GetDefaultDwarfVersion() const override { return 2; } getMaxDwarfVersion()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 getAuxTriple()192 const llvm::Triple *getAuxTriple() const override { 193 return &HostTC.getTriple(); 194 } 195 HasNativeLLVMSupport()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