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