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