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
24namespace clang {
25namespace targets {
26
27static 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 0, // hlsl_private
51 0, // hlsl_device
52 0, // hlsl_input
53 0, // hlsl_output
54 0, // hlsl_push_constant
55 // Wasm address space values for this target are dummy values,
56 // as it is only enabled for Wasm targets.
57 20, // wasm_funcref
58};
59
60/// The DWARF address class. Taken from
61/// https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
62static const int NVPTXDWARFAddrSpaceMap[] = {
63 -1, // Default, opencl_private or opencl_generic - not defined
64 5, // opencl_global
65 -1,
66 8, // opencl_local or cuda_shared
67 4, // opencl_constant or cuda_constant
68};
69
70class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
71 static const char *const GCCRegNames[];
72 OffloadArch GPU;
73 uint32_t PTXVersion;
74 std::unique_ptr<TargetInfo> HostTarget;
75
76public:
77 NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts,
78 unsigned TargetPointerWidth);
79
80 void getTargetDefines(const LangOptions &Opts,
81 MacroBuilder &Builder) const override;
82
83 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
84
85 bool useFP16ConversionIntrinsics() const override { return false; }
86
87 bool isCLZForZeroUndef() const override { return false; }
88
89 bool
90 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
91 StringRef CPU,
92 const std::vector<std::string> &FeaturesVec) const override {
93 if (GPU != OffloadArch::Unused)
94 Features[OffloadArchToString(A: GPU)] = true;
95 // Only add PTX feature if explicitly requested. Otherwise, let the backend
96 // use the minimum required PTX version for the target SM.
97 if (PTXVersion != 0)
98 Features["ptx" + std::to_string(val: PTXVersion)] = true;
99 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec: FeaturesVec);
100 }
101
102 bool hasFeature(StringRef Feature) const override;
103
104 virtual bool isAddressSpaceSupersetOf(LangAS A, LangAS B) const override {
105 // The generic address space AS(0) is a superset of all the other address
106 // spaces used by the backend target.
107 return A == B ||
108 ((A == LangAS::Default ||
109 (isTargetAddressSpace(AS: A) &&
110 toTargetAddressSpace(AS: A) ==
111 llvm::NVPTXAS::ADDRESS_SPACE_GENERIC)) &&
112 isTargetAddressSpace(AS: B) &&
113 toTargetAddressSpace(AS: B) >= llvm::NVPTXAS::ADDRESS_SPACE_GENERIC &&
114 toTargetAddressSpace(AS: B) <= llvm::NVPTXAS::ADDRESS_SPACE_LOCAL &&
115 toTargetAddressSpace(AS: B) != 2);
116 }
117
118 ArrayRef<const char *> getGCCRegNames() const override;
119
120 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
121 // No aliases.
122 return {};
123 }
124
125 bool validateAsmConstraint(const char *&Name,
126 TargetInfo::ConstraintInfo &Info) const override {
127 switch (*Name) {
128 default:
129 return false;
130 case 'c':
131 case 'h':
132 case 'r':
133 case 'l':
134 case 'f':
135 case 'd':
136 case 'q':
137 Info.setAllowsRegister();
138 return true;
139 }
140 }
141
142 std::string_view getClobbers() const override {
143 // FIXME: Is this really right?
144 return "";
145 }
146
147 BuiltinVaListKind getBuiltinVaListKind() const override {
148 return TargetInfo::CharPtrBuiltinVaList;
149 }
150
151 bool isValidCPUName(StringRef Name) const override {
152 return StringToOffloadArch(S: Name) != OffloadArch::Unknown;
153 }
154
155 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override {
156 for (int i = static_cast<int>(OffloadArch::SM_20);
157 i < static_cast<int>(OffloadArch::Generic); ++i)
158 Values.emplace_back(Args: OffloadArchToString(A: static_cast<OffloadArch>(i)));
159 }
160
161 bool setCPU(const std::string &Name) override {
162 GPU = StringToOffloadArch(S: Name);
163 return GPU != OffloadArch::Unknown;
164 }
165
166 void setSupportedOpenCLOpts() override {
167 auto &Opts = getSupportedOpenCLOpts();
168 Opts["cl_clang_storage_class_specifiers"] = true;
169 Opts["__cl_clang_function_pointers"] = true;
170 Opts["__cl_clang_variadic_functions"] = true;
171 Opts["__cl_clang_function_scope_local_variables"] = true;
172 Opts["__cl_clang_non_portable_kernel_param_types"] = true;
173 Opts["__cl_clang_bitfields"] = true;
174
175 Opts["cl_khr_fp64"] = true;
176 Opts["__opencl_c_fp64"] = true;
177 Opts["cl_khr_byte_addressable_store"] = true;
178 Opts["cl_khr_global_int32_base_atomics"] = true;
179 Opts["cl_khr_global_int32_extended_atomics"] = true;
180 Opts["cl_khr_local_int32_base_atomics"] = true;
181 Opts["cl_khr_local_int32_extended_atomics"] = true;
182
183 Opts["__opencl_c_images"] = true;
184 Opts["__opencl_c_3d_image_writes"] = true;
185 Opts["cl_khr_3d_image_writes"] = true;
186
187 Opts["__opencl_c_generic_address_space"] = true;
188 }
189
190 const llvm::omp::GV &getGridValue() const override {
191 return llvm::omp::NVPTXGridValues;
192 }
193
194 /// \returns If a target requires an address within a target specific address
195 /// space \p AddressSpace to be converted in order to be used, then return the
196 /// corresponding target specific DWARF address space.
197 ///
198 /// \returns Otherwise return std::nullopt and no conversion will be emitted
199 /// in the DWARF.
200 std::optional<unsigned>
201 getDWARFAddressSpace(unsigned AddressSpace) const override {
202 if (AddressSpace >= std::size(NVPTXDWARFAddrSpaceMap) ||
203 NVPTXDWARFAddrSpaceMap[AddressSpace] < 0)
204 return std::nullopt;
205 return NVPTXDWARFAddrSpaceMap[AddressSpace];
206 }
207
208 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
209 // CUDA compilations support all of the host's calling conventions.
210 //
211 // TODO: We should warn if you apply a non-default CC to anything other than
212 // a host function.
213 if (HostTarget)
214 return HostTarget->checkCallingConvention(CC);
215 return CC == CC_DeviceKernel ? CCCR_OK : CCCR_Warning;
216 }
217
218 bool hasBitIntType() const override { return true; }
219 bool hasBFloat16Type() const override { return true; }
220
221 OffloadArch getGPU() const { return GPU; }
222};
223} // namespace targets
224} // namespace clang
225#endif // LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
226