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