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