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/Support/VersionTuple.h"
21#include "llvm/TargetParser/Triple.h"
22#include <optional>
23
24namespace clang {
25namespace targets {
26
27// Used by both the SPIR and SPIR-V targets.
28static const unsigned SPIRDefIsPrivMap[] = {
29 0, // Default
30 1, // opencl_global
31 3, // opencl_local
32 2, // opencl_constant
33 0, // opencl_private
34 4, // opencl_generic
35 5, // opencl_global_device
36 6, // opencl_global_host
37 0, // cuda_device
38 0, // cuda_constant
39 0, // cuda_shared
40 // SYCL address space values for this map are dummy
41 0, // sycl_global
42 0, // sycl_global_device
43 0, // sycl_global_host
44 0, // sycl_local
45 0, // sycl_private
46 0, // ptr32_sptr
47 0, // ptr32_uptr
48 0, // ptr64
49 3, // hlsl_groupshared
50 12, // hlsl_constant
51 10, // hlsl_private
52 11, // hlsl_device
53 7, // hlsl_input
54 // Wasm address space values for this target are dummy values,
55 // as it is only enabled for Wasm targets.
56 20, // wasm_funcref
57};
58
59// Used by both the SPIR and SPIR-V targets.
60static const unsigned SPIRDefIsGenMap[] = {
61 4, // Default
62 1, // opencl_global
63 3, // opencl_local
64 2, // opencl_constant
65 0, // opencl_private
66 4, // opencl_generic
67 5, // opencl_global_device
68 6, // opencl_global_host
69 // cuda_* address space mapping is intended for HIPSPV (HIP to SPIR-V
70 // translation). This mapping is enabled when the language mode is HIP.
71 1, // cuda_device
72 // cuda_constant pointer can be casted to default/"flat" pointer, but in
73 // SPIR-V casts between constant and generic pointers are not allowed. For
74 // this reason cuda_constant is mapped to SPIR-V CrossWorkgroup.
75 1, // cuda_constant
76 3, // cuda_shared
77 1, // sycl_global
78 5, // sycl_global_device
79 6, // sycl_global_host
80 3, // sycl_local
81 0, // sycl_private
82 0, // ptr32_sptr
83 0, // ptr32_uptr
84 0, // ptr64
85 3, // hlsl_groupshared
86 0, // hlsl_constant
87 10, // hlsl_private
88 11, // hlsl_device
89 7, // hlsl_input
90 // Wasm address space values for this target are dummy values,
91 // as it is only enabled for Wasm targets.
92 20, // wasm_funcref
93};
94
95// Base class for SPIR and SPIR-V target info.
96class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
97 std::unique_ptr<TargetInfo> HostTarget;
98
99protected:
100 BaseSPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
101 : TargetInfo(Triple) {
102 assert((Triple.isSPIR() || Triple.isSPIRV()) &&
103 "Invalid architecture for SPIR or SPIR-V.");
104 TLSSupported = false;
105 VLASupported = false;
106 LongWidth = LongAlign = 64;
107 AddrSpaceMap = &SPIRDefIsPrivMap;
108 UseAddrSpaceMapMangling = true;
109 HasLegalHalfType = true;
110 HasFloat16 = true;
111 // Define available target features
112 // These must be defined in sorted order!
113 NoAsmVariants = true;
114
115 llvm::Triple HostTriple(Opts.HostTriple);
116 if (!HostTriple.isSPIR() && !HostTriple.isSPIRV() &&
117 HostTriple.getArch() != llvm::Triple::UnknownArch) {
118 HostTarget = AllocateTarget(Triple: llvm::Triple(Opts.HostTriple), Opts);
119
120 // Copy properties from host target.
121 BoolWidth = HostTarget->getBoolWidth();
122 BoolAlign = HostTarget->getBoolAlign();
123 IntWidth = HostTarget->getIntWidth();
124 IntAlign = HostTarget->getIntAlign();
125 HalfWidth = HostTarget->getHalfWidth();
126 HalfAlign = HostTarget->getHalfAlign();
127 FloatWidth = HostTarget->getFloatWidth();
128 FloatAlign = HostTarget->getFloatAlign();
129 DoubleWidth = HostTarget->getDoubleWidth();
130 DoubleAlign = HostTarget->getDoubleAlign();
131 LongWidth = HostTarget->getLongWidth();
132 LongAlign = HostTarget->getLongAlign();
133 LongLongWidth = HostTarget->getLongLongWidth();
134 LongLongAlign = HostTarget->getLongLongAlign();
135 MinGlobalAlign =
136 HostTarget->getMinGlobalAlign(/* TypeSize = */ Size: 0,
137 /* HasNonWeakDef = */ HasNonWeakDef: true);
138 NewAlign = HostTarget->getNewAlign();
139 DefaultAlignForAttributeAligned =
140 HostTarget->getDefaultAlignForAttributeAligned();
141 IntMaxType = HostTarget->getIntMaxType();
142 WCharType = HostTarget->getWCharType();
143 WIntType = HostTarget->getWIntType();
144 Char16Type = HostTarget->getChar16Type();
145 Char32Type = HostTarget->getChar32Type();
146 Int64Type = HostTarget->getInt64Type();
147 SigAtomicType = HostTarget->getSigAtomicType();
148 ProcessIDType = HostTarget->getProcessIDType();
149
150 UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();
151 UseZeroLengthBitfieldAlignment =
152 HostTarget->useZeroLengthBitfieldAlignment();
153 UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
154 ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();
155
156 // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
157 // we need those macros to be identical on host and device, because (among
158 // other things) they affect which standard library classes are defined,
159 // and we need all classes to be defined on both the host and device.
160 MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();
161 }
162 }
163
164public:
165 // SPIR supports the half type and the only llvm intrinsic allowed in SPIR is
166 // memcpy as per section 3 of the SPIR spec.
167 bool useFP16ConversionIntrinsics() const override { return false; }
168
169 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
170 return {};
171 }
172
173 std::string_view getClobbers() const override { return ""; }
174
175 ArrayRef<const char *> getGCCRegNames() const override { return {}; }
176
177 bool validateAsmConstraint(const char *&Name,
178 TargetInfo::ConstraintInfo &info) const override {
179 return true;
180 }
181
182 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
183 return {};
184 }
185
186 BuiltinVaListKind getBuiltinVaListKind() const override {
187 return TargetInfo::VoidPtrBuiltinVaList;
188 }
189
190 std::optional<unsigned>
191 getDWARFAddressSpace(unsigned AddressSpace) const override {
192 return AddressSpace;
193 }
194
195 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
196 return (CC == CC_SpirFunction || CC == CC_DeviceKernel) ? CCCR_OK
197 : CCCR_Warning;
198 }
199
200 CallingConv getDefaultCallingConv() const override {
201 return CC_SpirFunction;
202 }
203
204 void setAddressSpaceMap(bool DefaultIsGeneric) {
205 AddrSpaceMap = DefaultIsGeneric ? &SPIRDefIsGenMap : &SPIRDefIsPrivMap;
206 }
207
208 void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override {
209 TargetInfo::adjust(Diags, Opts);
210 // FIXME: SYCL specification considers unannotated pointers and references
211 // to be pointing to the generic address space. See section 5.9.3 of
212 // SYCL 2020 specification.
213 // Currently, there is no way of representing SYCL's and HIP/CUDA's default
214 // address space language semantic along with the semantics of embedded C's
215 // default address space in the same address space map. Hence the map needs
216 // to be reset to allow mapping to the desired value of 'Default' entry for
217 // SYCL and HIP/CUDA.
218 setAddressSpaceMap(
219 /*DefaultIsGeneric=*/Opts.SYCLIsDevice ||
220 // The address mapping from HIP/CUDA language for device code is only
221 // defined for SPIR-V.
222 (getTriple().isSPIRV() && Opts.CUDAIsDevice));
223 }
224
225 void setSupportedOpenCLOpts() override {
226 // Assume all OpenCL extensions and optional core features are supported
227 // for SPIR and SPIR-V since they are generic targets.
228 supportAllOpenCLOpts();
229 }
230
231 bool hasBitIntType() const override { return true; }
232
233 bool hasInt128Type() const override { return false; }
234};
235
236class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public BaseSPIRTargetInfo {
237public:
238 SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
239 : BaseSPIRTargetInfo(Triple, Opts) {
240 assert(Triple.isSPIR() && "Invalid architecture for SPIR.");
241 assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
242 "SPIR target must use unknown OS");
243 assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
244 "SPIR target must use unknown environment type");
245 }
246
247 void getTargetDefines(const LangOptions &Opts,
248 MacroBuilder &Builder) const override;
249
250 bool hasFeature(StringRef Feature) const override {
251 return Feature == "spir";
252 }
253
254 bool checkArithmeticFenceSupported() const override { return true; }
255};
256
257class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo {
258public:
259 SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
260 : SPIRTargetInfo(Triple, Opts) {
261 assert(Triple.getArch() == llvm::Triple::spir &&
262 "Invalid architecture for 32-bit SPIR.");
263 PointerWidth = PointerAlign = 32;
264 SizeType = TargetInfo::UnsignedInt;
265 PtrDiffType = IntPtrType = TargetInfo::SignedInt;
266 resetDataLayout(DL: "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
267 "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
268 }
269
270 void getTargetDefines(const LangOptions &Opts,
271 MacroBuilder &Builder) const override;
272};
273
274class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo {
275public:
276 SPIR64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
277 : SPIRTargetInfo(Triple, Opts) {
278 assert(Triple.getArch() == llvm::Triple::spir64 &&
279 "Invalid architecture for 64-bit SPIR.");
280 PointerWidth = PointerAlign = 64;
281 SizeType = TargetInfo::UnsignedLong;
282 PtrDiffType = IntPtrType = TargetInfo::SignedLong;
283 resetDataLayout(DL: "e-i64:64-v16:16-v24:32-v32:32-v48:64-"
284 "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
285 }
286
287 void getTargetDefines(const LangOptions &Opts,
288 MacroBuilder &Builder) const override;
289};
290
291class LLVM_LIBRARY_VISIBILITY BaseSPIRVTargetInfo : public BaseSPIRTargetInfo {
292public:
293 BaseSPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
294 : BaseSPIRTargetInfo(Triple, Opts) {
295 assert(Triple.isSPIRV() && "Invalid architecture for SPIR-V.");
296 }
297
298 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
299
300 bool hasFeature(StringRef Feature) const override {
301 return Feature == "spirv";
302 }
303
304 void getTargetDefines(const LangOptions &Opts,
305 MacroBuilder &Builder) const override;
306};
307
308class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRVTargetInfo {
309public:
310 SPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
311 : BaseSPIRVTargetInfo(Triple, Opts) {
312 assert(Triple.getArch() == llvm::Triple::spirv &&
313 "Invalid architecture for Logical SPIR-V.");
314 assert(Triple.getOS() == llvm::Triple::Vulkan &&
315 Triple.getVulkanVersion() != llvm::VersionTuple(0) &&
316 "Logical SPIR-V requires a valid Vulkan environment.");
317 assert(Triple.getEnvironment() >= llvm::Triple::Pixel &&
318 Triple.getEnvironment() <= llvm::Triple::Amplification &&
319 "Logical SPIR-V environment must be a valid shader stage.");
320 PointerWidth = PointerAlign = 64;
321
322 // SPIR-V IDs are represented with a single 32-bit word.
323 SizeType = TargetInfo::UnsignedInt;
324 resetDataLayout(DL: "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
325 "v256:256-v512:512-v1024:1024-n8:16:32:64-G10");
326 }
327
328 void getTargetDefines(const LangOptions &Opts,
329 MacroBuilder &Builder) const override;
330};
331
332class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public BaseSPIRVTargetInfo {
333public:
334 SPIRV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
335 : BaseSPIRVTargetInfo(Triple, Opts) {
336 assert(Triple.getArch() == llvm::Triple::spirv32 &&
337 "Invalid architecture for 32-bit SPIR-V.");
338 assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
339 "32-bit SPIR-V target must use unknown OS");
340 assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
341 "32-bit SPIR-V target must use unknown environment type");
342 PointerWidth = PointerAlign = 32;
343 SizeType = TargetInfo::UnsignedInt;
344 PtrDiffType = IntPtrType = TargetInfo::SignedInt;
345 // SPIR-V has core support for atomic ops, and Int32 is always available;
346 // we take the maximum because it's possible the Host supports wider types.
347 MaxAtomicInlineWidth = std::max<unsigned char>(a: MaxAtomicInlineWidth, b: 32);
348 resetDataLayout(DL: "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-"
349 "v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1");
350 }
351
352 void getTargetDefines(const LangOptions &Opts,
353 MacroBuilder &Builder) const override;
354};
355
356class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo {
357public:
358 SPIRV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
359 : BaseSPIRVTargetInfo(Triple, Opts) {
360 assert(Triple.getArch() == llvm::Triple::spirv64 &&
361 "Invalid architecture for 64-bit SPIR-V.");
362 assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
363 "64-bit SPIR-V target must use unknown OS");
364 assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
365 "64-bit SPIR-V target must use unknown environment type");
366 PointerWidth = PointerAlign = 64;
367 SizeType = TargetInfo::UnsignedLong;
368 PtrDiffType = IntPtrType = TargetInfo::SignedLong;
369 // SPIR-V has core support for atomic ops, and Int64 is always available;
370 // we take the maximum because it's possible the Host supports wider types.
371 MaxAtomicInlineWidth = std::max<unsigned char>(a: MaxAtomicInlineWidth, b: 64);
372 resetDataLayout(DL: "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
373 "v256:256-v512:512-v1024:1024-n8:16:32:64-G1");
374 }
375
376 void getTargetDefines(const LangOptions &Opts,
377 MacroBuilder &Builder) const override;
378
379 const llvm::omp::GV &getGridValue() const override {
380 return llvm::omp::SPIRVGridValues;
381 }
382
383 std::optional<LangAS> getConstantAddressSpace() const override {
384 return ConstantAS;
385 }
386 void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override {
387 BaseSPIRVTargetInfo::adjust(Diags, Opts);
388 // opencl_constant will map to UniformConstant in SPIR-V
389 if (Opts.OpenCL)
390 ConstantAS = LangAS::opencl_constant;
391 }
392
393private:
394 // opencl_global will map to CrossWorkgroup in SPIR-V
395 LangAS ConstantAS = LangAS::opencl_global;
396};
397
398class LLVM_LIBRARY_VISIBILITY SPIRV64AMDGCNTargetInfo final
399 : public BaseSPIRVTargetInfo {
400public:
401 SPIRV64AMDGCNTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
402 : BaseSPIRVTargetInfo(Triple, Opts) {
403 assert(Triple.getArch() == llvm::Triple::spirv64 &&
404 "Invalid architecture for 64-bit AMDGCN SPIR-V.");
405 assert(Triple.getVendor() == llvm::Triple::VendorType::AMD &&
406 "64-bit AMDGCN SPIR-V target must use AMD vendor");
407 assert(getTriple().getOS() == llvm::Triple::OSType::AMDHSA &&
408 "64-bit AMDGCN SPIR-V target must use AMDHSA OS");
409 assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
410 "64-bit SPIR-V target must use unknown environment type");
411 PointerWidth = PointerAlign = 64;
412 SizeType = TargetInfo::UnsignedLong;
413 PtrDiffType = IntPtrType = TargetInfo::SignedLong;
414 AddrSpaceMap = &SPIRDefIsGenMap;
415
416 resetDataLayout(DL: "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
417 "v256:256-v512:512-v1024:1024-n32:64-S32-G1-P4-A0");
418
419 BFloat16Width = BFloat16Align = 16;
420 BFloat16Format = &llvm::APFloat::BFloat();
421
422 HasLegalHalfType = true;
423 HasFloat16 = true;
424 HalfArgsAndReturns = true;
425
426 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
427 }
428
429 bool hasBFloat16Type() const override { return true; }
430
431 ArrayRef<const char *> getGCCRegNames() const override;
432
433 bool initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
434 StringRef,
435 const std::vector<std::string> &) const override;
436
437 bool validateAsmConstraint(const char *&Name,
438 TargetInfo::ConstraintInfo &Info) const override;
439
440 std::string convertConstraint(const char *&Constraint) const override;
441
442 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;
443
444 void getTargetDefines(const LangOptions &Opts,
445 MacroBuilder &Builder) const override;
446
447 void setAuxTarget(const TargetInfo *Aux) override;
448
449 void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override {
450 TargetInfo::adjust(Diags, Opts);
451 }
452
453 bool hasInt128Type() const override { return TargetInfo::hasInt128Type(); }
454};
455
456} // namespace targets
457} // namespace clang
458#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
459

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Basic/Targets/SPIR.h