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