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