1 //===- LLVMSPIRVInternal.h - SPIR-V internal header file --------*- C++ -*-===// 2 // 3 // The LLVM/SPIRV Translator 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. 9 // 10 // Permission is hereby granted, free of charge, to any person obtaining a 11 // copy of this software and associated documentation files (the "Software"), 12 // to deal with the Software without restriction, including without limitation 13 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 // and/or sell copies of the Software, and to permit persons to whom the 15 // Software is furnished to do so, subject to the following conditions: 16 // 17 // Redistributions of source code must retain the above copyright notice, 18 // this list of conditions and the following disclaimers. 19 // Redistributions in binary form must reproduce the above copyright notice, 20 // this list of conditions and the following disclaimers in the documentation 21 // and/or other materials provided with the distribution. 22 // Neither the names of Advanced Micro Devices, Inc., nor the names of its 23 // contributors may be used to endorse or promote products derived from this 24 // Software without specific prior written permission. 25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH 31 // THE SOFTWARE. 32 // 33 //===----------------------------------------------------------------------===// 34 /// \file 35 /// 36 /// This file declares classes and functions shared by SPIR-V reader/writer. 37 /// 38 //===----------------------------------------------------------------------===// 39 #ifndef LLVMSPIRVINTERNAL_HPP_ 40 #define LLVMSPIRVINTERNAL_HPP_ 41 42 #include "libSPIRV/SPIRVUtil.h" 43 #include "libSPIRV/SPIRVEnum.h" 44 #include "libSPIRV/SPIRVNameMapEnum.h" 45 #include "libSPIRV/SPIRVError.h" 46 #include "libSPIRV/SPIRVType.h" 47 #include "NameMangleAPI.h" 48 49 #include "llvm/IR/Attributes.h" 50 #include "llvm/IR/Constants.h" 51 #include "llvm/IR/Instructions.h" 52 #include "llvm/Support/SPIRV.h" 53 54 #include <utility> 55 #include <functional> 56 57 using namespace SPIRV; 58 using namespace llvm; 59 60 namespace SPIRV{ 61 62 /// The LLVM/SPIR-V translator version used to fill the lower 16 bits of the 63 /// generator's magic number in the generated SPIR-V module. 64 /// This number should be bumped up whenever the generated SPIR-V changes. 65 const static unsigned short kTranslatorVer = 14; 66 67 #define SPCV_TARGET_LLVM_IMAGE_TYPE_ENCODE_ACCESS_QUAL 0 68 // Workaround for SPIR 2 producer bug about kernel function calling convention. 69 // This workaround checks metadata to determine if a function is kernel. 70 #define SPCV_RELAX_KERNEL_CALLING_CONV 1 71 72 class SPIRVOpaqueType; 73 typedef SPIRVMap<std::string, Op, SPIRVOpaqueType> 74 SPIRVOpaqueTypeOpCodeMap; 75 76 // Ad hoc function used by LLVM/SPIRV converter for type casting 77 #define SPCV_CAST "spcv.cast" 78 #define LLVM_MEMCPY "llvm.memcpy" 79 80 namespace kOCLTypeQualifierName { 81 const static char *Const = "const"; 82 const static char *Volatile = "volatile"; 83 const static char *Restrict = "restrict"; 84 const static char *Pipe = "pipe"; 85 } 86 87 template<> inline void 88 SPIRVMap<unsigned, Op>::init() { 89 #define _SPIRV_OP(x,y) add(Instruction::x, Op##y); 90 /* Casts */ 91 _SPIRV_OP(ZExt, UConvert) 92 _SPIRV_OP(SExt, SConvert) 93 _SPIRV_OP(Trunc, UConvert) 94 _SPIRV_OP(FPToUI, ConvertFToU) 95 _SPIRV_OP(FPToSI, ConvertFToS) 96 _SPIRV_OP(UIToFP, ConvertUToF) 97 _SPIRV_OP(SIToFP, ConvertSToF) 98 _SPIRV_OP(FPTrunc, FConvert) 99 _SPIRV_OP(FPExt, FConvert) 100 _SPIRV_OP(PtrToInt, ConvertPtrToU) 101 _SPIRV_OP(IntToPtr, ConvertUToPtr) 102 _SPIRV_OP(BitCast, Bitcast) 103 _SPIRV_OP(AddrSpaceCast, GenericCastToPtr) 104 _SPIRV_OP(GetElementPtr, AccessChain) 105 /*Binary*/ 106 _SPIRV_OP(And, BitwiseAnd) 107 _SPIRV_OP(Or, BitwiseOr) 108 _SPIRV_OP(Xor, BitwiseXor) 109 _SPIRV_OP(Add, IAdd) 110 _SPIRV_OP(FAdd, FAdd) 111 _SPIRV_OP(Sub, ISub) 112 _SPIRV_OP(FSub, FSub) 113 _SPIRV_OP(Mul, IMul) 114 _SPIRV_OP(FMul, FMul) 115 _SPIRV_OP(UDiv, UDiv) 116 _SPIRV_OP(SDiv, SDiv) 117 _SPIRV_OP(FDiv, FDiv) 118 _SPIRV_OP(SRem, SRem) 119 _SPIRV_OP(FRem, FRem) 120 _SPIRV_OP(URem, UMod) 121 _SPIRV_OP(Shl, ShiftLeftLogical) 122 _SPIRV_OP(LShr, ShiftRightLogical) 123 _SPIRV_OP(AShr, ShiftRightArithmetic) 124 #undef _SPIRV_OP 125 } 126 typedef SPIRVMap<unsigned, Op> OpCodeMap; 127 128 template<> inline void 129 SPIRVMap<CmpInst::Predicate, Op>::init() { 130 #define _SPIRV_OP(x,y) add(CmpInst::x, Op##y); 131 _SPIRV_OP(FCMP_OEQ, FOrdEqual) 132 _SPIRV_OP(FCMP_OGT, FOrdGreaterThan) 133 _SPIRV_OP(FCMP_OGE, FOrdGreaterThanEqual) 134 _SPIRV_OP(FCMP_OLT, FOrdLessThan) 135 _SPIRV_OP(FCMP_OLE, FOrdLessThanEqual) 136 _SPIRV_OP(FCMP_ONE, FOrdNotEqual) 137 _SPIRV_OP(FCMP_ORD, Ordered) 138 _SPIRV_OP(FCMP_UNO, Unordered) 139 _SPIRV_OP(FCMP_UEQ, FUnordEqual) 140 _SPIRV_OP(FCMP_UGT, FUnordGreaterThan) 141 _SPIRV_OP(FCMP_UGE, FUnordGreaterThanEqual) 142 _SPIRV_OP(FCMP_ULT, FUnordLessThan) 143 _SPIRV_OP(FCMP_ULE, FUnordLessThanEqual) 144 _SPIRV_OP(FCMP_UNE, FUnordNotEqual) 145 _SPIRV_OP(ICMP_EQ, IEqual) 146 _SPIRV_OP(ICMP_NE, INotEqual) 147 _SPIRV_OP(ICMP_UGT, UGreaterThan) 148 _SPIRV_OP(ICMP_UGE, UGreaterThanEqual) 149 _SPIRV_OP(ICMP_ULT, ULessThan) 150 _SPIRV_OP(ICMP_ULE, ULessThanEqual) 151 _SPIRV_OP(ICMP_SGT, SGreaterThan) 152 _SPIRV_OP(ICMP_SGE, SGreaterThanEqual) 153 _SPIRV_OP(ICMP_SLT, SLessThan) 154 _SPIRV_OP(ICMP_SLE, SLessThanEqual) 155 #undef _SPIRV_OP 156 } 157 typedef SPIRVMap<CmpInst::Predicate, Op> CmpMap; 158 159 class IntBoolOpMapId; 160 template<> inline void 161 SPIRVMap<Op, Op, IntBoolOpMapId>::init() { 162 add(OpNot, OpLogicalNot); 163 add(OpBitwiseAnd, OpLogicalAnd); 164 add(OpBitwiseOr, OpLogicalOr); 165 add(OpBitwiseXor, OpLogicalNotEqual); 166 add(OpIEqual, OpLogicalEqual); 167 add(OpINotEqual, OpLogicalNotEqual); 168 } 169 typedef SPIRVMap<Op, Op, IntBoolOpMapId> IntBoolOpMap; 170 171 #define SPIR_TARGETTRIPLE32 "spir-unknown-unknown" 172 #define SPIR_TARGETTRIPLE64 "spir64-unknown-unknown" 173 #define SPIR_DATALAYOUT32 "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32"\ 174 "-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32"\ 175 "-v32:32:32-v48:64:64-v64:64:64-v96:128:128"\ 176 "-v128:128:128-v192:256:256-v256:256:256"\ 177 "-v512:512:512-v1024:1024:1024" 178 #define SPIR_DATALAYOUT64 "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32"\ 179 "-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32"\ 180 "-v32:32:32-v48:64:64-v64:64:64-v96:128:128"\ 181 "-v128:128:128-v192:256:256-v256:256:256"\ 182 "-v512:512:512-v1024:1024:1024" 183 184 enum SPIRAddressSpace { 185 SPIRAS_Private, 186 SPIRAS_Global, 187 SPIRAS_Constant, 188 SPIRAS_Local, 189 SPIRAS_Generic, 190 SPIRAS_Count, 191 }; 192 193 template<>inline void 194 SPIRVMap<SPIRAddressSpace, std::string>::init() { 195 add(SPIRAS_Private, "Private"); 196 add(SPIRAS_Global, "Global"); 197 add(SPIRAS_Constant, "Constant"); 198 add(SPIRAS_Local, "Local"); 199 add(SPIRAS_Generic, "Generic"); 200 } 201 typedef SPIRVMap<SPIRAddressSpace, SPIRVStorageClassKind> 202 SPIRAddrSpaceCapitalizedNameMap; 203 204 template<> inline void 205 SPIRVMap<SPIRAddressSpace, SPIRVStorageClassKind>::init() { 206 add(SPIRAS_Private, StorageClassFunction); 207 add(SPIRAS_Global, StorageClassCrossWorkgroup); 208 add(SPIRAS_Constant, StorageClassUniformConstant); 209 add(SPIRAS_Local, StorageClassWorkgroup); 210 add(SPIRAS_Generic, StorageClassGeneric); 211 } 212 typedef SPIRVMap<SPIRAddressSpace, SPIRVStorageClassKind> SPIRSPIRVAddrSpaceMap; 213 214 // Maps OCL builtin function to SPIRV builtin variable. 215 template<> inline void 216 SPIRVMap<std::string, SPIRVAccessQualifierKind>::init() { 217 add("read_only", AccessQualifierReadOnly); 218 add("write_only", AccessQualifierWriteOnly); 219 add("read_write", AccessQualifierReadWrite); 220 } 221 typedef SPIRVMap<std::string, SPIRVAccessQualifierKind> SPIRSPIRVAccessQualifierMap; 222 223 template<> inline void 224 SPIRVMap<Attribute::AttrKind, SPIRVFuncParamAttrKind>::init() { 225 add(Attribute::ZExt, FunctionParameterAttributeZext); 226 add(Attribute::SExt, FunctionParameterAttributeSext); 227 add(Attribute::ByVal, FunctionParameterAttributeByVal); 228 add(Attribute::StructRet, FunctionParameterAttributeSret); 229 add(Attribute::NoAlias, FunctionParameterAttributeNoAlias); 230 add(Attribute::NoCapture, FunctionParameterAttributeNoCapture); 231 } 232 typedef SPIRVMap<Attribute::AttrKind, SPIRVFuncParamAttrKind> 233 SPIRSPIRVFuncParamAttrMap; 234 235 template<> inline void 236 SPIRVMap<Attribute::AttrKind, SPIRVFunctionControlMaskKind>::init() { 237 add(Attribute::ReadNone, FunctionControlPureMask); 238 add(Attribute::ReadOnly, FunctionControlConstMask); 239 add(Attribute::AlwaysInline, FunctionControlInlineMask); 240 add(Attribute::NoInline, FunctionControlDontInlineMask); 241 } 242 typedef SPIRVMap<Attribute::AttrKind, SPIRVFunctionControlMaskKind> 243 SPIRSPIRVFuncCtlMaskMap; 244 245 class SPIRVExtSetShortName; 246 template<> inline void 247 SPIRVMap<SPIRVExtInstSetKind, std::string, SPIRVExtSetShortName>::init() { 248 add(SPIRVEIS_OpenCL, "ocl"); 249 } 250 typedef SPIRVMap<SPIRVExtInstSetKind, std::string, SPIRVExtSetShortName> 251 SPIRVExtSetShortNameMap; 252 253 #define SPIR_MD_KERNELS "opencl.kernels" 254 #define SPIR_MD_COMPILER_OPTIONS "opencl.compiler.options" 255 #define SPIR_MD_KERNEL_ARG_ADDR_SPACE "kernel_arg_addr_space" 256 #define SPIR_MD_KERNEL_ARG_ACCESS_QUAL "kernel_arg_access_qual" 257 #define SPIR_MD_KERNEL_ARG_TYPE "kernel_arg_type" 258 #define SPIR_MD_KERNEL_ARG_BASE_TYPE "kernel_arg_base_type" 259 #define SPIR_MD_KERNEL_ARG_TYPE_QUAL "kernel_arg_type_qual" 260 #define SPIR_MD_KERNEL_ARG_NAME "kernel_arg_name" 261 262 #define OCL_TYPE_NAME_SAMPLER_T "sampler_t" 263 #define SPIR_TYPE_NAME_EVENT_T "opencl.event_t" 264 #define SPIR_TYPE_NAME_CLK_EVENT_T "opencl.clk_event_t" 265 #define SPIR_TYPE_NAME_BLOCK_T "opencl.block" 266 #define SPIR_INTRINSIC_BLOCK_BIND "spir_block_bind" 267 #define SPIR_INTRINSIC_GET_BLOCK_INVOKE "spir_get_block_invoke" 268 #define SPIR_INTRINSIC_GET_BLOCK_CONTEXT "spir_get_block_context" 269 #define SPIR_TEMP_NAME_PREFIX_BLOCK "block" 270 #define SPIR_TEMP_NAME_PREFIX_CALL "call" 271 272 namespace kLLVMTypeName { 273 const static char StructPrefix[] = "struct."; 274 } 275 276 namespace kSPIRVImageSampledTypeName { 277 const static char Float[] = "float"; 278 const static char Half[] = "half"; 279 const static char Int[] = "int"; 280 const static char UInt[] = "uint"; 281 const static char Void[] = "void"; 282 } 283 284 namespace kSPIRVTypeName { 285 const static char Delimiter = '.'; 286 const static char DeviceEvent[] = "DeviceEvent"; 287 const static char Event[] = "Event"; 288 const static char Image[] = "Image"; 289 const static char Pipe[] = "Pipe"; 290 const static char PostfixDelim = '_'; 291 const static char Prefix[] = "spirv"; 292 const static char PrefixAndDelim[] = "spirv."; 293 const static char Queue[] = "Queue"; 294 const static char ReserveId[] = "ReserveId"; 295 const static char SampledImg[] = "SampledImage"; 296 const static char Sampler[] = "Sampler"; 297 const static char ConstantSampler[] = "ConstantSampler"; 298 const static char PipeStorage[] = "PipeStorage"; 299 const static char ConstantPipeStorage[] = "ConstantPipeStorage"; 300 } 301 302 namespace kSPR2TypeName { 303 const static char Delimiter = '.'; 304 const static char OCLPrefix[] = "opencl."; 305 const static char ImagePrefix[] = "opencl.image"; 306 const static char Pipe[] = "opencl.pipe_t"; 307 const static char Sampler[] = "opencl.sampler_t"; 308 const static char Event[] = "opencl.event_t"; 309 } 310 311 namespace kAccessQualName { 312 const static char ReadOnly[] = "read_only"; 313 const static char WriteOnly[] = "write_only"; 314 const static char ReadWrite[] = "read_write"; 315 } 316 317 namespace kMangledName { 318 const static char Sampler[] = "11ocl_sampler"; 319 const static char AtomicPrefixIncoming[] = "U7_Atomic"; 320 const static char AtomicPrefixInternal[] = "atomic_"; 321 } 322 323 namespace kSPIRVName { 324 const static char GroupPrefix[] = "group_"; 325 const static char Prefix[] = "__spirv_"; 326 const static char Postfix[] = "__"; 327 const static char ImageQuerySize[] = "ImageQuerySize"; 328 const static char ImageQuerySizeLod[] = "ImageQuerySizeLod"; 329 const static char ImageSampleExplicitLod[] = "ImageSampleExplicitLod"; 330 const static char ReservedPrefix[] = "reserved_"; 331 const static char SampledImage[] = "SampledImage"; 332 const static char TempSampledImage[] = "TempSampledImage"; 333 } 334 335 namespace kSPIRVPostfix { 336 const static char Sat[] = "sat"; 337 const static char Rtz[] = "rtz"; 338 const static char Rte[] = "rte"; 339 const static char Rtp[] = "rtp"; 340 const static char Rtn[] = "rtn"; 341 const static char Rt[] = "rt"; 342 const static char Return[] = "R"; 343 const static char Divider[] = "_"; 344 /// Divider between extended instruction name and postfix 345 const static char ExtDivider[] = "__"; 346 } 347 348 namespace kSPIRVMD { 349 const static char Capability[] = "spirv.Capability"; 350 const static char EntryPoint[] = "spirv.EntryPoint"; 351 const static char ExecutionMode[] = "spirv.ExecutionMode"; 352 const static char Extension[] = "spirv.Extension"; 353 const static char Generator[] = "spirv.Generator"; 354 const static char Source[] = "spirv.Source"; 355 const static char SourceExtension[] = "spirv.SourceExtension"; 356 const static char MemoryModel[] = "spirv.MemoryModel"; 357 } 358 359 namespace kSPIR2MD { 360 const static char Extensions[] = "opencl.used.extensions"; 361 const static char FPContract[] = "opencl.enable.FP_CONTRACT"; 362 const static char OCLVer[] = "opencl.ocl.version"; 363 const static char OptFeatures[] = "opencl.used.optional.core.features"; 364 const static char SPIRVer[] = "opencl.spir.version"; 365 const static char VecTyHint[] = "vec_type_hint"; 366 const static char WGSize[] = "reqd_work_group_size"; 367 const static char WGSizeHint[] = "work_group_size_hint"; 368 } 369 370 enum Spir2SamplerKind { 371 CLK_ADDRESS_NONE = 0x0000, 372 CLK_ADDRESS_CLAMP = 0x0004, 373 CLK_ADDRESS_CLAMP_TO_EDGE = 0x0002, 374 CLK_ADDRESS_REPEAT = 0x0006, 375 CLK_ADDRESS_MIRRORED_REPEAT = 0x0008, 376 CLK_NORMALIZED_COORDS_FALSE = 0x0000, 377 CLK_NORMALIZED_COORDS_TRUE = 0x0001, 378 CLK_FILTER_NEAREST = 0x0010, 379 CLK_FILTER_LINEAR = 0x0020, 380 }; 381 382 383 /// Additional information for mangling a function argument type. 384 struct BuiltinArgTypeMangleInfo { 385 bool IsSigned; 386 bool IsVoidPtr; 387 bool IsEnum; 388 bool IsSampler; 389 bool IsAtomic; 390 bool IsLocalArgBlock; 391 SPIR::TypePrimitiveEnum Enum; 392 unsigned Attr; 393 BuiltinArgTypeMangleInfo():IsSigned(true), IsVoidPtr(false), IsEnum(false), 394 IsSampler(false), IsAtomic(false), IsLocalArgBlock(false), 395 Enum(SPIR::PRIMITIVE_NONE), Attr(0) 396 {} 397 }; 398 399 /// Information for mangling builtin function. 400 class BuiltinFuncMangleInfo { 401 public: 402 /// Translate builtin function name and set 403 /// argument attributes and unsigned args. 404 BuiltinFuncMangleInfo(const std::string &UniqName = "") : LocalArgBlockIdx(-1), 405 VarArgIdx(-1) { 406 if (!UniqName.empty()) 407 init(UniqName); 408 } 409 virtual ~BuiltinFuncMangleInfo(){} 410 const std::string &getUnmangledName() const { return UnmangledName;} 411 void addUnsignedArg(int Ndx) { UnsignedArgs.insert(Ndx);} 412 void addVoidPtrArg(int Ndx) { VoidPtrArgs.insert(Ndx);} 413 void addSamplerArg(int Ndx) { SamplerArgs.insert(Ndx);} 414 void addAtomicArg(int Ndx) { AtomicArgs.insert(Ndx);} 415 void setLocalArgBlock(int Ndx) { 416 assert(0 <= Ndx && "it is not allowed to set less than zero index"); 417 LocalArgBlockIdx = Ndx; 418 } 419 void setEnumArg(int Ndx, SPIR::TypePrimitiveEnum Enum) { 420 EnumArgs[Ndx] = Enum;} 421 void setArgAttr(int Ndx, unsigned Attr) { 422 Attrs[Ndx] = Attr;} 423 void setVarArg(int Ndx) { 424 assert(0 <= Ndx && "it is not allowed to set less than zero index"); 425 VarArgIdx = Ndx; 426 } 427 bool isArgUnsigned(int Ndx) { 428 return UnsignedArgs.count(-1) || UnsignedArgs.count(Ndx);} 429 bool isArgVoidPtr(int Ndx) { 430 return VoidPtrArgs.count(-1) || VoidPtrArgs.count(Ndx);} 431 bool isArgSampler(int Ndx) { 432 return SamplerArgs.count(Ndx);} 433 bool isArgAtomic(int Ndx) { 434 return AtomicArgs.count(Ndx);} 435 bool isLocalArgBlock(int Ndx) { 436 return LocalArgBlockIdx == Ndx;} 437 bool isArgEnum(int Ndx, SPIR::TypePrimitiveEnum *Enum = nullptr) { 438 auto Loc = EnumArgs.find(Ndx); 439 if (Loc == EnumArgs.end()) 440 Loc = EnumArgs.find(-1); 441 if (Loc == EnumArgs.end()) 442 return false; 443 if (Enum) 444 *Enum = Loc->second; 445 return true; 446 } 447 unsigned getArgAttr(int Ndx) { 448 auto Loc = Attrs.find(Ndx); 449 if (Loc == Attrs.end()) 450 Loc = Attrs.find(-1); 451 if (Loc == Attrs.end()) 452 return 0; 453 return Loc->second; 454 } 455 // get ellipsis index, single ellipsis at the end of the function is possible only 456 // return value < 0 if none 457 int getVarArg() const { 458 return VarArgIdx; 459 } 460 BuiltinArgTypeMangleInfo getTypeMangleInfo(int Ndx) { 461 BuiltinArgTypeMangleInfo Info; 462 Info.IsSigned = !isArgUnsigned(Ndx); 463 Info.IsVoidPtr = isArgVoidPtr(Ndx); 464 Info.IsEnum = isArgEnum(Ndx, &Info.Enum); 465 Info.IsSampler = isArgSampler(Ndx); 466 Info.IsAtomic = isArgAtomic(Ndx); 467 Info.IsLocalArgBlock = isLocalArgBlock(Ndx); 468 Info.Attr = getArgAttr(Ndx); 469 return Info; 470 } 471 virtual void init(const std::string &UniqUnmangledName){ 472 UnmangledName = UniqUnmangledName; 473 } 474 protected: 475 std::string UnmangledName; 476 std::set<int> UnsignedArgs; // unsigned arguments, or -1 if all are unsigned 477 std::set<int> VoidPtrArgs; // void pointer arguments, or -1 if all are void 478 // pointer 479 std::set<int> SamplerArgs; // sampler arguments 480 std::set<int> AtomicArgs; // atomic arguments 481 std::map<int, SPIR::TypePrimitiveEnum> EnumArgs; // enum arguments 482 std::map<int, unsigned> Attrs; // argument attributes 483 int LocalArgBlockIdx; // index of a block with local arguments, idx < 0 if none 484 int VarArgIdx; // index of ellipsis argument, idx < 0 if none 485 }; 486 487 /// \returns a vector of types for a collection of values. 488 template<class T> 489 std::vector<Type *> 490 getTypes(T V) { 491 std::vector<Type *> Tys; 492 for (auto &I:V) 493 Tys.push_back(I->getType()); 494 return Tys; 495 } 496 497 /// Move elements of std::vector from [begin, end) to target. 498 template <typename T> 499 void move(std::vector<T>& V, size_t begin, size_t end, size_t target) { 500 assert(begin < end && end <= V.size() && target <= V.size() && 501 !(begin < target && target < end)); 502 if (begin <= target && target <= end) 503 return; 504 auto B = V.begin() + begin, E = V.begin() + end; 505 if (target > V.size()) 506 target = V.size(); 507 if (target > end) 508 target -= (end - begin); 509 std::vector<T> Segment(B, E); 510 V.erase(B, E); 511 V.insert(V.begin() + target, Segment.begin(), Segment.end()); 512 } 513 514 /// Find position of first pointer type value in a vector. 515 inline size_t findFirstPtr(const std::vector<Value *> &Args) { 516 auto PtArg = std::find_if(Args.begin(), Args.end(), [](Value *V){ 517 return V->getType()->isPointerTy(); 518 }); 519 return PtArg - Args.begin(); 520 } 521 522 void removeFnAttr(LLVMContext *Context, CallInst *Call, 523 Attribute::AttrKind Attr); 524 void addFnAttr(LLVMContext *Context, CallInst *Call, 525 Attribute::AttrKind Attr); 526 void saveLLVMModule(Module *M, const std::string &OutputFile); 527 std::string mapSPIRVTypeToOCLType(SPIRVType* Ty, bool Signed); 528 std::string mapLLVMTypeToOCLType(const Type* Ty, bool Signed); 529 SPIRVDecorate *mapPostfixToDecorate(StringRef Postfix, SPIRVEntry *Target); 530 531 /// Add decorations to a SPIR-V entry. 532 /// \param Decs Each string is a postfix without _ at the beginning. 533 SPIRVValue *addDecorations(SPIRVValue *Target, 534 const SmallVectorImpl<std::string>& Decs); 535 536 PointerType *getOrCreateOpaquePtrType(Module *M, const std::string &Name, 537 unsigned AddrSpace = SPIRAS_Global); 538 PointerType* getSamplerType(Module *M); 539 PointerType* getPipeStorageType(Module *M); 540 void getFunctionTypeParameterTypes(llvm::FunctionType* FT, 541 std::vector<Type*>& ArgTys); 542 Function *getOrCreateFunction(Module *M, Type *RetTy, 543 ArrayRef<Type *> ArgTypes, StringRef Name, 544 BuiltinFuncMangleInfo *Mangle = nullptr, 545 AttributeSet *Attrs = nullptr, bool takeName = true); 546 547 /// Get function call arguments. 548 /// \param Start Starting index. 549 /// \param End Ending index. 550 std::vector<Value *> getArguments(CallInst* CI, unsigned Start = 0, 551 unsigned End = 0); 552 553 /// Get constant function call argument as an integer. 554 /// \param I argument index. 555 uint64_t getArgAsInt(CallInst *CI, unsigned I); 556 557 /// Get constant function call argument as type \param T. 558 /// \param I argument index. 559 template<typename T> 560 T getArgAs(CallInst *CI, unsigned I){ 561 return static_cast<T>(getArgAsInt(CI, I)); 562 } 563 564 /// Get constant function call argument as a Scope enum. 565 /// \param I argument index. 566 Scope getArgAsScope(CallInst *CI, unsigned I); 567 568 /// Get constant function call argument as a Decoration enum. 569 /// \param I argument index. 570 Decoration getArgAsDecoration(CallInst *CI, unsigned I); 571 572 bool isPointerToOpaqueStructType(llvm::Type* Ty); 573 bool isPointerToOpaqueStructType(llvm::Type* Ty, const std::string &Name); 574 575 /// Check if a type is OCL image type. 576 /// \return type name without "opencl." prefix. 577 bool isOCLImageType(llvm::Type* Ty, StringRef *Name = nullptr); 578 579 /// \param BaseTyName is the type name as in spirv.BaseTyName.Postfixes 580 /// \param Postfix contains postfixes extracted from the SPIR-V image 581 /// type name as spirv.BaseTyName.Postfixes. 582 bool 583 isSPIRVType(llvm::Type* Ty, StringRef BaseTyName, StringRef *Postfix = 0); 584 585 /// Decorate a function name as __spirv_{Name}_ 586 std::string decorateSPIRVFunction(const std::string &S); 587 588 /// Remove prefix/postfix from __spirv_{Name}_ 589 std::string undecorateSPIRVFunction(const std::string &S); 590 591 /// Check if a function has decorated name as __spirv_{Name}_ 592 /// and get the original name. 593 bool isDecoratedSPIRVFunc(const Function *F, std::string *UndecName = nullptr); 594 595 /// Get a canonical function name for a SPIR-V op code. 596 std::string getSPIRVFuncName(Op OC, StringRef PostFix = ""); 597 598 std::string getSPIRVFuncName(Op OC, const Type *pRetTy, bool IsSigned = false); 599 600 /// Get a canonical function name for a SPIR-V extended instruction 601 std::string getSPIRVExtFuncName(SPIRVExtInstSetKind Set, unsigned ExtOp, 602 StringRef PostFix = ""); 603 604 /// Get SPIR-V op code given the canonical function name. 605 /// Assume \param Name is either IA64 mangled or unmangled, and the unmangled 606 /// name takes the __spirv_{OpName}_{Postfixes} format. 607 /// \return op code if the unmangled function name is a valid op code name, 608 /// otherwise return OpNop. 609 /// \param Dec contains decorations decoded from function name if it is 610 /// not nullptr. 611 Op getSPIRVFuncOC(const std::string& Name, 612 SmallVectorImpl<std::string> *Dec = nullptr); 613 614 /// Get SPIR-V builtin variable enum given the canonical builtin name 615 /// Assume \param Name is in format __spirv_BuiltIn{Name} 616 /// \return false if \param Name is not a valid builtin name. 617 bool getSPIRVBuiltin(const std::string &Name, spv::BuiltIn &Builtin); 618 619 /// \param Name LLVM function name 620 /// \param DemangledName demanged name of the OpenCL built-in function 621 /// \returns true if Name is the name of the OpenCL built-in function, 622 /// false for other functions 623 bool oclIsBuiltin(const StringRef &Name, std::string *DemangledName = nullptr, 624 bool isCPP = false); 625 626 /// Check if a function type is void(void). 627 bool isVoidFuncTy(FunctionType *FT); 628 629 /// \returns true if \p T is a function pointer type. 630 bool isFunctionPointerType(Type *T); 631 632 /// \returns true if function \p F has function pointer type argument. 633 /// \param AI points to the function pointer type argument if returns true. 634 bool hasFunctionPointerArg(Function *F, Function::arg_iterator& AI); 635 636 /// \returns true if function \p F has array type argument. 637 bool hasArrayArg(Function *F); 638 639 /// Mutates function call instruction by changing the arguments. 640 /// \param ArgMutate mutates the function arguments. 641 /// \return mutated call instruction. 642 CallInst *mutateCallInst(Module *M, CallInst *CI, 643 std::function<std::string (CallInst *, std::vector<Value *> &)>ArgMutate, 644 BuiltinFuncMangleInfo *Mangle = nullptr, AttributeSet *Attrs = nullptr, 645 bool takeName = false); 646 647 /// Mutates function call instruction by changing the arguments and return 648 /// value. 649 /// \param ArgMutate mutates the function arguments. 650 /// \param RetMutate mutates the return value. 651 /// \return mutated instruction. 652 Instruction *mutateCallInst(Module *M, CallInst *CI, 653 std::function<std::string (CallInst *, std::vector<Value *> &, 654 Type *&RetTy)> ArgMutate, 655 std::function<Instruction *(CallInst *)> RetMutate, 656 BuiltinFuncMangleInfo *Mangle = nullptr, AttributeSet *Attrs = nullptr, 657 bool takeName = false); 658 659 /// Mutate call instruction to call SPIR-V builtin function. 660 CallInst * 661 mutateCallInstSPIRV(Module *M, CallInst *CI, 662 std::function<std::string (CallInst *, std::vector<Value *> &)>ArgMutate, 663 AttributeSet *Attrs = nullptr); 664 665 /// Mutate call instruction to call SPIR-V builtin function. 666 Instruction * 667 mutateCallInstSPIRV(Module *M, CallInst *CI, 668 std::function<std::string (CallInst *, std::vector<Value *> &, 669 Type *&RetTy)> ArgMutate, 670 std::function<Instruction *(CallInst *)> RetMutate, 671 AttributeSet *Attrs = nullptr); 672 673 /// Mutate function by change the arguments. 674 /// \param ArgMutate mutates the function arguments. 675 /// \param TakeName Take the original function's name if a new function with 676 /// different type needs to be created. 677 void mutateFunction(Function *F, 678 std::function<std::string (CallInst *, std::vector<Value *> &)>ArgMutate, 679 BuiltinFuncMangleInfo *Mangle = nullptr, AttributeSet *Attrs = nullptr, 680 bool TakeName = true); 681 682 /// Add a call instruction at \p Pos. 683 CallInst *addCallInst(Module *M, StringRef FuncName, Type *RetTy, 684 ArrayRef<Value *> Args, AttributeSet *Attrs, Instruction *Pos, 685 BuiltinFuncMangleInfo *Mangle = nullptr, 686 StringRef InstName = SPIR_TEMP_NAME_PREFIX_CALL, 687 bool TakeFuncName = true); 688 689 /// Add a call instruction for SPIR-V builtin function. 690 CallInst * 691 addCallInstSPIRV(Module *M, StringRef FuncName, Type *RetTy, 692 ArrayRef<Value *> Args, 693 AttributeSet *Attrs, Instruction *Pos, StringRef InstName); 694 695 /// Add a call of spir_block_bind function. 696 CallInst * 697 addBlockBind(Module *M, Function *InvokeFunc, Value *BlkCtx, Value *CtxLen, 698 Value *CtxAlign, Instruction *InsPos, 699 StringRef InstName = SPIR_TEMP_NAME_PREFIX_BLOCK); 700 701 typedef std::pair<std::vector<Value *>::iterator, 702 std::vector<Value *>::iterator> ValueVecRange; 703 704 /// Add a vector at \param InsPos. 705 Value * 706 addVector(Instruction *InsPos, ValueVecRange Range); 707 708 /// Replace scalar values with a vector created at \param InsPos. 709 void 710 makeVector(Instruction *InsPos, std::vector<Value *> &Ops, 711 ValueVecRange Range); 712 713 /// Expand a vector type value in \param Ops at index \param VecPos. 714 /// Generate extract element instructions at \param InsPos and replace 715 /// the vector type value with scalar type values. 716 /// If the value to be expanded is not vector type, do nothing. 717 void 718 expandVector(Instruction *InsPos, std::vector<Value *> &Ops, size_t VecPos); 719 720 /// Get size_t type. 721 IntegerType *getSizetType(Module *M); 722 723 /// Get void(void) function type. 724 Type *getVoidFuncType(Module *M); 725 726 /// Get void(void) function pointer type. 727 Type *getVoidFuncPtrType(Module *M, unsigned AddrSpace = 0); 728 729 /// Get a 64 bit integer constant. 730 ConstantInt *getInt64(Module *M, int64_t value); 731 732 /// Get a 32 bit integer constant. 733 ConstantInt *getInt32(Module *M, int value); 734 735 /// Get a 32 bit unsigned integer constant. 736 ConstantInt *getUInt32(Module *M, unsigned value); 737 738 /// Get a 16 bit unsigned integer constant. 739 ConstantInt *getUInt16(Module *M, unsigned short value); 740 741 // Get a 32 bit floating point constant. 742 Constant *getFloat32(Module *M, float value); 743 744 /// Get a 32 bit integer constant vector. 745 std::vector<Value *> getInt32(Module *M, const std::vector<int> &value); 746 747 /// Get a size_t type constant. 748 ConstantInt *getSizet(Module *M, uint64_t value); 749 750 /// Get metadata operand as int. 751 int getMDOperandAsInt(MDNode* N, unsigned I); 752 753 /// Get metadata operand as string. 754 std::string getMDOperandAsString(MDNode* N, unsigned I); 755 756 /// Get metadata operand as type. 757 Type* getMDOperandAsType(MDNode* N, unsigned I); 758 759 /// Get a named metadata as a set of string. 760 /// Assume the named metadata has one or more operands each of which might 761 /// contain set of strings. For instance: 762 /// !opencl.used.optional.core.features = !{!0} 763 /// !0 = !{!"cl_doubles", !"cl_images"} 764 /// or if we linked two modules we may have 765 /// !opencl.used.optional.core.features = !{!0, !1} 766 /// !0 = !{!"cl_doubles"} 767 /// !1 = !{!"cl_images"} 768 std::set<std::string> getNamedMDAsStringSet(Module *M, 769 const std::string &MDName); 770 771 /// Get SPIR-V language by SPIR-V metadata spirv.Source 772 std::tuple<unsigned, unsigned, std::string> 773 getSPIRVSource(Module *M); 774 775 /// Map an unsigned integer constant by applying a function. 776 ConstantInt *mapUInt(Module *M, ConstantInt *I, 777 std::function<unsigned(unsigned)> F); 778 779 /// Map a signed integer constant by applying a function. 780 ConstantInt *mapSInt(Module *M, ConstantInt *I, 781 std::function<int(int)> F); 782 783 /// Get postfix for given decoration. 784 /// The returned postfix does not include "_" at the beginning. 785 std::string getPostfix(Decoration Dec, unsigned Value = 0); 786 787 /// Get postfix _R{ReturnType} for return type 788 /// The returned postfix does not includ "_" at the beginning 789 std::string getPostfixForReturnType(CallInst *CI, bool IsSigned = false); 790 std::string getPostfixForReturnType(const Type *pRetTy, bool IsSigned = false); 791 792 Constant * 793 getScalarOrVectorConstantInt(Type *T, uint64_t V, bool isSigned = false); 794 795 /// Get a constant int or a constant int array. 796 /// \param T is the type of the constant. It should be an integer type or 797 // an integer pointer type. 798 /// \param Len is the length of the array. 799 /// \param V is the value to fill the array. 800 Value * 801 getScalarOrArrayConstantInt(Instruction *P, Type *T, unsigned Len, uint64_t V, 802 bool isSigned = false); 803 804 /// Get the array from GEP. 805 /// \param V is a GEP whose pointer operand is a pointer to an array of size 806 /// \param Size. 807 Value * 808 getScalarOrArray(Value *V, unsigned Size, Instruction *Pos); 809 810 void 811 dumpUsers(Value* V, StringRef Prompt = ""); 812 813 /// Get SPIR-V type name as spirv.BaseTyName.Postfixes. 814 std::string 815 getSPIRVTypeName(StringRef BaseTyName, StringRef Postfixes = ""); 816 817 /// Checks if given type name is either ConstantSampler or ConsantPipeStorage. 818 bool 819 isSPIRVConstantName(StringRef TyName); 820 821 /// Get SPIR-V type by changing the type name from spirv.OldName.Postfixes 822 /// to spirv.NewName.Postfixes. 823 Type * 824 getSPIRVTypeByChangeBaseTypeName(Module *M, Type *T, StringRef OldName, 825 StringRef NewName); 826 827 /// Get the postfixes of SPIR-V image type name as in spirv.Image.postfixes. 828 std::string 829 getSPIRVImageTypePostfixes(StringRef SampledType, 830 SPIRVTypeImageDescriptor Desc, 831 SPIRVAccessQualifierKind Acc); 832 833 /// Get the sampled type name used in postfix of image type in SPIR-V 834 /// friendly LLVM IR. 835 std::string 836 getSPIRVImageSampledTypeName(SPIRVType *Ty); 837 838 /// Translates OpenCL image type names to SPIR-V. 839 /// E.g. %opencl.image1d_rw_t -> %spirv.Image._void_0_0_0_0_0_0_2 840 Type *getSPIRVImageTypeFromOCL(Module *M, Type *T); 841 842 /// Get LLVM type for sampled type of SPIR-V image type by postfix. 843 Type* 844 getLLVMTypeForSPIRVImageSampledTypePostfix(StringRef Postfix, 845 LLVMContext &Ctx); 846 847 /// Map OpenCL opaque type name to SPIR-V type name. 848 std::string 849 mapOCLTypeNameToSPIRV(StringRef Name, StringRef Acc = ""); 850 851 /// Check if access qualifier is encoded in the type name. 852 bool hasAccessQualifiedName(StringRef TyName); 853 854 /// Get access qualifier from the type name. 855 StringRef getAccessQualifier(StringRef TyName); 856 857 bool 858 eraseUselessFunctions(Module *M); 859 860 /// Erase a function if it is declaration, has internal linkage and has no use. 861 bool 862 eraseIfNoUse(Function *F); 863 864 void 865 eraseIfNoUse(Value *V); 866 867 // Check if a mangled type name is unsigned 868 bool 869 isMangledTypeUnsigned(char Mangled); 870 871 // Check if a mangled type name is signed 872 bool 873 isMangledTypeSigned(char Mangled); 874 875 // Check if a mangled type name is floating point (except half) 876 bool 877 isMangledTypeFP(char Mangled); 878 879 // Check if a mangled type name is half 880 bool 881 isMangledTypeHalf(std::string Mangled); 882 883 // Check if \param I is valid vector size: 2, 3, 4, 8, 16. 884 bool 885 isValidVectorSize(unsigned I); 886 887 enum class ParamType 888 { 889 FLOAT = 0, 890 SIGNED = 1, 891 UNSIGNED = 2, 892 UNKNOWN = 3 893 }; 894 895 ParamType LastFuncParamType(const std::string& MangledName); 896 897 // Check if the last function parameter is signed 898 bool 899 isLastFuncParamSigned(const std::string& MangledName); 900 901 // Check if a mangled function name contains unsigned atomic type 902 bool 903 containsUnsignedAtomicType(StringRef Name); 904 905 /// Mangle builtin function name. 906 /// \return \param UniqName if \param BtnInfo is null pointer, otherwise 907 /// return IA64 mangled name. 908 std::string 909 mangleBuiltin(const std::string &UniqName, 910 ArrayRef<Type*> ArgTypes, BuiltinFuncMangleInfo* BtnInfo); 911 912 /// Remove cast from a value. 913 Value * 914 removeCast(Value *V); 915 916 /// Cast a function to a void(void) funtion pointer. 917 Constant * 918 castToVoidFuncPtr(Function *F); 919 920 /// Get i8* with the same address space. 921 PointerType *getInt8PtrTy(PointerType *T); 922 923 /// Cast a value to a i8* by inserting a cast instruction. 924 Value * 925 castToInt8Ptr(Value *V, Instruction *Pos); 926 927 template<> inline void 928 SPIRVMap<std::string, Op, SPIRVOpaqueType>::init() { 929 add(kSPIRVTypeName::DeviceEvent, OpTypeDeviceEvent); 930 add(kSPIRVTypeName::Event, OpTypeEvent); 931 add(kSPIRVTypeName::Image, OpTypeImage); 932 add(kSPIRVTypeName::Pipe, OpTypePipe); 933 add(kSPIRVTypeName::Queue, OpTypeQueue); 934 add(kSPIRVTypeName::ReserveId, OpTypeReserveId); 935 add(kSPIRVTypeName::Sampler, OpTypeSampler); 936 add(kSPIRVTypeName::SampledImg, OpTypeSampledImage); 937 } 938 939 } 940 941 #endif 942