xref: /freebsd-src/contrib/llvm-project/clang/lib/Basic/Targets/NVPTX.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- NVPTX.h - Declare NVPTX target feature support ---------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file declares NVPTX TargetInfo objects.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "clang/Basic/Cuda.h"
170b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
180b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h"
190b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
2006c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
21bdd1243dSDimitry Andric #include <optional>
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric namespace clang {
240b57cec5SDimitry Andric namespace targets {
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric static const unsigned NVPTXAddrSpaceMap[] = {
270b57cec5SDimitry Andric     0, // Default
280b57cec5SDimitry Andric     1, // opencl_global
290b57cec5SDimitry Andric     3, // opencl_local
300b57cec5SDimitry Andric     4, // opencl_constant
310b57cec5SDimitry Andric     0, // opencl_private
320b57cec5SDimitry Andric     // FIXME: generic has to be added to the target
330b57cec5SDimitry Andric     0, // opencl_generic
34e8d8bef9SDimitry Andric     1, // opencl_global_device
35e8d8bef9SDimitry Andric     1, // opencl_global_host
360b57cec5SDimitry Andric     1, // cuda_device
370b57cec5SDimitry Andric     4, // cuda_constant
380b57cec5SDimitry Andric     3, // cuda_shared
39fe6060f1SDimitry Andric     1, // sycl_global
40fe6060f1SDimitry Andric     1, // sycl_global_device
41fe6060f1SDimitry Andric     1, // sycl_global_host
42fe6060f1SDimitry Andric     3, // sycl_local
43fe6060f1SDimitry Andric     0, // sycl_private
44480093f4SDimitry Andric     0, // ptr32_sptr
45480093f4SDimitry Andric     0, // ptr32_uptr
46bdd1243dSDimitry Andric     0, // ptr64
47bdd1243dSDimitry Andric     0, // hlsl_groupshared
4806c3fb27SDimitry Andric     // Wasm address space values for this target are dummy values,
4906c3fb27SDimitry Andric     // as it is only enabled for Wasm targets.
5006c3fb27SDimitry Andric     20, // wasm_funcref
510b57cec5SDimitry Andric };
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric /// The DWARF address class. Taken from
540b57cec5SDimitry Andric /// https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
550b57cec5SDimitry Andric static const int NVPTXDWARFAddrSpaceMap[] = {
560b57cec5SDimitry Andric     -1, // Default, opencl_private or opencl_generic - not defined
570b57cec5SDimitry Andric     5,  // opencl_global
580b57cec5SDimitry Andric     -1,
590b57cec5SDimitry Andric     8,  // opencl_local or cuda_shared
600b57cec5SDimitry Andric     4,  // opencl_constant or cuda_constant
610b57cec5SDimitry Andric };
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
640b57cec5SDimitry Andric   static const char *const GCCRegNames[];
65*0fca6ea1SDimitry Andric   OffloadArch GPU;
660b57cec5SDimitry Andric   uint32_t PTXVersion;
670b57cec5SDimitry Andric   std::unique_ptr<TargetInfo> HostTarget;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric public:
700b57cec5SDimitry Andric   NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts,
710b57cec5SDimitry Andric                   unsigned TargetPointerWidth);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   void getTargetDefines(const LangOptions &Opts,
740b57cec5SDimitry Andric                         MacroBuilder &Builder) const override;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   ArrayRef<Builtin::Info> getTargetBuiltins() const override;
770b57cec5SDimitry Andric 
78*0fca6ea1SDimitry Andric   bool useFP16ConversionIntrinsics() const override { return false; }
79*0fca6ea1SDimitry Andric 
800b57cec5SDimitry Andric   bool
810b57cec5SDimitry Andric   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
820b57cec5SDimitry Andric                  StringRef CPU,
830b57cec5SDimitry Andric                  const std::vector<std::string> &FeaturesVec) const override {
84*0fca6ea1SDimitry Andric     if (GPU != OffloadArch::UNUSED)
85*0fca6ea1SDimitry Andric       Features[OffloadArchToString(GPU)] = true;
860b57cec5SDimitry Andric     Features["ptx" + std::to_string(PTXVersion)] = true;
870b57cec5SDimitry Andric     return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
880b57cec5SDimitry Andric   }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   bool hasFeature(StringRef Feature) const override;
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   ArrayRef<const char *> getGCCRegNames() const override;
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
950b57cec5SDimitry Andric     // No aliases.
96bdd1243dSDimitry Andric     return std::nullopt;
970b57cec5SDimitry Andric   }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   bool validateAsmConstraint(const char *&Name,
1000b57cec5SDimitry Andric                              TargetInfo::ConstraintInfo &Info) const override {
1010b57cec5SDimitry Andric     switch (*Name) {
1020b57cec5SDimitry Andric     default:
1030b57cec5SDimitry Andric       return false;
1040b57cec5SDimitry Andric     case 'c':
1050b57cec5SDimitry Andric     case 'h':
1060b57cec5SDimitry Andric     case 'r':
1070b57cec5SDimitry Andric     case 'l':
1080b57cec5SDimitry Andric     case 'f':
1090b57cec5SDimitry Andric     case 'd':
110*0fca6ea1SDimitry Andric     case 'q':
1110b57cec5SDimitry Andric       Info.setAllowsRegister();
1120b57cec5SDimitry Andric       return true;
1130b57cec5SDimitry Andric     }
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric 
11606c3fb27SDimitry Andric   std::string_view getClobbers() const override {
1170b57cec5SDimitry Andric     // FIXME: Is this really right?
1180b57cec5SDimitry Andric     return "";
1190b57cec5SDimitry Andric   }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   BuiltinVaListKind getBuiltinVaListKind() const override {
122*0fca6ea1SDimitry Andric     return TargetInfo::VoidPtrBuiltinVaList;
1230b57cec5SDimitry Andric   }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   bool isValidCPUName(StringRef Name) const override {
126*0fca6ea1SDimitry Andric     return StringToOffloadArch(Name) != OffloadArch::UNKNOWN;
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override {
130*0fca6ea1SDimitry Andric     for (int i = static_cast<int>(OffloadArch::SM_20);
131*0fca6ea1SDimitry Andric          i < static_cast<int>(OffloadArch::Generic); ++i)
132*0fca6ea1SDimitry Andric       Values.emplace_back(OffloadArchToString(static_cast<OffloadArch>(i)));
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   bool setCPU(const std::string &Name) override {
136*0fca6ea1SDimitry Andric     GPU = StringToOffloadArch(Name);
137*0fca6ea1SDimitry Andric     return GPU != OffloadArch::UNKNOWN;
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   void setSupportedOpenCLOpts() override {
1410b57cec5SDimitry Andric     auto &Opts = getSupportedOpenCLOpts();
142e8d8bef9SDimitry Andric     Opts["cl_clang_storage_class_specifiers"] = true;
143e8d8bef9SDimitry Andric     Opts["__cl_clang_function_pointers"] = true;
144e8d8bef9SDimitry Andric     Opts["__cl_clang_variadic_functions"] = true;
145fe6060f1SDimitry Andric     Opts["__cl_clang_non_portable_kernel_param_types"] = true;
146fe6060f1SDimitry Andric     Opts["__cl_clang_bitfields"] = true;
1470b57cec5SDimitry Andric 
148e8d8bef9SDimitry Andric     Opts["cl_khr_fp64"] = true;
149fe6060f1SDimitry Andric     Opts["__opencl_c_fp64"] = true;
150e8d8bef9SDimitry Andric     Opts["cl_khr_byte_addressable_store"] = true;
151e8d8bef9SDimitry Andric     Opts["cl_khr_global_int32_base_atomics"] = true;
152e8d8bef9SDimitry Andric     Opts["cl_khr_global_int32_extended_atomics"] = true;
153e8d8bef9SDimitry Andric     Opts["cl_khr_local_int32_base_atomics"] = true;
154e8d8bef9SDimitry Andric     Opts["cl_khr_local_int32_extended_atomics"] = true;
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric 
157349cc55cSDimitry Andric   const llvm::omp::GV &getGridValue() const override {
158349cc55cSDimitry Andric     return llvm::omp::NVPTXGridValues;
159349cc55cSDimitry Andric   }
160349cc55cSDimitry Andric 
1610b57cec5SDimitry Andric   /// \returns If a target requires an address within a target specific address
1620b57cec5SDimitry Andric   /// space \p AddressSpace to be converted in order to be used, then return the
1630b57cec5SDimitry Andric   /// corresponding target specific DWARF address space.
1640b57cec5SDimitry Andric   ///
165bdd1243dSDimitry Andric   /// \returns Otherwise return std::nullopt and no conversion will be emitted
166bdd1243dSDimitry Andric   /// in the DWARF.
167bdd1243dSDimitry Andric   std::optional<unsigned>
1680b57cec5SDimitry Andric   getDWARFAddressSpace(unsigned AddressSpace) const override {
169bdd1243dSDimitry Andric     if (AddressSpace >= std::size(NVPTXDWARFAddrSpaceMap) ||
1700b57cec5SDimitry Andric         NVPTXDWARFAddrSpaceMap[AddressSpace] < 0)
171bdd1243dSDimitry Andric       return std::nullopt;
1720b57cec5SDimitry Andric     return NVPTXDWARFAddrSpaceMap[AddressSpace];
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
1760b57cec5SDimitry Andric     // CUDA compilations support all of the host's calling conventions.
1770b57cec5SDimitry Andric     //
1780b57cec5SDimitry Andric     // TODO: We should warn if you apply a non-default CC to anything other than
1790b57cec5SDimitry Andric     // a host function.
1800b57cec5SDimitry Andric     if (HostTarget)
1810b57cec5SDimitry Andric       return HostTarget->checkCallingConvention(CC);
1820b57cec5SDimitry Andric     return CCCR_Warning;
1830b57cec5SDimitry Andric   }
1845ffd83dbSDimitry Andric 
1850eae32dcSDimitry Andric   bool hasBitIntType() const override { return true; }
186bdd1243dSDimitry Andric   bool hasBFloat16Type() const override { return true; }
1875f757f3fSDimitry Andric 
188*0fca6ea1SDimitry Andric   OffloadArch getGPU() const { return GPU; }
1890b57cec5SDimitry Andric };
1900b57cec5SDimitry Andric } // namespace targets
1910b57cec5SDimitry Andric } // namespace clang
1920b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
193