xref: /llvm-project/clang/lib/Basic/Targets/NVPTX.h (revision d92bac8a3ebb19106f6bca6b7613a27c52cb48ab)
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