xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/SPIR.h (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
1 //===--- SPIR.h - Declare SPIR and SPIR-V 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 SPIR and SPIR-V TargetInfo objects.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
14 #define LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
15 
16 #include "Targets.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 
23 namespace clang {
24 namespace targets {
25 
26 // Used by both the SPIR and SPIR-V targets.
27 static const unsigned SPIRDefIsPrivMap[] = {
28     0, // Default
29     1, // opencl_global
30     3, // opencl_local
31     2, // opencl_constant
32     0, // opencl_private
33     4, // opencl_generic
34     5, // opencl_global_device
35     6, // opencl_global_host
36     0, // cuda_device
37     0, // cuda_constant
38     0, // cuda_shared
39     // SYCL address space values for this map are dummy
40     0, // sycl_global
41     0, // sycl_global_device
42     0, // sycl_global_host
43     0, // sycl_local
44     0, // sycl_private
45     0, // ptr32_sptr
46     0, // ptr32_uptr
47     0, // ptr64
48     0, // hlsl_groupshared
49     // Wasm address space values for this target are dummy values,
50     // as it is only enabled for Wasm targets.
51     20, // wasm_funcref
52 };
53 
54 // Used by both the SPIR and SPIR-V targets.
55 static const unsigned SPIRDefIsGenMap[] = {
56     4, // Default
57     // OpenCL address space values for this map are dummy and they can't be used
58     0, // opencl_global
59     0, // opencl_local
60     0, // opencl_constant
61     0, // opencl_private
62     0, // opencl_generic
63     0, // opencl_global_device
64     0, // opencl_global_host
65     // cuda_* address space mapping is intended for HIPSPV (HIP to SPIR-V
66     // translation). This mapping is enabled when the language mode is HIP.
67     1, // cuda_device
68     // cuda_constant pointer can be casted to default/"flat" pointer, but in
69     // SPIR-V casts between constant and generic pointers are not allowed. For
70     // this reason cuda_constant is mapped to SPIR-V CrossWorkgroup.
71     1, // cuda_constant
72     3, // cuda_shared
73     1, // sycl_global
74     5, // sycl_global_device
75     6, // sycl_global_host
76     3, // sycl_local
77     0, // sycl_private
78     0, // ptr32_sptr
79     0, // ptr32_uptr
80     0, // ptr64
81     0, // hlsl_groupshared
82     // Wasm address space values for this target are dummy values,
83     // as it is only enabled for Wasm targets.
84     20, // wasm_funcref
85 };
86 
87 // Base class for SPIR and SPIR-V target info.
88 class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
89   std::unique_ptr<TargetInfo> HostTarget;
90 
91 protected:
92   BaseSPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
93       : TargetInfo(Triple) {
94     assert((Triple.isSPIR() || Triple.isSPIRV()) &&
95            "Invalid architecture for SPIR or SPIR-V.");
96     TLSSupported = false;
97     VLASupported = false;
98     LongWidth = LongAlign = 64;
99     AddrSpaceMap = &SPIRDefIsPrivMap;
100     UseAddrSpaceMapMangling = true;
101     HasLegalHalfType = true;
102     HasFloat16 = true;
103     // Define available target features
104     // These must be defined in sorted order!
105     NoAsmVariants = true;
106 
107     llvm::Triple HostTriple(Opts.HostTriple);
108     if (!HostTriple.isSPIR() && !HostTriple.isSPIRV() &&
109         HostTriple.getArch() != llvm::Triple::UnknownArch) {
110       HostTarget = AllocateTarget(llvm::Triple(Opts.HostTriple), Opts);
111 
112       // Copy properties from host target.
113       BoolWidth = HostTarget->getBoolWidth();
114       BoolAlign = HostTarget->getBoolAlign();
115       IntWidth = HostTarget->getIntWidth();
116       IntAlign = HostTarget->getIntAlign();
117       HalfWidth = HostTarget->getHalfWidth();
118       HalfAlign = HostTarget->getHalfAlign();
119       FloatWidth = HostTarget->getFloatWidth();
120       FloatAlign = HostTarget->getFloatAlign();
121       DoubleWidth = HostTarget->getDoubleWidth();
122       DoubleAlign = HostTarget->getDoubleAlign();
123       LongWidth = HostTarget->getLongWidth();
124       LongAlign = HostTarget->getLongAlign();
125       LongLongWidth = HostTarget->getLongLongWidth();
126       LongLongAlign = HostTarget->getLongLongAlign();
127       MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0);
128       NewAlign = HostTarget->getNewAlign();
129       DefaultAlignForAttributeAligned =
130           HostTarget->getDefaultAlignForAttributeAligned();
131       IntMaxType = HostTarget->getIntMaxType();
132       WCharType = HostTarget->getWCharType();
133       WIntType = HostTarget->getWIntType();
134       Char16Type = HostTarget->getChar16Type();
135       Char32Type = HostTarget->getChar32Type();
136       Int64Type = HostTarget->getInt64Type();
137       SigAtomicType = HostTarget->getSigAtomicType();
138       ProcessIDType = HostTarget->getProcessIDType();
139 
140       UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();
141       UseZeroLengthBitfieldAlignment =
142           HostTarget->useZeroLengthBitfieldAlignment();
143       UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
144       ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();
145 
146       // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
147       // we need those macros to be identical on host and device, because (among
148       // other things) they affect which standard library classes are defined,
149       // and we need all classes to be defined on both the host and device.
150       MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();
151     }
152   }
153 
154 public:
155   // SPIR supports the half type and the only llvm intrinsic allowed in SPIR is
156   // memcpy as per section 3 of the SPIR spec.
157   bool useFP16ConversionIntrinsics() const override { return false; }
158 
159   ArrayRef<Builtin::Info> getTargetBuiltins() const override {
160     return std::nullopt;
161   }
162 
163   std::string_view getClobbers() const override { return ""; }
164 
165   ArrayRef<const char *> getGCCRegNames() const override {
166     return std::nullopt;
167   }
168 
169   bool validateAsmConstraint(const char *&Name,
170                              TargetInfo::ConstraintInfo &info) const override {
171     return true;
172   }
173 
174   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
175     return std::nullopt;
176   }
177 
178   BuiltinVaListKind getBuiltinVaListKind() const override {
179     return TargetInfo::VoidPtrBuiltinVaList;
180   }
181 
182   std::optional<unsigned>
183   getDWARFAddressSpace(unsigned AddressSpace) const override {
184     return AddressSpace;
185   }
186 
187   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
188     return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK
189                                                             : CCCR_Warning;
190   }
191 
192   CallingConv getDefaultCallingConv() const override {
193     return CC_SpirFunction;
194   }
195 
196   void setAddressSpaceMap(bool DefaultIsGeneric) {
197     AddrSpaceMap = DefaultIsGeneric ? &SPIRDefIsGenMap : &SPIRDefIsPrivMap;
198   }
199 
200   void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override {
201     TargetInfo::adjust(Diags, Opts);
202     // FIXME: SYCL specification considers unannotated pointers and references
203     // to be pointing to the generic address space. See section 5.9.3 of
204     // SYCL 2020 specification.
205     // Currently, there is no way of representing SYCL's and HIP/CUDA's default
206     // address space language semantic along with the semantics of embedded C's
207     // default address space in the same address space map. Hence the map needs
208     // to be reset to allow mapping to the desired value of 'Default' entry for
209     // SYCL and HIP/CUDA.
210     setAddressSpaceMap(
211         /*DefaultIsGeneric=*/Opts.SYCLIsDevice ||
212         // The address mapping from HIP/CUDA language for device code is only
213         // defined for SPIR-V.
214         (getTriple().isSPIRV() && Opts.CUDAIsDevice));
215   }
216 
217   void setSupportedOpenCLOpts() override {
218     // Assume all OpenCL extensions and optional core features are supported
219     // for SPIR and SPIR-V since they are generic targets.
220     supportAllOpenCLOpts();
221   }
222 
223   bool hasBitIntType() const override { return true; }
224 
225   bool hasInt128Type() const override { return false; }
226 };
227 
228 class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public BaseSPIRTargetInfo {
229 public:
230   SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
231       : BaseSPIRTargetInfo(Triple, Opts) {
232     assert(Triple.isSPIR() && "Invalid architecture for SPIR.");
233     assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
234            "SPIR target must use unknown OS");
235     assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
236            "SPIR target must use unknown environment type");
237   }
238 
239   void getTargetDefines(const LangOptions &Opts,
240                         MacroBuilder &Builder) const override;
241 
242   bool hasFeature(StringRef Feature) const override {
243     return Feature == "spir";
244   }
245 
246   bool checkArithmeticFenceSupported() const override { return true; }
247 };
248 
249 class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo {
250 public:
251   SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
252       : SPIRTargetInfo(Triple, Opts) {
253     assert(Triple.getArch() == llvm::Triple::spir &&
254            "Invalid architecture for 32-bit SPIR.");
255     PointerWidth = PointerAlign = 32;
256     SizeType = TargetInfo::UnsignedInt;
257     PtrDiffType = IntPtrType = TargetInfo::SignedInt;
258     resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
259                     "v96:128-v192:256-v256:256-v512:512-v1024:1024");
260   }
261 
262   void getTargetDefines(const LangOptions &Opts,
263                         MacroBuilder &Builder) const override;
264 };
265 
266 class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo {
267 public:
268   SPIR64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
269       : SPIRTargetInfo(Triple, Opts) {
270     assert(Triple.getArch() == llvm::Triple::spir64 &&
271            "Invalid architecture for 64-bit SPIR.");
272     PointerWidth = PointerAlign = 64;
273     SizeType = TargetInfo::UnsignedLong;
274     PtrDiffType = IntPtrType = TargetInfo::SignedLong;
275     resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
276                     "v96:128-v192:256-v256:256-v512:512-v1024:1024");
277   }
278 
279   void getTargetDefines(const LangOptions &Opts,
280                         MacroBuilder &Builder) const override;
281 };
282 
283 class LLVM_LIBRARY_VISIBILITY BaseSPIRVTargetInfo : public BaseSPIRTargetInfo {
284 public:
285   BaseSPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
286       : BaseSPIRTargetInfo(Triple, Opts) {
287     assert(Triple.isSPIRV() && "Invalid architecture for SPIR-V.");
288   }
289 
290   bool hasFeature(StringRef Feature) const override {
291     return Feature == "spirv";
292   }
293 
294   void getTargetDefines(const LangOptions &Opts,
295                         MacroBuilder &Builder) const override;
296 };
297 
298 class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRVTargetInfo {
299 public:
300   SPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
301       : BaseSPIRVTargetInfo(Triple, Opts) {
302     assert(Triple.getArch() == llvm::Triple::spirv &&
303            "Invalid architecture for Logical SPIR-V.");
304     assert(Triple.getOS() == llvm::Triple::ShaderModel &&
305            "Logical SPIR-V requires a valid ShaderModel.");
306     assert(Triple.getEnvironment() >= llvm::Triple::Pixel &&
307            Triple.getEnvironment() <= llvm::Triple::Amplification &&
308            "Logical SPIR-V environment must be a valid shader stage.");
309 
310     // SPIR-V IDs are represented with a single 32-bit word.
311     SizeType = TargetInfo::UnsignedInt;
312     resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
313                     "v96:128-v192:256-v256:256-v512:512-v1024:1024");
314   }
315 
316   void getTargetDefines(const LangOptions &Opts,
317                         MacroBuilder &Builder) const override;
318 };
319 
320 class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public BaseSPIRVTargetInfo {
321 public:
322   SPIRV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
323       : BaseSPIRVTargetInfo(Triple, Opts) {
324     assert(Triple.getArch() == llvm::Triple::spirv32 &&
325            "Invalid architecture for 32-bit SPIR-V.");
326     assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
327            "32-bit SPIR-V target must use unknown OS");
328     assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
329            "32-bit SPIR-V target must use unknown environment type");
330     PointerWidth = PointerAlign = 32;
331     SizeType = TargetInfo::UnsignedInt;
332     PtrDiffType = IntPtrType = TargetInfo::SignedInt;
333     resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
334                     "v96:128-v192:256-v256:256-v512:512-v1024:1024");
335   }
336 
337   void getTargetDefines(const LangOptions &Opts,
338                         MacroBuilder &Builder) const override;
339 };
340 
341 class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo {
342 public:
343   SPIRV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
344       : BaseSPIRVTargetInfo(Triple, Opts) {
345     assert(Triple.getArch() == llvm::Triple::spirv64 &&
346            "Invalid architecture for 64-bit SPIR-V.");
347     assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
348            "64-bit SPIR-V target must use unknown OS");
349     assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
350            "64-bit SPIR-V target must use unknown environment type");
351     PointerWidth = PointerAlign = 64;
352     SizeType = TargetInfo::UnsignedLong;
353     PtrDiffType = IntPtrType = TargetInfo::SignedLong;
354     resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
355                     "v96:128-v192:256-v256:256-v512:512-v1024:1024");
356   }
357 
358   void getTargetDefines(const LangOptions &Opts,
359                         MacroBuilder &Builder) const override;
360 };
361 
362 } // namespace targets
363 } // namespace clang
364 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
365