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