10b57cec5SDimitry Andric //===-- AMDGPULibFunc.cpp -------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains utility functions to work with Itanium mangled names 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "AMDGPULibFunc.h" 145ffd83dbSDimitry Andric #include "AMDGPU.h" 155ffd83dbSDimitry Andric #include "llvm/ADT/StringExtras.h" 16e8d8bef9SDimitry Andric #include "llvm/ADT/StringMap.h" 175ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h" 180b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 190b57cec5SDimitry Andric #include "llvm/IR/Function.h" 200b57cec5SDimitry Andric #include "llvm/IR/Module.h" 210b57cec5SDimitry Andric #include "llvm/IR/ValueSymbolTable.h" 22fe6060f1SDimitry Andric #include "llvm/Support/CommandLine.h" 23bdd1243dSDimitry Andric #include "llvm/Support/ModRef.h" 245ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric using namespace llvm; 270b57cec5SDimitry Andric 28fe6060f1SDimitry Andric static cl::opt<bool> EnableOCLManglingMismatchWA( 29fe6060f1SDimitry Andric "amdgpu-enable-ocl-mangling-mismatch-workaround", cl::init(true), 30fe6060f1SDimitry Andric cl::ReallyHidden, 31fe6060f1SDimitry Andric cl::desc("Enable the workaround for OCL name mangling mismatch.")); 32fe6060f1SDimitry Andric 330b57cec5SDimitry Andric namespace { 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric enum EManglingParam { 360b57cec5SDimitry Andric E_NONE, 370b57cec5SDimitry Andric EX_EVENT, 380b57cec5SDimitry Andric EX_FLOAT4, 390b57cec5SDimitry Andric EX_INTV4, 400b57cec5SDimitry Andric EX_RESERVEDID, 410b57cec5SDimitry Andric EX_SAMPLER, 420b57cec5SDimitry Andric EX_SIZET, 430b57cec5SDimitry Andric EX_UINT, 440b57cec5SDimitry Andric EX_UINTV4, 450b57cec5SDimitry Andric E_ANY, 460b57cec5SDimitry Andric E_CONSTPTR_ANY, 470b57cec5SDimitry Andric E_CONSTPTR_SWAPGL, 480b57cec5SDimitry Andric E_COPY, 490b57cec5SDimitry Andric E_IMAGECOORDS, 500b57cec5SDimitry Andric E_POINTEE, 510b57cec5SDimitry Andric E_SETBASE_I32, 520b57cec5SDimitry Andric E_SETBASE_U32, 530b57cec5SDimitry Andric E_MAKEBASE_UNS, 540b57cec5SDimitry Andric E_V16_OF_POINTEE, 550b57cec5SDimitry Andric E_V2_OF_POINTEE, 560b57cec5SDimitry Andric E_V3_OF_POINTEE, 570b57cec5SDimitry Andric E_V4_OF_POINTEE, 580b57cec5SDimitry Andric E_V8_OF_POINTEE, 590b57cec5SDimitry Andric E_VLTLPTR_ANY, 600b57cec5SDimitry Andric }; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric struct ManglingRule { 638bcb0991SDimitry Andric const char *Name; 640b57cec5SDimitry Andric unsigned char Lead[2]; 650b57cec5SDimitry Andric unsigned char Param[5]; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric int maxLeadIndex() const { return (std::max)(Lead[0], Lead[1]); } 680b57cec5SDimitry Andric int getNumLeads() const { return (Lead[0] ? 1 : 0) + (Lead[1] ? 1 : 0); } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric unsigned getNumArgs() const; 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric static StringMap<int> buildManglingRulesMap(); 730b57cec5SDimitry Andric }; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric // Information about library functions with unmangled names. 760b57cec5SDimitry Andric class UnmangledFuncInfo { 778bcb0991SDimitry Andric const char *Name; 780b57cec5SDimitry Andric unsigned NumArgs; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric // Table for all lib functions with unmangled names. 810b57cec5SDimitry Andric static const UnmangledFuncInfo Table[]; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric // Number of entries in Table. 840b57cec5SDimitry Andric static const unsigned TableSize; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric static StringMap<unsigned> buildNameMap(); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric public: 890b57cec5SDimitry Andric using ID = AMDGPULibFunc::EFuncId; 908bcb0991SDimitry Andric constexpr UnmangledFuncInfo(const char *_Name, unsigned _NumArgs) 910b57cec5SDimitry Andric : Name(_Name), NumArgs(_NumArgs) {} 920b57cec5SDimitry Andric // Get index to Table by function name. 930b57cec5SDimitry Andric static bool lookup(StringRef Name, ID &Id); 940b57cec5SDimitry Andric static unsigned toIndex(ID Id) { 950b57cec5SDimitry Andric assert(static_cast<unsigned>(Id) > 960b57cec5SDimitry Andric static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED) && 970b57cec5SDimitry Andric "Invalid unmangled library function"); 980b57cec5SDimitry Andric return static_cast<unsigned>(Id) - 1 - 990b57cec5SDimitry Andric static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric static ID toFuncId(unsigned Index) { 1020b57cec5SDimitry Andric assert(Index < TableSize && 1030b57cec5SDimitry Andric "Invalid unmangled library function"); 1040b57cec5SDimitry Andric return static_cast<ID>( 1050b57cec5SDimitry Andric Index + 1 + static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED)); 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric static unsigned getNumArgs(ID Id) { return Table[toIndex(Id)].NumArgs; } 1080b57cec5SDimitry Andric static StringRef getName(ID Id) { return Table[toIndex(Id)].Name; } 1090b57cec5SDimitry Andric }; 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric unsigned ManglingRule::getNumArgs() const { 1120b57cec5SDimitry Andric unsigned I=0; 1130b57cec5SDimitry Andric while (I < (sizeof Param/sizeof Param[0]) && Param[I]) ++I; 1140b57cec5SDimitry Andric return I; 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric // This table describes function formal argument type rules. The order of rules 1180b57cec5SDimitry Andric // corresponds to the EFuncId enum at AMDGPULibFunc.h 1190b57cec5SDimitry Andric // 1200b57cec5SDimitry Andric // "<func name>", { <leads> }, { <param rules> } 1210b57cec5SDimitry Andric // where: 1220b57cec5SDimitry Andric // <leads> - list of integers that are one-based indexes of formal argument 1230b57cec5SDimitry Andric // used to mangle a function name. Other argument types are derived from types 1240b57cec5SDimitry Andric // of these 'leads'. The order of integers in this list correspond to the 1250b57cec5SDimitry Andric // order in which these arguments are mangled in the EDG mangling scheme. The 1260b57cec5SDimitry Andric // same order should be preserved for arguments in the AMDGPULibFunc structure 1270b57cec5SDimitry Andric // when it is used for mangling. For example: 1280b57cec5SDimitry Andric // { "vstorea_half", {3,1}, {E_ANY,EX_SIZET,E_ANY}}, 1290b57cec5SDimitry Andric // will be mangled in EDG scheme as vstorea_half_<3dparam>_<1stparam> 1300b57cec5SDimitry Andric // When mangling from code use: 1310b57cec5SDimitry Andric // AMDGPULibFunc insc; 1320b57cec5SDimitry Andric // insc.param[0] = ... // describe 3rd parameter 1330b57cec5SDimitry Andric // insc.param[1] = ... // describe 1rd parameter 1340b57cec5SDimitry Andric // 1350b57cec5SDimitry Andric // <param rules> - list of rules used to derive all of the function formal 1360b57cec5SDimitry Andric // argument types. EX_ prefixed are simple types, other derived from the 1370b57cec5SDimitry Andric // latest 'lead' argument type in the order of encoding from first to last. 1380b57cec5SDimitry Andric // E_ANY - use prev lead type, E_CONSTPTR_ANY - make const pointer out of 1390b57cec5SDimitry Andric // prev lead type, etc. see ParamIterator::getNextParam() for details. 1400b57cec5SDimitry Andric 1418bcb0991SDimitry Andric static constexpr ManglingRule manglingRules[] = { 1428bcb0991SDimitry Andric { "", {0}, {0} }, 1430b57cec5SDimitry Andric { "abs" , {1}, {E_ANY}}, 1440b57cec5SDimitry Andric { "abs_diff" , {1}, {E_ANY,E_COPY}}, 1450b57cec5SDimitry Andric { "acos" , {1}, {E_ANY}}, 1460b57cec5SDimitry Andric { "acosh" , {1}, {E_ANY}}, 1470b57cec5SDimitry Andric { "acospi" , {1}, {E_ANY}}, 1480b57cec5SDimitry Andric { "add_sat" , {1}, {E_ANY,E_COPY}}, 1490b57cec5SDimitry Andric { "all" , {1}, {E_ANY}}, 1500b57cec5SDimitry Andric { "any" , {1}, {E_ANY}}, 1510b57cec5SDimitry Andric { "asin" , {1}, {E_ANY}}, 1520b57cec5SDimitry Andric { "asinh" , {1}, {E_ANY}}, 1530b57cec5SDimitry Andric { "asinpi" , {1}, {E_ANY}}, 1540b57cec5SDimitry Andric { "async_work_group_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_EVENT}}, 1550b57cec5SDimitry Andric { "async_work_group_strided_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_SIZET,EX_EVENT}}, 1560b57cec5SDimitry Andric { "atan" , {1}, {E_ANY}}, 1570b57cec5SDimitry Andric { "atan2" , {1}, {E_ANY,E_COPY}}, 1580b57cec5SDimitry Andric { "atan2pi" , {1}, {E_ANY,E_COPY}}, 1590b57cec5SDimitry Andric { "atanh" , {1}, {E_ANY}}, 1600b57cec5SDimitry Andric { "atanpi" , {1}, {E_ANY}}, 1610b57cec5SDimitry Andric { "atomic_add" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 1620b57cec5SDimitry Andric { "atomic_and" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 1630b57cec5SDimitry Andric { "atomic_cmpxchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE,E_POINTEE}}, 1640b57cec5SDimitry Andric { "atomic_dec" , {1}, {E_VLTLPTR_ANY}}, 1650b57cec5SDimitry Andric { "atomic_inc" , {1}, {E_VLTLPTR_ANY}}, 1660b57cec5SDimitry Andric { "atomic_max" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 1670b57cec5SDimitry Andric { "atomic_min" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 1680b57cec5SDimitry Andric { "atomic_or" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 1690b57cec5SDimitry Andric { "atomic_sub" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 1700b57cec5SDimitry Andric { "atomic_xchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 1710b57cec5SDimitry Andric { "atomic_xor" , {1}, {E_VLTLPTR_ANY,E_POINTEE}}, 1720b57cec5SDimitry Andric { "bitselect" , {1}, {E_ANY,E_COPY,E_COPY}}, 1730b57cec5SDimitry Andric { "cbrt" , {1}, {E_ANY}}, 1740b57cec5SDimitry Andric { "ceil" , {1}, {E_ANY}}, 1750b57cec5SDimitry Andric { "clamp" , {1}, {E_ANY,E_COPY,E_COPY}}, 1760b57cec5SDimitry Andric { "clz" , {1}, {E_ANY}}, 1770b57cec5SDimitry Andric { "commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 1780b57cec5SDimitry Andric { "commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 1790b57cec5SDimitry Andric { "copysign" , {1}, {E_ANY,E_COPY}}, 1800b57cec5SDimitry Andric { "cos" , {1}, {E_ANY}}, 1810b57cec5SDimitry Andric { "cosh" , {1}, {E_ANY}}, 1820b57cec5SDimitry Andric { "cospi" , {1}, {E_ANY}}, 1830b57cec5SDimitry Andric { "cross" , {1}, {E_ANY,E_COPY}}, 1840b57cec5SDimitry Andric { "ctz" , {1}, {E_ANY}}, 1850b57cec5SDimitry Andric { "degrees" , {1}, {E_ANY}}, 1860b57cec5SDimitry Andric { "distance" , {1}, {E_ANY,E_COPY}}, 1870b57cec5SDimitry Andric { "divide" , {1}, {E_ANY,E_COPY}}, 1880b57cec5SDimitry Andric { "dot" , {1}, {E_ANY,E_COPY}}, 1890b57cec5SDimitry Andric { "erf" , {1}, {E_ANY}}, 1900b57cec5SDimitry Andric { "erfc" , {1}, {E_ANY}}, 1910b57cec5SDimitry Andric { "exp" , {1}, {E_ANY}}, 1920b57cec5SDimitry Andric { "exp10" , {1}, {E_ANY}}, 1930b57cec5SDimitry Andric { "exp2" , {1}, {E_ANY}}, 1940b57cec5SDimitry Andric { "expm1" , {1}, {E_ANY}}, 1950b57cec5SDimitry Andric { "fabs" , {1}, {E_ANY}}, 1960b57cec5SDimitry Andric { "fast_distance" , {1}, {E_ANY,E_COPY}}, 1970b57cec5SDimitry Andric { "fast_length" , {1}, {E_ANY}}, 1980b57cec5SDimitry Andric { "fast_normalize" , {1}, {E_ANY}}, 1990b57cec5SDimitry Andric { "fdim" , {1}, {E_ANY,E_COPY}}, 2000b57cec5SDimitry Andric { "floor" , {1}, {E_ANY}}, 2010b57cec5SDimitry Andric { "fma" , {1}, {E_ANY,E_COPY,E_COPY}}, 2020b57cec5SDimitry Andric { "fmax" , {1}, {E_ANY,E_COPY}}, 2030b57cec5SDimitry Andric { "fmin" , {1}, {E_ANY,E_COPY}}, 2040b57cec5SDimitry Andric { "fmod" , {1}, {E_ANY,E_COPY}}, 2050b57cec5SDimitry Andric { "fract" , {2}, {E_POINTEE,E_ANY}}, 2060b57cec5SDimitry Andric { "frexp" , {1,2}, {E_ANY,E_ANY}}, 2070b57cec5SDimitry Andric { "get_image_array_size" , {1}, {E_ANY}}, 2080b57cec5SDimitry Andric { "get_image_channel_data_type" , {1}, {E_ANY}}, 2090b57cec5SDimitry Andric { "get_image_channel_order" , {1}, {E_ANY}}, 2100b57cec5SDimitry Andric { "get_image_dim" , {1}, {E_ANY}}, 2110b57cec5SDimitry Andric { "get_image_height" , {1}, {E_ANY}}, 2120b57cec5SDimitry Andric { "get_image_width" , {1}, {E_ANY}}, 2130b57cec5SDimitry Andric { "get_pipe_max_packets" , {1}, {E_ANY}}, 2140b57cec5SDimitry Andric { "get_pipe_num_packets" , {1}, {E_ANY}}, 2150b57cec5SDimitry Andric { "hadd" , {1}, {E_ANY,E_COPY}}, 2160b57cec5SDimitry Andric { "hypot" , {1}, {E_ANY,E_COPY}}, 2170b57cec5SDimitry Andric { "ilogb" , {1}, {E_ANY}}, 2180b57cec5SDimitry Andric { "isequal" , {1}, {E_ANY,E_COPY}}, 2190b57cec5SDimitry Andric { "isfinite" , {1}, {E_ANY}}, 2200b57cec5SDimitry Andric { "isgreater" , {1}, {E_ANY,E_COPY}}, 2210b57cec5SDimitry Andric { "isgreaterequal" , {1}, {E_ANY,E_COPY}}, 2220b57cec5SDimitry Andric { "isinf" , {1}, {E_ANY}}, 2230b57cec5SDimitry Andric { "isless" , {1}, {E_ANY,E_COPY}}, 2240b57cec5SDimitry Andric { "islessequal" , {1}, {E_ANY,E_COPY}}, 2250b57cec5SDimitry Andric { "islessgreater" , {1}, {E_ANY,E_COPY}}, 2260b57cec5SDimitry Andric { "isnan" , {1}, {E_ANY}}, 2270b57cec5SDimitry Andric { "isnormal" , {1}, {E_ANY}}, 2280b57cec5SDimitry Andric { "isnotequal" , {1}, {E_ANY,E_COPY}}, 2290b57cec5SDimitry Andric { "isordered" , {1}, {E_ANY,E_COPY}}, 2300b57cec5SDimitry Andric { "isunordered" , {1}, {E_ANY,E_COPY}}, 2310b57cec5SDimitry Andric { "ldexp" , {1}, {E_ANY,E_SETBASE_I32}}, 2320b57cec5SDimitry Andric { "length" , {1}, {E_ANY}}, 2330b57cec5SDimitry Andric { "lgamma" , {1}, {E_ANY}}, 2340b57cec5SDimitry Andric { "lgamma_r" , {1,2}, {E_ANY,E_ANY}}, 2350b57cec5SDimitry Andric { "log" , {1}, {E_ANY}}, 2360b57cec5SDimitry Andric { "log10" , {1}, {E_ANY}}, 2370b57cec5SDimitry Andric { "log1p" , {1}, {E_ANY}}, 2380b57cec5SDimitry Andric { "log2" , {1}, {E_ANY}}, 2390b57cec5SDimitry Andric { "logb" , {1}, {E_ANY}}, 2400b57cec5SDimitry Andric { "mad" , {1}, {E_ANY,E_COPY,E_COPY}}, 2410b57cec5SDimitry Andric { "mad24" , {1}, {E_ANY,E_COPY,E_COPY}}, 2420b57cec5SDimitry Andric { "mad_hi" , {1}, {E_ANY,E_COPY,E_COPY}}, 2430b57cec5SDimitry Andric { "mad_sat" , {1}, {E_ANY,E_COPY,E_COPY}}, 2440b57cec5SDimitry Andric { "max" , {1}, {E_ANY,E_COPY}}, 2450b57cec5SDimitry Andric { "maxmag" , {1}, {E_ANY,E_COPY}}, 2460b57cec5SDimitry Andric { "min" , {1}, {E_ANY,E_COPY}}, 2470b57cec5SDimitry Andric { "minmag" , {1}, {E_ANY,E_COPY}}, 2480b57cec5SDimitry Andric { "mix" , {1}, {E_ANY,E_COPY,E_COPY}}, 2490b57cec5SDimitry Andric { "modf" , {2}, {E_POINTEE,E_ANY}}, 2500b57cec5SDimitry Andric { "mul24" , {1}, {E_ANY,E_COPY}}, 2510b57cec5SDimitry Andric { "mul_hi" , {1}, {E_ANY,E_COPY}}, 2520b57cec5SDimitry Andric { "nan" , {1}, {E_ANY}}, 2530b57cec5SDimitry Andric { "nextafter" , {1}, {E_ANY,E_COPY}}, 2540b57cec5SDimitry Andric { "normalize" , {1}, {E_ANY}}, 2550b57cec5SDimitry Andric { "popcount" , {1}, {E_ANY}}, 2560b57cec5SDimitry Andric { "pow" , {1}, {E_ANY,E_COPY}}, 2570b57cec5SDimitry Andric { "pown" , {1}, {E_ANY,E_SETBASE_I32}}, 2580b57cec5SDimitry Andric { "powr" , {1}, {E_ANY,E_COPY}}, 2590b57cec5SDimitry Andric { "prefetch" , {1}, {E_CONSTPTR_ANY,EX_SIZET}}, 2600b57cec5SDimitry Andric { "radians" , {1}, {E_ANY}}, 2610b57cec5SDimitry Andric { "recip" , {1}, {E_ANY}}, 2620b57cec5SDimitry Andric { "remainder" , {1}, {E_ANY,E_COPY}}, 2630b57cec5SDimitry Andric { "remquo" , {1,3}, {E_ANY,E_COPY,E_ANY}}, 2640b57cec5SDimitry Andric { "reserve_read_pipe" , {1}, {E_ANY,EX_UINT}}, 2650b57cec5SDimitry Andric { "reserve_write_pipe" , {1}, {E_ANY,EX_UINT}}, 2660b57cec5SDimitry Andric { "rhadd" , {1}, {E_ANY,E_COPY}}, 2670b57cec5SDimitry Andric { "rint" , {1}, {E_ANY}}, 2680b57cec5SDimitry Andric { "rootn" , {1}, {E_ANY,E_SETBASE_I32}}, 2690b57cec5SDimitry Andric { "rotate" , {1}, {E_ANY,E_COPY}}, 2700b57cec5SDimitry Andric { "round" , {1}, {E_ANY}}, 2710b57cec5SDimitry Andric { "rsqrt" , {1}, {E_ANY}}, 2720b57cec5SDimitry Andric { "select" , {1,3}, {E_ANY,E_COPY,E_ANY}}, 2730b57cec5SDimitry Andric { "shuffle" , {1,2}, {E_ANY,E_ANY}}, 2740b57cec5SDimitry Andric { "shuffle2" , {1,3}, {E_ANY,E_COPY,E_ANY}}, 2750b57cec5SDimitry Andric { "sign" , {1}, {E_ANY}}, 2760b57cec5SDimitry Andric { "signbit" , {1}, {E_ANY}}, 2770b57cec5SDimitry Andric { "sin" , {1}, {E_ANY}}, 2780b57cec5SDimitry Andric { "sincos" , {2}, {E_POINTEE,E_ANY}}, 2790b57cec5SDimitry Andric { "sinh" , {1}, {E_ANY}}, 2800b57cec5SDimitry Andric { "sinpi" , {1}, {E_ANY}}, 2810b57cec5SDimitry Andric { "smoothstep" , {1}, {E_ANY,E_COPY,E_COPY}}, 2820b57cec5SDimitry Andric { "sqrt" , {1}, {E_ANY}}, 2830b57cec5SDimitry Andric { "step" , {1}, {E_ANY,E_COPY}}, 2840b57cec5SDimitry Andric { "sub_group_broadcast" , {1}, {E_ANY,EX_UINT}}, 2850b57cec5SDimitry Andric { "sub_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 2860b57cec5SDimitry Andric { "sub_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 2870b57cec5SDimitry Andric { "sub_group_reduce_add" , {1}, {E_ANY}}, 2880b57cec5SDimitry Andric { "sub_group_reduce_max" , {1}, {E_ANY}}, 2890b57cec5SDimitry Andric { "sub_group_reduce_min" , {1}, {E_ANY}}, 2900b57cec5SDimitry Andric { "sub_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}}, 2910b57cec5SDimitry Andric { "sub_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}}, 2920b57cec5SDimitry Andric { "sub_group_scan_exclusive_add" , {1}, {E_ANY}}, 2930b57cec5SDimitry Andric { "sub_group_scan_exclusive_max" , {1}, {E_ANY}}, 2940b57cec5SDimitry Andric { "sub_group_scan_exclusive_min" , {1}, {E_ANY}}, 2950b57cec5SDimitry Andric { "sub_group_scan_inclusive_add" , {1}, {E_ANY}}, 2960b57cec5SDimitry Andric { "sub_group_scan_inclusive_max" , {1}, {E_ANY}}, 2970b57cec5SDimitry Andric { "sub_group_scan_inclusive_min" , {1}, {E_ANY}}, 2980b57cec5SDimitry Andric { "sub_sat" , {1}, {E_ANY,E_COPY}}, 2990b57cec5SDimitry Andric { "tan" , {1}, {E_ANY}}, 3000b57cec5SDimitry Andric { "tanh" , {1}, {E_ANY}}, 3010b57cec5SDimitry Andric { "tanpi" , {1}, {E_ANY}}, 3020b57cec5SDimitry Andric { "tgamma" , {1}, {E_ANY}}, 3030b57cec5SDimitry Andric { "trunc" , {1}, {E_ANY}}, 3040b57cec5SDimitry Andric { "upsample" , {1}, {E_ANY,E_MAKEBASE_UNS}}, 3050b57cec5SDimitry Andric { "vec_step" , {1}, {E_ANY}}, 3060b57cec5SDimitry Andric { "vstore" , {3}, {E_POINTEE,EX_SIZET,E_ANY}}, 3070b57cec5SDimitry Andric { "vstore16" , {3}, {E_V16_OF_POINTEE,EX_SIZET,E_ANY}}, 3080b57cec5SDimitry Andric { "vstore2" , {3}, {E_V2_OF_POINTEE,EX_SIZET,E_ANY}}, 3090b57cec5SDimitry Andric { "vstore3" , {3}, {E_V3_OF_POINTEE,EX_SIZET,E_ANY}}, 3100b57cec5SDimitry Andric { "vstore4" , {3}, {E_V4_OF_POINTEE,EX_SIZET,E_ANY}}, 3110b57cec5SDimitry Andric { "vstore8" , {3}, {E_V8_OF_POINTEE,EX_SIZET,E_ANY}}, 3120b57cec5SDimitry Andric { "work_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 3130b57cec5SDimitry Andric { "work_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}}, 3140b57cec5SDimitry Andric { "work_group_reduce_add" , {1}, {E_ANY}}, 3150b57cec5SDimitry Andric { "work_group_reduce_max" , {1}, {E_ANY}}, 3160b57cec5SDimitry Andric { "work_group_reduce_min" , {1}, {E_ANY}}, 3170b57cec5SDimitry Andric { "work_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}}, 3180b57cec5SDimitry Andric { "work_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}}, 3190b57cec5SDimitry Andric { "work_group_scan_exclusive_add" , {1}, {E_ANY}}, 3200b57cec5SDimitry Andric { "work_group_scan_exclusive_max" , {1}, {E_ANY}}, 3210b57cec5SDimitry Andric { "work_group_scan_exclusive_min" , {1}, {E_ANY}}, 3220b57cec5SDimitry Andric { "work_group_scan_inclusive_add" , {1}, {E_ANY}}, 3230b57cec5SDimitry Andric { "work_group_scan_inclusive_max" , {1}, {E_ANY}}, 3240b57cec5SDimitry Andric { "work_group_scan_inclusive_min" , {1}, {E_ANY}}, 3250b57cec5SDimitry Andric { "write_imagef" , {1}, {E_ANY,E_IMAGECOORDS,EX_FLOAT4}}, 3260b57cec5SDimitry Andric { "write_imagei" , {1}, {E_ANY,E_IMAGECOORDS,EX_INTV4}}, 3270b57cec5SDimitry Andric { "write_imageui" , {1}, {E_ANY,E_IMAGECOORDS,EX_UINTV4}}, 3280b57cec5SDimitry Andric { "ncos" , {1}, {E_ANY} }, 3290b57cec5SDimitry Andric { "nexp2" , {1}, {E_ANY} }, 3300b57cec5SDimitry Andric { "nfma" , {1}, {E_ANY, E_COPY, E_COPY} }, 3310b57cec5SDimitry Andric { "nlog2" , {1}, {E_ANY} }, 3320b57cec5SDimitry Andric { "nrcp" , {1}, {E_ANY} }, 3330b57cec5SDimitry Andric { "nrsqrt" , {1}, {E_ANY} }, 3340b57cec5SDimitry Andric { "nsin" , {1}, {E_ANY} }, 3350b57cec5SDimitry Andric { "nsqrt" , {1}, {E_ANY} }, 3360b57cec5SDimitry Andric { "ftz" , {1}, {E_ANY} }, 3370b57cec5SDimitry Andric { "fldexp" , {1}, {E_ANY, EX_UINT} }, 3380b57cec5SDimitry Andric { "class" , {1}, {E_ANY, EX_UINT} }, 3390b57cec5SDimitry Andric { "rcbrt" , {1}, {E_ANY} }, 3400b57cec5SDimitry Andric }; 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric // Library functions with unmangled name. 3430b57cec5SDimitry Andric const UnmangledFuncInfo UnmangledFuncInfo::Table[] = { 3440b57cec5SDimitry Andric {"__read_pipe_2", 4}, 3450b57cec5SDimitry Andric {"__read_pipe_4", 6}, 3460b57cec5SDimitry Andric {"__write_pipe_2", 4}, 3470b57cec5SDimitry Andric {"__write_pipe_4", 6}, 3480b57cec5SDimitry Andric }; 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric const unsigned UnmangledFuncInfo::TableSize = 351bdd1243dSDimitry Andric std::size(UnmangledFuncInfo::Table); 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric static AMDGPULibFunc::Param getRetType(AMDGPULibFunc::EFuncId id, 3540b57cec5SDimitry Andric const AMDGPULibFunc::Param (&Leads)[2]) { 3550b57cec5SDimitry Andric AMDGPULibFunc::Param Res = Leads[0]; 356349cc55cSDimitry Andric // TBD - This switch may require to be extended for other intrinsics 3570b57cec5SDimitry Andric switch (id) { 3580b57cec5SDimitry Andric case AMDGPULibFunc::EI_SINCOS: 3590b57cec5SDimitry Andric Res.PtrKind = AMDGPULibFunc::BYVALUE; 3600b57cec5SDimitry Andric break; 3610b57cec5SDimitry Andric default: 3620b57cec5SDimitry Andric break; 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric return Res; 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric class ParamIterator { 3680b57cec5SDimitry Andric const AMDGPULibFunc::Param (&Leads)[2]; 3690b57cec5SDimitry Andric const ManglingRule& Rule; 370*0fca6ea1SDimitry Andric int Index = 0; 3710b57cec5SDimitry Andric public: 3720b57cec5SDimitry Andric ParamIterator(const AMDGPULibFunc::Param (&leads)[2], 3730b57cec5SDimitry Andric const ManglingRule& rule) 374*0fca6ea1SDimitry Andric : Leads(leads), Rule(rule) {} 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric AMDGPULibFunc::Param getNextParam(); 3770b57cec5SDimitry Andric }; 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric AMDGPULibFunc::Param ParamIterator::getNextParam() { 3800b57cec5SDimitry Andric AMDGPULibFunc::Param P; 3810b57cec5SDimitry Andric if (Index >= int(sizeof Rule.Param/sizeof Rule.Param[0])) return P; 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric const char R = Rule.Param[Index]; 3840b57cec5SDimitry Andric switch (R) { 3850b57cec5SDimitry Andric case E_NONE: break; 3860b57cec5SDimitry Andric case EX_UINT: 3870b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::U32; break; 3880b57cec5SDimitry Andric case EX_INTV4: 3890b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::I32; P.VectorSize = 4; break; 3900b57cec5SDimitry Andric case EX_UINTV4: 3910b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::U32; P.VectorSize = 4; break; 3920b57cec5SDimitry Andric case EX_FLOAT4: 3930b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::F32; P.VectorSize = 4; break; 3940b57cec5SDimitry Andric case EX_SIZET: 3950b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::U64; break; 3960b57cec5SDimitry Andric case EX_EVENT: 3970b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::EVENT; break; 3980b57cec5SDimitry Andric case EX_SAMPLER: 3990b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::SAMPLER; break; 4000b57cec5SDimitry Andric case EX_RESERVEDID: break; // TBD 4010b57cec5SDimitry Andric default: 4020b57cec5SDimitry Andric if (Index == (Rule.Lead[1] - 1)) P = Leads[1]; 4030b57cec5SDimitry Andric else P = Leads[0]; 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric switch (R) { 4060b57cec5SDimitry Andric case E_ANY: 4070b57cec5SDimitry Andric case E_COPY: break; 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric case E_POINTEE: 4100b57cec5SDimitry Andric P.PtrKind = AMDGPULibFunc::BYVALUE; break; 4110b57cec5SDimitry Andric case E_V2_OF_POINTEE: 4120b57cec5SDimitry Andric P.VectorSize = 2; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 4130b57cec5SDimitry Andric case E_V3_OF_POINTEE: 4140b57cec5SDimitry Andric P.VectorSize = 3; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 4150b57cec5SDimitry Andric case E_V4_OF_POINTEE: 4160b57cec5SDimitry Andric P.VectorSize = 4; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 4170b57cec5SDimitry Andric case E_V8_OF_POINTEE: 4180b57cec5SDimitry Andric P.VectorSize = 8; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 4190b57cec5SDimitry Andric case E_V16_OF_POINTEE: 4200b57cec5SDimitry Andric P.VectorSize = 16; P.PtrKind = AMDGPULibFunc::BYVALUE; break; 4210b57cec5SDimitry Andric case E_CONSTPTR_ANY: 4220b57cec5SDimitry Andric P.PtrKind |= AMDGPULibFunc::CONST; break; 4230b57cec5SDimitry Andric case E_VLTLPTR_ANY: 4240b57cec5SDimitry Andric P.PtrKind |= AMDGPULibFunc::VOLATILE; break; 4250b57cec5SDimitry Andric case E_SETBASE_I32: 4260b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::I32; break; 4270b57cec5SDimitry Andric case E_SETBASE_U32: 4280b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::U32; break; 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric case E_MAKEBASE_UNS: 4310b57cec5SDimitry Andric P.ArgType &= ~AMDGPULibFunc::BASE_TYPE_MASK; 4320b57cec5SDimitry Andric P.ArgType |= AMDGPULibFunc::UINT; 4330b57cec5SDimitry Andric break; 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric case E_IMAGECOORDS: 4360b57cec5SDimitry Andric switch (P.ArgType) { 4370b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DA: P.VectorSize = 2; break; 4380b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DB: P.VectorSize = 1; break; 4390b57cec5SDimitry Andric case AMDGPULibFunc::IMG2DA: P.VectorSize = 4; break; 4400b57cec5SDimitry Andric case AMDGPULibFunc::IMG1D: P.VectorSize = 1; break; 4410b57cec5SDimitry Andric case AMDGPULibFunc::IMG2D: P.VectorSize = 2; break; 4420b57cec5SDimitry Andric case AMDGPULibFunc::IMG3D: P.VectorSize = 4; break; 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric P.PtrKind = AMDGPULibFunc::BYVALUE; 4450b57cec5SDimitry Andric P.ArgType = AMDGPULibFunc::I32; 4460b57cec5SDimitry Andric break; 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric case E_CONSTPTR_SWAPGL: { 4490b57cec5SDimitry Andric unsigned AS = AMDGPULibFunc::getAddrSpaceFromEPtrKind(P.PtrKind); 4500b57cec5SDimitry Andric switch (AS) { 4510b57cec5SDimitry Andric case AMDGPUAS::GLOBAL_ADDRESS: AS = AMDGPUAS::LOCAL_ADDRESS; break; 4520b57cec5SDimitry Andric case AMDGPUAS::LOCAL_ADDRESS: AS = AMDGPUAS::GLOBAL_ADDRESS; break; 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric P.PtrKind = AMDGPULibFunc::getEPtrKindFromAddrSpace(AS); 4550b57cec5SDimitry Andric P.PtrKind |= AMDGPULibFunc::CONST; 4560b57cec5SDimitry Andric break; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 459349cc55cSDimitry Andric default: 460349cc55cSDimitry Andric llvm_unreachable("Unhandled param rule"); 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric ++Index; 4640b57cec5SDimitry Andric return P; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric inline static void drop_front(StringRef& str, size_t n = 1) { 4680b57cec5SDimitry Andric str = str.drop_front(n); 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric static bool eatTerm(StringRef& mangledName, const char c) { 4720b57cec5SDimitry Andric if (mangledName.front() == c) { 4730b57cec5SDimitry Andric drop_front(mangledName); 4740b57cec5SDimitry Andric return true; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric return false; 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric template <size_t N> 4800b57cec5SDimitry Andric static bool eatTerm(StringRef& mangledName, const char (&str)[N]) { 4815f757f3fSDimitry Andric if (mangledName.starts_with(StringRef(str, N - 1))) { 4820b57cec5SDimitry Andric drop_front(mangledName, N-1); 4830b57cec5SDimitry Andric return true; 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric return false; 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric static int eatNumber(StringRef& s) { 4890b57cec5SDimitry Andric size_t const savedSize = s.size(); 4900b57cec5SDimitry Andric int n = 0; 4910b57cec5SDimitry Andric while (!s.empty() && isDigit(s.front())) { 4920b57cec5SDimitry Andric n = n*10 + s.front() - '0'; 4930b57cec5SDimitry Andric drop_front(s); 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric return s.size() < savedSize ? n : -1; 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric static StringRef eatLengthPrefixedName(StringRef& mangledName) { 4990b57cec5SDimitry Andric int const Len = eatNumber(mangledName); 5000b57cec5SDimitry Andric if (Len <= 0 || static_cast<size_t>(Len) > mangledName.size()) 5010b57cec5SDimitry Andric return StringRef(); 5020b57cec5SDimitry Andric StringRef Res = mangledName.substr(0, Len); 5030b57cec5SDimitry Andric drop_front(mangledName, Len); 5040b57cec5SDimitry Andric return Res; 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric } // end anonymous namespace 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric AMDGPUMangledLibFunc::AMDGPUMangledLibFunc() { 5100b57cec5SDimitry Andric FuncId = EI_NONE; 5110b57cec5SDimitry Andric FKind = NOPFX; 5120b57cec5SDimitry Andric Leads[0].reset(); 5130b57cec5SDimitry Andric Leads[1].reset(); 5140b57cec5SDimitry Andric Name.clear(); 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric AMDGPUUnmangledLibFunc::AMDGPUUnmangledLibFunc() { 5180b57cec5SDimitry Andric FuncId = EI_NONE; 5190b57cec5SDimitry Andric FuncTy = nullptr; 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric AMDGPUMangledLibFunc::AMDGPUMangledLibFunc( 5230b57cec5SDimitry Andric EFuncId id, const AMDGPUMangledLibFunc ©From) { 5240b57cec5SDimitry Andric FuncId = id; 5250b57cec5SDimitry Andric FKind = copyFrom.FKind; 5260b57cec5SDimitry Andric Leads[0] = copyFrom.Leads[0]; 5270b57cec5SDimitry Andric Leads[1] = copyFrom.Leads[1]; 5280b57cec5SDimitry Andric } 5290b57cec5SDimitry Andric 5305f757f3fSDimitry Andric AMDGPUMangledLibFunc::AMDGPUMangledLibFunc(EFuncId id, FunctionType *FT, 5315f757f3fSDimitry Andric bool SignedInts) { 5325f757f3fSDimitry Andric FuncId = id; 5335f757f3fSDimitry Andric unsigned NumArgs = FT->getNumParams(); 5345f757f3fSDimitry Andric if (NumArgs >= 1) 5355f757f3fSDimitry Andric Leads[0] = Param::getFromTy(FT->getParamType(0), SignedInts); 5365f757f3fSDimitry Andric if (NumArgs >= 2) 5375f757f3fSDimitry Andric Leads[1] = Param::getFromTy(FT->getParamType(1), SignedInts); 5385f757f3fSDimitry Andric } 5395f757f3fSDimitry Andric 5400b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 5410b57cec5SDimitry Andric // Demangling 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric static int parseVecSize(StringRef& mangledName) { 5440b57cec5SDimitry Andric size_t const Len = eatNumber(mangledName); 5450b57cec5SDimitry Andric switch (Len) { 5460b57cec5SDimitry Andric case 2: case 3: case 4: case 8: case 16: 5470b57cec5SDimitry Andric return Len; 5480b57cec5SDimitry Andric default: 5490b57cec5SDimitry Andric break; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric return 1; 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric static AMDGPULibFunc::ENamePrefix parseNamePrefix(StringRef& mangledName) { 5550b57cec5SDimitry Andric std::pair<StringRef, StringRef> const P = mangledName.split('_'); 5560b57cec5SDimitry Andric AMDGPULibFunc::ENamePrefix Pfx = 5570b57cec5SDimitry Andric StringSwitch<AMDGPULibFunc::ENamePrefix>(P.first) 5580b57cec5SDimitry Andric .Case("native", AMDGPULibFunc::NATIVE) 5590b57cec5SDimitry Andric .Case("half" , AMDGPULibFunc::HALF) 5600b57cec5SDimitry Andric .Default(AMDGPULibFunc::NOPFX); 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric if (Pfx != AMDGPULibFunc::NOPFX) 5630b57cec5SDimitry Andric mangledName = P.second; 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric return Pfx; 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric StringMap<int> ManglingRule::buildManglingRulesMap() { 569bdd1243dSDimitry Andric StringMap<int> Map(std::size(manglingRules)); 5700b57cec5SDimitry Andric int Id = 0; 5710b57cec5SDimitry Andric for (auto Rule : manglingRules) 5720b57cec5SDimitry Andric Map.insert({Rule.Name, Id++}); 5730b57cec5SDimitry Andric return Map; 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric bool AMDGPUMangledLibFunc::parseUnmangledName(StringRef FullName) { 5770b57cec5SDimitry Andric static const StringMap<int> manglingRulesMap = 5780b57cec5SDimitry Andric ManglingRule::buildManglingRulesMap(); 5790b57cec5SDimitry Andric FuncId = static_cast<EFuncId>(manglingRulesMap.lookup(FullName)); 5800b57cec5SDimitry Andric return FuncId != EI_NONE; 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 5840b57cec5SDimitry Andric // Itanium Demangling 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric namespace { 5870b57cec5SDimitry Andric struct ItaniumParamParser { 5880b57cec5SDimitry Andric AMDGPULibFunc::Param Prev; 5890b57cec5SDimitry Andric bool parseItaniumParam(StringRef& param, AMDGPULibFunc::Param &res); 5900b57cec5SDimitry Andric }; 5910b57cec5SDimitry Andric } // namespace 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric bool ItaniumParamParser::parseItaniumParam(StringRef& param, 5940b57cec5SDimitry Andric AMDGPULibFunc::Param &res) { 5950b57cec5SDimitry Andric res.reset(); 5960b57cec5SDimitry Andric if (param.empty()) return false; 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric // parse pointer prefix 5990b57cec5SDimitry Andric if (eatTerm(param, 'P')) { 6000b57cec5SDimitry Andric if (eatTerm(param, 'K')) res.PtrKind |= AMDGPULibFunc::CONST; 6010b57cec5SDimitry Andric if (eatTerm(param, 'V')) res.PtrKind |= AMDGPULibFunc::VOLATILE; 6020b57cec5SDimitry Andric unsigned AS; 6030b57cec5SDimitry Andric if (!eatTerm(param, "U3AS")) { 6040b57cec5SDimitry Andric AS = 0; 6050b57cec5SDimitry Andric } else { 6060b57cec5SDimitry Andric AS = param.front() - '0'; 6070b57cec5SDimitry Andric drop_front(param, 1); 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric res.PtrKind |= AMDGPULibFuncBase::getEPtrKindFromAddrSpace(AS); 6100b57cec5SDimitry Andric } else { 6110b57cec5SDimitry Andric res.PtrKind = AMDGPULibFunc::BYVALUE; 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric // parse vector size 6150b57cec5SDimitry Andric if (eatTerm(param,"Dv")) { 6160b57cec5SDimitry Andric res.VectorSize = parseVecSize(param); 6170b57cec5SDimitry Andric if (res.VectorSize==1 || !eatTerm(param, '_')) return false; 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric // parse type 6210b57cec5SDimitry Andric char const TC = param.front(); 6225ffd83dbSDimitry Andric if (isDigit(TC)) { 6230b57cec5SDimitry Andric res.ArgType = StringSwitch<AMDGPULibFunc::EType> 6240b57cec5SDimitry Andric (eatLengthPrefixedName(param)) 6250b57cec5SDimitry Andric .Case("ocl_image1darray" , AMDGPULibFunc::IMG1DA) 6260b57cec5SDimitry Andric .Case("ocl_image1dbuffer", AMDGPULibFunc::IMG1DB) 6270b57cec5SDimitry Andric .Case("ocl_image2darray" , AMDGPULibFunc::IMG2DA) 6280b57cec5SDimitry Andric .Case("ocl_image1d" , AMDGPULibFunc::IMG1D) 6290b57cec5SDimitry Andric .Case("ocl_image2d" , AMDGPULibFunc::IMG2D) 6300b57cec5SDimitry Andric .Case("ocl_image3d" , AMDGPULibFunc::IMG3D) 6310b57cec5SDimitry Andric .Case("ocl_event" , AMDGPULibFunc::DUMMY) 6320b57cec5SDimitry Andric .Case("ocl_sampler" , AMDGPULibFunc::DUMMY) 6330b57cec5SDimitry Andric .Default(AMDGPULibFunc::DUMMY); 6340b57cec5SDimitry Andric } else { 6350b57cec5SDimitry Andric drop_front(param); 6360b57cec5SDimitry Andric switch (TC) { 6370b57cec5SDimitry Andric case 'h': res.ArgType = AMDGPULibFunc::U8; break; 6380b57cec5SDimitry Andric case 't': res.ArgType = AMDGPULibFunc::U16; break; 6390b57cec5SDimitry Andric case 'j': res.ArgType = AMDGPULibFunc::U32; break; 6400b57cec5SDimitry Andric case 'm': res.ArgType = AMDGPULibFunc::U64; break; 6410b57cec5SDimitry Andric case 'c': res.ArgType = AMDGPULibFunc::I8; break; 6420b57cec5SDimitry Andric case 's': res.ArgType = AMDGPULibFunc::I16; break; 6430b57cec5SDimitry Andric case 'i': res.ArgType = AMDGPULibFunc::I32; break; 6440b57cec5SDimitry Andric case 'l': res.ArgType = AMDGPULibFunc::I64; break; 6450b57cec5SDimitry Andric case 'f': res.ArgType = AMDGPULibFunc::F32; break; 6460b57cec5SDimitry Andric case 'd': res.ArgType = AMDGPULibFunc::F64; break; 6470b57cec5SDimitry Andric case 'D': if (!eatTerm(param, 'h')) return false; 6480b57cec5SDimitry Andric res.ArgType = AMDGPULibFunc::F16; break; 6490b57cec5SDimitry Andric case 'S': 6500b57cec5SDimitry Andric if (!eatTerm(param, '_')) { 6510b57cec5SDimitry Andric eatNumber(param); 6520b57cec5SDimitry Andric if (!eatTerm(param, '_')) return false; 6530b57cec5SDimitry Andric } 6540b57cec5SDimitry Andric res.VectorSize = Prev.VectorSize; 6550b57cec5SDimitry Andric res.ArgType = Prev.ArgType; 6560b57cec5SDimitry Andric break; 6570b57cec5SDimitry Andric default:; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric if (res.ArgType == 0) return false; 6610b57cec5SDimitry Andric Prev.VectorSize = res.VectorSize; 6620b57cec5SDimitry Andric Prev.ArgType = res.ArgType; 6630b57cec5SDimitry Andric return true; 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric bool AMDGPUMangledLibFunc::parseFuncName(StringRef &mangledName) { 6670b57cec5SDimitry Andric StringRef Name = eatLengthPrefixedName(mangledName); 6680b57cec5SDimitry Andric FKind = parseNamePrefix(Name); 6690b57cec5SDimitry Andric if (!parseUnmangledName(Name)) 6700b57cec5SDimitry Andric return false; 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric const ManglingRule& Rule = manglingRules[FuncId]; 6730b57cec5SDimitry Andric ItaniumParamParser Parser; 6740b57cec5SDimitry Andric for (int I=0; I < Rule.maxLeadIndex(); ++I) { 6750b57cec5SDimitry Andric Param P; 6760b57cec5SDimitry Andric if (!Parser.parseItaniumParam(mangledName, P)) 6770b57cec5SDimitry Andric return false; 6780b57cec5SDimitry Andric 6790b57cec5SDimitry Andric if ((I + 1) == Rule.Lead[0]) Leads[0] = P; 6800b57cec5SDimitry Andric if ((I + 1) == Rule.Lead[1]) Leads[1] = P; 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric return true; 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric bool AMDGPUUnmangledLibFunc::parseFuncName(StringRef &Name) { 6860b57cec5SDimitry Andric if (!UnmangledFuncInfo::lookup(Name, FuncId)) 6870b57cec5SDimitry Andric return false; 6880b57cec5SDimitry Andric setName(Name); 6890b57cec5SDimitry Andric return true; 6900b57cec5SDimitry Andric } 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric bool AMDGPULibFunc::parse(StringRef FuncName, AMDGPULibFunc &F) { 6930b57cec5SDimitry Andric if (FuncName.empty()) { 6940b57cec5SDimitry Andric F.Impl = std::unique_ptr<AMDGPULibFuncImpl>(); 6950b57cec5SDimitry Andric return false; 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric if (eatTerm(FuncName, "_Z")) 6998bcb0991SDimitry Andric F.Impl = std::make_unique<AMDGPUMangledLibFunc>(); 7000b57cec5SDimitry Andric else 7018bcb0991SDimitry Andric F.Impl = std::make_unique<AMDGPUUnmangledLibFunc>(); 7020b57cec5SDimitry Andric if (F.Impl->parseFuncName(FuncName)) 7030b57cec5SDimitry Andric return true; 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric F.Impl = std::unique_ptr<AMDGPULibFuncImpl>(); 7060b57cec5SDimitry Andric return false; 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric StringRef AMDGPUMangledLibFunc::getUnmangledName(StringRef mangledName) { 7100b57cec5SDimitry Andric StringRef S = mangledName; 7110b57cec5SDimitry Andric if (eatTerm(S, "_Z")) 7120b57cec5SDimitry Andric return eatLengthPrefixedName(S); 7130b57cec5SDimitry Andric return StringRef(); 7140b57cec5SDimitry Andric } 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 7170b57cec5SDimitry Andric // Mangling 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric template <typename Stream> 7200b57cec5SDimitry Andric void AMDGPUMangledLibFunc::writeName(Stream &OS) const { 7210b57cec5SDimitry Andric const char *Pfx = ""; 7220b57cec5SDimitry Andric switch (FKind) { 7230b57cec5SDimitry Andric case NATIVE: Pfx = "native_"; break; 7240b57cec5SDimitry Andric case HALF: Pfx = "half_"; break; 7250b57cec5SDimitry Andric default: break; 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric if (!Name.empty()) { 7280b57cec5SDimitry Andric OS << Pfx << Name; 7290b57cec5SDimitry Andric } else if (FuncId != EI_NONE) { 7300b57cec5SDimitry Andric OS << Pfx; 7310b57cec5SDimitry Andric const StringRef& S = manglingRules[FuncId].Name; 7320b57cec5SDimitry Andric OS.write(S.data(), S.size()); 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric std::string AMDGPUMangledLibFunc::mangle() const { return mangleNameItanium(); } 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 7390b57cec5SDimitry Andric // Itanium Mangling 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric static const char *getItaniumTypeName(AMDGPULibFunc::EType T) { 7420b57cec5SDimitry Andric switch (T) { 7430b57cec5SDimitry Andric case AMDGPULibFunc::U8: return "h"; 7440b57cec5SDimitry Andric case AMDGPULibFunc::U16: return "t"; 7450b57cec5SDimitry Andric case AMDGPULibFunc::U32: return "j"; 7460b57cec5SDimitry Andric case AMDGPULibFunc::U64: return "m"; 7470b57cec5SDimitry Andric case AMDGPULibFunc::I8: return "c"; 7480b57cec5SDimitry Andric case AMDGPULibFunc::I16: return "s"; 7490b57cec5SDimitry Andric case AMDGPULibFunc::I32: return "i"; 7500b57cec5SDimitry Andric case AMDGPULibFunc::I64: return "l"; 7510b57cec5SDimitry Andric case AMDGPULibFunc::F16: return "Dh"; 7520b57cec5SDimitry Andric case AMDGPULibFunc::F32: return "f"; 7530b57cec5SDimitry Andric case AMDGPULibFunc::F64: return "d"; 7540b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DA: return "16ocl_image1darray"; 7550b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DB: return "17ocl_image1dbuffer"; 7560b57cec5SDimitry Andric case AMDGPULibFunc::IMG2DA: return "16ocl_image2darray"; 7570b57cec5SDimitry Andric case AMDGPULibFunc::IMG1D: return "11ocl_image1d"; 7580b57cec5SDimitry Andric case AMDGPULibFunc::IMG2D: return "11ocl_image2d"; 7590b57cec5SDimitry Andric case AMDGPULibFunc::IMG3D: return "11ocl_image3d"; 7600b57cec5SDimitry Andric case AMDGPULibFunc::SAMPLER: return "11ocl_sampler"; 7610b57cec5SDimitry Andric case AMDGPULibFunc::EVENT: return "9ocl_event"; 762349cc55cSDimitry Andric default: 763349cc55cSDimitry Andric llvm_unreachable("Unhandled param type"); 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric return nullptr; 7660b57cec5SDimitry Andric } 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric namespace { 7690b57cec5SDimitry Andric // Itanium mangling ABI says: 7700b57cec5SDimitry Andric // "5.1.8. Compression 7710b57cec5SDimitry Andric // ... Each non-terminal in the grammar for which <substitution> appears on the 7720b57cec5SDimitry Andric // right-hand side is both a source of future substitutions and a candidate 7730b57cec5SDimitry Andric // for being substituted. There are two exceptions that appear to be 7740b57cec5SDimitry Andric // substitution candidates from the grammar, but are explicitly excluded: 7750b57cec5SDimitry Andric // 1. <builtin-type> other than vendor extended types ..." 7760b57cec5SDimitry Andric 777349cc55cSDimitry Andric // For the purpose of functions the following productions make sense for the 7780b57cec5SDimitry Andric // substitution: 7790b57cec5SDimitry Andric // <type> ::= <builtin-type> 7800b57cec5SDimitry Andric // ::= <class-enum-type> 7810b57cec5SDimitry Andric // ::= <array-type> 7820b57cec5SDimitry Andric // ::=<CV-qualifiers> <type> 7830b57cec5SDimitry Andric // ::= P <type> # pointer-to 7840b57cec5SDimitry Andric // ::= <substitution> 7850b57cec5SDimitry Andric // 7860b57cec5SDimitry Andric // Note that while types like images, samplers and events are by the ABI encoded 7870b57cec5SDimitry Andric // using <class-enum-type> production rule they're not used for substitution 7880b57cec5SDimitry Andric // because clang consider them as builtin types. 7890b57cec5SDimitry Andric // 790349cc55cSDimitry Andric // DvNN_ type is GCC extension for vectors and is a subject for the 791349cc55cSDimitry Andric // substitution. 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric class ItaniumMangler { 794349cc55cSDimitry Andric SmallVector<AMDGPULibFunc::Param, 10> Str; // list of accumulated substitutions 7950b57cec5SDimitry Andric bool UseAddrSpace; 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric int findSubst(const AMDGPULibFunc::Param& P) const { 7980b57cec5SDimitry Andric for(unsigned I = 0; I < Str.size(); ++I) { 7990b57cec5SDimitry Andric const AMDGPULibFunc::Param& T = Str[I]; 8000b57cec5SDimitry Andric if (P.PtrKind == T.PtrKind && 8010b57cec5SDimitry Andric P.VectorSize == T.VectorSize && 8020b57cec5SDimitry Andric P.ArgType == T.ArgType) { 8030b57cec5SDimitry Andric return I; 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric } 8060b57cec5SDimitry Andric return -1; 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric template <typename Stream> 8100b57cec5SDimitry Andric bool trySubst(Stream& os, const AMDGPULibFunc::Param& p) { 8110b57cec5SDimitry Andric int const subst = findSubst(p); 8120b57cec5SDimitry Andric if (subst < 0) return false; 8130b57cec5SDimitry Andric // Substitutions are mangled as S(XX)?_ where XX is a hexadecimal number 8140b57cec5SDimitry Andric // 0 1 2 8150b57cec5SDimitry Andric // S_ S0_ S1_ 8160b57cec5SDimitry Andric if (subst == 0) os << "S_"; 8170b57cec5SDimitry Andric else os << 'S' << (subst-1) << '_'; 8180b57cec5SDimitry Andric return true; 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric public: 8220b57cec5SDimitry Andric ItaniumMangler(bool useAddrSpace) 8230b57cec5SDimitry Andric : UseAddrSpace(useAddrSpace) {} 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric template <typename Stream> 8260b57cec5SDimitry Andric void operator()(Stream& os, AMDGPULibFunc::Param p) { 8270b57cec5SDimitry Andric 8280b57cec5SDimitry Andric // Itanium mangling ABI 5.1.8. Compression: 8290b57cec5SDimitry Andric // Logically, the substitutable components of a mangled name are considered 8300b57cec5SDimitry Andric // left-to-right, components before the composite structure of which they 8310b57cec5SDimitry Andric // are a part. If a component has been encountered before, it is substituted 8320b57cec5SDimitry Andric // as described below. This decision is independent of whether its components 8330b57cec5SDimitry Andric // have been substituted, so an implementation may optimize by considering 8340b57cec5SDimitry Andric // large structures for substitution before their components. If a component 8350b57cec5SDimitry Andric // has not been encountered before, its mangling is identified, and it is 8360b57cec5SDimitry Andric // added to a dictionary of substitution candidates. No entity is added to 8370b57cec5SDimitry Andric // the dictionary twice. 8380b57cec5SDimitry Andric AMDGPULibFunc::Param Ptr; 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric if (p.PtrKind) { 8410b57cec5SDimitry Andric if (trySubst(os, p)) return; 8420b57cec5SDimitry Andric os << 'P'; 8430b57cec5SDimitry Andric if (p.PtrKind & AMDGPULibFunc::CONST) os << 'K'; 8440b57cec5SDimitry Andric if (p.PtrKind & AMDGPULibFunc::VOLATILE) os << 'V'; 8450b57cec5SDimitry Andric unsigned AS = UseAddrSpace 8460b57cec5SDimitry Andric ? AMDGPULibFuncBase::getAddrSpaceFromEPtrKind(p.PtrKind) 8470b57cec5SDimitry Andric : 0; 848fe6060f1SDimitry Andric if (EnableOCLManglingMismatchWA || AS != 0) 849fe6060f1SDimitry Andric os << "U3AS" << AS; 8500b57cec5SDimitry Andric Ptr = p; 8510b57cec5SDimitry Andric p.PtrKind = 0; 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric if (p.VectorSize > 1) { 8550b57cec5SDimitry Andric if (trySubst(os, p)) goto exit; 8560b57cec5SDimitry Andric Str.push_back(p); 8570b57cec5SDimitry Andric os << "Dv" << static_cast<unsigned>(p.VectorSize) << '_'; 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric os << getItaniumTypeName((AMDGPULibFunc::EType)p.ArgType); 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric exit: 8630b57cec5SDimitry Andric if (Ptr.ArgType) Str.push_back(Ptr); 8640b57cec5SDimitry Andric } 8650b57cec5SDimitry Andric }; 8660b57cec5SDimitry Andric } // namespace 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric std::string AMDGPUMangledLibFunc::mangleNameItanium() const { 8690b57cec5SDimitry Andric SmallString<128> Buf; 8700b57cec5SDimitry Andric raw_svector_ostream S(Buf); 8710b57cec5SDimitry Andric SmallString<128> NameBuf; 8720b57cec5SDimitry Andric raw_svector_ostream Name(NameBuf); 8730b57cec5SDimitry Andric writeName(Name); 8740b57cec5SDimitry Andric const StringRef& NameStr = Name.str(); 8750b57cec5SDimitry Andric S << "_Z" << static_cast<int>(NameStr.size()) << NameStr; 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric ItaniumMangler Mangler(true); 8780b57cec5SDimitry Andric ParamIterator I(Leads, manglingRules[FuncId]); 8790b57cec5SDimitry Andric Param P; 8800b57cec5SDimitry Andric while ((P = I.getNextParam()).ArgType != 0) 8810b57cec5SDimitry Andric Mangler(S, P); 8825ffd83dbSDimitry Andric return std::string(S.str()); 8830b57cec5SDimitry Andric } 8840b57cec5SDimitry Andric 8850b57cec5SDimitry Andric /////////////////////////////////////////////////////////////////////////////// 8860b57cec5SDimitry Andric // Misc 8870b57cec5SDimitry Andric 8885f757f3fSDimitry Andric AMDGPULibFuncBase::Param AMDGPULibFuncBase::Param::getFromTy(Type *Ty, 8895f757f3fSDimitry Andric bool Signed) { 8905f757f3fSDimitry Andric Param P; 8915f757f3fSDimitry Andric if (FixedVectorType *VT = dyn_cast<FixedVectorType>(Ty)) { 8925f757f3fSDimitry Andric P.VectorSize = VT->getNumElements(); 8935f757f3fSDimitry Andric Ty = VT->getElementType(); 8945f757f3fSDimitry Andric } 8955f757f3fSDimitry Andric 8965f757f3fSDimitry Andric switch (Ty->getTypeID()) { 8975f757f3fSDimitry Andric case Type::FloatTyID: 8985f757f3fSDimitry Andric P.ArgType = AMDGPULibFunc::F32; 8995f757f3fSDimitry Andric break; 9005f757f3fSDimitry Andric case Type::DoubleTyID: 9015f757f3fSDimitry Andric P.ArgType = AMDGPULibFunc::F64; 9025f757f3fSDimitry Andric break; 9035f757f3fSDimitry Andric case Type::HalfTyID: 9045f757f3fSDimitry Andric P.ArgType = AMDGPULibFunc::F16; 9055f757f3fSDimitry Andric break; 9065f757f3fSDimitry Andric case Type::IntegerTyID: 9075f757f3fSDimitry Andric switch (cast<IntegerType>(Ty)->getBitWidth()) { 9085f757f3fSDimitry Andric case 8: 9095f757f3fSDimitry Andric P.ArgType = Signed ? AMDGPULibFunc::I8 : AMDGPULibFunc::U8; 9105f757f3fSDimitry Andric break; 9115f757f3fSDimitry Andric case 16: 9125f757f3fSDimitry Andric P.ArgType = Signed ? AMDGPULibFunc::I16 : AMDGPULibFunc::U16; 9135f757f3fSDimitry Andric break; 9145f757f3fSDimitry Andric case 32: 9155f757f3fSDimitry Andric P.ArgType = Signed ? AMDGPULibFunc::I32 : AMDGPULibFunc::U32; 9165f757f3fSDimitry Andric break; 9175f757f3fSDimitry Andric case 64: 9185f757f3fSDimitry Andric P.ArgType = Signed ? AMDGPULibFunc::I64 : AMDGPULibFunc::U64; 9195f757f3fSDimitry Andric break; 9205f757f3fSDimitry Andric default: 9215f757f3fSDimitry Andric llvm_unreachable("unhandled libcall argument type"); 9225f757f3fSDimitry Andric } 9235f757f3fSDimitry Andric 9245f757f3fSDimitry Andric break; 9255f757f3fSDimitry Andric default: 9265f757f3fSDimitry Andric llvm_unreachable("unhandled libcall argument type"); 9275f757f3fSDimitry Andric } 9285f757f3fSDimitry Andric 9295f757f3fSDimitry Andric return P; 9305f757f3fSDimitry Andric } 9315f757f3fSDimitry Andric 9320b57cec5SDimitry Andric static Type* getIntrinsicParamType( 9330b57cec5SDimitry Andric LLVMContext& C, 9340b57cec5SDimitry Andric const AMDGPULibFunc::Param& P, 9350b57cec5SDimitry Andric bool useAddrSpace) { 9360b57cec5SDimitry Andric Type* T = nullptr; 9370b57cec5SDimitry Andric switch (P.ArgType) { 9380b57cec5SDimitry Andric case AMDGPULibFunc::U8: 9390b57cec5SDimitry Andric case AMDGPULibFunc::I8: T = Type::getInt8Ty(C); break; 9400b57cec5SDimitry Andric case AMDGPULibFunc::U16: 9410b57cec5SDimitry Andric case AMDGPULibFunc::I16: T = Type::getInt16Ty(C); break; 9420b57cec5SDimitry Andric case AMDGPULibFunc::U32: 9430b57cec5SDimitry Andric case AMDGPULibFunc::I32: T = Type::getInt32Ty(C); break; 9440b57cec5SDimitry Andric case AMDGPULibFunc::U64: 9450b57cec5SDimitry Andric case AMDGPULibFunc::I64: T = Type::getInt64Ty(C); break; 9460b57cec5SDimitry Andric case AMDGPULibFunc::F16: T = Type::getHalfTy(C); break; 9470b57cec5SDimitry Andric case AMDGPULibFunc::F32: T = Type::getFloatTy(C); break; 9480b57cec5SDimitry Andric case AMDGPULibFunc::F64: T = Type::getDoubleTy(C); break; 9490b57cec5SDimitry Andric 9500b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DA: 9510b57cec5SDimitry Andric case AMDGPULibFunc::IMG1DB: 9520b57cec5SDimitry Andric case AMDGPULibFunc::IMG2DA: 9530b57cec5SDimitry Andric case AMDGPULibFunc::IMG1D: 9540b57cec5SDimitry Andric case AMDGPULibFunc::IMG2D: 9550b57cec5SDimitry Andric case AMDGPULibFunc::IMG3D: 9560b57cec5SDimitry Andric T = StructType::create(C,"ocl_image")->getPointerTo(); break; 9570b57cec5SDimitry Andric case AMDGPULibFunc::SAMPLER: 9580b57cec5SDimitry Andric T = StructType::create(C,"ocl_sampler")->getPointerTo(); break; 9590b57cec5SDimitry Andric case AMDGPULibFunc::EVENT: 9600b57cec5SDimitry Andric T = StructType::create(C,"ocl_event")->getPointerTo(); break; 9610b57cec5SDimitry Andric default: 962349cc55cSDimitry Andric llvm_unreachable("Unhandled param type"); 9630b57cec5SDimitry Andric return nullptr; 9640b57cec5SDimitry Andric } 9650b57cec5SDimitry Andric if (P.VectorSize > 1) 9665ffd83dbSDimitry Andric T = FixedVectorType::get(T, P.VectorSize); 9670b57cec5SDimitry Andric if (P.PtrKind != AMDGPULibFunc::BYVALUE) 9680b57cec5SDimitry Andric T = useAddrSpace ? T->getPointerTo((P.PtrKind & AMDGPULibFunc::ADDR_SPACE) 9690b57cec5SDimitry Andric - 1) 9700b57cec5SDimitry Andric : T->getPointerTo(); 9710b57cec5SDimitry Andric return T; 9720b57cec5SDimitry Andric } 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric FunctionType *AMDGPUMangledLibFunc::getFunctionType(Module &M) const { 9750b57cec5SDimitry Andric LLVMContext& C = M.getContext(); 9760b57cec5SDimitry Andric std::vector<Type*> Args; 9770b57cec5SDimitry Andric ParamIterator I(Leads, manglingRules[FuncId]); 9780b57cec5SDimitry Andric Param P; 9790b57cec5SDimitry Andric while ((P=I.getNextParam()).ArgType != 0) 9800b57cec5SDimitry Andric Args.push_back(getIntrinsicParamType(C, P, true)); 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric return FunctionType::get( 9830b57cec5SDimitry Andric getIntrinsicParamType(C, getRetType(FuncId, Leads), true), 9840b57cec5SDimitry Andric Args, false); 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric unsigned AMDGPUMangledLibFunc::getNumArgs() const { 9880b57cec5SDimitry Andric return manglingRules[FuncId].getNumArgs(); 9890b57cec5SDimitry Andric } 9900b57cec5SDimitry Andric 9910b57cec5SDimitry Andric unsigned AMDGPUUnmangledLibFunc::getNumArgs() const { 9920b57cec5SDimitry Andric return UnmangledFuncInfo::getNumArgs(FuncId); 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andric std::string AMDGPUMangledLibFunc::getName() const { 9960b57cec5SDimitry Andric SmallString<128> Buf; 9970b57cec5SDimitry Andric raw_svector_ostream OS(Buf); 9980b57cec5SDimitry Andric writeName(OS); 9995ffd83dbSDimitry Andric return std::string(OS.str()); 10000b57cec5SDimitry Andric } 10010b57cec5SDimitry Andric 10025f757f3fSDimitry Andric bool AMDGPULibFunc::isCompatibleSignature(const FunctionType *FuncTy) const { 10035f757f3fSDimitry Andric // TODO: Validate types make sense 10045f757f3fSDimitry Andric return !FuncTy->isVarArg() && FuncTy->getNumParams() == getNumArgs(); 10055f757f3fSDimitry Andric } 10065f757f3fSDimitry Andric 10070b57cec5SDimitry Andric Function *AMDGPULibFunc::getFunction(Module *M, const AMDGPULibFunc &fInfo) { 10080b57cec5SDimitry Andric std::string FuncName = fInfo.mangle(); 10090b57cec5SDimitry Andric Function *F = dyn_cast_or_null<Function>( 10100b57cec5SDimitry Andric M->getValueSymbolTable().lookup(FuncName)); 10115f757f3fSDimitry Andric if (!F || F->isDeclaration()) 10120b57cec5SDimitry Andric return nullptr; 10135f757f3fSDimitry Andric 10145f757f3fSDimitry Andric if (F->hasFnAttribute(Attribute::NoBuiltin)) 10155f757f3fSDimitry Andric return nullptr; 10165f757f3fSDimitry Andric 10175f757f3fSDimitry Andric if (!fInfo.isCompatibleSignature(F->getFunctionType())) 10185f757f3fSDimitry Andric return nullptr; 10195f757f3fSDimitry Andric 10205f757f3fSDimitry Andric return F; 10210b57cec5SDimitry Andric } 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric FunctionCallee AMDGPULibFunc::getOrInsertFunction(Module *M, 10240b57cec5SDimitry Andric const AMDGPULibFunc &fInfo) { 10250b57cec5SDimitry Andric std::string const FuncName = fInfo.mangle(); 10260b57cec5SDimitry Andric Function *F = dyn_cast_or_null<Function>( 10270b57cec5SDimitry Andric M->getValueSymbolTable().lookup(FuncName)); 10280b57cec5SDimitry Andric 10295f757f3fSDimitry Andric if (F) { 10305f757f3fSDimitry Andric if (F->hasFnAttribute(Attribute::NoBuiltin)) 10315f757f3fSDimitry Andric return nullptr; 10325f757f3fSDimitry Andric if (!F->isDeclaration() && 10335f757f3fSDimitry Andric fInfo.isCompatibleSignature(F->getFunctionType())) 10340b57cec5SDimitry Andric return F; 10350b57cec5SDimitry Andric } 10360b57cec5SDimitry Andric 10370b57cec5SDimitry Andric FunctionType *FuncTy = fInfo.getFunctionType(*M); 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric bool hasPtr = false; 10400b57cec5SDimitry Andric for (FunctionType::param_iterator 10410b57cec5SDimitry Andric PI = FuncTy->param_begin(), 10420b57cec5SDimitry Andric PE = FuncTy->param_end(); 10430b57cec5SDimitry Andric PI != PE; ++PI) { 10440b57cec5SDimitry Andric const Type* argTy = static_cast<const Type*>(*PI); 10450b57cec5SDimitry Andric if (argTy->isPointerTy()) { 10460b57cec5SDimitry Andric hasPtr = true; 10470b57cec5SDimitry Andric break; 10480b57cec5SDimitry Andric } 10490b57cec5SDimitry Andric } 10500b57cec5SDimitry Andric 10510b57cec5SDimitry Andric FunctionCallee C; 10520b57cec5SDimitry Andric if (hasPtr) { 10530b57cec5SDimitry Andric // Do not set extra attributes for functions with pointer arguments. 10540b57cec5SDimitry Andric C = M->getOrInsertFunction(FuncName, FuncTy); 10550b57cec5SDimitry Andric } else { 10560b57cec5SDimitry Andric AttributeList Attr; 10570b57cec5SDimitry Andric LLVMContext &Ctx = M->getContext(); 1058bdd1243dSDimitry Andric Attr = Attr.addFnAttribute( 1059bdd1243dSDimitry Andric Ctx, Attribute::getWithMemoryEffects(Ctx, MemoryEffects::readOnly())); 1060349cc55cSDimitry Andric Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind); 10610b57cec5SDimitry Andric C = M->getOrInsertFunction(FuncName, FuncTy, Attr); 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric return C; 10650b57cec5SDimitry Andric } 10660b57cec5SDimitry Andric 10670b57cec5SDimitry Andric StringMap<unsigned> UnmangledFuncInfo::buildNameMap() { 10680b57cec5SDimitry Andric StringMap<unsigned> Map; 10690b57cec5SDimitry Andric for (unsigned I = 0; I != TableSize; ++I) 10700b57cec5SDimitry Andric Map[Table[I].Name] = I; 10710b57cec5SDimitry Andric return Map; 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric bool UnmangledFuncInfo::lookup(StringRef Name, ID &Id) { 10750b57cec5SDimitry Andric static const StringMap<unsigned> Map = buildNameMap(); 10760b57cec5SDimitry Andric auto Loc = Map.find(Name); 10770b57cec5SDimitry Andric if (Loc != Map.end()) { 10780b57cec5SDimitry Andric Id = toFuncId(Loc->second); 10790b57cec5SDimitry Andric return true; 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric Id = AMDGPULibFunc::EI_NONE; 10820b57cec5SDimitry Andric return false; 10830b57cec5SDimitry Andric } 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric AMDGPULibFunc::AMDGPULibFunc(const AMDGPULibFunc &F) { 10860b57cec5SDimitry Andric if (auto *MF = dyn_cast<AMDGPUMangledLibFunc>(F.Impl.get())) 1087*0fca6ea1SDimitry Andric Impl = std::make_unique<AMDGPUMangledLibFunc>(*MF); 10880b57cec5SDimitry Andric else if (auto *UMF = dyn_cast<AMDGPUUnmangledLibFunc>(F.Impl.get())) 1089*0fca6ea1SDimitry Andric Impl = std::make_unique<AMDGPUUnmangledLibFunc>(*UMF); 10900b57cec5SDimitry Andric else 10910b57cec5SDimitry Andric Impl = std::unique_ptr<AMDGPULibFuncImpl>(); 10920b57cec5SDimitry Andric } 10930b57cec5SDimitry Andric 10940b57cec5SDimitry Andric AMDGPULibFunc &AMDGPULibFunc::operator=(const AMDGPULibFunc &F) { 10950b57cec5SDimitry Andric if (this == &F) 10960b57cec5SDimitry Andric return *this; 10970b57cec5SDimitry Andric new (this) AMDGPULibFunc(F); 10980b57cec5SDimitry Andric return *this; 10990b57cec5SDimitry Andric } 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric AMDGPULibFunc::AMDGPULibFunc(EFuncId Id, const AMDGPULibFunc &CopyFrom) { 11020b57cec5SDimitry Andric assert(AMDGPULibFuncBase::isMangled(Id) && CopyFrom.isMangled() && 11030b57cec5SDimitry Andric "not supported"); 1104*0fca6ea1SDimitry Andric Impl = std::make_unique<AMDGPUMangledLibFunc>( 1105*0fca6ea1SDimitry Andric Id, *cast<AMDGPUMangledLibFunc>(CopyFrom.Impl.get())); 11060b57cec5SDimitry Andric } 11070b57cec5SDimitry Andric 11085f757f3fSDimitry Andric AMDGPULibFunc::AMDGPULibFunc(EFuncId Id, FunctionType *FT, bool SignedInts) { 1109*0fca6ea1SDimitry Andric Impl = std::make_unique<AMDGPUMangledLibFunc>(Id, FT, SignedInts); 11105f757f3fSDimitry Andric } 11115f757f3fSDimitry Andric 11120b57cec5SDimitry Andric AMDGPULibFunc::AMDGPULibFunc(StringRef Name, FunctionType *FT) { 1113*0fca6ea1SDimitry Andric Impl = std::make_unique<AMDGPUUnmangledLibFunc>(Name, FT); 11140b57cec5SDimitry Andric } 11150b57cec5SDimitry Andric 1116*0fca6ea1SDimitry Andric void AMDGPULibFunc::initMangled() { 1117*0fca6ea1SDimitry Andric Impl = std::make_unique<AMDGPUMangledLibFunc>(); 1118*0fca6ea1SDimitry Andric } 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() { 11210b57cec5SDimitry Andric if (!Impl) 11220b57cec5SDimitry Andric initMangled(); 11230b57cec5SDimitry Andric return cast<AMDGPUMangledLibFunc>(Impl.get())->Leads; 11240b57cec5SDimitry Andric } 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric const AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() const { 11270b57cec5SDimitry Andric return cast<const AMDGPUMangledLibFunc>(Impl.get())->Leads; 11280b57cec5SDimitry Andric } 1129