NVPTX.cpp revision 1.1.1.2
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
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  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
165ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
166  return llvm::makeArrayRef(GCCRegNames);
167}
168
169bool NVPTXTargetInfo::hasFeature(StringRef Feature) const {
170  return llvm::StringSwitch<bool>(Feature)
171      .Cases("ptx", "nvptx", true)
172      .Default(false);
173}
174
175void 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::GFX700:
186      case CudaArch::GFX701:
187      case CudaArch::GFX702:
188      case CudaArch::GFX703:
189      case CudaArch::GFX704:
190      case CudaArch::GFX801:
191      case CudaArch::GFX802:
192      case CudaArch::GFX803:
193      case CudaArch::GFX810:
194      case CudaArch::GFX900:
195      case CudaArch::GFX902:
196      case CudaArch::GFX904:
197      case CudaArch::GFX906:
198      case CudaArch::GFX908:
199      case CudaArch::GFX909:
200      case CudaArch::GFX1010:
201      case CudaArch::GFX1011:
202      case CudaArch::GFX1012:
203      case CudaArch::GFX1030:
204      case CudaArch::LAST:
205        break;
206      case CudaArch::UNKNOWN:
207        assert(false && "No GPU arch when compiling CUDA device code.");
208        return "";
209      case CudaArch::SM_20:
210        return "200";
211      case CudaArch::SM_21:
212        return "210";
213      case CudaArch::SM_30:
214        return "300";
215      case CudaArch::SM_32:
216        return "320";
217      case CudaArch::SM_35:
218        return "350";
219      case CudaArch::SM_37:
220        return "370";
221      case CudaArch::SM_50:
222        return "500";
223      case CudaArch::SM_52:
224        return "520";
225      case CudaArch::SM_53:
226        return "530";
227      case CudaArch::SM_60:
228        return "600";
229      case CudaArch::SM_61:
230        return "610";
231      case CudaArch::SM_62:
232        return "620";
233      case CudaArch::SM_70:
234        return "700";
235      case CudaArch::SM_72:
236        return "720";
237      case CudaArch::SM_75:
238        return "750";
239      case CudaArch::SM_80:
240        return "800";
241      }
242      llvm_unreachable("unhandled CudaArch");
243    }();
244    Builder.defineMacro("__CUDA_ARCH__", CUDAArchCode);
245  }
246}
247
248ArrayRef<Builtin::Info> NVPTXTargetInfo::getTargetBuiltins() const {
249  return llvm::makeArrayRef(BuiltinInfo, clang::NVPTX::LastTSBuiltin -
250                                             Builtin::FirstTSBuiltin);
251}
252