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