NVPTX.h revision 360784
1//===--- NVPTX.h - Declare NVPTX target feature support ---------*- C++ -*-===//
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 declares NVPTX TargetInfo objects.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
14#define LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
15
16#include "clang/Basic/Cuda.h"
17#include "clang/Basic/TargetInfo.h"
18#include "clang/Basic/TargetOptions.h"
19#include "llvm/ADT/Triple.h"
20#include "llvm/Support/Compiler.h"
21
22namespace clang {
23namespace targets {
24
25static const unsigned NVPTXAddrSpaceMap[] = {
26    0, // Default
27    1, // opencl_global
28    3, // opencl_local
29    4, // opencl_constant
30    0, // opencl_private
31    // FIXME: generic has to be added to the target
32    0, // opencl_generic
33    1, // cuda_device
34    4, // cuda_constant
35    3, // cuda_shared
36    0, // ptr32_sptr
37    0, // ptr32_uptr
38    0  // ptr64
39};
40
41/// The DWARF address class. Taken from
42/// https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
43static const int NVPTXDWARFAddrSpaceMap[] = {
44    -1, // Default, opencl_private or opencl_generic - not defined
45    5,  // opencl_global
46    -1,
47    8,  // opencl_local or cuda_shared
48    4,  // opencl_constant or cuda_constant
49};
50
51class LLVM_LIBRARY_VISIBILITY NVPTXTargetInfo : public TargetInfo {
52  static const char *const GCCRegNames[];
53  static const Builtin::Info BuiltinInfo[];
54  CudaArch GPU;
55  uint32_t PTXVersion;
56  std::unique_ptr<TargetInfo> HostTarget;
57
58public:
59  NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts,
60                  unsigned TargetPointerWidth);
61
62  void getTargetDefines(const LangOptions &Opts,
63                        MacroBuilder &Builder) const override;
64
65  ArrayRef<Builtin::Info> getTargetBuiltins() const override;
66
67  bool
68  initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
69                 StringRef CPU,
70                 const std::vector<std::string> &FeaturesVec) const override {
71    Features[CudaArchToString(GPU)] = true;
72    Features["ptx" + std::to_string(PTXVersion)] = true;
73    return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
74  }
75
76  bool hasFeature(StringRef Feature) const override;
77
78  ArrayRef<const char *> getGCCRegNames() const override;
79
80  ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
81    // No aliases.
82    return None;
83  }
84
85  bool validateAsmConstraint(const char *&Name,
86                             TargetInfo::ConstraintInfo &Info) const override {
87    switch (*Name) {
88    default:
89      return false;
90    case 'c':
91    case 'h':
92    case 'r':
93    case 'l':
94    case 'f':
95    case 'd':
96      Info.setAllowsRegister();
97      return true;
98    }
99  }
100
101  const char *getClobbers() const override {
102    // FIXME: Is this really right?
103    return "";
104  }
105
106  BuiltinVaListKind getBuiltinVaListKind() const override {
107    // FIXME: implement
108    return TargetInfo::CharPtrBuiltinVaList;
109  }
110
111  bool isValidCPUName(StringRef Name) const override {
112    return StringToCudaArch(Name) != CudaArch::UNKNOWN;
113  }
114
115  void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override {
116    for (int i = static_cast<int>(CudaArch::SM_20);
117         i < static_cast<int>(CudaArch::LAST); ++i)
118      Values.emplace_back(CudaArchToString(static_cast<CudaArch>(i)));
119  }
120
121  bool setCPU(const std::string &Name) override {
122    GPU = StringToCudaArch(Name);
123    return GPU != CudaArch::UNKNOWN;
124  }
125
126  void setSupportedOpenCLOpts() override {
127    auto &Opts = getSupportedOpenCLOpts();
128    Opts.support("cl_clang_storage_class_specifiers");
129    Opts.support("cl_khr_gl_sharing");
130    Opts.support("cl_khr_icd");
131
132    Opts.support("cl_khr_fp64");
133    Opts.support("cl_khr_byte_addressable_store");
134    Opts.support("cl_khr_global_int32_base_atomics");
135    Opts.support("cl_khr_global_int32_extended_atomics");
136    Opts.support("cl_khr_local_int32_base_atomics");
137    Opts.support("cl_khr_local_int32_extended_atomics");
138  }
139
140  /// \returns If a target requires an address within a target specific address
141  /// space \p AddressSpace to be converted in order to be used, then return the
142  /// corresponding target specific DWARF address space.
143  ///
144  /// \returns Otherwise return None and no conversion will be emitted in the
145  /// DWARF.
146  Optional<unsigned>
147  getDWARFAddressSpace(unsigned AddressSpace) const override {
148    if (AddressSpace >= llvm::array_lengthof(NVPTXDWARFAddrSpaceMap) ||
149        NVPTXDWARFAddrSpaceMap[AddressSpace] < 0)
150      return llvm::None;
151    return NVPTXDWARFAddrSpaceMap[AddressSpace];
152  }
153
154  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
155    // CUDA compilations support all of the host's calling conventions.
156    //
157    // TODO: We should warn if you apply a non-default CC to anything other than
158    // a host function.
159    if (HostTarget)
160      return HostTarget->checkCallingConvention(CC);
161    return CCCR_Warning;
162  }
163};
164} // namespace targets
165} // namespace clang
166#endif // LLVM_CLANG_LIB_BASIC_TARGETS_NVPTX_H
167