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