blob: 92e21c34b8f3527f27a0d5ffe9a2ad236a1764c7 [file] [log] [blame]
Erich Keaneebba5922017-07-21 22:37:03 +00001//===--- 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
21using namespace clang;
22using namespace clang::targets;
23
24const 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
34const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};
35
36NVPTXTargetInfo::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
140ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
141 return llvm::makeArrayRef(GCCRegNames);
142}
143
144bool 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
151void 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
193ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const {
194 return llvm::makeArrayRef(BuiltinInfo, clang::NVPTX::LastTSBuiltin -
195 Builtin::FirstTSBuiltin);
196}