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