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