1 //===--- NVPTX.cpp - Implement NVPTX target feature support ---------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements NVPTX TargetInfo objects.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "NVPTX.h"
15 #include "Targets.h"
16 #include "clang/Basic/Builtins.h"
17 #include "clang/Basic/MacroBuilder.h"
18 #include "clang/Basic/TargetBuiltins.h"
19 #include "llvm/ADT/StringSwitch.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 
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   TLSSupported = false;
44   VLASupported = false;
45   AddrSpaceMap = &NVPTXAddrSpaceMap;
46   UseAddrSpaceMapMangling = true;
47 
48   // Define available target features
49   // These must be defined in sorted order!
50   NoAsmVariants = true;
51   GPU = CudaArch::SM_20;
52 
53   if (TargetPointerWidth == 32)
54     resetDataLayout("e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64");
55   else
56     resetDataLayout("e-i64:64-i128:128-v16:16-v32:32-n16:32:64");
57 
58   // If possible, get a TargetInfo for our host triple, so we can match its
59   // types.
60   llvm::Triple HostTriple(Opts.HostTriple);
61   if (!HostTriple.isNVPTX())
62     HostTarget.reset(AllocateTarget(llvm::Triple(Opts.HostTriple), Opts));
63 
64   // If no host target, make some guesses about the data layout and return.
65   if (!HostTarget) {
66     LongWidth = LongAlign = TargetPointerWidth;
67     PointerWidth = PointerAlign = TargetPointerWidth;
68     switch (TargetPointerWidth) {
69     case 32:
70       SizeType = TargetInfo::UnsignedInt;
71       PtrDiffType = TargetInfo::SignedInt;
72       IntPtrType = TargetInfo::SignedInt;
73       break;
74     case 64:
75       SizeType = TargetInfo::UnsignedLong;
76       PtrDiffType = TargetInfo::SignedLong;
77       IntPtrType = TargetInfo::SignedLong;
78       break;
79     default:
80       llvm_unreachable("TargetPointerWidth must be 32 or 64");
81     }
82     return;
83   }
84 
85   // Copy properties from host target.
86   PointerWidth = HostTarget->getPointerWidth(/* AddrSpace = */ 0);
87   PointerAlign = HostTarget->getPointerAlign(/* AddrSpace = */ 0);
88   BoolWidth = HostTarget->getBoolWidth();
89   BoolAlign = HostTarget->getBoolAlign();
90   IntWidth = HostTarget->getIntWidth();
91   IntAlign = HostTarget->getIntAlign();
92   HalfWidth = HostTarget->getHalfWidth();
93   HalfAlign = HostTarget->getHalfAlign();
94   FloatWidth = HostTarget->getFloatWidth();
95   FloatAlign = HostTarget->getFloatAlign();
96   DoubleWidth = HostTarget->getDoubleWidth();
97   DoubleAlign = HostTarget->getDoubleAlign();
98   LongWidth = HostTarget->getLongWidth();
99   LongAlign = HostTarget->getLongAlign();
100   LongLongWidth = HostTarget->getLongLongWidth();
101   LongLongAlign = HostTarget->getLongLongAlign();
102   MinGlobalAlign = HostTarget->getMinGlobalAlign();
103   NewAlign = HostTarget->getNewAlign();
104   DefaultAlignForAttributeAligned =
105       HostTarget->getDefaultAlignForAttributeAligned();
106   SizeType = HostTarget->getSizeType();
107   IntMaxType = HostTarget->getIntMaxType();
108   PtrDiffType = HostTarget->getPtrDiffType(/* AddrSpace = */ 0);
109   IntPtrType = HostTarget->getIntPtrType();
110   WCharType = HostTarget->getWCharType();
111   WIntType = HostTarget->getWIntType();
112   Char16Type = HostTarget->getChar16Type();
113   Char32Type = HostTarget->getChar32Type();
114   Int64Type = HostTarget->getInt64Type();
115   SigAtomicType = HostTarget->getSigAtomicType();
116   ProcessIDType = HostTarget->getProcessIDType();
117 
118   UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();
119   UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment();
120   UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
121   ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();
122 
123   // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
124   // we need those macros to be identical on host and device, because (among
125   // other things) they affect which standard library classes are defined, and
126   // we need all classes to be defined on both the host and device.
127   MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();
128 
129   // Properties intentionally not copied from host:
130   // - LargeArrayMinWidth, LargeArrayAlign: Not visible across the
131   //   host/device boundary.
132   // - SuitableAlign: Not visible across the host/device boundary, and may
133   //   correctly be different on host/device, e.g. if host has wider vector
134   //   types than device.
135   // - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same
136   //   as its double type, but that's not necessarily true on the host.
137   //   TODO: nvcc emits a warning when using long double on device; we should
138   //   do the same.
139 }
140 
141 ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
142   return llvm::makeArrayRef(GCCRegNames);
143 }
144 
145 bool NVPTXTargetInfo::hasFeature(StringRef Feature) const {
146   return llvm::StringSwitch<bool>(Feature)
147       .Cases("ptx", "nvptx", true)
148       .Case("satom", GPU >= CudaArch::SM_60) // Atomics w/ scope.
149       .Default(false);
150 }
151 
152 void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
153                                        MacroBuilder &Builder) const {
154   Builder.defineMacro("__PTX__");
155   Builder.defineMacro("__NVPTX__");
156   if (Opts.CUDAIsDevice) {
157     // Set __CUDA_ARCH__ for the GPU specified.
158     std::string CUDAArchCode = [this] {
159       switch (GPU) {
160       case CudaArch::LAST:
161         break;
162       case CudaArch::UNKNOWN:
163         assert(false && "No GPU arch when compiling CUDA device code.");
164         return "";
165       case CudaArch::SM_20:
166         return "200";
167       case CudaArch::SM_21:
168         return "210";
169       case CudaArch::SM_30:
170         return "300";
171       case CudaArch::SM_32:
172         return "320";
173       case CudaArch::SM_35:
174         return "350";
175       case CudaArch::SM_37:
176         return "370";
177       case CudaArch::SM_50:
178         return "500";
179       case CudaArch::SM_52:
180         return "520";
181       case CudaArch::SM_53:
182         return "530";
183       case CudaArch::SM_60:
184         return "600";
185       case CudaArch::SM_61:
186         return "610";
187       case CudaArch::SM_62:
188         return "620";
189       case CudaArch::SM_70:
190         return "700";
191       case CudaArch::SM_72:
192         return "720";
193       }
194       llvm_unreachable("unhandled CudaArch");
195     }();
196     Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);
197   }
198 }
199 
200 ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const {
201   return llvm::makeArrayRef(BuiltinInfo, clang::NVPTX::LastTSBuiltin -
202                                              Builtin::FirstTSBuiltin);
203 }
204