Home | History | Annotate | Download | only in SPIRV
      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