1*0b57cec5SDimitry Andric //===-- AMDGPULibFunc.cpp -------------------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file contains utility functions to work with Itanium mangled names 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "AMDGPULibFunc.h" 145ffd83dbSDimitry Andric #include "AMDGPU.h" 155ffd83dbSDimitry Andric #include "llvm/ADT/SmallString.h" 165ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h" 175ffd83dbSDimitry Andric #include "llvm/ADT/StringExtras.h" 185ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h" 19*0b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 20*0b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 21*0b57cec5SDimitry Andric #include "llvm/IR/Function.h" 22*0b57cec5SDimitry Andric #include "llvm/IR/Module.h" 23*0b57cec5SDimitry Andric #include "llvm/IR/ValueSymbolTable.h" 245ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h" 25*0b57cec5SDimitry Andric #include <string> 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric using namespace llvm; 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric namespace { 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric enum EManglingParam { 32*0b57cec5SDimitry Andric E_NONE, 33*0b57cec5SDimitry Andric EX_EVENT, 34*0b57cec5SDimitry Andric EX_FLOAT4, 35*0b57cec5SDimitry Andric EX_INTV4, 36*0b57cec5SDimitry Andric EX_RESERVEDID, 37*0b57cec5SDimitry Andric EX_SAMPLER, 38*0b57cec5SDimitry Andric EX_SIZET, 39*0b57cec5SDimitry Andric EX_UINT, 40*0b57cec5SDimitry Andric EX_UINTV4, 41*0b57cec5SDimitry Andric E_ANY, 42*0b57cec5SDimitry Andric E_CONSTPTR_ANY, 43*0b57cec5SDimitry Andric E_CONSTPTR_SWAPGL, 44*0b57cec5SDimitry Andric E_COPY, 45*0b57cec5SDimitry Andric E_IMAGECOORDS, 46*0b57cec5SDimitry Andric E_POINTEE, 47*0b57cec5SDimitry Andric E_SETBASE_I32, 48*0b57cec5SDimitry Andric E_SETBASE_U32, 49*0b57cec5SDimitry Andric E_MAKEBASE_UNS, 50*0b57cec5SDimitry Andric E_V16_OF_POINTEE, 51*0b57cec5SDimitry Andric E_V2_OF_POINTEE, 52*0b57cec5SDimitry Andric E_V3_OF_POINTEE, 53*0b57cec5SDimitry Andric E_V4_OF_POINTEE, 54*0b57cec5SDimitry Andric E_V8_OF_POINTEE, 55*0b57cec5SDimitry Andric E_VLTLPTR_ANY, 56*0b57cec5SDimitry Andric }; 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric struct ManglingRule { 598bcb0991SDimitry Andric const char *Name; 60*0b57cec5SDimitry Andric unsigned char Lead[2]; 61*0b57cec5SDimitry Andric unsigned char Param[5]; 62*0b57cec5SDimitry Andric 63*0b57cec5SDimitry Andric int maxLeadIndex() const { return (std::max)(Lead[0], Lead[1]); } 64*0b57cec5SDimitry Andric int getNumLeads() const { return (Lead[0] ? 1 : 0) + (Lead[1] ? 1 : 0); } 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric unsigned getNumArgs() const; 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric static StringMap<int> buildManglingRulesMap(); 69*0b57cec5SDimitry Andric }; 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric // Information about library functions with unmangled names. 72*0b57cec5SDimitry Andric class UnmangledFuncInfo { 738bcb0991SDimitry Andric const char *Name; 74*0b57cec5SDimitry Andric unsigned NumArgs; 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric // Table for all lib functions with unmangled names. 77*0b57cec5SDimitry Andric static const UnmangledFuncInfo Table[]; 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric // Number of entries in Table. 80*0b57cec5SDimitry Andric static const unsigned TableSize; 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric static StringMap<unsigned> buildNameMap(); 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric public: 85*0b57cec5SDimitry Andric using ID = AMDGPULibFunc::EFuncId; 868bcb0991SDimitry Andric constexpr UnmangledFuncInfo(const char *_Name, unsigned _NumArgs) 87*0b57cec5SDimitry Andric : Name(_Name), NumArgs(_NumArgs) {} 88*0b57cec5SDimitry Andric // Get index to Table by function name. 89*0b57cec5SDimitry Andric static bool lookup(StringRef Name, ID &Id); 90*0b57cec5SDimitry Andric static unsigned toIndex(ID Id) { 91*0b57cec5SDimitry Andric assert(static_cast<unsigned>(Id) > 92*0b57cec5SDimitry Andric static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED) && 93*0b57cec5SDimitry Andric "Invalid unmangled library function"); 94*0b57cec5SDimitry Andric return static_cast<unsigned>(Id) - 1 - 95*0b57cec5SDimitry Andric static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED); 96*0b57cec5SDimitry Andric } 97*0b57cec5SDimitry Andric static ID toFuncId(unsigned Index) { 98*0b57cec5SDimitry Andric assert(Index < TableSize && 99*0b57cec5SDimitry Andric "Invalid unmangled library function"); 100*0b57cec5SDimitry Andric return static_cast<ID>( 101*0b57cec5SDimitry Andric Index + 1 + static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED)); 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric static unsigned getNumArgs(ID Id) { return Table[toIndex(Id)].NumArgs; } 104*0b57cec5SDimitry Andric static StringRef getName(ID Id) { return Table[toIndex(Id)].Name; } 105*0b57cec5SDimitry Andric }; 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric unsigned ManglingRule::getNumArgs() const { 108*0b57cec5SDimitry Andric unsigned I=0; 109*0b57cec5SDimitry Andric while (I < (sizeof Param/sizeof Param[0]) && Param[I]) ++I; 110*0b57cec5SDimitry Andric return I; 111*0b57cec5SDimitry Andric } 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric // This table describes function formal argument type rules. The order of rules 114*0b57cec5SDimitry Andric // corresponds to the EFuncId enum at AMDGPULibFunc.h 115*0b57cec5SDimitry Andric // 116*0b57cec5SDimitry Andric // "<func name>", { <leads> }, { <param rules> } 117*0b57cec5SDimitry Andric // where: 118*0b57cec5SDimitry Andric // <leads> - list of integers that are one-based indexes of formal argument 119*0b57cec5SDimitry Andric // used to mangle a function name. Other argument types are derived from types 120*0b57cec5SDimitry Andric // of these 'leads'. The order of integers in this list correspond to the 121*0b57cec5SDimitry Andric // order in which these arguments are mangled in the EDG mangling scheme. The 122*0b57cec5SDimitry Andric // same order should be preserved for arguments in the AMDGPULibFunc structure 123*0b57cec5SDimitry Andric // when it is used for mangling. For example: 124*0b57cec5SDimitry Andric // { "vstorea_half", {3,1}, {E_ANY,EX_SIZET,E_ANY}}, 125*0b57cec5SDimitry Andric // will be mangled in EDG scheme as vstorea_half_<3dparam>_<1stparam> 126*0b57cec5SDimitry Andric // When mangling from code use: 127*0b57cec5SDimitry Andric // AMDGPULibFunc insc; 128*0b57cec5SDimitry Andric // insc.param[0] = ... // describe 3rd parameter 129*0b57cec5SDimitry Andric // insc.param[1] = ... // describe 1rd parameter 130*0b57cec5SDimitry Andric // 131*0b57cec5SDimitry Andric // <param rules> - list of rules used to derive all of the function formal 132*0b57cec5SDimitry Andric // argument types. EX_ prefixed are simple types, other derived from the 133*0b57cec5SDimitry Andric // latest 'lead' argument type in the order of encoding from first to last. 134*0b57cec5SDimitry Andric // E_ANY - use prev lead type, E_CONSTPTR_ANY - make const pointer out of 135*0b57cec5SDimitry Andric // prev lead type, etc. see ParamIterator::getNextParam() for details. 136*0b57cec5SDimitry Andric 1378bcb0991SDimitry Andric static constexpr ManglingRule manglingRules[] = { 1388bcb0991SDimitry Andric { "", {0}, {0} }, 139*0b57cec5SDimitry Andric { "abs" , {1}, {E_ANY}}, 140*0b57cec5SDimitry Andric { "abs_diff" , {1}, {E_ANY,E_COPY}}, 141*0b57cec5SDimitry Andric { "acos" , {1}, {E_ANY}}, 142*0b57cec5SDimitry Andric { "acosh" , {1}, {E_ANY}}, 143*0b57cec5SDimitry Andric { "acospi" , {1}, {E_ANY}}, 144*0b57cec5SDimitry Andric { "add_sat" , {1}, {E_ANY,E_COPY}}, 145*0b57cec5SDimitry Andric { "all" , {1}, {E_ANY}}, 146*0b57cec5SDimitry Andric { "any" , {1}, {E_ANY}}, 147*0b57cec5SDimitry Andric { "asin" , {1}, {E_ANY}}, 148*0b57cec5SDimitry Andric { "asinh" , {1}, {E_ANY}}, 149*0b57cec5SDimitry Andric { "asinpi" , {1}, {E_ANY}}, 150*0b57cec5SDimitry Andric { "async_work_group_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_EVENT}}, 151*0b57cec5SDimitry Andric { "async_work_group_strided_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_SIZET,EX_EVENT}}, 152*0b57cec5SDimitry Andric { "atan" , {1}, {E_ANY}}, 153*0b57cec5SDimitry Andric { "atan2" , {1}, {E_ANY,E_COPY}}, 154*0b57cec5SDimitry Andric { "atan2pi" , {1}, {E_ANY,E_COPY}}, 155*0b57cec5SDimitry Andric { "atanh" , {1}, {E_ANY}}, 156*0b57cec5SDimitry Andric { "atanpi" , {1}, {E_ANY}}, 157*0b57cec5SDimitry Andric { "atomic_add" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 158*0b57cec5SDimitry Andric { "atomic_and" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 159*0b57cec5SDimitry Andric { "atomic_cmpxchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE,E_POINTEE}}, 160*0b57cec5SDimitry Andric { "atomic_dec" , {1}, {E_VLTLPTR_ANY}}, 161*0b57cec5SDimitry Andric { "atomic_inc" , {1}, {E_VLTLPTR_ANY}}, 162*0b57cec5SDimitry Andric { "atomic_max" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 163*0b57cec5SDimitry Andric { "atomic_min" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 164*0b57cec5SDimitry Andric { "atomic_or" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 165*0b57cec5SDimitry Andric { "atomic_sub" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 166*0b57cec5SDimitry Andric { "atomic_xchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 167*0b57cec5SDimitry Andric { "atomic_xor" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 168*0b57cec5SDimitry Andric { "bitselect" , {1}, {E_ANY,E_COPY,E_COPY}}, 169*0b57cec5SDimitry Andric { "cbrt" , {1}, {E_ANY}}, 170*0b57cec5SDimitry Andric { "ceil" , {1}, {E_ANY}}, 171*0b57cec5SDimitry Andric { "clamp" , {1}, {E_ANY,E_COPY,E_COPY}}, 172*0b57cec5SDimitry Andric { "clz" , {1}, {E_ANY}}, 173*0b57cec5SDimitry Andric { "commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 174*0b57cec5SDimitry Andric { "commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 175*0b57cec5SDimitry Andric { "copysign" , {1}, {E_ANY,E_COPY}}, 176*0b57cec5SDimitry Andric { "cos" , {1}, {E_ANY}}, 177*0b57cec5SDimitry Andric { "cosh" , {1}, {E_ANY}}, 178*0b57cec5SDimitry Andric { "cospi" , {1}, {E_ANY}}, 179*0b57cec5SDimitry Andric { "cross" , {1}, {E_ANY,E_COPY}}, 180*0b57cec5SDimitry Andric { "ctz" , {1}, {E_ANY}}, 181*0b57cec5SDimitry Andric { "degrees" , {1}, {E_ANY}}, 182*0b57cec5SDimitry Andric { "distance" , {1}, {E_ANY,E_COPY}}, 183*0b57cec5SDimitry Andric { "divide" , {1}, {E_ANY,E_COPY}}, 184*0b57cec5SDimitry Andric { "dot" , {1}, {E_ANY,E_COPY}}, 185*0b57cec5SDimitry Andric { "erf" , {1}, {E_ANY}}, 186*0b57cec5SDimitry Andric { "erfc" , {1}, {E_ANY}}, 187*0b57cec5SDimitry Andric { "exp" , {1}, {E_ANY}}, 188*0b57cec5SDimitry Andric { "exp10" , {1}, {E_ANY}}, 189*0b57cec5SDimitry Andric { "exp2" , {1}, {E_ANY}}, 190*0b57cec5SDimitry Andric { "expm1" , {1}, {E_ANY}}, 191*0b57cec5SDimitry Andric { "fabs" , {1}, {E_ANY}}, 192*0b57cec5SDimitry Andric { "fast_distance" , {1}, {E_ANY,E_COPY}}, 193*0b57cec5SDimitry Andric { "fast_length" , {1}, {E_ANY}}, 194*0b57cec5SDimitry Andric { "fast_normalize" , {1}, {E_ANY}}, 195*0b57cec5SDimitry Andric { "fdim" , {1}, {E_ANY,E_COPY}}, 196*0b57cec5SDimitry Andric { "floor" , {1}, {E_ANY}}, 197*0b57cec5SDimitry Andric { "fma" , {1}, {E_ANY,E_COPY,E_COPY}}, 198*0b57cec5SDimitry Andric { "fmax" , {1}, {E_ANY,E_COPY}}, 199*0b57cec5SDimitry Andric { "fmin" , {1}, {E_ANY,E_COPY}}, 200*0b57cec5SDimitry Andric { "fmod" , {1}, {E_ANY,E_COPY}}, 201*0b57cec5SDimitry Andric { "fract" , {2}, {E_POINTEE,E_ANY}}, 202*0b57cec5SDimitry Andric { "frexp" , {1,2}, {E_ANY,E_ANY}}, 203*0b57cec5SDimitry Andric { "get_image_array_size" , {1}, {E_ANY}}, 204*0b57cec5SDimitry Andric { "get_image_channel_data_type" , {1}, {E_ANY}}, 205*0b57cec5SDimitry Andric { "get_image_channel_order" , {1}, {E_ANY}}, 206*0b57cec5SDimitry Andric { "get_image_dim" , {1}, {E_ANY}}, 207*0b57cec5SDimitry Andric { "get_image_height" , {1}, {E_ANY}}, 208*0b57cec5SDimitry Andric { "get_image_width" , {1}, {E_ANY}}, 209*0b57cec5SDimitry Andric { "get_pipe_max_packets" , {1}, {E_ANY}}, 210*0b57cec5SDimitry Andric { "get_pipe_num_packets" , {1}, {E_ANY}}, 211*0b57cec5SDimitry Andric { "hadd" , {1}, {E_ANY,E_COPY}}, 212*0b57cec5SDimitry Andric { "hypot" , {1}, {E_ANY,E_COPY}}, 213*0b57cec5SDimitry Andric { "ilogb" , {1}, {E_ANY}}, 214*0b57cec5SDimitry Andric { "isequal" , {1}, {E_ANY,E_COPY}}, 215*0b57cec5SDimitry Andric { "isfinite" , {1}, {E_ANY}}, 216*0b57cec5SDimitry Andric { "isgreater" , {1}, {E_ANY,E_COPY}}, 217*0b57cec5SDimitry Andric { "isgreaterequal" , {1}, {E_ANY,E_COPY}}, 218*0b57cec5SDimitry Andric { "isinf" , {1}, {E_ANY}}, 219*0b57cec5SDimitry Andric { "isless" , {1}, {E_ANY,E_COPY}}, 220*0b57cec5SDimitry Andric { "islessequal" , {1}, {E_ANY,E_COPY}}, 221*0b57cec5SDimitry Andric { "islessgreater" , {1}, {E_ANY,E_COPY}}, 222*0b57cec5SDimitry Andric { "isnan" , {1}, {E_ANY}}, 223*0b57cec5SDimitry Andric { "isnormal" , {1}, {E_ANY}}, 224*0b57cec5SDimitry Andric { "isnotequal" , {1}, {E_ANY,E_COPY}}, 225*0b57cec5SDimitry Andric { "isordered" , {1}, {E_ANY,E_COPY}}, 226*0b57cec5SDimitry Andric { "isunordered" , {1}, {E_ANY,E_COPY}}, 227*0b57cec5SDimitry Andric { "ldexp" , {1}, {E_ANY,E_SETBASE_I32}}, 228*0b57cec5SDimitry Andric { "length" , {1}, {E_ANY}}, 229*0b57cec5SDimitry Andric { "lgamma" , {1}, {E_ANY}}, 230*0b57cec5SDimitry Andric { "lgamma_r" , {1,2}, {E_ANY,E_ANY}}, 231*0b57cec5SDimitry Andric { "log" , {1}, {E_ANY}}, 232*0b57cec5SDimitry Andric { "log10" , {1}, {E_ANY}}, 233*0b57cec5SDimitry Andric { "log1p" , {1}, {E_ANY}}, 234*0b57cec5SDimitry Andric { "log2" , {1}, {E_ANY}}, 235*0b57cec5SDimitry Andric { "logb" , {1}, {E_ANY}}, 236*0b57cec5SDimitry Andric { "mad" , {1}, {E_ANY,E_COPY,E_COPY}}, 237*0b57cec5SDimitry Andric { "mad24" , {1}, {E_ANY,E_COPY,E_COPY}}, 238*0b57cec5SDimitry Andric { "mad_hi" , {1}, {E_ANY,E_COPY,E_COPY}}, 239*0b57cec5SDimitry Andric { "mad_sat" , {1}, {E_ANY,E_COPY,E_COPY}}, 240*0b57cec5SDimitry Andric { "max" , {1}, {E_ANY,E_COPY}}, 241*0b57cec5SDimitry Andric { "maxmag" , {1}, {E_ANY,E_COPY}}, 242*0b57cec5SDimitry Andric { "min" , {1}, {E_ANY,E_COPY}}, 243*0b57cec5SDimitry Andric { "minmag" , {1}, {E_ANY,E_COPY}}, 244*0b57cec5SDimitry Andric { "mix" , {1}, {E_ANY,E_COPY,E_COPY}}, 245*0b57cec5SDimitry Andric { "modf" , {2}, {E_POINTEE,E_ANY}}, 246*0b57cec5SDimitry Andric { "mul24" , {1}, {E_ANY,E_COPY}}, 247*0b57cec5SDimitry Andric { "mul_hi" , {1}, {E_ANY,E_COPY}}, 248*0b57cec5SDimitry Andric { "nan" , {1}, {E_ANY}}, 249*0b57cec5SDimitry Andric { "nextafter" , {1}, {E_ANY,E_COPY}}, 250*0b57cec5SDimitry Andric { "normalize" , {1}, {E_ANY}}, 251*0b57cec5SDimitry Andric { "popcount" , {1}, {E_ANY}}, 252*0b57cec5SDimitry Andric { "pow" , {1}, {E_ANY,E_COPY}}, 253*0b57cec5SDimitry Andric { "pown" , {1}, {E_ANY,E_SETBASE_I32}}, 254*0b57cec5SDimitry Andric { "powr" , {1}, {E_ANY,E_COPY}}, 255*0b57cec5SDimitry Andric { "prefetch" , {1}, {E_CONSTPTR_ANY,EX_SIZET}}, 256*0b57cec5SDimitry Andric { "radians" , {1}, {E_ANY}}, 257*0b57cec5SDimitry Andric { "recip" , {1}, {E_ANY}}, 258*0b57cec5SDimitry Andric { "remainder" , {1}, {E_ANY,E_COPY}}, 259*0b57cec5SDimitry Andric { "remquo" , {1,3}, {E_ANY,E_COPY,E_ANY}}, 260*0b57cec5SDimitry Andric { "reserve_read_pipe" , {1}, {E_ANY,EX_UINT}}, 261*0b57cec5SDimitry Andric { "reserve_write_pipe" , {1}, {E_ANY,EX_UINT}}, 262*0b57cec5SDimitry Andric { "rhadd" , {1}, {E_ANY,E_COPY}}, 263*0b57cec5SDimitry Andric { "rint" , {1}, {E_ANY}}, 264*0b57cec5SDimitry Andric { "rootn" , {1}, {E_ANY,E_SETBASE_I32}}, 265*0b57cec5SDimitry Andric { "rotate" , {1}, {E_ANY,E_COPY}}, 266*0b57cec5SDimitry Andric { "round" , {1}, {E_ANY}}, 267*0b57cec5SDimitry Andric { "rsqrt" , {1}, {E_ANY}}, 268*0b57cec5SDimitry Andric { "select" , {1,3}, {E_ANY,E_COPY,E_ANY}}, 269*0b57cec5SDimitry Andric { "shuffle" , {1,2}, {E_ANY,E_ANY}}, 270*0b57cec5SDimitry Andric { "shuffle2" , {1,3}, {E_ANY,E_COPY,E_ANY}}, 271*0b57cec5SDimitry Andric { "sign" , {1}, {E_ANY}}, 272*0b57cec5SDimitry Andric { "signbit" , {1}, {E_ANY}}, 273*0b57cec5SDimitry Andric { "sin" , {1}, {E_ANY}}, 274*0b57cec5SDimitry Andric { "sincos" , {2}, {E_POINTEE,E_ANY}}, 275*0b57cec5SDimitry Andric { "sinh" , {1}, {E_ANY}}, 276*0b57cec5SDimitry Andric { "sinpi" , {1}, {E_ANY}}, 277*0b57cec5SDimitry Andric { "smoothstep" , {1}, {E_ANY,E_COPY,E_COPY}}, 278*0b57cec5SDimitry Andric { "sqrt" , {1}, {E_ANY}}, 279*0b57cec5SDimitry Andric { "step" , {1}, {E_ANY,E_COPY}}, 280*0b57cec5SDimitry Andric { "sub_group_broadcast" , {1}, {E_ANY,EX_UINT}}, 281*0b57cec5SDimitry Andric { "sub_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 282*0b57cec5SDimitry Andric { "sub_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 283*0b57cec5SDimitry Andric { "sub_group_reduce_add" , {1}, {E_ANY}}, 284*0b57cec5SDimitry Andric { "sub_group_reduce_max" , {1}, {E_ANY}}, 285*0b57cec5SDimitry Andric { "sub_group_reduce_min" , {1}, {E_ANY}}, 286*0b57cec5SDimitry Andric { "sub_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}}, 287*0b57cec5SDimitry Andric { "sub_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}}, 288*0b57cec5SDimitry Andric { "sub_group_scan_exclusive_add" , {1}, {E_ANY}}, 289*0b57cec5SDimitry Andric { "sub_group_scan_exclusive_max" , {1}, {E_ANY}}, 290*0b57cec5SDimitry Andric { "sub_group_scan_exclusive_min" , {1}, {E_ANY}}, 291*0b57cec5SDimitry Andric { "sub_group_scan_inclusive_add" , {1}, {E_ANY}}, 292*0b57cec5SDimitry Andric { "sub_group_scan_inclusive_max" , {1}, {E_ANY}}, 293*0b57cec5SDimitry Andric { "sub_group_scan_inclusive_min" , {1}, {E_ANY}}, 294*0b57cec5SDimitry Andric { "sub_sat" , {1}, {E_ANY,E_COPY}}, 295*0b57cec5SDimitry Andric { "tan" , {1}, {E_ANY}}, 296*0b57cec5SDimitry Andric { "tanh" , {1}, {E_ANY}}, 297*0b57cec5SDimitry Andric { "tanpi" , {1}, {E_ANY}}, 298*0b57cec5SDimitry Andric { "tgamma" , {1}, {E_ANY}}, 299*0b57cec5SDimitry Andric { "trunc" , {1}, {E_ANY}}, 300*0b57cec5SDimitry Andric { "upsample" , {1}, {E_ANY,E_MAKEBASE_UNS}}, 301*0b57cec5SDimitry Andric { "vec_step" , {1}, {E_ANY}}, 302*0b57cec5SDimitry Andric { "vstore" , {3}, {E_POINTEE,EX_SIZET,E_ANY}}, 303*0b57cec5SDimitry Andric { "vstore16" , {3}, {E_V16_OF_POINTEE,EX_SIZET,E_ANY}}, 304*0b57cec5SDimitry Andric { "vstore2" , {3}, {E_V2_OF_POINTEE,EX_SIZET,E_ANY}}, 305*0b57cec5SDimitry Andric { "vstore3" , {3}, {E_V3_OF_POINTEE,EX_SIZET,E_ANY}}, 306*0b57cec5SDimitry Andric { "vstore4" , {3}, {E_V4_OF_POINTEE,EX_SIZET,E_ANY}}, 307*0b57cec5SDimitry Andric { "vstore8" , {3}, {E_V8_OF_POINTEE,EX_SIZET,E_ANY}}, 308*0b57cec5SDimitry Andric { "work_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 309*0b57cec5SDimitry Andric { "work_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 310*0b57cec5SDimitry Andric { "work_group_reduce_add" , {1}, {E_ANY}}, 311*0b57cec5SDimitry Andric { "work_group_reduce_max" , {1}, {E_ANY}}, 312*0b57cec5SDimitry Andric { "work_group_reduce_min" , {1}, {E_ANY}}, 313*0b57cec5SDimitry Andric { "work_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}}, 314*0b57cec5SDimitry Andric { "work_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}}, 315*0b57cec5SDimitry Andric { "work_group_scan_exclusive_add" , {1}, {E_ANY}}, 316*0b57cec5SDimitry Andric { "work_group_scan_exclusive_max" , {1}, {E_ANY}}, 317*0b57cec5SDimitry Andric { "work_group_scan_exclusive_min" , {1}, {E_ANY}}, 318*0b57cec5SDimitry Andric { "work_group_scan_inclusive_add" , {1}, {E_ANY}}, 319*0b57cec5SDimitry Andric { "work_group_scan_inclusive_max" , {1}, {E_ANY}}, 320*0b57cec5SDimitry Andric { "work_group_scan_inclusive_min" , {1}, {E_ANY}}, 321*0b57cec5SDimitry Andric { "write_imagef" , {1}, {E_ANY,E_IMAGECOORDS,EX_FLOAT4}}, 322*0b57cec5SDimitry Andric { "write_imagei" , {1}, {E_ANY,E_IMAGECOORDS,EX_INTV4}}, 323*0b57cec5SDimitry Andric { "write_imageui" , {1}, {E_ANY,E_IMAGECOORDS,EX_UINTV4}}, 324*0b57cec5SDimitry Andric { "ncos" , {1}, {E_ANY} }, 325*0b57cec5SDimitry Andric { "nexp2" , {1}, {E_ANY} }, 326*0b57cec5SDimitry Andric { "nfma" , {1}, {E_ANY, E_COPY, E_COPY} }, 327*0b57cec5SDimitry Andric { "nlog2" , {1}, {E_ANY} }, 328*0b57cec5SDimitry Andric { "nrcp" , {1}, {E_ANY} }, 329*0b57cec5SDimitry Andric { "nrsqrt" , {1}, {E_ANY} }, 330*0b57cec5SDimitry Andric { "nsin" , {1}, {E_ANY} }, 331*0b57cec5SDimitry Andric { "nsqrt" , {1}, {E_ANY} }, 332*0b57cec5SDimitry Andric { "ftz" , {1}, {E_ANY} }, 333*0b57cec5SDimitry Andric { "fldexp" , {1}, {E_ANY, EX_UINT} }, 334*0b57cec5SDimitry Andric { "class" , {1}, {E_ANY, EX_UINT} }, 335*0b57cec5SDimitry Andric { "rcbrt" , {1}, {E_ANY} }, 336*0b57cec5SDimitry Andric }; 337*0b57cec5SDimitry Andric 338*0b57cec5SDimitry Andric // Library functions with unmangled name. 339*0b57cec5SDimitry Andric const UnmangledFuncInfo UnmangledFuncInfo::Table[] = { 340*0b57cec5SDimitry Andric {"__read_pipe_2", 4}, 341*0b57cec5SDimitry Andric {"__read_pipe_4", 6}, 342*0b57cec5SDimitry Andric {"__write_pipe_2", 4}, 343*0b57cec5SDimitry Andric {"__write_pipe_4", 6}, 344*0b57cec5SDimitry Andric }; 345*0b57cec5SDimitry Andric 346*0b57cec5SDimitry Andric const unsigned UnmangledFuncInfo::TableSize = 347*0b57cec5SDimitry Andric array_lengthof(UnmangledFuncInfo::Table); 348*0b57cec5SDimitry Andric 349*0b57cec5SDimitry Andric static AMDGPULibFunc::Param getRetType(AMDGPULibFunc::EFuncId id, 350*0b57cec5SDimitry Andric const AMDGPULibFunc::Param (&Leads)[2]) { 351*0b57cec5SDimitry Andric AMDGPULibFunc::Param Res = Leads[0]; 352*0b57cec5SDimitry Andric // TBD - This switch may require to be extended for other intriniscs 353*0b57cec5SDimitry Andric switch (id) { 354*0b57cec5SDimitry Andric case AMDGPULibFunc::EI_SINCOS: 355*0b57cec5SDimitry Andric Res.PtrKind = AMDGPULibFunc::BYVALUE; 356*0b57cec5SDimitry Andric break; 357*0b57cec5SDimitry Andric default: 358*0b57cec5SDimitry Andric break; 359*0b57cec5SDimitry Andric } 360*0b57cec5SDimitry Andric return Res; 361*0b57cec5SDimitry Andric } 362*0b57cec5SDimitry Andric 363*0b57cec5SDimitry Andric class ParamIterator { 364*0b57cec5SDimitry Andric const AMDGPULibFunc::Param (&Leads)[2]; 365*0b57cec5SDimitry Andric const ManglingRule& Rule; 366*0b57cec5SDimitry Andric int Index; 367*0b57cec5SDimitry Andric public: 368*0b57cec5SDimitry Andric ParamIterator(const AMDGPULibFunc::Param (&leads)[2], 369*0b57cec5SDimitry Andric const ManglingRule& rule) 370*0b57cec5SDimitry Andric : Leads(leads), Rule(rule), Index(0) {} 371*0b57cec5SDimitry Andric 372*0b57cec5SDimitry Andric AMDGPULibFunc::Param getNextParam(); 373*0b57cec5SDimitry Andric }; 374*0b57cec5SDimitry Andric 375*0b57cec5SDimitry Andric AMDGPULibFunc::Param ParamIterator::getNextParam() { 376*0b57cec5SDimitry Andric AMDGPULibFunc::Param P; 377*0b57cec5SDimitry Andric if (Index >= int(sizeof Rule.Param/sizeof Rule.Param[0])) return P; 378*0b57cec5SDimitry Andric 379*0b57cec5SDimitry Andric const char R = Rule.Param[Index]; 380*0b57cec5SDimitry Andric switch (R) { 381*0b57cec5SDimitry Andric case E_NONE: break; 382*0b57cec5SDimitry Andric case EX_UINT: 383*0b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::U32; break; 384*0b57cec5SDimitry Andric case EX_INTV4: 385*0b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::I32; P.VectorSize = 4; break; 386*0b57cec5SDimitry Andric case EX_UINTV4: 387*0b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::U32; P.VectorSize = 4; break; 388*0b57cec5SDimitry Andric case EX_FLOAT4: 389*0b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::F32; P.VectorSize = 4; break; 390*0b57cec5SDimitry Andric case EX_SIZET: 391*0b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::U64; break; 392*0b57cec5SDimitry Andric case EX_EVENT: 393*0b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::EVENT; break; 394*0b57cec5SDimitry Andric case EX_SAMPLER: 395*0b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::SAMPLER; break; 396*0b57cec5SDimitry Andric case EX_RESERVEDID: break; // TBD 397*0b57cec5SDimitry Andric default: 398*0b57cec5SDimitry Andric if (Index == (Rule.Lead[1] - 1)) P = Leads[1]; 399*0b57cec5SDimitry Andric else P = Leads[0]; 400*0b57cec5SDimitry Andric 401*0b57cec5SDimitry Andric switch (R) { 402*0b57cec5SDimitry Andric case E_ANY: 403*0b57cec5SDimitry Andric case E_COPY: break; 404*0b57cec5SDimitry Andric 405*0b57cec5SDimitry Andric case E_POINTEE: 406*0b57cec5SDimitry Andric P.PtrKind = AMDGPULibFunc::BYVALUE; break; 407*0b57cec5SDimitry Andric case E_V2_OF_POINTEE: 408*0b57cec5SDimitry Andric P.VectorSize = 2; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 409*0b57cec5SDimitry Andric case E_V3_OF_POINTEE: 410*0b57cec5SDimitry Andric P.VectorSize = 3; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 411*0b57cec5SDimitry Andric case E_V4_OF_POINTEE: 412*0b57cec5SDimitry Andric P.VectorSize = 4; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 413*0b57cec5SDimitry Andric case E_V8_OF_POINTEE: 414*0b57cec5SDimitry Andric P.VectorSize = 8; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 415*0b57cec5SDimitry Andric case E_V16_OF_POINTEE: 416*0b57cec5SDimitry Andric P.VectorSize = 16; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 417*0b57cec5SDimitry Andric case E_CONSTPTR_ANY: 418*0b57cec5SDimitry Andric P.PtrKind |= AMDGPULibFunc::CONST; break; 419*0b57cec5SDimitry Andric case E_VLTLPTR_ANY: 420*0b57cec5SDimitry Andric P.PtrKind |= AMDGPULibFunc::VOLATILE; break; 421*0b57cec5SDimitry Andric case E_SETBASE_I32: 422*0b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::I32; break; 423*0b57cec5SDimitry Andric case E_SETBASE_U32: 424*0b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::U32; break; 425*0b57cec5SDimitry Andric 426*0b57cec5SDimitry Andric case E_MAKEBASE_UNS: 427*0b57cec5SDimitry Andric P.ArgType &= ~AMDGPULibFunc::BASE_TYPE_MASK; 428*0b57cec5SDimitry Andric P.ArgType |= AMDGPULibFunc::UINT; 429*0b57cec5SDimitry Andric break; 430*0b57cec5SDimitry Andric 431*0b57cec5SDimitry Andric case E_IMAGECOORDS: 432*0b57cec5SDimitry Andric switch (P.ArgType) { 433*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DA: P.VectorSize = 2; break; 434*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DB: P.VectorSize = 1; break; 435*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG2DA: P.VectorSize = 4; break; 436*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG1D: P.VectorSize = 1; break; 437*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG2D: P.VectorSize = 2; break; 438*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG3D: P.VectorSize = 4; break; 439*0b57cec5SDimitry Andric } 440*0b57cec5SDimitry Andric P.PtrKind = AMDGPULibFunc::BYVALUE; 441*0b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::I32; 442*0b57cec5SDimitry Andric break; 443*0b57cec5SDimitry Andric 444*0b57cec5SDimitry Andric case E_CONSTPTR_SWAPGL: { 445*0b57cec5SDimitry Andric unsigned AS = AMDGPULibFunc::getAddrSpaceFromEPtrKind(P.PtrKind); 446*0b57cec5SDimitry Andric switch (AS) { 447*0b57cec5SDimitry Andric case AMDGPUAS::GLOBAL_ADDRESS: AS = AMDGPUAS::LOCAL_ADDRESS; break; 448*0b57cec5SDimitry Andric case AMDGPUAS::LOCAL_ADDRESS: AS = AMDGPUAS::GLOBAL_ADDRESS; break; 449*0b57cec5SDimitry Andric } 450*0b57cec5SDimitry Andric P.PtrKind = AMDGPULibFunc::getEPtrKindFromAddrSpace(AS); 451*0b57cec5SDimitry Andric P.PtrKind |= AMDGPULibFunc::CONST; 452*0b57cec5SDimitry Andric break; 453*0b57cec5SDimitry Andric } 454*0b57cec5SDimitry Andric 455*0b57cec5SDimitry Andric default: llvm_unreachable("Unhandeled param rule"); 456*0b57cec5SDimitry Andric } 457*0b57cec5SDimitry Andric } 458*0b57cec5SDimitry Andric ++Index; 459*0b57cec5SDimitry Andric return P; 460*0b57cec5SDimitry Andric } 461*0b57cec5SDimitry Andric 462*0b57cec5SDimitry Andric inline static void drop_front(StringRef& str, size_t n = 1) { 463*0b57cec5SDimitry Andric str = str.drop_front(n); 464*0b57cec5SDimitry Andric } 465*0b57cec5SDimitry Andric 466*0b57cec5SDimitry Andric static bool eatTerm(StringRef& mangledName, const char c) { 467*0b57cec5SDimitry Andric if (mangledName.front() == c) { 468*0b57cec5SDimitry Andric drop_front(mangledName); 469*0b57cec5SDimitry Andric return true; 470*0b57cec5SDimitry Andric } 471*0b57cec5SDimitry Andric return false; 472*0b57cec5SDimitry Andric } 473*0b57cec5SDimitry Andric 474*0b57cec5SDimitry Andric template <size_t N> 475*0b57cec5SDimitry Andric static bool eatTerm(StringRef& mangledName, const char (&str)[N]) { 476*0b57cec5SDimitry Andric if (mangledName.startswith(StringRef(str, N-1))) { 477*0b57cec5SDimitry Andric drop_front(mangledName, N-1); 478*0b57cec5SDimitry Andric return true; 479*0b57cec5SDimitry Andric } 480*0b57cec5SDimitry Andric return false; 481*0b57cec5SDimitry Andric } 482*0b57cec5SDimitry Andric 483*0b57cec5SDimitry Andric static int eatNumber(StringRef& s) { 484*0b57cec5SDimitry Andric size_t const savedSize = s.size(); 485*0b57cec5SDimitry Andric int n = 0; 486*0b57cec5SDimitry Andric while (!s.empty() && isDigit(s.front())) { 487*0b57cec5SDimitry Andric n = n*10 + s.front() - '0'; 488*0b57cec5SDimitry Andric drop_front(s); 489*0b57cec5SDimitry Andric } 490*0b57cec5SDimitry Andric return s.size() < savedSize ? n : -1; 491*0b57cec5SDimitry Andric } 492*0b57cec5SDimitry Andric 493*0b57cec5SDimitry Andric static StringRef eatLengthPrefixedName(StringRef& mangledName) { 494*0b57cec5SDimitry Andric int const Len = eatNumber(mangledName); 495*0b57cec5SDimitry Andric if (Len <= 0 || static_cast<size_t>(Len) > mangledName.size()) 496*0b57cec5SDimitry Andric return StringRef(); 497*0b57cec5SDimitry Andric StringRef Res = mangledName.substr(0, Len); 498*0b57cec5SDimitry Andric drop_front(mangledName, Len); 499*0b57cec5SDimitry Andric return Res; 500*0b57cec5SDimitry Andric } 501*0b57cec5SDimitry Andric 502*0b57cec5SDimitry Andric } // end anonymous namespace 503*0b57cec5SDimitry Andric 504*0b57cec5SDimitry Andric AMDGPUMangledLibFunc::AMDGPUMangledLibFunc() { 505*0b57cec5SDimitry Andric FuncId = EI_NONE; 506*0b57cec5SDimitry Andric FKind = NOPFX; 507*0b57cec5SDimitry Andric Leads[0].reset(); 508*0b57cec5SDimitry Andric Leads[1].reset(); 509*0b57cec5SDimitry Andric Name.clear(); 510*0b57cec5SDimitry Andric } 511*0b57cec5SDimitry Andric 512*0b57cec5SDimitry Andric AMDGPUUnmangledLibFunc::AMDGPUUnmangledLibFunc() { 513*0b57cec5SDimitry Andric FuncId = EI_NONE; 514*0b57cec5SDimitry Andric FuncTy = nullptr; 515*0b57cec5SDimitry Andric } 516*0b57cec5SDimitry Andric 517*0b57cec5SDimitry Andric AMDGPUMangledLibFunc::AMDGPUMangledLibFunc( 518*0b57cec5SDimitry Andric EFuncId id, const AMDGPUMangledLibFunc ©From) { 519*0b57cec5SDimitry Andric FuncId = id; 520*0b57cec5SDimitry Andric FKind = copyFrom.FKind; 521*0b57cec5SDimitry Andric Leads[0] = copyFrom.Leads[0]; 522*0b57cec5SDimitry Andric Leads[1] = copyFrom.Leads[1]; 523*0b57cec5SDimitry Andric } 524*0b57cec5SDimitry Andric 525*0b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 526*0b57cec5SDimitry Andric // Demangling 527*0b57cec5SDimitry Andric 528*0b57cec5SDimitry Andric static int parseVecSize(StringRef& mangledName) { 529*0b57cec5SDimitry Andric size_t const Len = eatNumber(mangledName); 530*0b57cec5SDimitry Andric switch (Len) { 531*0b57cec5SDimitry Andric case 2: case 3: case 4: case 8: case 16: 532*0b57cec5SDimitry Andric return Len; 533*0b57cec5SDimitry Andric default: 534*0b57cec5SDimitry Andric break; 535*0b57cec5SDimitry Andric } 536*0b57cec5SDimitry Andric return 1; 537*0b57cec5SDimitry Andric } 538*0b57cec5SDimitry Andric 539*0b57cec5SDimitry Andric static AMDGPULibFunc::ENamePrefix parseNamePrefix(StringRef& mangledName) { 540*0b57cec5SDimitry Andric std::pair<StringRef, StringRef> const P = mangledName.split('_'); 541*0b57cec5SDimitry Andric AMDGPULibFunc::ENamePrefix Pfx = 542*0b57cec5SDimitry Andric StringSwitch<AMDGPULibFunc::ENamePrefix>(P.first) 543*0b57cec5SDimitry Andric .Case("native", AMDGPULibFunc::NATIVE) 544*0b57cec5SDimitry Andric .Case("half" , AMDGPULibFunc::HALF) 545*0b57cec5SDimitry Andric .Default(AMDGPULibFunc::NOPFX); 546*0b57cec5SDimitry Andric 547*0b57cec5SDimitry Andric if (Pfx != AMDGPULibFunc::NOPFX) 548*0b57cec5SDimitry Andric mangledName = P.second; 549*0b57cec5SDimitry Andric 550*0b57cec5SDimitry Andric return Pfx; 551*0b57cec5SDimitry Andric } 552*0b57cec5SDimitry Andric 553*0b57cec5SDimitry Andric StringMap<int> ManglingRule::buildManglingRulesMap() { 554*0b57cec5SDimitry Andric StringMap<int> Map(array_lengthof(manglingRules)); 555*0b57cec5SDimitry Andric int Id = 0; 556*0b57cec5SDimitry Andric for (auto Rule : manglingRules) 557*0b57cec5SDimitry Andric Map.insert({Rule.Name, Id++}); 558*0b57cec5SDimitry Andric return Map; 559*0b57cec5SDimitry Andric } 560*0b57cec5SDimitry Andric 561*0b57cec5SDimitry Andric bool AMDGPUMangledLibFunc::parseUnmangledName(StringRef FullName) { 562*0b57cec5SDimitry Andric static const StringMap<int> manglingRulesMap = 563*0b57cec5SDimitry Andric ManglingRule::buildManglingRulesMap(); 564*0b57cec5SDimitry Andric FuncId = static_cast<EFuncId>(manglingRulesMap.lookup(FullName)); 565*0b57cec5SDimitry Andric return FuncId != EI_NONE; 566*0b57cec5SDimitry Andric } 567*0b57cec5SDimitry Andric 568*0b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 569*0b57cec5SDimitry Andric // Itanium Demangling 570*0b57cec5SDimitry Andric 571*0b57cec5SDimitry Andric namespace { 572*0b57cec5SDimitry Andric struct ItaniumParamParser { 573*0b57cec5SDimitry Andric AMDGPULibFunc::Param Prev; 574*0b57cec5SDimitry Andric bool parseItaniumParam(StringRef& param, AMDGPULibFunc::Param &res); 575*0b57cec5SDimitry Andric }; 576*0b57cec5SDimitry Andric } // namespace 577*0b57cec5SDimitry Andric 578*0b57cec5SDimitry Andric bool ItaniumParamParser::parseItaniumParam(StringRef& param, 579*0b57cec5SDimitry Andric AMDGPULibFunc::Param &res) { 580*0b57cec5SDimitry Andric res.reset(); 581*0b57cec5SDimitry Andric if (param.empty()) return false; 582*0b57cec5SDimitry Andric 583*0b57cec5SDimitry Andric // parse pointer prefix 584*0b57cec5SDimitry Andric if (eatTerm(param, 'P')) { 585*0b57cec5SDimitry Andric if (eatTerm(param, 'K')) res.PtrKind |= AMDGPULibFunc::CONST; 586*0b57cec5SDimitry Andric if (eatTerm(param, 'V')) res.PtrKind |= AMDGPULibFunc::VOLATILE; 587*0b57cec5SDimitry Andric unsigned AS; 588*0b57cec5SDimitry Andric if (!eatTerm(param, "U3AS")) { 589*0b57cec5SDimitry Andric AS = 0; 590*0b57cec5SDimitry Andric } else { 591*0b57cec5SDimitry Andric AS = param.front() - '0'; 592*0b57cec5SDimitry Andric drop_front(param, 1); 593*0b57cec5SDimitry Andric } 594*0b57cec5SDimitry Andric res.PtrKind |= AMDGPULibFuncBase::getEPtrKindFromAddrSpace(AS); 595*0b57cec5SDimitry Andric } else { 596*0b57cec5SDimitry Andric res.PtrKind = AMDGPULibFunc::BYVALUE; 597*0b57cec5SDimitry Andric } 598*0b57cec5SDimitry Andric 599*0b57cec5SDimitry Andric // parse vector size 600*0b57cec5SDimitry Andric if (eatTerm(param,"Dv")) { 601*0b57cec5SDimitry Andric res.VectorSize = parseVecSize(param); 602*0b57cec5SDimitry Andric if (res.VectorSize==1 || !eatTerm(param, '_')) return false; 603*0b57cec5SDimitry Andric } 604*0b57cec5SDimitry Andric 605*0b57cec5SDimitry Andric // parse type 606*0b57cec5SDimitry Andric char const TC = param.front(); 6075ffd83dbSDimitry Andric if (isDigit(TC)) { 608*0b57cec5SDimitry Andric res.ArgType = StringSwitch<AMDGPULibFunc::EType> 609*0b57cec5SDimitry Andric (eatLengthPrefixedName(param)) 610*0b57cec5SDimitry Andric .Case("ocl_image1darray" , AMDGPULibFunc::IMG1DA) 611*0b57cec5SDimitry Andric .Case("ocl_image1dbuffer", AMDGPULibFunc::IMG1DB) 612*0b57cec5SDimitry Andric .Case("ocl_image2darray" , AMDGPULibFunc::IMG2DA) 613*0b57cec5SDimitry Andric .Case("ocl_image1d" , AMDGPULibFunc::IMG1D) 614*0b57cec5SDimitry Andric .Case("ocl_image2d" , AMDGPULibFunc::IMG2D) 615*0b57cec5SDimitry Andric .Case("ocl_image3d" , AMDGPULibFunc::IMG3D) 616*0b57cec5SDimitry Andric .Case("ocl_event" , AMDGPULibFunc::DUMMY) 617*0b57cec5SDimitry Andric .Case("ocl_sampler" , AMDGPULibFunc::DUMMY) 618*0b57cec5SDimitry Andric .Default(AMDGPULibFunc::DUMMY); 619*0b57cec5SDimitry Andric } else { 620*0b57cec5SDimitry Andric drop_front(param); 621*0b57cec5SDimitry Andric switch (TC) { 622*0b57cec5SDimitry Andric case 'h': res.ArgType = AMDGPULibFunc::U8; break; 623*0b57cec5SDimitry Andric case 't': res.ArgType = AMDGPULibFunc::U16; break; 624*0b57cec5SDimitry Andric case 'j': res.ArgType = AMDGPULibFunc::U32; break; 625*0b57cec5SDimitry Andric case 'm': res.ArgType = AMDGPULibFunc::U64; break; 626*0b57cec5SDimitry Andric case 'c': res.ArgType = AMDGPULibFunc::I8; break; 627*0b57cec5SDimitry Andric case 's': res.ArgType = AMDGPULibFunc::I16; break; 628*0b57cec5SDimitry Andric case 'i': res.ArgType = AMDGPULibFunc::I32; break; 629*0b57cec5SDimitry Andric case 'l': res.ArgType = AMDGPULibFunc::I64; break; 630*0b57cec5SDimitry Andric case 'f': res.ArgType = AMDGPULibFunc::F32; break; 631*0b57cec5SDimitry Andric case 'd': res.ArgType = AMDGPULibFunc::F64; break; 632*0b57cec5SDimitry Andric case 'D': if (!eatTerm(param, 'h')) return false; 633*0b57cec5SDimitry Andric res.ArgType = AMDGPULibFunc::F16; break; 634*0b57cec5SDimitry Andric case 'S': 635*0b57cec5SDimitry Andric if (!eatTerm(param, '_')) { 636*0b57cec5SDimitry Andric eatNumber(param); 637*0b57cec5SDimitry Andric if (!eatTerm(param, '_')) return false; 638*0b57cec5SDimitry Andric } 639*0b57cec5SDimitry Andric res.VectorSize = Prev.VectorSize; 640*0b57cec5SDimitry Andric res.ArgType = Prev.ArgType; 641*0b57cec5SDimitry Andric break; 642*0b57cec5SDimitry Andric default:; 643*0b57cec5SDimitry Andric } 644*0b57cec5SDimitry Andric } 645*0b57cec5SDimitry Andric if (res.ArgType == 0) return false; 646*0b57cec5SDimitry Andric Prev.VectorSize = res.VectorSize; 647*0b57cec5SDimitry Andric Prev.ArgType = res.ArgType; 648*0b57cec5SDimitry Andric return true; 649*0b57cec5SDimitry Andric } 650*0b57cec5SDimitry Andric 651*0b57cec5SDimitry Andric bool AMDGPUMangledLibFunc::parseFuncName(StringRef &mangledName) { 652*0b57cec5SDimitry Andric StringRef Name = eatLengthPrefixedName(mangledName); 653*0b57cec5SDimitry Andric FKind = parseNamePrefix(Name); 654*0b57cec5SDimitry Andric if (!parseUnmangledName(Name)) 655*0b57cec5SDimitry Andric return false; 656*0b57cec5SDimitry Andric 657*0b57cec5SDimitry Andric const ManglingRule& Rule = manglingRules[FuncId]; 658*0b57cec5SDimitry Andric ItaniumParamParser Parser; 659*0b57cec5SDimitry Andric for (int I=0; I < Rule.maxLeadIndex(); ++I) { 660*0b57cec5SDimitry Andric Param P; 661*0b57cec5SDimitry Andric if (!Parser.parseItaniumParam(mangledName, P)) 662*0b57cec5SDimitry Andric return false; 663*0b57cec5SDimitry Andric 664*0b57cec5SDimitry Andric if ((I + 1) == Rule.Lead[0]) Leads[0] = P; 665*0b57cec5SDimitry Andric if ((I + 1) == Rule.Lead[1]) Leads[1] = P; 666*0b57cec5SDimitry Andric } 667*0b57cec5SDimitry Andric return true; 668*0b57cec5SDimitry Andric } 669*0b57cec5SDimitry Andric 670*0b57cec5SDimitry Andric bool AMDGPUUnmangledLibFunc::parseFuncName(StringRef &Name) { 671*0b57cec5SDimitry Andric if (!UnmangledFuncInfo::lookup(Name, FuncId)) 672*0b57cec5SDimitry Andric return false; 673*0b57cec5SDimitry Andric setName(Name); 674*0b57cec5SDimitry Andric return true; 675*0b57cec5SDimitry Andric } 676*0b57cec5SDimitry Andric 677*0b57cec5SDimitry Andric bool AMDGPULibFunc::parse(StringRef FuncName, AMDGPULibFunc &F) { 678*0b57cec5SDimitry Andric if (FuncName.empty()) { 679*0b57cec5SDimitry Andric F.Impl = std::unique_ptr<AMDGPULibFuncImpl>(); 680*0b57cec5SDimitry Andric return false; 681*0b57cec5SDimitry Andric } 682*0b57cec5SDimitry Andric 683*0b57cec5SDimitry Andric if (eatTerm(FuncName, "_Z")) 6848bcb0991SDimitry Andric F.Impl = std::make_unique<AMDGPUMangledLibFunc>(); 685*0b57cec5SDimitry Andric else 6868bcb0991SDimitry Andric F.Impl = std::make_unique<AMDGPUUnmangledLibFunc>(); 687*0b57cec5SDimitry Andric if (F.Impl->parseFuncName(FuncName)) 688*0b57cec5SDimitry Andric return true; 689*0b57cec5SDimitry Andric 690*0b57cec5SDimitry Andric F.Impl = std::unique_ptr<AMDGPULibFuncImpl>(); 691*0b57cec5SDimitry Andric return false; 692*0b57cec5SDimitry Andric } 693*0b57cec5SDimitry Andric 694*0b57cec5SDimitry Andric StringRef AMDGPUMangledLibFunc::getUnmangledName(StringRef mangledName) { 695*0b57cec5SDimitry Andric StringRef S = mangledName; 696*0b57cec5SDimitry Andric if (eatTerm(S, "_Z")) 697*0b57cec5SDimitry Andric return eatLengthPrefixedName(S); 698*0b57cec5SDimitry Andric return StringRef(); 699*0b57cec5SDimitry Andric } 700*0b57cec5SDimitry Andric 701*0b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 702*0b57cec5SDimitry Andric // Mangling 703*0b57cec5SDimitry Andric 704*0b57cec5SDimitry Andric template <typename Stream> 705*0b57cec5SDimitry Andric void AMDGPUMangledLibFunc::writeName(Stream &OS) const { 706*0b57cec5SDimitry Andric const char *Pfx = ""; 707*0b57cec5SDimitry Andric switch (FKind) { 708*0b57cec5SDimitry Andric case NATIVE: Pfx = "native_"; break; 709*0b57cec5SDimitry Andric case HALF: Pfx = "half_"; break; 710*0b57cec5SDimitry Andric default: break; 711*0b57cec5SDimitry Andric } 712*0b57cec5SDimitry Andric if (!Name.empty()) { 713*0b57cec5SDimitry Andric OS << Pfx << Name; 714*0b57cec5SDimitry Andric } else if (FuncId != EI_NONE) { 715*0b57cec5SDimitry Andric OS << Pfx; 716*0b57cec5SDimitry Andric const StringRef& S = manglingRules[FuncId].Name; 717*0b57cec5SDimitry Andric OS.write(S.data(), S.size()); 718*0b57cec5SDimitry Andric } 719*0b57cec5SDimitry Andric } 720*0b57cec5SDimitry Andric 721*0b57cec5SDimitry Andric std::string AMDGPUMangledLibFunc::mangle() const { return mangleNameItanium(); } 722*0b57cec5SDimitry Andric 723*0b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 724*0b57cec5SDimitry Andric // Itanium Mangling 725*0b57cec5SDimitry Andric 726*0b57cec5SDimitry Andric static const char *getItaniumTypeName(AMDGPULibFunc::EType T) { 727*0b57cec5SDimitry Andric switch (T) { 728*0b57cec5SDimitry Andric case AMDGPULibFunc::U8: return "h"; 729*0b57cec5SDimitry Andric case AMDGPULibFunc::U16: return "t"; 730*0b57cec5SDimitry Andric case AMDGPULibFunc::U32: return "j"; 731*0b57cec5SDimitry Andric case AMDGPULibFunc::U64: return "m"; 732*0b57cec5SDimitry Andric case AMDGPULibFunc::I8: return "c"; 733*0b57cec5SDimitry Andric case AMDGPULibFunc::I16: return "s"; 734*0b57cec5SDimitry Andric case AMDGPULibFunc::I32: return "i"; 735*0b57cec5SDimitry Andric case AMDGPULibFunc::I64: return "l"; 736*0b57cec5SDimitry Andric case AMDGPULibFunc::F16: return "Dh"; 737*0b57cec5SDimitry Andric case AMDGPULibFunc::F32: return "f"; 738*0b57cec5SDimitry Andric case AMDGPULibFunc::F64: return "d"; 739*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DA: return "16ocl_image1darray"; 740*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DB: return "17ocl_image1dbuffer"; 741*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG2DA: return "16ocl_image2darray"; 742*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG1D: return "11ocl_image1d"; 743*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG2D: return "11ocl_image2d"; 744*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG3D: return "11ocl_image3d"; 745*0b57cec5SDimitry Andric case AMDGPULibFunc::SAMPLER: return "11ocl_sampler"; 746*0b57cec5SDimitry Andric case AMDGPULibFunc::EVENT: return "9ocl_event"; 747*0b57cec5SDimitry Andric default: llvm_unreachable("Unhandeled param type"); 748*0b57cec5SDimitry Andric } 749*0b57cec5SDimitry Andric return nullptr; 750*0b57cec5SDimitry Andric } 751*0b57cec5SDimitry Andric 752*0b57cec5SDimitry Andric namespace { 753*0b57cec5SDimitry Andric // Itanium mangling ABI says: 754*0b57cec5SDimitry Andric // "5.1.8. Compression 755*0b57cec5SDimitry Andric // ... Each non-terminal in the grammar for which <substitution> appears on the 756*0b57cec5SDimitry Andric // right-hand side is both a source of future substitutions and a candidate 757*0b57cec5SDimitry Andric // for being substituted. There are two exceptions that appear to be 758*0b57cec5SDimitry Andric // substitution candidates from the grammar, but are explicitly excluded: 759*0b57cec5SDimitry Andric // 1. <builtin-type> other than vendor extended types ..." 760*0b57cec5SDimitry Andric 761*0b57cec5SDimitry Andric // For the purpose of functions the following productions make sence for the 762*0b57cec5SDimitry Andric // substitution: 763*0b57cec5SDimitry Andric // <type> ::= <builtin-type> 764*0b57cec5SDimitry Andric // ::= <class-enum-type> 765*0b57cec5SDimitry Andric // ::= <array-type> 766*0b57cec5SDimitry Andric // ::=<CV-qualifiers> <type> 767*0b57cec5SDimitry Andric // ::= P <type> # pointer-to 768*0b57cec5SDimitry Andric // ::= <substitution> 769*0b57cec5SDimitry Andric // 770*0b57cec5SDimitry Andric // Note that while types like images, samplers and events are by the ABI encoded 771*0b57cec5SDimitry Andric // using <class-enum-type> production rule they're not used for substitution 772*0b57cec5SDimitry Andric // because clang consider them as builtin types. 773*0b57cec5SDimitry Andric // 774*0b57cec5SDimitry Andric // DvNN_ type is GCC extension for vectors and is a subject for the substitution. 775*0b57cec5SDimitry Andric 776*0b57cec5SDimitry Andric 777*0b57cec5SDimitry Andric class ItaniumMangler { 778*0b57cec5SDimitry Andric SmallVector<AMDGPULibFunc::Param, 10> Str; // list of accumulated substituions 779*0b57cec5SDimitry Andric bool UseAddrSpace; 780*0b57cec5SDimitry Andric 781*0b57cec5SDimitry Andric int findSubst(const AMDGPULibFunc::Param& P) const { 782*0b57cec5SDimitry Andric for(unsigned I = 0; I < Str.size(); ++I) { 783*0b57cec5SDimitry Andric const AMDGPULibFunc::Param& T = Str[I]; 784*0b57cec5SDimitry Andric if (P.PtrKind == T.PtrKind && 785*0b57cec5SDimitry Andric P.VectorSize == T.VectorSize && 786*0b57cec5SDimitry Andric P.ArgType == T.ArgType) { 787*0b57cec5SDimitry Andric return I; 788*0b57cec5SDimitry Andric } 789*0b57cec5SDimitry Andric } 790*0b57cec5SDimitry Andric return -1; 791*0b57cec5SDimitry Andric } 792*0b57cec5SDimitry Andric 793*0b57cec5SDimitry Andric template <typename Stream> 794*0b57cec5SDimitry Andric bool trySubst(Stream& os, const AMDGPULibFunc::Param& p) { 795*0b57cec5SDimitry Andric int const subst = findSubst(p); 796*0b57cec5SDimitry Andric if (subst < 0) return false; 797*0b57cec5SDimitry Andric // Substitutions are mangled as S(XX)?_ where XX is a hexadecimal number 798*0b57cec5SDimitry Andric // 0 1 2 799*0b57cec5SDimitry Andric // S_ S0_ S1_ 800*0b57cec5SDimitry Andric if (subst == 0) os << "S_"; 801*0b57cec5SDimitry Andric else os << 'S' << (subst-1) << '_'; 802*0b57cec5SDimitry Andric return true; 803*0b57cec5SDimitry Andric } 804*0b57cec5SDimitry Andric 805*0b57cec5SDimitry Andric public: 806*0b57cec5SDimitry Andric ItaniumMangler(bool useAddrSpace) 807*0b57cec5SDimitry Andric : UseAddrSpace(useAddrSpace) {} 808*0b57cec5SDimitry Andric 809*0b57cec5SDimitry Andric template <typename Stream> 810*0b57cec5SDimitry Andric void operator()(Stream& os, AMDGPULibFunc::Param p) { 811*0b57cec5SDimitry Andric 812*0b57cec5SDimitry Andric // Itanium mangling ABI 5.1.8. Compression: 813*0b57cec5SDimitry Andric // Logically, the substitutable components of a mangled name are considered 814*0b57cec5SDimitry Andric // left-to-right, components before the composite structure of which they 815*0b57cec5SDimitry Andric // are a part. If a component has been encountered before, it is substituted 816*0b57cec5SDimitry Andric // as described below. This decision is independent of whether its components 817*0b57cec5SDimitry Andric // have been substituted, so an implementation may optimize by considering 818*0b57cec5SDimitry Andric // large structures for substitution before their components. If a component 819*0b57cec5SDimitry Andric // has not been encountered before, its mangling is identified, and it is 820*0b57cec5SDimitry Andric // added to a dictionary of substitution candidates. No entity is added to 821*0b57cec5SDimitry Andric // the dictionary twice. 822*0b57cec5SDimitry Andric AMDGPULibFunc::Param Ptr; 823*0b57cec5SDimitry Andric 824*0b57cec5SDimitry Andric if (p.PtrKind) { 825*0b57cec5SDimitry Andric if (trySubst(os, p)) return; 826*0b57cec5SDimitry Andric os << 'P'; 827*0b57cec5SDimitry Andric if (p.PtrKind & AMDGPULibFunc::CONST) os << 'K'; 828*0b57cec5SDimitry Andric if (p.PtrKind & AMDGPULibFunc::VOLATILE) os << 'V'; 829*0b57cec5SDimitry Andric unsigned AS = UseAddrSpace 830*0b57cec5SDimitry Andric ? AMDGPULibFuncBase::getAddrSpaceFromEPtrKind(p.PtrKind) 831*0b57cec5SDimitry Andric : 0; 832*0b57cec5SDimitry Andric if (AS != 0) os << "U3AS" << AS; 833*0b57cec5SDimitry Andric Ptr = p; 834*0b57cec5SDimitry Andric p.PtrKind = 0; 835*0b57cec5SDimitry Andric } 836*0b57cec5SDimitry Andric 837*0b57cec5SDimitry Andric if (p.VectorSize > 1) { 838*0b57cec5SDimitry Andric if (trySubst(os, p)) goto exit; 839*0b57cec5SDimitry Andric Str.push_back(p); 840*0b57cec5SDimitry Andric os << "Dv" << static_cast<unsigned>(p.VectorSize) << '_'; 841*0b57cec5SDimitry Andric } 842*0b57cec5SDimitry Andric 843*0b57cec5SDimitry Andric os << getItaniumTypeName((AMDGPULibFunc::EType)p.ArgType); 844*0b57cec5SDimitry Andric 845*0b57cec5SDimitry Andric exit: 846*0b57cec5SDimitry Andric if (Ptr.ArgType) Str.push_back(Ptr); 847*0b57cec5SDimitry Andric } 848*0b57cec5SDimitry Andric }; 849*0b57cec5SDimitry Andric } // namespace 850*0b57cec5SDimitry Andric 851*0b57cec5SDimitry Andric std::string AMDGPUMangledLibFunc::mangleNameItanium() const { 852*0b57cec5SDimitry Andric SmallString<128> Buf; 853*0b57cec5SDimitry Andric raw_svector_ostream S(Buf); 854*0b57cec5SDimitry Andric SmallString<128> NameBuf; 855*0b57cec5SDimitry Andric raw_svector_ostream Name(NameBuf); 856*0b57cec5SDimitry Andric writeName(Name); 857*0b57cec5SDimitry Andric const StringRef& NameStr = Name.str(); 858*0b57cec5SDimitry Andric S << "_Z" << static_cast<int>(NameStr.size()) << NameStr; 859*0b57cec5SDimitry Andric 860*0b57cec5SDimitry Andric ItaniumMangler Mangler(true); 861*0b57cec5SDimitry Andric ParamIterator I(Leads, manglingRules[FuncId]); 862*0b57cec5SDimitry Andric Param P; 863*0b57cec5SDimitry Andric while ((P = I.getNextParam()).ArgType != 0) 864*0b57cec5SDimitry Andric Mangler(S, P); 8655ffd83dbSDimitry Andric return std::string(S.str()); 866*0b57cec5SDimitry Andric } 867*0b57cec5SDimitry Andric 868*0b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 869*0b57cec5SDimitry Andric // Misc 870*0b57cec5SDimitry Andric 871*0b57cec5SDimitry Andric static Type* getIntrinsicParamType( 872*0b57cec5SDimitry Andric LLVMContext& C, 873*0b57cec5SDimitry Andric const AMDGPULibFunc::Param& P, 874*0b57cec5SDimitry Andric bool useAddrSpace) { 875*0b57cec5SDimitry Andric Type* T = nullptr; 876*0b57cec5SDimitry Andric switch (P.ArgType) { 877*0b57cec5SDimitry Andric case AMDGPULibFunc::U8: 878*0b57cec5SDimitry Andric case AMDGPULibFunc::I8: T = Type::getInt8Ty(C); break; 879*0b57cec5SDimitry Andric case AMDGPULibFunc::U16: 880*0b57cec5SDimitry Andric case AMDGPULibFunc::I16: T = Type::getInt16Ty(C); break; 881*0b57cec5SDimitry Andric case AMDGPULibFunc::U32: 882*0b57cec5SDimitry Andric case AMDGPULibFunc::I32: T = Type::getInt32Ty(C); break; 883*0b57cec5SDimitry Andric case AMDGPULibFunc::U64: 884*0b57cec5SDimitry Andric case AMDGPULibFunc::I64: T = Type::getInt64Ty(C); break; 885*0b57cec5SDimitry Andric case AMDGPULibFunc::F16: T = Type::getHalfTy(C); break; 886*0b57cec5SDimitry Andric case AMDGPULibFunc::F32: T = Type::getFloatTy(C); break; 887*0b57cec5SDimitry Andric case AMDGPULibFunc::F64: T = Type::getDoubleTy(C); break; 888*0b57cec5SDimitry Andric 889*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DA: 890*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DB: 891*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG2DA: 892*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG1D: 893*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG2D: 894*0b57cec5SDimitry Andric case AMDGPULibFunc::IMG3D: 895*0b57cec5SDimitry Andric T = StructType::create(C,"ocl_image")->getPointerTo(); break; 896*0b57cec5SDimitry Andric case AMDGPULibFunc::SAMPLER: 897*0b57cec5SDimitry Andric T = StructType::create(C,"ocl_sampler")->getPointerTo(); break; 898*0b57cec5SDimitry Andric case AMDGPULibFunc::EVENT: 899*0b57cec5SDimitry Andric T = StructType::create(C,"ocl_event")->getPointerTo(); break; 900*0b57cec5SDimitry Andric default: 901*0b57cec5SDimitry Andric llvm_unreachable("Unhandeled param type"); 902*0b57cec5SDimitry Andric return nullptr; 903*0b57cec5SDimitry Andric } 904*0b57cec5SDimitry Andric if (P.VectorSize > 1) 9055ffd83dbSDimitry Andric T = FixedVectorType::get(T, P.VectorSize); 906*0b57cec5SDimitry Andric if (P.PtrKind != AMDGPULibFunc::BYVALUE) 907*0b57cec5SDimitry Andric T = useAddrSpace ? T->getPointerTo((P.PtrKind & AMDGPULibFunc::ADDR_SPACE) 908*0b57cec5SDimitry Andric - 1) 909*0b57cec5SDimitry Andric : T->getPointerTo(); 910*0b57cec5SDimitry Andric return T; 911*0b57cec5SDimitry Andric } 912*0b57cec5SDimitry Andric 913*0b57cec5SDimitry Andric FunctionType *AMDGPUMangledLibFunc::getFunctionType(Module &M) const { 914*0b57cec5SDimitry Andric LLVMContext& C = M.getContext(); 915*0b57cec5SDimitry Andric std::vector<Type*> Args; 916*0b57cec5SDimitry Andric ParamIterator I(Leads, manglingRules[FuncId]); 917*0b57cec5SDimitry Andric Param P; 918*0b57cec5SDimitry Andric while ((P=I.getNextParam()).ArgType != 0) 919*0b57cec5SDimitry Andric Args.push_back(getIntrinsicParamType(C, P, true)); 920*0b57cec5SDimitry Andric 921*0b57cec5SDimitry Andric return FunctionType::get( 922*0b57cec5SDimitry Andric getIntrinsicParamType(C, getRetType(FuncId, Leads), true), 923*0b57cec5SDimitry Andric Args, false); 924*0b57cec5SDimitry Andric } 925*0b57cec5SDimitry Andric 926*0b57cec5SDimitry Andric unsigned AMDGPUMangledLibFunc::getNumArgs() const { 927*0b57cec5SDimitry Andric return manglingRules[FuncId].getNumArgs(); 928*0b57cec5SDimitry Andric } 929*0b57cec5SDimitry Andric 930*0b57cec5SDimitry Andric unsigned AMDGPUUnmangledLibFunc::getNumArgs() const { 931*0b57cec5SDimitry Andric return UnmangledFuncInfo::getNumArgs(FuncId); 932*0b57cec5SDimitry Andric } 933*0b57cec5SDimitry Andric 934*0b57cec5SDimitry Andric std::string AMDGPUMangledLibFunc::getName() const { 935*0b57cec5SDimitry Andric SmallString<128> Buf; 936*0b57cec5SDimitry Andric raw_svector_ostream OS(Buf); 937*0b57cec5SDimitry Andric writeName(OS); 9385ffd83dbSDimitry Andric return std::string(OS.str()); 939*0b57cec5SDimitry Andric } 940*0b57cec5SDimitry Andric 941*0b57cec5SDimitry Andric Function *AMDGPULibFunc::getFunction(Module *M, const AMDGPULibFunc &fInfo) { 942*0b57cec5SDimitry Andric std::string FuncName = fInfo.mangle(); 943*0b57cec5SDimitry Andric Function *F = dyn_cast_or_null<Function>( 944*0b57cec5SDimitry Andric M->getValueSymbolTable().lookup(FuncName)); 945*0b57cec5SDimitry Andric 946*0b57cec5SDimitry Andric // check formal with actual types conformance 947*0b57cec5SDimitry Andric if (F && !F->isDeclaration() 948*0b57cec5SDimitry Andric && !F->isVarArg() 949*0b57cec5SDimitry Andric && F->arg_size() == fInfo.getNumArgs()) { 950*0b57cec5SDimitry Andric return F; 951*0b57cec5SDimitry Andric } 952*0b57cec5SDimitry Andric return nullptr; 953*0b57cec5SDimitry Andric } 954*0b57cec5SDimitry Andric 955*0b57cec5SDimitry Andric FunctionCallee AMDGPULibFunc::getOrInsertFunction(Module *M, 956*0b57cec5SDimitry Andric const AMDGPULibFunc &fInfo) { 957*0b57cec5SDimitry Andric std::string const FuncName = fInfo.mangle(); 958*0b57cec5SDimitry Andric Function *F = dyn_cast_or_null<Function>( 959*0b57cec5SDimitry Andric M->getValueSymbolTable().lookup(FuncName)); 960*0b57cec5SDimitry Andric 961*0b57cec5SDimitry Andric // check formal with actual types conformance 962*0b57cec5SDimitry Andric if (F && !F->isDeclaration() 963*0b57cec5SDimitry Andric && !F->isVarArg() 964*0b57cec5SDimitry Andric && F->arg_size() == fInfo.getNumArgs()) { 965*0b57cec5SDimitry Andric return F; 966*0b57cec5SDimitry Andric } 967*0b57cec5SDimitry Andric 968*0b57cec5SDimitry Andric FunctionType *FuncTy = fInfo.getFunctionType(*M); 969*0b57cec5SDimitry Andric 970*0b57cec5SDimitry Andric bool hasPtr = false; 971*0b57cec5SDimitry Andric for (FunctionType::param_iterator 972*0b57cec5SDimitry Andric PI = FuncTy->param_begin(), 973*0b57cec5SDimitry Andric PE = FuncTy->param_end(); 974*0b57cec5SDimitry Andric PI != PE; ++PI) { 975*0b57cec5SDimitry Andric const Type* argTy = static_cast<const Type*>(*PI); 976*0b57cec5SDimitry Andric if (argTy->isPointerTy()) { 977*0b57cec5SDimitry Andric hasPtr = true; 978*0b57cec5SDimitry Andric break; 979*0b57cec5SDimitry Andric } 980*0b57cec5SDimitry Andric } 981*0b57cec5SDimitry Andric 982*0b57cec5SDimitry Andric FunctionCallee C; 983*0b57cec5SDimitry Andric if (hasPtr) { 984*0b57cec5SDimitry Andric // Do not set extra attributes for functions with pointer arguments. 985*0b57cec5SDimitry Andric C = M->getOrInsertFunction(FuncName, FuncTy); 986*0b57cec5SDimitry Andric } else { 987*0b57cec5SDimitry Andric AttributeList Attr; 988*0b57cec5SDimitry Andric LLVMContext &Ctx = M->getContext(); 989*0b57cec5SDimitry Andric Attr = Attr.addAttribute(Ctx, AttributeList::FunctionIndex, 990*0b57cec5SDimitry Andric Attribute::ReadOnly); 991*0b57cec5SDimitry Andric Attr = Attr.addAttribute(Ctx, AttributeList::FunctionIndex, 992*0b57cec5SDimitry Andric Attribute::NoUnwind); 993*0b57cec5SDimitry Andric C = M->getOrInsertFunction(FuncName, FuncTy, Attr); 994*0b57cec5SDimitry Andric } 995*0b57cec5SDimitry Andric 996*0b57cec5SDimitry Andric return C; 997*0b57cec5SDimitry Andric } 998*0b57cec5SDimitry Andric 999*0b57cec5SDimitry Andric StringMap<unsigned> UnmangledFuncInfo::buildNameMap() { 1000*0b57cec5SDimitry Andric StringMap<unsigned> Map; 1001*0b57cec5SDimitry Andric for (unsigned I = 0; I != TableSize; ++I) 1002*0b57cec5SDimitry Andric Map[Table[I].Name] = I; 1003*0b57cec5SDimitry Andric return Map; 1004*0b57cec5SDimitry Andric } 1005*0b57cec5SDimitry Andric 1006*0b57cec5SDimitry Andric bool UnmangledFuncInfo::lookup(StringRef Name, ID &Id) { 1007*0b57cec5SDimitry Andric static const StringMap<unsigned> Map = buildNameMap(); 1008*0b57cec5SDimitry Andric auto Loc = Map.find(Name); 1009*0b57cec5SDimitry Andric if (Loc != Map.end()) { 1010*0b57cec5SDimitry Andric Id = toFuncId(Loc->second); 1011*0b57cec5SDimitry Andric return true; 1012*0b57cec5SDimitry Andric } 1013*0b57cec5SDimitry Andric Id = AMDGPULibFunc::EI_NONE; 1014*0b57cec5SDimitry Andric return false; 1015*0b57cec5SDimitry Andric } 1016*0b57cec5SDimitry Andric 1017*0b57cec5SDimitry Andric AMDGPULibFunc::AMDGPULibFunc(const AMDGPULibFunc &F) { 1018*0b57cec5SDimitry Andric if (auto *MF = dyn_cast<AMDGPUMangledLibFunc>(F.Impl.get())) 1019*0b57cec5SDimitry Andric Impl.reset(new AMDGPUMangledLibFunc(*MF)); 1020*0b57cec5SDimitry Andric else if (auto *UMF = dyn_cast<AMDGPUUnmangledLibFunc>(F.Impl.get())) 1021*0b57cec5SDimitry Andric Impl.reset(new AMDGPUUnmangledLibFunc(*UMF)); 1022*0b57cec5SDimitry Andric else 1023*0b57cec5SDimitry Andric Impl = std::unique_ptr<AMDGPULibFuncImpl>(); 1024*0b57cec5SDimitry Andric } 1025*0b57cec5SDimitry Andric 1026*0b57cec5SDimitry Andric AMDGPULibFunc &AMDGPULibFunc::operator=(const AMDGPULibFunc &F) { 1027*0b57cec5SDimitry Andric if (this == &F) 1028*0b57cec5SDimitry Andric return *this; 1029*0b57cec5SDimitry Andric new (this) AMDGPULibFunc(F); 1030*0b57cec5SDimitry Andric return *this; 1031*0b57cec5SDimitry Andric } 1032*0b57cec5SDimitry Andric 1033*0b57cec5SDimitry Andric AMDGPULibFunc::AMDGPULibFunc(EFuncId Id, const AMDGPULibFunc &CopyFrom) { 1034*0b57cec5SDimitry Andric assert(AMDGPULibFuncBase::isMangled(Id) && CopyFrom.isMangled() && 1035*0b57cec5SDimitry Andric "not supported"); 1036*0b57cec5SDimitry Andric Impl.reset(new AMDGPUMangledLibFunc( 1037*0b57cec5SDimitry Andric Id, *cast<AMDGPUMangledLibFunc>(CopyFrom.Impl.get()))); 1038*0b57cec5SDimitry Andric } 1039*0b57cec5SDimitry Andric 1040*0b57cec5SDimitry Andric AMDGPULibFunc::AMDGPULibFunc(StringRef Name, FunctionType *FT) { 1041*0b57cec5SDimitry Andric Impl.reset(new AMDGPUUnmangledLibFunc(Name, FT)); 1042*0b57cec5SDimitry Andric } 1043*0b57cec5SDimitry Andric 1044*0b57cec5SDimitry Andric void AMDGPULibFunc::initMangled() { Impl.reset(new AMDGPUMangledLibFunc()); } 1045*0b57cec5SDimitry Andric 1046*0b57cec5SDimitry Andric AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() { 1047*0b57cec5SDimitry Andric if (!Impl) 1048*0b57cec5SDimitry Andric initMangled(); 1049*0b57cec5SDimitry Andric return cast<AMDGPUMangledLibFunc>(Impl.get())->Leads; 1050*0b57cec5SDimitry Andric } 1051*0b57cec5SDimitry Andric 1052*0b57cec5SDimitry Andric const AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() const { 1053*0b57cec5SDimitry Andric return cast<const AMDGPUMangledLibFunc>(Impl.get())->Leads; 1054*0b57cec5SDimitry Andric } 1055