1e5dd7070Spatrick //===--- NVPTX.h - Declare NVPTX target feature support ---------*- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick // 9e5dd7070Spatrick // This file declares NVPTX TargetInfo objects. 10e5dd7070Spatrick // 11e5dd7070Spatrick //===----------------------------------------------------------------------===// 12e5dd7070Spatrick 13e5dd7070Spatrick #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H 14e5dd7070Spatrick #define LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H 15e5dd7070Spatrick 16e5dd7070Spatrick #include "clang/Basic/Cuda.h" 17e5dd7070Spatrick #include "clang/Basic/TargetInfo.h" 18e5dd7070Spatrick #include "clang/Basic/TargetOptions.h" 19e5dd7070Spatrick #include "llvm/ADT/Triple.h" 20e5dd7070Spatrick #include "llvm/Support/Compiler.h" 21*12c85518Srobert #include <optional> 22e5dd7070Spatrick 23e5dd7070Spatrick namespace clang { 24e5dd7070Spatrick namespace targets { 25e5dd7070Spatrick 26e5dd7070Spatrick static const unsigned NVPTXAddrSpaceMap[] = { 27e5dd7070Spatrick 0, // Default 28e5dd7070Spatrick 1, // opencl_global 29e5dd7070Spatrick 3, // opencl_local 30e5dd7070Spatrick 4, // opencl_constant 31e5dd7070Spatrick 0, // opencl_private 32e5dd7070Spatrick // FIXME: generic has to be added to the target 33e5dd7070Spatrick 0, // opencl_generic 34a9ac8606Spatrick 1, // opencl_global_device 35a9ac8606Spatrick 1, // opencl_global_host 36e5dd7070Spatrick 1, // cuda_device 37e5dd7070Spatrick 4, // cuda_constant 38e5dd7070Spatrick 3, // cuda_shared 39a9ac8606Spatrick 1, // sycl_global 40a9ac8606Spatrick 1, // sycl_global_device 41a9ac8606Spatrick 1, // sycl_global_host 42a9ac8606Spatrick 3, // sycl_local 43a9ac8606Spatrick 0, // sycl_private 44e5dd7070Spatrick 0, // ptr32_sptr 45e5dd7070Spatrick 0, // ptr32_uptr 46*12c85518Srobert 0, // ptr64 47*12c85518Srobert 0, // hlsl_groupshared 48e5dd7070Spatrick }; 49e5dd7070Spatrick 50e5dd7070Spatrick /// The DWARF address class. Taken from 51e5dd7070Spatrick /// https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf 52e5dd7070Spatrick static const int NVPTXDWARFAddrSpaceMap[] = { 53e5dd7070Spatrick -1, // Default, opencl_private or opencl_generic - not defined 54e5dd7070Spatrick 5, // opencl_global 55e5dd7070Spatrick -1, 56e5dd7070Spatrick 8, // opencl_local or cuda_shared 57e5dd7070Spatrick 4, // opencl_constant or cuda_constant 58e5dd7070Spatrick }; 59e5dd7070Spatrick 60e5dd7070Spatrick class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo { 61e5dd7070Spatrick static const char *const GCCRegNames[]; 62e5dd7070Spatrick CudaArch GPU; 63e5dd7070Spatrick uint32_t PTXVersion; 64e5dd7070Spatrick std::unique_ptr<TargetInfo> HostTarget; 65e5dd7070Spatrick 66e5dd7070Spatrick public: 67e5dd7070Spatrick NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts, 68e5dd7070Spatrick unsigned TargetPointerWidth); 69e5dd7070Spatrick 70e5dd7070Spatrick void getTargetDefines(const LangOptions &Opts, 71e5dd7070Spatrick MacroBuilder &Builder) const override; 72e5dd7070Spatrick 73e5dd7070Spatrick ArrayRef<Builtin::Info> getTargetBuiltins() const override; 74e5dd7070Spatrick 75e5dd7070Spatrick bool initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec)76e5dd7070Spatrick initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 77e5dd7070Spatrick StringRef CPU, 78e5dd7070Spatrick const std::vector<std::string> &FeaturesVec) const override { 79e5dd7070Spatrick Features[CudaArchToString(GPU)] = true; 80e5dd7070Spatrick Features["ptx" + std::to_string(PTXVersion)] = true; 81e5dd7070Spatrick return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 82e5dd7070Spatrick } 83e5dd7070Spatrick 84e5dd7070Spatrick bool hasFeature(StringRef Feature) const override; 85e5dd7070Spatrick 86e5dd7070Spatrick ArrayRef<const char *> getGCCRegNames() const override; 87e5dd7070Spatrick getGCCRegAliases()88e5dd7070Spatrick ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 89e5dd7070Spatrick // No aliases. 90*12c85518Srobert return std::nullopt; 91e5dd7070Spatrick } 92e5dd7070Spatrick validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info)93e5dd7070Spatrick bool validateAsmConstraint(const char *&Name, 94e5dd7070Spatrick TargetInfo::ConstraintInfo &Info) const override { 95e5dd7070Spatrick switch (*Name) { 96e5dd7070Spatrick default: 97e5dd7070Spatrick return false; 98e5dd7070Spatrick case 'c': 99e5dd7070Spatrick case 'h': 100e5dd7070Spatrick case 'r': 101e5dd7070Spatrick case 'l': 102e5dd7070Spatrick case 'f': 103e5dd7070Spatrick case 'd': 104e5dd7070Spatrick Info.setAllowsRegister(); 105e5dd7070Spatrick return true; 106e5dd7070Spatrick } 107e5dd7070Spatrick } 108e5dd7070Spatrick getClobbers()109e5dd7070Spatrick const char *getClobbers() const override { 110e5dd7070Spatrick // FIXME: Is this really right? 111e5dd7070Spatrick return ""; 112e5dd7070Spatrick } 113e5dd7070Spatrick getBuiltinVaListKind()114e5dd7070Spatrick BuiltinVaListKind getBuiltinVaListKind() const override { 115e5dd7070Spatrick // FIXME: implement 116e5dd7070Spatrick return TargetInfo::CharPtrBuiltinVaList; 117e5dd7070Spatrick } 118e5dd7070Spatrick isValidCPUName(StringRef Name)119e5dd7070Spatrick bool isValidCPUName(StringRef Name) const override { 120e5dd7070Spatrick return StringToCudaArch(Name) != CudaArch::UNKNOWN; 121e5dd7070Spatrick } 122e5dd7070Spatrick fillValidCPUList(SmallVectorImpl<StringRef> & Values)123e5dd7070Spatrick void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override { 124e5dd7070Spatrick for (int i = static_cast<int>(CudaArch::SM_20); 125*12c85518Srobert i < static_cast<int>(CudaArch::Generic); ++i) 126e5dd7070Spatrick Values.emplace_back(CudaArchToString(static_cast<CudaArch>(i))); 127e5dd7070Spatrick } 128e5dd7070Spatrick setCPU(const std::string & Name)129e5dd7070Spatrick bool setCPU(const std::string &Name) override { 130e5dd7070Spatrick GPU = StringToCudaArch(Name); 131e5dd7070Spatrick return GPU != CudaArch::UNKNOWN; 132e5dd7070Spatrick } 133e5dd7070Spatrick setSupportedOpenCLOpts()134e5dd7070Spatrick void setSupportedOpenCLOpts() override { 135e5dd7070Spatrick auto &Opts = getSupportedOpenCLOpts(); 136a9ac8606Spatrick Opts["cl_clang_storage_class_specifiers"] = true; 137a9ac8606Spatrick Opts["__cl_clang_function_pointers"] = true; 138a9ac8606Spatrick Opts["__cl_clang_variadic_functions"] = true; 139a9ac8606Spatrick Opts["__cl_clang_non_portable_kernel_param_types"] = true; 140a9ac8606Spatrick Opts["__cl_clang_bitfields"] = true; 141e5dd7070Spatrick 142a9ac8606Spatrick Opts["cl_khr_fp64"] = true; 143a9ac8606Spatrick Opts["__opencl_c_fp64"] = true; 144a9ac8606Spatrick Opts["cl_khr_byte_addressable_store"] = true; 145a9ac8606Spatrick Opts["cl_khr_global_int32_base_atomics"] = true; 146a9ac8606Spatrick Opts["cl_khr_global_int32_extended_atomics"] = true; 147a9ac8606Spatrick Opts["cl_khr_local_int32_base_atomics"] = true; 148a9ac8606Spatrick Opts["cl_khr_local_int32_extended_atomics"] = true; 149e5dd7070Spatrick } 150e5dd7070Spatrick getGridValue()151*12c85518Srobert const llvm::omp::GV &getGridValue() const override { 152*12c85518Srobert return llvm::omp::NVPTXGridValues; 153*12c85518Srobert } 154*12c85518Srobert 155e5dd7070Spatrick /// \returns If a target requires an address within a target specific address 156e5dd7070Spatrick /// space \p AddressSpace to be converted in order to be used, then return the 157e5dd7070Spatrick /// corresponding target specific DWARF address space. 158e5dd7070Spatrick /// 159*12c85518Srobert /// \returns Otherwise return std::nullopt and no conversion will be emitted 160*12c85518Srobert /// in the DWARF. 161*12c85518Srobert std::optional<unsigned> getDWARFAddressSpace(unsigned AddressSpace)162e5dd7070Spatrick getDWARFAddressSpace(unsigned AddressSpace) const override { 163*12c85518Srobert if (AddressSpace >= std::size(NVPTXDWARFAddrSpaceMap) || 164e5dd7070Spatrick NVPTXDWARFAddrSpaceMap[AddressSpace] < 0) 165*12c85518Srobert return std::nullopt; 166e5dd7070Spatrick return NVPTXDWARFAddrSpaceMap[AddressSpace]; 167e5dd7070Spatrick } 168e5dd7070Spatrick checkCallingConvention(CallingConv CC)169e5dd7070Spatrick CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 170e5dd7070Spatrick // CUDA compilations support all of the host's calling conventions. 171e5dd7070Spatrick // 172e5dd7070Spatrick // TODO: We should warn if you apply a non-default CC to anything other than 173e5dd7070Spatrick // a host function. 174e5dd7070Spatrick if (HostTarget) 175e5dd7070Spatrick return HostTarget->checkCallingConvention(CC); 176e5dd7070Spatrick return CCCR_Warning; 177e5dd7070Spatrick } 178ec727ea7Spatrick hasBitIntType()179*12c85518Srobert bool hasBitIntType() const override { return true; } hasBFloat16Type()180*12c85518Srobert bool hasBFloat16Type() const override { return true; } getBFloat16Mangling()181*12c85518Srobert const char *getBFloat16Mangling() const override { return "u6__bf16"; }; 182e5dd7070Spatrick }; 183e5dd7070Spatrick } // namespace targets 184e5dd7070Spatrick } // namespace clang 185e5dd7070Spatrick #endif // LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H 186