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
init()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
init()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
init()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
init()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
init()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
init()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
init()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
init()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
init()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;
BuiltinArgTypeMangleInfoBuiltinArgTypeMangleInfo393 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 }
~BuiltinFuncMangleInfo()409 virtual ~BuiltinFuncMangleInfo(){}
getUnmangledName()410 const std::string &getUnmangledName() const { return UnmangledName;}
addUnsignedArg(int Ndx)411 void addUnsignedArg(int Ndx) { UnsignedArgs.insert(Ndx);}
addVoidPtrArg(int Ndx)412 void addVoidPtrArg(int Ndx) { VoidPtrArgs.insert(Ndx);}
addSamplerArg(int Ndx)413 void addSamplerArg(int Ndx) { SamplerArgs.insert(Ndx);}
addAtomicArg(int Ndx)414 void addAtomicArg(int Ndx) { AtomicArgs.insert(Ndx);}
setLocalArgBlock(int Ndx)415 void setLocalArgBlock(int Ndx) {
416 assert(0 <= Ndx && "it is not allowed to set less than zero index");
417 LocalArgBlockIdx = Ndx;
418 }
setEnumArg(int Ndx,SPIR::TypePrimitiveEnum Enum)419 void setEnumArg(int Ndx, SPIR::TypePrimitiveEnum Enum) {
420 EnumArgs[Ndx] = Enum;}
setArgAttr(int Ndx,unsigned Attr)421 void setArgAttr(int Ndx, unsigned Attr) {
422 Attrs[Ndx] = Attr;}
setVarArg(int Ndx)423 void setVarArg(int Ndx) {
424 assert(0 <= Ndx && "it is not allowed to set less than zero index");
425 VarArgIdx = Ndx;
426 }
isArgUnsigned(int Ndx)427 bool isArgUnsigned(int Ndx) {
428 return UnsignedArgs.count(-1) || UnsignedArgs.count(Ndx);}
isArgVoidPtr(int Ndx)429 bool isArgVoidPtr(int Ndx) {
430 return VoidPtrArgs.count(-1) || VoidPtrArgs.count(Ndx);}
isArgSampler(int Ndx)431 bool isArgSampler(int Ndx) {
432 return SamplerArgs.count(Ndx);}
isArgAtomic(int Ndx)433 bool isArgAtomic(int Ndx) {
434 return AtomicArgs.count(Ndx);}
isLocalArgBlock(int 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 }
getArgAttr(int Ndx)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
getVarArg()457 int getVarArg() const {
458 return VarArgIdx;
459 }
getTypeMangleInfo(int Ndx)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 }
init(const std::string & UniqUnmangledName)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 *>
getTypes(T V)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>
move(std::vector<T> & V,size_t begin,size_t end,size_t target)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.
findFirstPtr(const std::vector<Value * > & Args)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>
getArgAs(CallInst * CI,unsigned I)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
init()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