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