xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/NVPTX.cpp (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
1 //===--- NVPTX.cpp - Implement NVPTX target feature support ---------------===//
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 implements NVPTX TargetInfo objects.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "NVPTX.h"
14 #include "Targets.h"
15 #include "clang/Basic/Builtins.h"
16 #include "clang/Basic/MacroBuilder.h"
17 #include "clang/Basic/TargetBuiltins.h"
18 #include "llvm/ADT/StringSwitch.h"
19 
20 using namespace clang;
21 using namespace clang::targets;
22 
23 static constexpr Builtin::Info BuiltinInfo[] = {
24 #define BUILTIN(ID, TYPE, ATTRS)                                               \
25   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
26 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
27   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},
28 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
29   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
30 #include "clang/Basic/BuiltinsNVPTX.def"
31 };
32 
33 const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};
34 
35 NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
36                                  const TargetOptions &Opts,
37                                  unsigned TargetPointerWidth)
38     : TargetInfo(Triple) {
39   assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) &&
40          "NVPTX only supports 32- and 64-bit modes.");
41 
42   PTXVersion = 32;
43   for (const StringRef Feature : Opts.FeaturesAsWritten) {
44     int PTXV;
45     if (!Feature.startswith("+ptx") ||
46         Feature.drop_front(4).getAsInteger(10, PTXV))
47       continue;
48     PTXVersion = PTXV; // TODO: should it be max(PTXVersion, PTXV)?
49   }
50 
51   TLSSupported = false;
52   VLASupported = false;
53   AddrSpaceMap = &NVPTXAddrSpaceMap;
54   UseAddrSpaceMapMangling = true;
55   // __bf16 is always available as a load/store only type.
56   BFloat16Width = BFloat16Align = 16;
57   BFloat16Format = &llvm::APFloat::BFloat();
58 
59   // Define available target features
60   // These must be defined in sorted order!
61   NoAsmVariants = true;
62   GPU = CudaArch::SM_20;
63 
64   if (TargetPointerWidth == 32)
65     resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
66   else if (Opts.NVPTXUseShortPointers)
67     resetDataLayout(
68         "e-p3:32:32-p4:32:32-p5:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
69   else
70     resetDataLayout("e-i64:64-i128:128-v16:16-v32:32-n16:32:64");
71 
72   // If possible, get a TargetInfo for our host triple, so we can match its
73   // types.
74   llvm::Triple HostTriple(Opts.HostTriple);
75   if (!HostTriple.isNVPTX())
76     HostTarget.reset(AllocateTarget(llvm::Triple(Opts.HostTriple), Opts));
77 
78   // If no host target, make some guesses about the data layout and return.
79   if (!HostTarget) {
80     LongWidth = LongAlign = TargetPointerWidth;
81     PointerWidth = PointerAlign = TargetPointerWidth;
82     switch (TargetPointerWidth) {
83     case 32:
84       SizeType = TargetInfo::UnsignedInt;
85       PtrDiffType = TargetInfo::SignedInt;
86       IntPtrType = TargetInfo::SignedInt;
87       break;
88     case 64:
89       SizeType = TargetInfo::UnsignedLong;
90       PtrDiffType = TargetInfo::SignedLong;
91       IntPtrType = TargetInfo::SignedLong;
92       break;
93     default:
94       llvm_unreachable("TargetPointerWidth must be 32 or 64");
95     }
96     return;
97   }
98 
99   // Copy properties from host target.
100   PointerWidth = HostTarget->getPointerWidth(LangAS::Default);
101   PointerAlign = HostTarget->getPointerAlign(LangAS::Default);
102   BoolWidth = HostTarget->getBoolWidth();
103   BoolAlign = HostTarget->getBoolAlign();
104   IntWidth = HostTarget->getIntWidth();
105   IntAlign = HostTarget->getIntAlign();
106   HalfWidth = HostTarget->getHalfWidth();
107   HalfAlign = HostTarget->getHalfAlign();
108   FloatWidth = HostTarget->getFloatWidth();
109   FloatAlign = HostTarget->getFloatAlign();
110   DoubleWidth = HostTarget->getDoubleWidth();
111   DoubleAlign = HostTarget->getDoubleAlign();
112   LongWidth = HostTarget->getLongWidth();
113   LongAlign = HostTarget->getLongAlign();
114   LongLongWidth = HostTarget->getLongLongWidth();
115   LongLongAlign = HostTarget->getLongLongAlign();
116   MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0);
117   NewAlign = HostTarget->getNewAlign();
118   DefaultAlignForAttributeAligned =
119       HostTarget->getDefaultAlignForAttributeAligned();
120   SizeType = HostTarget->getSizeType();
121   IntMaxType = HostTarget->getIntMaxType();
122   PtrDiffType = HostTarget->getPtrDiffType(LangAS::Default);
123   IntPtrType = HostTarget->getIntPtrType();
124   WCharType = HostTarget->getWCharType();
125   WIntType = HostTarget->getWIntType();
126   Char16Type = HostTarget->getChar16Type();
127   Char32Type = HostTarget->getChar32Type();
128   Int64Type = HostTarget->getInt64Type();
129   SigAtomicType = HostTarget->getSigAtomicType();
130   ProcessIDType = HostTarget->getProcessIDType();
131 
132   UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();
133   UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment();
134   UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
135   ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();
136 
137   // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
138   // we need those macros to be identical on host and device, because (among
139   // other things) they affect which standard library classes are defined, and
140   // we need all classes to be defined on both the host and device.
141   MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();
142 
143   // Properties intentionally not copied from host:
144   // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the
145   //   host/device boundary.
146   // - SuitableAlign: Not visible across the host/device boundary, and may
147   //   correctly be different on host/device, e.g. if host has wider vector
148   //   types than device.
149   // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same
150   //   as its double type, but that's not necessarily true on the host.
151   //   TODO: nvcc emits a warning when using long double on device; we should
152   //   do the same.
153 }
154 
155 ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
156   return llvm::ArrayRef(GCCRegNames);
157 }
158 
159 bool NVPTXTargetInfo::hasFeature(StringRef Feature) const {
160   return llvm::StringSwitch<bool>(Feature)
161       .Cases("ptx", "nvptx", true)
162       .Default(false);
163 }
164 
165 void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
166                                        MacroBuilder &Builder) const {
167   Builder.defineMacro("__PTX__");
168   Builder.defineMacro("__NVPTX__");
169   if (Opts.CUDAIsDevice || Opts.OpenMPIsDevice) {
170     // Set __CUDA_ARCH__ for the GPU specified.
171     std::string CUDAArchCode = [this] {
172       switch (GPU) {
173       case CudaArch::GFX600:
174       case CudaArch::GFX601:
175       case CudaArch::GFX602:
176       case CudaArch::GFX700:
177       case CudaArch::GFX701:
178       case CudaArch::GFX702:
179       case CudaArch::GFX703:
180       case CudaArch::GFX704:
181       case CudaArch::GFX705:
182       case CudaArch::GFX801:
183       case CudaArch::GFX802:
184       case CudaArch::GFX803:
185       case CudaArch::GFX805:
186       case CudaArch::GFX810:
187       case CudaArch::GFX900:
188       case CudaArch::GFX902:
189       case CudaArch::GFX904:
190       case CudaArch::GFX906:
191       case CudaArch::GFX908:
192       case CudaArch::GFX909:
193       case CudaArch::GFX90a:
194       case CudaArch::GFX90c:
195       case CudaArch::GFX940:
196       case CudaArch::GFX1010:
197       case CudaArch::GFX1011:
198       case CudaArch::GFX1012:
199       case CudaArch::GFX1013:
200       case CudaArch::GFX1030:
201       case CudaArch::GFX1031:
202       case CudaArch::GFX1032:
203       case CudaArch::GFX1033:
204       case CudaArch::GFX1034:
205       case CudaArch::GFX1035:
206       case CudaArch::GFX1036:
207       case CudaArch::GFX1100:
208       case CudaArch::GFX1101:
209       case CudaArch::GFX1102:
210       case CudaArch::GFX1103:
211       case CudaArch::Generic:
212       case CudaArch::LAST:
213         break;
214       case CudaArch::UNUSED:
215       case CudaArch::UNKNOWN:
216         assert(false && "No GPU arch when compiling CUDA device code.");
217         return "";
218       case CudaArch::SM_20:
219         return "200";
220       case CudaArch::SM_21:
221         return "210";
222       case CudaArch::SM_30:
223         return "300";
224       case CudaArch::SM_32:
225         return "320";
226       case CudaArch::SM_35:
227         return "350";
228       case CudaArch::SM_37:
229         return "370";
230       case CudaArch::SM_50:
231         return "500";
232       case CudaArch::SM_52:
233         return "520";
234       case CudaArch::SM_53:
235         return "530";
236       case CudaArch::SM_60:
237         return "600";
238       case CudaArch::SM_61:
239         return "610";
240       case CudaArch::SM_62:
241         return "620";
242       case CudaArch::SM_70:
243         return "700";
244       case CudaArch::SM_72:
245         return "720";
246       case CudaArch::SM_75:
247         return "750";
248       case CudaArch::SM_80:
249         return "800";
250       case CudaArch::SM_86:
251         return "860";
252       case CudaArch::SM_87:
253         return "870";
254       case CudaArch::SM_89:
255         return "890";
256       case CudaArch::SM_90:
257         return "900";
258       }
259       llvm_unreachable("unhandled CudaArch");
260     }();
261     Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);
262   }
263 }
264 
265 ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const {
266   return llvm::ArrayRef(BuiltinInfo,
267                         clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin);
268 }
269