1349cc55cSDimitry Andric //===--- SPIR.h - Declare SPIR and SPIR-V target feature support *- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 9349cc55cSDimitry Andric // This file declares SPIR and SPIR-V TargetInfo objects. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H 140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 170b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h" 180b57cec5SDimitry Andric #include "llvm/ADT/Triple.h" 190b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 20*bdd1243dSDimitry Andric #include <optional> 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric namespace clang { 230b57cec5SDimitry Andric namespace targets { 240b57cec5SDimitry Andric 25349cc55cSDimitry Andric // Used by both the SPIR and SPIR-V targets. 26fe6060f1SDimitry Andric static const unsigned SPIRDefIsPrivMap[] = { 270b57cec5SDimitry Andric 0, // Default 280b57cec5SDimitry Andric 1, // opencl_global 290b57cec5SDimitry Andric 3, // opencl_local 300b57cec5SDimitry Andric 2, // opencl_constant 310b57cec5SDimitry Andric 0, // opencl_private 320b57cec5SDimitry Andric 4, // opencl_generic 33e8d8bef9SDimitry Andric 5, // opencl_global_device 34e8d8bef9SDimitry Andric 6, // opencl_global_host 350b57cec5SDimitry Andric 0, // cuda_device 360b57cec5SDimitry Andric 0, // cuda_constant 37480093f4SDimitry Andric 0, // cuda_shared 38fe6060f1SDimitry Andric // SYCL address space values for this map are dummy 39fe6060f1SDimitry Andric 0, // sycl_global 40fe6060f1SDimitry Andric 0, // sycl_global_device 41fe6060f1SDimitry Andric 0, // sycl_global_host 42fe6060f1SDimitry Andric 0, // sycl_local 43fe6060f1SDimitry Andric 0, // sycl_private 44fe6060f1SDimitry Andric 0, // ptr32_sptr 45fe6060f1SDimitry Andric 0, // ptr32_uptr 46*bdd1243dSDimitry Andric 0, // ptr64 47*bdd1243dSDimitry Andric 0, // hlsl_groupshared 48fe6060f1SDimitry Andric }; 49fe6060f1SDimitry Andric 50349cc55cSDimitry Andric // Used by both the SPIR and SPIR-V targets. 51fe6060f1SDimitry Andric static const unsigned SPIRDefIsGenMap[] = { 52fe6060f1SDimitry Andric 4, // Default 53fe6060f1SDimitry Andric // OpenCL address space values for this map are dummy and they can't be used 54fe6060f1SDimitry Andric 0, // opencl_global 55fe6060f1SDimitry Andric 0, // opencl_local 56fe6060f1SDimitry Andric 0, // opencl_constant 57fe6060f1SDimitry Andric 0, // opencl_private 58fe6060f1SDimitry Andric 0, // opencl_generic 59fe6060f1SDimitry Andric 0, // opencl_global_device 60fe6060f1SDimitry Andric 0, // opencl_global_host 614824e7fdSDimitry Andric // cuda_* address space mapping is intended for HIPSPV (HIP to SPIR-V 624824e7fdSDimitry Andric // translation). This mapping is enabled when the language mode is HIP. 634824e7fdSDimitry Andric 1, // cuda_device 644824e7fdSDimitry Andric // cuda_constant pointer can be casted to default/"flat" pointer, but in 654824e7fdSDimitry Andric // SPIR-V casts between constant and generic pointers are not allowed. For 664824e7fdSDimitry Andric // this reason cuda_constant is mapped to SPIR-V CrossWorkgroup. 674824e7fdSDimitry Andric 1, // cuda_constant 684824e7fdSDimitry Andric 3, // cuda_shared 69fe6060f1SDimitry Andric 1, // sycl_global 70fe6060f1SDimitry Andric 5, // sycl_global_device 71fe6060f1SDimitry Andric 6, // sycl_global_host 72fe6060f1SDimitry Andric 3, // sycl_local 73fe6060f1SDimitry Andric 0, // sycl_private 74480093f4SDimitry Andric 0, // ptr32_sptr 75480093f4SDimitry Andric 0, // ptr32_uptr 76*bdd1243dSDimitry Andric 0, // ptr64 77*bdd1243dSDimitry Andric 0, // hlsl_groupshared 780b57cec5SDimitry Andric }; 790b57cec5SDimitry Andric 80349cc55cSDimitry Andric // Base class for SPIR and SPIR-V target info. 81349cc55cSDimitry Andric class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo { 82349cc55cSDimitry Andric protected: 83349cc55cSDimitry Andric BaseSPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 840b57cec5SDimitry Andric : TargetInfo(Triple) { 854824e7fdSDimitry Andric assert((Triple.isSPIR() || Triple.isSPIRV()) && 864824e7fdSDimitry Andric "Invalid architecture for SPIR or SPIR-V."); 870b57cec5SDimitry Andric assert(getTriple().getOS() == llvm::Triple::UnknownOS && 88349cc55cSDimitry Andric "SPIR(-V) target must use unknown OS"); 890b57cec5SDimitry Andric assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && 90349cc55cSDimitry Andric "SPIR(-V) target must use unknown environment type"); 910b57cec5SDimitry Andric TLSSupported = false; 920b57cec5SDimitry Andric VLASupported = false; 930b57cec5SDimitry Andric LongWidth = LongAlign = 64; 94fe6060f1SDimitry Andric AddrSpaceMap = &SPIRDefIsPrivMap; 950b57cec5SDimitry Andric UseAddrSpaceMapMangling = true; 960b57cec5SDimitry Andric HasLegalHalfType = true; 970b57cec5SDimitry Andric HasFloat16 = true; 980b57cec5SDimitry Andric // Define available target features 990b57cec5SDimitry Andric // These must be defined in sorted order! 1000b57cec5SDimitry Andric NoAsmVariants = true; 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 103349cc55cSDimitry Andric public: 1040b57cec5SDimitry Andric // SPIR supports the half type and the only llvm intrinsic allowed in SPIR is 1050b57cec5SDimitry Andric // memcpy as per section 3 of the SPIR spec. 1060b57cec5SDimitry Andric bool useFP16ConversionIntrinsics() const override { return false; } 1070b57cec5SDimitry Andric 108*bdd1243dSDimitry Andric ArrayRef<Builtin::Info> getTargetBuiltins() const override { 109*bdd1243dSDimitry Andric return std::nullopt; 110*bdd1243dSDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric const char *getClobbers() const override { return ""; } 1130b57cec5SDimitry Andric 114*bdd1243dSDimitry Andric ArrayRef<const char *> getGCCRegNames() const override { 115*bdd1243dSDimitry Andric return std::nullopt; 116*bdd1243dSDimitry Andric } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric bool validateAsmConstraint(const char *&Name, 1190b57cec5SDimitry Andric TargetInfo::ConstraintInfo &info) const override { 1200b57cec5SDimitry Andric return true; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 124*bdd1243dSDimitry Andric return std::nullopt; 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric BuiltinVaListKind getBuiltinVaListKind() const override { 1280b57cec5SDimitry Andric return TargetInfo::VoidPtrBuiltinVaList; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 131*bdd1243dSDimitry Andric std::optional<unsigned> 132fe6060f1SDimitry Andric getDWARFAddressSpace(unsigned AddressSpace) const override { 133fe6060f1SDimitry Andric return AddressSpace; 134fe6060f1SDimitry Andric } 135fe6060f1SDimitry Andric 1360b57cec5SDimitry Andric CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 1370b57cec5SDimitry Andric return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK 1380b57cec5SDimitry Andric : CCCR_Warning; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric CallingConv getDefaultCallingConv() const override { 1420b57cec5SDimitry Andric return CC_SpirFunction; 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 145fe6060f1SDimitry Andric void setAddressSpaceMap(bool DefaultIsGeneric) { 146fe6060f1SDimitry Andric AddrSpaceMap = DefaultIsGeneric ? &SPIRDefIsGenMap : &SPIRDefIsPrivMap; 147fe6060f1SDimitry Andric } 148fe6060f1SDimitry Andric 149fe6060f1SDimitry Andric void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override { 150fe6060f1SDimitry Andric TargetInfo::adjust(Diags, Opts); 151fe6060f1SDimitry Andric // FIXME: SYCL specification considers unannotated pointers and references 152fe6060f1SDimitry Andric // to be pointing to the generic address space. See section 5.9.3 of 153fe6060f1SDimitry Andric // SYCL 2020 specification. 15481ad6265SDimitry Andric // Currently, there is no way of representing SYCL's and HIP/CUDA's default 1554824e7fdSDimitry Andric // address space language semantic along with the semantics of embedded C's 1564824e7fdSDimitry Andric // default address space in the same address space map. Hence the map needs 1574824e7fdSDimitry Andric // to be reset to allow mapping to the desired value of 'Default' entry for 15881ad6265SDimitry Andric // SYCL and HIP/CUDA. 1594824e7fdSDimitry Andric setAddressSpaceMap( 1604824e7fdSDimitry Andric /*DefaultIsGeneric=*/Opts.SYCLIsDevice || 16181ad6265SDimitry Andric // The address mapping from HIP/CUDA language for device code is only 16281ad6265SDimitry Andric // defined for SPIR-V. 16381ad6265SDimitry Andric (getTriple().isSPIRV() && Opts.CUDAIsDevice)); 164fe6060f1SDimitry Andric } 165fe6060f1SDimitry Andric 1660b57cec5SDimitry Andric void setSupportedOpenCLOpts() override { 1670b57cec5SDimitry Andric // Assume all OpenCL extensions and optional core features are supported 168349cc55cSDimitry Andric // for SPIR and SPIR-V since they are generic targets. 169e8d8bef9SDimitry Andric supportAllOpenCLOpts(); 1700b57cec5SDimitry Andric } 1715ffd83dbSDimitry Andric 1720eae32dcSDimitry Andric bool hasBitIntType() const override { return true; } 173e8d8bef9SDimitry Andric 174e8d8bef9SDimitry Andric bool hasInt128Type() const override { return false; } 1750b57cec5SDimitry Andric }; 176fe6060f1SDimitry Andric 177349cc55cSDimitry Andric class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public BaseSPIRTargetInfo { 178349cc55cSDimitry Andric public: 179349cc55cSDimitry Andric SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 180349cc55cSDimitry Andric : BaseSPIRTargetInfo(Triple, Opts) { 1814824e7fdSDimitry Andric assert(Triple.isSPIR() && "Invalid architecture for SPIR."); 182349cc55cSDimitry Andric assert(getTriple().getOS() == llvm::Triple::UnknownOS && 183349cc55cSDimitry Andric "SPIR target must use unknown OS"); 184349cc55cSDimitry Andric assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && 185349cc55cSDimitry Andric "SPIR target must use unknown environment type"); 186349cc55cSDimitry Andric } 187349cc55cSDimitry Andric 188349cc55cSDimitry Andric void getTargetDefines(const LangOptions &Opts, 189349cc55cSDimitry Andric MacroBuilder &Builder) const override; 190349cc55cSDimitry Andric 191349cc55cSDimitry Andric bool hasFeature(StringRef Feature) const override { 192349cc55cSDimitry Andric return Feature == "spir"; 193349cc55cSDimitry Andric } 194349cc55cSDimitry Andric }; 195349cc55cSDimitry Andric 1960b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo { 1970b57cec5SDimitry Andric public: 1980b57cec5SDimitry Andric SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 1990b57cec5SDimitry Andric : SPIRTargetInfo(Triple, Opts) { 2004824e7fdSDimitry Andric assert(Triple.getArch() == llvm::Triple::spir && 2014824e7fdSDimitry Andric "Invalid architecture for 32-bit SPIR."); 2020b57cec5SDimitry Andric PointerWidth = PointerAlign = 32; 2030b57cec5SDimitry Andric SizeType = TargetInfo::UnsignedInt; 2040b57cec5SDimitry Andric PtrDiffType = IntPtrType = TargetInfo::SignedInt; 2050b57cec5SDimitry Andric resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-" 2060b57cec5SDimitry Andric "v96:128-v192:256-v256:256-v512:512-v1024:1024"); 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 2100b57cec5SDimitry Andric MacroBuilder &Builder) const override; 2110b57cec5SDimitry Andric }; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo { 2140b57cec5SDimitry Andric public: 2150b57cec5SDimitry Andric SPIR64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 2160b57cec5SDimitry Andric : SPIRTargetInfo(Triple, Opts) { 2174824e7fdSDimitry Andric assert(Triple.getArch() == llvm::Triple::spir64 && 2184824e7fdSDimitry Andric "Invalid architecture for 64-bit SPIR."); 2190b57cec5SDimitry Andric PointerWidth = PointerAlign = 64; 2200b57cec5SDimitry Andric SizeType = TargetInfo::UnsignedLong; 2210b57cec5SDimitry Andric PtrDiffType = IntPtrType = TargetInfo::SignedLong; 2220b57cec5SDimitry Andric resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-" 2230b57cec5SDimitry Andric "v96:128-v192:256-v256:256-v512:512-v1024:1024"); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 2270b57cec5SDimitry Andric MacroBuilder &Builder) const override; 2280b57cec5SDimitry Andric }; 229349cc55cSDimitry Andric 230349cc55cSDimitry Andric class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRTargetInfo { 231349cc55cSDimitry Andric public: 232349cc55cSDimitry Andric SPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 233349cc55cSDimitry Andric : BaseSPIRTargetInfo(Triple, Opts) { 2344824e7fdSDimitry Andric assert(Triple.isSPIRV() && "Invalid architecture for SPIR-V."); 235349cc55cSDimitry Andric assert(getTriple().getOS() == llvm::Triple::UnknownOS && 236349cc55cSDimitry Andric "SPIR-V target must use unknown OS"); 237349cc55cSDimitry Andric assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && 238349cc55cSDimitry Andric "SPIR-V target must use unknown environment type"); 239349cc55cSDimitry Andric } 240349cc55cSDimitry Andric 241349cc55cSDimitry Andric void getTargetDefines(const LangOptions &Opts, 242349cc55cSDimitry Andric MacroBuilder &Builder) const override; 243349cc55cSDimitry Andric 244349cc55cSDimitry Andric bool hasFeature(StringRef Feature) const override { 245349cc55cSDimitry Andric return Feature == "spirv"; 246349cc55cSDimitry Andric } 247349cc55cSDimitry Andric }; 248349cc55cSDimitry Andric 249349cc55cSDimitry Andric class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public SPIRVTargetInfo { 250349cc55cSDimitry Andric public: 251349cc55cSDimitry Andric SPIRV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 252349cc55cSDimitry Andric : SPIRVTargetInfo(Triple, Opts) { 2534824e7fdSDimitry Andric assert(Triple.getArch() == llvm::Triple::spirv32 && 2544824e7fdSDimitry Andric "Invalid architecture for 32-bit SPIR-V."); 255349cc55cSDimitry Andric PointerWidth = PointerAlign = 32; 256349cc55cSDimitry Andric SizeType = TargetInfo::UnsignedInt; 257349cc55cSDimitry Andric PtrDiffType = IntPtrType = TargetInfo::SignedInt; 258349cc55cSDimitry Andric resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-" 259349cc55cSDimitry Andric "v96:128-v192:256-v256:256-v512:512-v1024:1024"); 260349cc55cSDimitry Andric } 261349cc55cSDimitry Andric 262349cc55cSDimitry Andric void getTargetDefines(const LangOptions &Opts, 263349cc55cSDimitry Andric MacroBuilder &Builder) const override; 264349cc55cSDimitry Andric }; 265349cc55cSDimitry Andric 266349cc55cSDimitry Andric class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public SPIRVTargetInfo { 267349cc55cSDimitry Andric public: 268349cc55cSDimitry Andric SPIRV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 269349cc55cSDimitry Andric : SPIRVTargetInfo(Triple, Opts) { 2704824e7fdSDimitry Andric assert(Triple.getArch() == llvm::Triple::spirv64 && 2714824e7fdSDimitry Andric "Invalid architecture for 64-bit SPIR-V."); 272349cc55cSDimitry Andric PointerWidth = PointerAlign = 64; 273349cc55cSDimitry Andric SizeType = TargetInfo::UnsignedLong; 274349cc55cSDimitry Andric PtrDiffType = IntPtrType = TargetInfo::SignedLong; 275349cc55cSDimitry Andric resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-" 276349cc55cSDimitry Andric "v96:128-v192:256-v256:256-v512:512-v1024:1024"); 277349cc55cSDimitry Andric } 278349cc55cSDimitry Andric 279349cc55cSDimitry Andric void getTargetDefines(const LangOptions &Opts, 280349cc55cSDimitry Andric MacroBuilder &Builder) const override; 281349cc55cSDimitry Andric }; 282349cc55cSDimitry Andric 2830b57cec5SDimitry Andric } // namespace targets 2840b57cec5SDimitry Andric } // namespace clang 2850b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H 286