1 //===--- SPIR.h - Declare SPIR and SPIR-V target feature support *- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file declares SPIR and SPIR-V TargetInfo objects.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
14 #define LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_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"
26 // Used by both the SPIR and SPIR-V targets.
27 static const unsigned SPIRDefIsPrivMap
[] = {
34 5, // opencl_global_device
35 6, // opencl_global_host
39 // SYCL address space values for this map are dummy
41 0, // sycl_global_device
42 0, // sycl_global_host
48 0, // hlsl_groupshared
49 // Wasm address space values for this target are dummy values,
50 // as it is only enabled for Wasm targets.
54 // Used by both the SPIR and SPIR-V targets.
55 static const unsigned SPIRDefIsGenMap
[] = {
57 // OpenCL address space values for this map are dummy and they can't be used
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.
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.
74 5, // sycl_global_device
75 6, // sycl_global_host
81 0, // hlsl_groupshared
82 // Wasm address space values for this target are dummy values,
83 // as it is only enabled for Wasm targets.
87 // Base class for SPIR and SPIR-V target info.
88 class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo
: public TargetInfo
{
89 std::unique_ptr
<TargetInfo
> HostTarget
;
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 assert(getTriple().getOS() == llvm::Triple::UnknownOS
&&
97 "SPIR(-V) target must use unknown OS");
98 assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment
&&
99 "SPIR(-V) target must use unknown environment type");
100 TLSSupported
= false;
101 VLASupported
= false;
102 LongWidth
= LongAlign
= 64;
103 AddrSpaceMap
= &SPIRDefIsPrivMap
;
104 UseAddrSpaceMapMangling
= true;
105 HasLegalHalfType
= true;
107 // Define available target features
108 // These must be defined in sorted order!
109 NoAsmVariants
= true;
111 llvm::Triple
HostTriple(Opts
.HostTriple
);
112 if (!HostTriple
.isSPIR() && !HostTriple
.isSPIRV() &&
113 HostTriple
.getArch() != llvm::Triple::UnknownArch
) {
114 HostTarget
= AllocateTarget(llvm::Triple(Opts
.HostTriple
), Opts
);
116 // Copy properties from host target.
117 BoolWidth
= HostTarget
->getBoolWidth();
118 BoolAlign
= HostTarget
->getBoolAlign();
119 IntWidth
= HostTarget
->getIntWidth();
120 IntAlign
= HostTarget
->getIntAlign();
121 HalfWidth
= HostTarget
->getHalfWidth();
122 HalfAlign
= HostTarget
->getHalfAlign();
123 FloatWidth
= HostTarget
->getFloatWidth();
124 FloatAlign
= HostTarget
->getFloatAlign();
125 DoubleWidth
= HostTarget
->getDoubleWidth();
126 DoubleAlign
= HostTarget
->getDoubleAlign();
127 LongWidth
= HostTarget
->getLongWidth();
128 LongAlign
= HostTarget
->getLongAlign();
129 LongLongWidth
= HostTarget
->getLongLongWidth();
130 LongLongAlign
= HostTarget
->getLongLongAlign();
131 MinGlobalAlign
= HostTarget
->getMinGlobalAlign(/* TypeSize = */ 0);
132 NewAlign
= HostTarget
->getNewAlign();
133 DefaultAlignForAttributeAligned
=
134 HostTarget
->getDefaultAlignForAttributeAligned();
135 IntMaxType
= HostTarget
->getIntMaxType();
136 WCharType
= HostTarget
->getWCharType();
137 WIntType
= HostTarget
->getWIntType();
138 Char16Type
= HostTarget
->getChar16Type();
139 Char32Type
= HostTarget
->getChar32Type();
140 Int64Type
= HostTarget
->getInt64Type();
141 SigAtomicType
= HostTarget
->getSigAtomicType();
142 ProcessIDType
= HostTarget
->getProcessIDType();
144 UseBitFieldTypeAlignment
= HostTarget
->useBitFieldTypeAlignment();
145 UseZeroLengthBitfieldAlignment
=
146 HostTarget
->useZeroLengthBitfieldAlignment();
147 UseExplicitBitFieldAlignment
= HostTarget
->useExplicitBitFieldAlignment();
148 ZeroLengthBitfieldBoundary
= HostTarget
->getZeroLengthBitfieldBoundary();
150 // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
151 // we need those macros to be identical on host and device, because (among
152 // other things) they affect which standard library classes are defined,
153 // and we need all classes to be defined on both the host and device.
154 MaxAtomicInlineWidth
= HostTarget
->getMaxAtomicInlineWidth();
159 // SPIR supports the half type and the only llvm intrinsic allowed in SPIR is
160 // memcpy as per section 3 of the SPIR spec.
161 bool useFP16ConversionIntrinsics() const override
{ return false; }
163 ArrayRef
<Builtin::Info
> getTargetBuiltins() const override
{
167 std::string_view
getClobbers() const override
{ return ""; }
169 ArrayRef
<const char *> getGCCRegNames() const override
{
173 bool validateAsmConstraint(const char *&Name
,
174 TargetInfo::ConstraintInfo
&info
) const override
{
178 ArrayRef
<TargetInfo::GCCRegAlias
> getGCCRegAliases() const override
{
182 BuiltinVaListKind
getBuiltinVaListKind() const override
{
183 return TargetInfo::VoidPtrBuiltinVaList
;
186 std::optional
<unsigned>
187 getDWARFAddressSpace(unsigned AddressSpace
) const override
{
191 CallingConvCheckResult
checkCallingConvention(CallingConv CC
) const override
{
192 return (CC
== CC_SpirFunction
|| CC
== CC_OpenCLKernel
) ? CCCR_OK
196 CallingConv
getDefaultCallingConv() const override
{
197 return CC_SpirFunction
;
200 void setAddressSpaceMap(bool DefaultIsGeneric
) {
201 AddrSpaceMap
= DefaultIsGeneric
? &SPIRDefIsGenMap
: &SPIRDefIsPrivMap
;
204 void adjust(DiagnosticsEngine
&Diags
, LangOptions
&Opts
) override
{
205 TargetInfo::adjust(Diags
, Opts
);
206 // FIXME: SYCL specification considers unannotated pointers and references
207 // to be pointing to the generic address space. See section 5.9.3 of
208 // SYCL 2020 specification.
209 // Currently, there is no way of representing SYCL's and HIP/CUDA's default
210 // address space language semantic along with the semantics of embedded C's
211 // default address space in the same address space map. Hence the map needs
212 // to be reset to allow mapping to the desired value of 'Default' entry for
213 // SYCL and HIP/CUDA.
215 /*DefaultIsGeneric=*/Opts
.SYCLIsDevice
||
216 // The address mapping from HIP/CUDA language for device code is only
217 // defined for SPIR-V.
218 (getTriple().isSPIRV() && Opts
.CUDAIsDevice
));
221 void setSupportedOpenCLOpts() override
{
222 // Assume all OpenCL extensions and optional core features are supported
223 // for SPIR and SPIR-V since they are generic targets.
224 supportAllOpenCLOpts();
227 bool hasBitIntType() const override
{ return true; }
229 bool hasInt128Type() const override
{ return false; }
232 class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo
: public BaseSPIRTargetInfo
{
234 SPIRTargetInfo(const llvm::Triple
&Triple
, const TargetOptions
&Opts
)
235 : BaseSPIRTargetInfo(Triple
, Opts
) {
236 assert(Triple
.isSPIR() && "Invalid architecture for SPIR.");
237 assert(getTriple().getOS() == llvm::Triple::UnknownOS
&&
238 "SPIR target must use unknown OS");
239 assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment
&&
240 "SPIR target must use unknown environment type");
243 void getTargetDefines(const LangOptions
&Opts
,
244 MacroBuilder
&Builder
) const override
;
246 bool hasFeature(StringRef Feature
) const override
{
247 return Feature
== "spir";
250 bool checkArithmeticFenceSupported() const override
{ return true; }
253 class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo
: public SPIRTargetInfo
{
255 SPIR32TargetInfo(const llvm::Triple
&Triple
, const TargetOptions
&Opts
)
256 : SPIRTargetInfo(Triple
, Opts
) {
257 assert(Triple
.getArch() == llvm::Triple::spir
&&
258 "Invalid architecture for 32-bit SPIR.");
259 PointerWidth
= PointerAlign
= 32;
260 SizeType
= TargetInfo::UnsignedInt
;
261 PtrDiffType
= IntPtrType
= TargetInfo::SignedInt
;
262 resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
263 "v96:128-v192:256-v256:256-v512:512-v1024:1024");
266 void getTargetDefines(const LangOptions
&Opts
,
267 MacroBuilder
&Builder
) const override
;
270 class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo
: public SPIRTargetInfo
{
272 SPIR64TargetInfo(const llvm::Triple
&Triple
, const TargetOptions
&Opts
)
273 : SPIRTargetInfo(Triple
, Opts
) {
274 assert(Triple
.getArch() == llvm::Triple::spir64
&&
275 "Invalid architecture for 64-bit SPIR.");
276 PointerWidth
= PointerAlign
= 64;
277 SizeType
= TargetInfo::UnsignedLong
;
278 PtrDiffType
= IntPtrType
= TargetInfo::SignedLong
;
279 resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
280 "v96:128-v192:256-v256:256-v512:512-v1024:1024");
283 void getTargetDefines(const LangOptions
&Opts
,
284 MacroBuilder
&Builder
) const override
;
287 class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo
: public BaseSPIRTargetInfo
{
289 SPIRVTargetInfo(const llvm::Triple
&Triple
, const TargetOptions
&Opts
)
290 : BaseSPIRTargetInfo(Triple
, Opts
) {
291 assert(Triple
.isSPIRV() && "Invalid architecture for SPIR-V.");
292 assert(getTriple().getOS() == llvm::Triple::UnknownOS
&&
293 "SPIR-V target must use unknown OS");
294 assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment
&&
295 "SPIR-V target must use unknown environment type");
298 void getTargetDefines(const LangOptions
&Opts
,
299 MacroBuilder
&Builder
) const override
;
301 bool hasFeature(StringRef Feature
) const override
{
302 return Feature
== "spirv";
306 class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo
: public SPIRVTargetInfo
{
308 SPIRV32TargetInfo(const llvm::Triple
&Triple
, const TargetOptions
&Opts
)
309 : SPIRVTargetInfo(Triple
, Opts
) {
310 assert(Triple
.getArch() == llvm::Triple::spirv32
&&
311 "Invalid architecture for 32-bit SPIR-V.");
312 PointerWidth
= PointerAlign
= 32;
313 SizeType
= TargetInfo::UnsignedInt
;
314 PtrDiffType
= IntPtrType
= TargetInfo::SignedInt
;
315 resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
316 "v96:128-v192:256-v256:256-v512:512-v1024:1024");
319 void getTargetDefines(const LangOptions
&Opts
,
320 MacroBuilder
&Builder
) const override
;
323 class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo
: public SPIRVTargetInfo
{
325 SPIRV64TargetInfo(const llvm::Triple
&Triple
, const TargetOptions
&Opts
)
326 : SPIRVTargetInfo(Triple
, Opts
) {
327 assert(Triple
.getArch() == llvm::Triple::spirv64
&&
328 "Invalid architecture for 64-bit SPIR-V.");
329 PointerWidth
= PointerAlign
= 64;
330 SizeType
= TargetInfo::UnsignedLong
;
331 PtrDiffType
= IntPtrType
= TargetInfo::SignedLong
;
332 resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
333 "v96:128-v192:256-v256:256-v512:512-v1024:1024");
336 void getTargetDefines(const LangOptions
&Opts
,
337 MacroBuilder
&Builder
) const override
;
340 } // namespace targets
342 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H