1*12c85518Srobert //===--- SPIR.h - Declare SPIR and SPIR-V target feature support *- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick // 9*12c85518Srobert // This file declares SPIR and SPIR-V TargetInfo objects. 10e5dd7070Spatrick // 11e5dd7070Spatrick //===----------------------------------------------------------------------===// 12e5dd7070Spatrick 13e5dd7070Spatrick #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H 14e5dd7070Spatrick #define LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H 15e5dd7070Spatrick 16e5dd7070Spatrick #include "clang/Basic/TargetInfo.h" 17e5dd7070Spatrick #include "clang/Basic/TargetOptions.h" 18e5dd7070Spatrick #include "llvm/ADT/Triple.h" 19e5dd7070Spatrick #include "llvm/Support/Compiler.h" 20*12c85518Srobert #include <optional> 21e5dd7070Spatrick 22e5dd7070Spatrick namespace clang { 23e5dd7070Spatrick namespace targets { 24e5dd7070Spatrick 25*12c85518Srobert // Used by both the SPIR and SPIR-V targets. 26a9ac8606Spatrick static const unsigned SPIRDefIsPrivMap[] = { 27e5dd7070Spatrick 0, // Default 28e5dd7070Spatrick 1, // opencl_global 29e5dd7070Spatrick 3, // opencl_local 30e5dd7070Spatrick 2, // opencl_constant 31e5dd7070Spatrick 0, // opencl_private 32e5dd7070Spatrick 4, // opencl_generic 33a9ac8606Spatrick 5, // opencl_global_device 34a9ac8606Spatrick 6, // opencl_global_host 35e5dd7070Spatrick 0, // cuda_device 36e5dd7070Spatrick 0, // cuda_constant 37e5dd7070Spatrick 0, // cuda_shared 38a9ac8606Spatrick // SYCL address space values for this map are dummy 39a9ac8606Spatrick 0, // sycl_global 40a9ac8606Spatrick 0, // sycl_global_device 41a9ac8606Spatrick 0, // sycl_global_host 42a9ac8606Spatrick 0, // sycl_local 43a9ac8606Spatrick 0, // sycl_private 44a9ac8606Spatrick 0, // ptr32_sptr 45a9ac8606Spatrick 0, // ptr32_uptr 46*12c85518Srobert 0, // ptr64 47*12c85518Srobert 0, // hlsl_groupshared 48a9ac8606Spatrick }; 49a9ac8606Spatrick 50*12c85518Srobert // Used by both the SPIR and SPIR-V targets. 51a9ac8606Spatrick static const unsigned SPIRDefIsGenMap[] = { 52a9ac8606Spatrick 4, // Default 53a9ac8606Spatrick // OpenCL address space values for this map are dummy and they can't be used 54a9ac8606Spatrick 0, // opencl_global 55a9ac8606Spatrick 0, // opencl_local 56a9ac8606Spatrick 0, // opencl_constant 57a9ac8606Spatrick 0, // opencl_private 58a9ac8606Spatrick 0, // opencl_generic 59a9ac8606Spatrick 0, // opencl_global_device 60a9ac8606Spatrick 0, // opencl_global_host 61*12c85518Srobert // cuda_* address space mapping is intended for HIPSPV (HIP to SPIR-V 62*12c85518Srobert // translation). This mapping is enabled when the language mode is HIP. 63*12c85518Srobert 1, // cuda_device 64*12c85518Srobert // cuda_constant pointer can be casted to default/"flat" pointer, but in 65*12c85518Srobert // SPIR-V casts between constant and generic pointers are not allowed. For 66*12c85518Srobert // this reason cuda_constant is mapped to SPIR-V CrossWorkgroup. 67*12c85518Srobert 1, // cuda_constant 68*12c85518Srobert 3, // cuda_shared 69a9ac8606Spatrick 1, // sycl_global 70a9ac8606Spatrick 5, // sycl_global_device 71a9ac8606Spatrick 6, // sycl_global_host 72a9ac8606Spatrick 3, // sycl_local 73a9ac8606Spatrick 0, // sycl_private 74e5dd7070Spatrick 0, // ptr32_sptr 75e5dd7070Spatrick 0, // ptr32_uptr 76*12c85518Srobert 0, // ptr64 77*12c85518Srobert 0, // hlsl_groupshared 78e5dd7070Spatrick }; 79e5dd7070Spatrick 80*12c85518Srobert // Base class for SPIR and SPIR-V target info. 81*12c85518Srobert class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo { 82*12c85518Srobert protected: BaseSPIRTargetInfo(const llvm::Triple & Triple,const TargetOptions &)83*12c85518Srobert BaseSPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 84e5dd7070Spatrick : TargetInfo(Triple) { 85*12c85518Srobert assert((Triple.isSPIR() || Triple.isSPIRV()) && 86*12c85518Srobert "Invalid architecture for SPIR or SPIR-V."); 87e5dd7070Spatrick assert(getTriple().getOS() == llvm::Triple::UnknownOS && 88*12c85518Srobert "SPIR(-V) target must use unknown OS"); 89e5dd7070Spatrick assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && 90*12c85518Srobert "SPIR(-V) target must use unknown environment type"); 91e5dd7070Spatrick TLSSupported = false; 92e5dd7070Spatrick VLASupported = false; 93e5dd7070Spatrick LongWidth = LongAlign = 64; 94a9ac8606Spatrick AddrSpaceMap = &SPIRDefIsPrivMap; 95e5dd7070Spatrick UseAddrSpaceMapMangling = true; 96e5dd7070Spatrick HasLegalHalfType = true; 97e5dd7070Spatrick HasFloat16 = true; 98e5dd7070Spatrick // Define available target features 99e5dd7070Spatrick // These must be defined in sorted order! 100e5dd7070Spatrick NoAsmVariants = true; 101e5dd7070Spatrick } 102e5dd7070Spatrick 103*12c85518Srobert public: 104e5dd7070Spatrick // SPIR supports the half type and the only llvm intrinsic allowed in SPIR is 105e5dd7070Spatrick // memcpy as per section 3 of the SPIR spec. useFP16ConversionIntrinsics()106e5dd7070Spatrick bool useFP16ConversionIntrinsics() const override { return false; } 107e5dd7070Spatrick getTargetBuiltins()108*12c85518Srobert ArrayRef<Builtin::Info> getTargetBuiltins() const override { 109*12c85518Srobert return std::nullopt; 110*12c85518Srobert } 111e5dd7070Spatrick getClobbers()112e5dd7070Spatrick const char *getClobbers() const override { return ""; } 113e5dd7070Spatrick getGCCRegNames()114*12c85518Srobert ArrayRef<const char *> getGCCRegNames() const override { 115*12c85518Srobert return std::nullopt; 116*12c85518Srobert } 117e5dd7070Spatrick validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & info)118e5dd7070Spatrick bool validateAsmConstraint(const char *&Name, 119e5dd7070Spatrick TargetInfo::ConstraintInfo &info) const override { 120e5dd7070Spatrick return true; 121e5dd7070Spatrick } 122e5dd7070Spatrick getGCCRegAliases()123e5dd7070Spatrick ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 124*12c85518Srobert return std::nullopt; 125e5dd7070Spatrick } 126e5dd7070Spatrick getBuiltinVaListKind()127e5dd7070Spatrick BuiltinVaListKind getBuiltinVaListKind() const override { 128e5dd7070Spatrick return TargetInfo::VoidPtrBuiltinVaList; 129e5dd7070Spatrick } 130e5dd7070Spatrick 131*12c85518Srobert std::optional<unsigned> getDWARFAddressSpace(unsigned AddressSpace)132a9ac8606Spatrick getDWARFAddressSpace(unsigned AddressSpace) const override { 133a9ac8606Spatrick return AddressSpace; 134a9ac8606Spatrick } 135a9ac8606Spatrick checkCallingConvention(CallingConv CC)136e5dd7070Spatrick CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 137e5dd7070Spatrick return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK 138e5dd7070Spatrick : CCCR_Warning; 139e5dd7070Spatrick } 140e5dd7070Spatrick getDefaultCallingConv()141e5dd7070Spatrick CallingConv getDefaultCallingConv() const override { 142e5dd7070Spatrick return CC_SpirFunction; 143e5dd7070Spatrick } 144e5dd7070Spatrick setAddressSpaceMap(bool DefaultIsGeneric)145a9ac8606Spatrick void setAddressSpaceMap(bool DefaultIsGeneric) { 146a9ac8606Spatrick AddrSpaceMap = DefaultIsGeneric ? &SPIRDefIsGenMap : &SPIRDefIsPrivMap; 147a9ac8606Spatrick } 148a9ac8606Spatrick adjust(DiagnosticsEngine & Diags,LangOptions & Opts)149a9ac8606Spatrick void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override { 150a9ac8606Spatrick TargetInfo::adjust(Diags, Opts); 151a9ac8606Spatrick // FIXME: SYCL specification considers unannotated pointers and references 152a9ac8606Spatrick // to be pointing to the generic address space. See section 5.9.3 of 153a9ac8606Spatrick // SYCL 2020 specification. 154*12c85518Srobert // Currently, there is no way of representing SYCL's and HIP/CUDA's default 155*12c85518Srobert // address space language semantic along with the semantics of embedded C's 156*12c85518Srobert // default address space in the same address space map. Hence the map needs 157*12c85518Srobert // to be reset to allow mapping to the desired value of 'Default' entry for 158*12c85518Srobert // SYCL and HIP/CUDA. 159*12c85518Srobert setAddressSpaceMap( 160*12c85518Srobert /*DefaultIsGeneric=*/Opts.SYCLIsDevice || 161*12c85518Srobert // The address mapping from HIP/CUDA language for device code is only 162*12c85518Srobert // defined for SPIR-V. 163*12c85518Srobert (getTriple().isSPIRV() && Opts.CUDAIsDevice)); 164a9ac8606Spatrick } 165a9ac8606Spatrick setSupportedOpenCLOpts()166e5dd7070Spatrick void setSupportedOpenCLOpts() override { 167e5dd7070Spatrick // Assume all OpenCL extensions and optional core features are supported 168*12c85518Srobert // for SPIR and SPIR-V since they are generic targets. 169a9ac8606Spatrick supportAllOpenCLOpts(); 170e5dd7070Spatrick } 171ec727ea7Spatrick hasBitIntType()172*12c85518Srobert bool hasBitIntType() const override { return true; } 173a9ac8606Spatrick hasInt128Type()174a9ac8606Spatrick bool hasInt128Type() const override { return false; } 175e5dd7070Spatrick }; 176a9ac8606Spatrick 177*12c85518Srobert class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public BaseSPIRTargetInfo { 178*12c85518Srobert public: SPIRTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)179*12c85518Srobert SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 180*12c85518Srobert : BaseSPIRTargetInfo(Triple, Opts) { 181*12c85518Srobert assert(Triple.isSPIR() && "Invalid architecture for SPIR."); 182*12c85518Srobert assert(getTriple().getOS() == llvm::Triple::UnknownOS && 183*12c85518Srobert "SPIR target must use unknown OS"); 184*12c85518Srobert assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && 185*12c85518Srobert "SPIR target must use unknown environment type"); 186*12c85518Srobert } 187*12c85518Srobert 188*12c85518Srobert void getTargetDefines(const LangOptions &Opts, 189*12c85518Srobert MacroBuilder &Builder) const override; 190*12c85518Srobert hasFeature(StringRef Feature)191*12c85518Srobert bool hasFeature(StringRef Feature) const override { 192*12c85518Srobert return Feature == "spir"; 193*12c85518Srobert } 194*12c85518Srobert }; 195*12c85518Srobert 196e5dd7070Spatrick class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo { 197e5dd7070Spatrick public: SPIR32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)198e5dd7070Spatrick SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 199e5dd7070Spatrick : SPIRTargetInfo(Triple, Opts) { 200*12c85518Srobert assert(Triple.getArch() == llvm::Triple::spir && 201*12c85518Srobert "Invalid architecture for 32-bit SPIR."); 202e5dd7070Spatrick PointerWidth = PointerAlign = 32; 203e5dd7070Spatrick SizeType = TargetInfo::UnsignedInt; 204e5dd7070Spatrick PtrDiffType = IntPtrType = TargetInfo::SignedInt; 205e5dd7070Spatrick resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-" 206e5dd7070Spatrick "v96:128-v192:256-v256:256-v512:512-v1024:1024"); 207e5dd7070Spatrick } 208e5dd7070Spatrick 209e5dd7070Spatrick void getTargetDefines(const LangOptions &Opts, 210e5dd7070Spatrick MacroBuilder &Builder) const override; 211e5dd7070Spatrick }; 212e5dd7070Spatrick 213e5dd7070Spatrick class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo { 214e5dd7070Spatrick public: SPIR64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)215e5dd7070Spatrick SPIR64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 216e5dd7070Spatrick : SPIRTargetInfo(Triple, Opts) { 217*12c85518Srobert assert(Triple.getArch() == llvm::Triple::spir64 && 218*12c85518Srobert "Invalid architecture for 64-bit SPIR."); 219e5dd7070Spatrick PointerWidth = PointerAlign = 64; 220e5dd7070Spatrick SizeType = TargetInfo::UnsignedLong; 221e5dd7070Spatrick PtrDiffType = IntPtrType = TargetInfo::SignedLong; 222e5dd7070Spatrick resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-" 223e5dd7070Spatrick "v96:128-v192:256-v256:256-v512:512-v1024:1024"); 224e5dd7070Spatrick } 225e5dd7070Spatrick 226e5dd7070Spatrick void getTargetDefines(const LangOptions &Opts, 227e5dd7070Spatrick MacroBuilder &Builder) const override; 228e5dd7070Spatrick }; 229*12c85518Srobert 230*12c85518Srobert class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRTargetInfo { 231*12c85518Srobert public: SPIRVTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)232*12c85518Srobert SPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 233*12c85518Srobert : BaseSPIRTargetInfo(Triple, Opts) { 234*12c85518Srobert assert(Triple.isSPIRV() && "Invalid architecture for SPIR-V."); 235*12c85518Srobert assert(getTriple().getOS() == llvm::Triple::UnknownOS && 236*12c85518Srobert "SPIR-V target must use unknown OS"); 237*12c85518Srobert assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && 238*12c85518Srobert "SPIR-V target must use unknown environment type"); 239*12c85518Srobert } 240*12c85518Srobert 241*12c85518Srobert void getTargetDefines(const LangOptions &Opts, 242*12c85518Srobert MacroBuilder &Builder) const override; 243*12c85518Srobert hasFeature(StringRef Feature)244*12c85518Srobert bool hasFeature(StringRef Feature) const override { 245*12c85518Srobert return Feature == "spirv"; 246*12c85518Srobert } 247*12c85518Srobert }; 248*12c85518Srobert 249*12c85518Srobert class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public SPIRVTargetInfo { 250*12c85518Srobert public: SPIRV32TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)251*12c85518Srobert SPIRV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 252*12c85518Srobert : SPIRVTargetInfo(Triple, Opts) { 253*12c85518Srobert assert(Triple.getArch() == llvm::Triple::spirv32 && 254*12c85518Srobert "Invalid architecture for 32-bit SPIR-V."); 255*12c85518Srobert PointerWidth = PointerAlign = 32; 256*12c85518Srobert SizeType = TargetInfo::UnsignedInt; 257*12c85518Srobert PtrDiffType = IntPtrType = TargetInfo::SignedInt; 258*12c85518Srobert resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-" 259*12c85518Srobert "v96:128-v192:256-v256:256-v512:512-v1024:1024"); 260*12c85518Srobert } 261*12c85518Srobert 262*12c85518Srobert void getTargetDefines(const LangOptions &Opts, 263*12c85518Srobert MacroBuilder &Builder) const override; 264*12c85518Srobert }; 265*12c85518Srobert 266*12c85518Srobert class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public SPIRVTargetInfo { 267*12c85518Srobert public: SPIRV64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)268*12c85518Srobert SPIRV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) 269*12c85518Srobert : SPIRVTargetInfo(Triple, Opts) { 270*12c85518Srobert assert(Triple.getArch() == llvm::Triple::spirv64 && 271*12c85518Srobert "Invalid architecture for 64-bit SPIR-V."); 272*12c85518Srobert PointerWidth = PointerAlign = 64; 273*12c85518Srobert SizeType = TargetInfo::UnsignedLong; 274*12c85518Srobert PtrDiffType = IntPtrType = TargetInfo::SignedLong; 275*12c85518Srobert resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-" 276*12c85518Srobert "v96:128-v192:256-v256:256-v512:512-v1024:1024"); 277*12c85518Srobert } 278*12c85518Srobert 279*12c85518Srobert void getTargetDefines(const LangOptions &Opts, 280*12c85518Srobert MacroBuilder &Builder) const override; 281*12c85518Srobert }; 282*12c85518Srobert 283e5dd7070Spatrick } // namespace targets 284e5dd7070Spatrick } // namespace clang 285e5dd7070Spatrick #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H 286