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