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