17f37794eSStanislav Mekhanoshin //===-- AMDGPULibFunc.cpp -------------------------------------------------===//
27f37794eSStanislav Mekhanoshin //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67f37794eSStanislav Mekhanoshin //
77f37794eSStanislav Mekhanoshin //===----------------------------------------------------------------------===//
87f37794eSStanislav Mekhanoshin //
97f37794eSStanislav Mekhanoshin // This file contains utility functions to work with Itanium mangled names
107f37794eSStanislav Mekhanoshin //
117f37794eSStanislav Mekhanoshin //===----------------------------------------------------------------------===//
127f37794eSStanislav Mekhanoshin
137f37794eSStanislav Mekhanoshin #include "AMDGPULibFunc.h"
14a6502560SSimon Pilgrim #include "AMDGPU.h"
158105935dSSander de Smalen #include "llvm/ADT/StringExtras.h"
166a87e9b0Sdfukalov #include "llvm/ADT/StringMap.h"
17a6502560SSimon Pilgrim #include "llvm/ADT/StringSwitch.h"
187f37794eSStanislav Mekhanoshin #include "llvm/IR/DerivedTypes.h"
197f37794eSStanislav Mekhanoshin #include "llvm/IR/Function.h"
207f37794eSStanislav Mekhanoshin #include "llvm/IR/Module.h"
217f37794eSStanislav Mekhanoshin #include "llvm/IR/ValueSymbolTable.h"
2227332968SMichael Liao #include "llvm/Support/CommandLine.h"
23a6502560SSimon Pilgrim #include "llvm/Support/raw_ostream.h"
247f37794eSStanislav Mekhanoshin
257f37794eSStanislav Mekhanoshin using namespace llvm;
267f37794eSStanislav Mekhanoshin
2727332968SMichael Liao static cl::opt<bool> EnableOCLManglingMismatchWA(
2827332968SMichael Liao "amdgpu-enable-ocl-mangling-mismatch-workaround", cl::init(true),
2927332968SMichael Liao cl::ReallyHidden,
3027332968SMichael Liao cl::desc("Enable the workaround for OCL name mangling mismatch."));
3127332968SMichael Liao
327f37794eSStanislav Mekhanoshin namespace {
337f37794eSStanislav Mekhanoshin
347f37794eSStanislav Mekhanoshin enum EManglingParam {
357f37794eSStanislav Mekhanoshin E_NONE,
367f37794eSStanislav Mekhanoshin EX_EVENT,
377f37794eSStanislav Mekhanoshin EX_FLOAT4,
387f37794eSStanislav Mekhanoshin EX_INTV4,
397f37794eSStanislav Mekhanoshin EX_RESERVEDID,
407f37794eSStanislav Mekhanoshin EX_SAMPLER,
417f37794eSStanislav Mekhanoshin EX_SIZET,
427f37794eSStanislav Mekhanoshin EX_UINT,
437f37794eSStanislav Mekhanoshin EX_UINTV4,
447f37794eSStanislav Mekhanoshin E_ANY,
457f37794eSStanislav Mekhanoshin E_CONSTPTR_ANY,
467f37794eSStanislav Mekhanoshin E_CONSTPTR_SWAPGL,
477f37794eSStanislav Mekhanoshin E_COPY,
487f37794eSStanislav Mekhanoshin E_IMAGECOORDS,
497f37794eSStanislav Mekhanoshin E_POINTEE,
507f37794eSStanislav Mekhanoshin E_SETBASE_I32,
517f37794eSStanislav Mekhanoshin E_SETBASE_U32,
527f37794eSStanislav Mekhanoshin E_MAKEBASE_UNS,
537f37794eSStanislav Mekhanoshin E_V16_OF_POINTEE,
547f37794eSStanislav Mekhanoshin E_V2_OF_POINTEE,
557f37794eSStanislav Mekhanoshin E_V3_OF_POINTEE,
567f37794eSStanislav Mekhanoshin E_V4_OF_POINTEE,
577f37794eSStanislav Mekhanoshin E_V8_OF_POINTEE,
587f37794eSStanislav Mekhanoshin E_VLTLPTR_ANY,
597f37794eSStanislav Mekhanoshin };
607f37794eSStanislav Mekhanoshin
617f37794eSStanislav Mekhanoshin struct ManglingRule {
6255e8c91dSBenjamin Kramer const char *Name;
637f37794eSStanislav Mekhanoshin unsigned char Lead[2];
647f37794eSStanislav Mekhanoshin unsigned char Param[5];
657f37794eSStanislav Mekhanoshin
maxLeadIndex__anon04d7f3640111::ManglingRule667f37794eSStanislav Mekhanoshin int maxLeadIndex() const { return (std::max)(Lead[0], Lead[1]); }
getNumLeads__anon04d7f3640111::ManglingRule677f37794eSStanislav Mekhanoshin int getNumLeads() const { return (Lead[0] ? 1 : 0) + (Lead[1] ? 1 : 0); }
687f37794eSStanislav Mekhanoshin
697f37794eSStanislav Mekhanoshin unsigned getNumArgs() const;
7085e2cdacSReid Kleckner
7185e2cdacSReid Kleckner static StringMap<int> buildManglingRulesMap();
727f37794eSStanislav Mekhanoshin };
737f37794eSStanislav Mekhanoshin
74fc5121a7SYaxun Liu // Information about library functions with unmangled names.
75fc5121a7SYaxun Liu class UnmangledFuncInfo {
7655e8c91dSBenjamin Kramer const char *Name;
77fc5121a7SYaxun Liu unsigned NumArgs;
78fc5121a7SYaxun Liu
79fc5121a7SYaxun Liu // Table for all lib functions with unmangled names.
80fc5121a7SYaxun Liu static const UnmangledFuncInfo Table[];
81fc5121a7SYaxun Liu
82fc5121a7SYaxun Liu // Number of entries in Table.
83fc5121a7SYaxun Liu static const unsigned TableSize;
84fc5121a7SYaxun Liu
8585e2cdacSReid Kleckner static StringMap<unsigned> buildNameMap();
86fc5121a7SYaxun Liu
87fc5121a7SYaxun Liu public:
88fc5121a7SYaxun Liu using ID = AMDGPULibFunc::EFuncId;
UnmangledFuncInfo(const char * _Name,unsigned _NumArgs)8955e8c91dSBenjamin Kramer constexpr UnmangledFuncInfo(const char *_Name, unsigned _NumArgs)
90fc5121a7SYaxun Liu : Name(_Name), NumArgs(_NumArgs) {}
91fc5121a7SYaxun Liu // Get index to Table by function name.
92fc5121a7SYaxun Liu static bool lookup(StringRef Name, ID &Id);
toIndex(ID Id)93fc5121a7SYaxun Liu static unsigned toIndex(ID Id) {
94fc5121a7SYaxun Liu assert(static_cast<unsigned>(Id) >
95fc5121a7SYaxun Liu static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED) &&
96fc5121a7SYaxun Liu "Invalid unmangled library function");
97fc5121a7SYaxun Liu return static_cast<unsigned>(Id) - 1 -
98fc5121a7SYaxun Liu static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED);
99fc5121a7SYaxun Liu }
toFuncId(unsigned Index)100fc5121a7SYaxun Liu static ID toFuncId(unsigned Index) {
10185e2cdacSReid Kleckner assert(Index < TableSize &&
10285e2cdacSReid Kleckner "Invalid unmangled library function");
103fc5121a7SYaxun Liu return static_cast<ID>(
104fc5121a7SYaxun Liu Index + 1 + static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED));
105fc5121a7SYaxun Liu }
getNumArgs(ID Id)106fc5121a7SYaxun Liu static unsigned getNumArgs(ID Id) { return Table[toIndex(Id)].NumArgs; }
getName(ID Id)107fc5121a7SYaxun Liu static StringRef getName(ID Id) { return Table[toIndex(Id)].Name; }
108fc5121a7SYaxun Liu };
109fc5121a7SYaxun Liu
getNumArgs() const1107f37794eSStanislav Mekhanoshin unsigned ManglingRule::getNumArgs() const {
1117f37794eSStanislav Mekhanoshin unsigned I=0;
1127f37794eSStanislav Mekhanoshin while (I < (sizeof Param/sizeof Param[0]) && Param[I]) ++I;
1137f37794eSStanislav Mekhanoshin return I;
1147f37794eSStanislav Mekhanoshin }
1157f37794eSStanislav Mekhanoshin
1167f37794eSStanislav Mekhanoshin // This table describes function formal argument type rules. The order of rules
1177f37794eSStanislav Mekhanoshin // corresponds to the EFuncId enum at AMDGPULibFunc.h
1187f37794eSStanislav Mekhanoshin //
1197f37794eSStanislav Mekhanoshin // "<func name>", { <leads> }, { <param rules> }
1207f37794eSStanislav Mekhanoshin // where:
1217f37794eSStanislav Mekhanoshin // <leads> - list of integers that are one-based indexes of formal argument
1227f37794eSStanislav Mekhanoshin // used to mangle a function name. Other argument types are derived from types
1237f37794eSStanislav Mekhanoshin // of these 'leads'. The order of integers in this list correspond to the
1247f37794eSStanislav Mekhanoshin // order in which these arguments are mangled in the EDG mangling scheme. The
1257f37794eSStanislav Mekhanoshin // same order should be preserved for arguments in the AMDGPULibFunc structure
1267f37794eSStanislav Mekhanoshin // when it is used for mangling. For example:
1277f37794eSStanislav Mekhanoshin // { "vstorea_half", {3,1}, {E_ANY,EX_SIZET,E_ANY}},
1287f37794eSStanislav Mekhanoshin // will be mangled in EDG scheme as vstorea_half_<3dparam>_<1stparam>
1297f37794eSStanislav Mekhanoshin // When mangling from code use:
1307f37794eSStanislav Mekhanoshin // AMDGPULibFunc insc;
1317f37794eSStanislav Mekhanoshin // insc.param[0] = ... // describe 3rd parameter
1327f37794eSStanislav Mekhanoshin // insc.param[1] = ... // describe 1rd parameter
1337f37794eSStanislav Mekhanoshin //
1347f37794eSStanislav Mekhanoshin // <param rules> - list of rules used to derive all of the function formal
1357f37794eSStanislav Mekhanoshin // argument types. EX_ prefixed are simple types, other derived from the
1367f37794eSStanislav Mekhanoshin // latest 'lead' argument type in the order of encoding from first to last.
1377f37794eSStanislav Mekhanoshin // E_ANY - use prev lead type, E_CONSTPTR_ANY - make const pointer out of
1387f37794eSStanislav Mekhanoshin // prev lead type, etc. see ParamIterator::getNextParam() for details.
1397f37794eSStanislav Mekhanoshin
14070434770SBenjamin Kramer static constexpr ManglingRule manglingRules[] = {
14170434770SBenjamin Kramer { "", {0}, {0} },
1427f37794eSStanislav Mekhanoshin { "abs" , {1}, {E_ANY}},
1437f37794eSStanislav Mekhanoshin { "abs_diff" , {1}, {E_ANY,E_COPY}},
1447f37794eSStanislav Mekhanoshin { "acos" , {1}, {E_ANY}},
1457f37794eSStanislav Mekhanoshin { "acosh" , {1}, {E_ANY}},
1467f37794eSStanislav Mekhanoshin { "acospi" , {1}, {E_ANY}},
1477f37794eSStanislav Mekhanoshin { "add_sat" , {1}, {E_ANY,E_COPY}},
1487f37794eSStanislav Mekhanoshin { "all" , {1}, {E_ANY}},
1497f37794eSStanislav Mekhanoshin { "any" , {1}, {E_ANY}},
1507f37794eSStanislav Mekhanoshin { "asin" , {1}, {E_ANY}},
1517f37794eSStanislav Mekhanoshin { "asinh" , {1}, {E_ANY}},
1527f37794eSStanislav Mekhanoshin { "asinpi" , {1}, {E_ANY}},
1537f37794eSStanislav Mekhanoshin { "async_work_group_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_EVENT}},
1547f37794eSStanislav Mekhanoshin { "async_work_group_strided_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_SIZET,EX_EVENT}},
1557f37794eSStanislav Mekhanoshin { "atan" , {1}, {E_ANY}},
1567f37794eSStanislav Mekhanoshin { "atan2" , {1}, {E_ANY,E_COPY}},
1577f37794eSStanislav Mekhanoshin { "atan2pi" , {1}, {E_ANY,E_COPY}},
1587f37794eSStanislav Mekhanoshin { "atanh" , {1}, {E_ANY}},
1597f37794eSStanislav Mekhanoshin { "atanpi" , {1}, {E_ANY}},
1607f37794eSStanislav Mekhanoshin { "atomic_add" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1617f37794eSStanislav Mekhanoshin { "atomic_and" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1627f37794eSStanislav Mekhanoshin { "atomic_cmpxchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE,E_POINTEE}},
1637f37794eSStanislav Mekhanoshin { "atomic_dec" , {1}, {E_VLTLPTR_ANY}},
1647f37794eSStanislav Mekhanoshin { "atomic_inc" , {1}, {E_VLTLPTR_ANY}},
1657f37794eSStanislav Mekhanoshin { "atomic_max" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1667f37794eSStanislav Mekhanoshin { "atomic_min" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1677f37794eSStanislav Mekhanoshin { "atomic_or" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1687f37794eSStanislav Mekhanoshin { "atomic_sub" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1697f37794eSStanislav Mekhanoshin { "atomic_xchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1707f37794eSStanislav Mekhanoshin { "atomic_xor" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1717f37794eSStanislav Mekhanoshin { "bitselect" , {1}, {E_ANY,E_COPY,E_COPY}},
1727f37794eSStanislav Mekhanoshin { "cbrt" , {1}, {E_ANY}},
1737f37794eSStanislav Mekhanoshin { "ceil" , {1}, {E_ANY}},
1747f37794eSStanislav Mekhanoshin { "clamp" , {1}, {E_ANY,E_COPY,E_COPY}},
1757f37794eSStanislav Mekhanoshin { "clz" , {1}, {E_ANY}},
1767f37794eSStanislav Mekhanoshin { "commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
1777f37794eSStanislav Mekhanoshin { "commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
1787f37794eSStanislav Mekhanoshin { "copysign" , {1}, {E_ANY,E_COPY}},
1797f37794eSStanislav Mekhanoshin { "cos" , {1}, {E_ANY}},
1807f37794eSStanislav Mekhanoshin { "cosh" , {1}, {E_ANY}},
1817f37794eSStanislav Mekhanoshin { "cospi" , {1}, {E_ANY}},
1827f37794eSStanislav Mekhanoshin { "cross" , {1}, {E_ANY,E_COPY}},
1837f37794eSStanislav Mekhanoshin { "ctz" , {1}, {E_ANY}},
1847f37794eSStanislav Mekhanoshin { "degrees" , {1}, {E_ANY}},
1857f37794eSStanislav Mekhanoshin { "distance" , {1}, {E_ANY,E_COPY}},
1867f37794eSStanislav Mekhanoshin { "divide" , {1}, {E_ANY,E_COPY}},
1877f37794eSStanislav Mekhanoshin { "dot" , {1}, {E_ANY,E_COPY}},
1887f37794eSStanislav Mekhanoshin { "erf" , {1}, {E_ANY}},
1897f37794eSStanislav Mekhanoshin { "erfc" , {1}, {E_ANY}},
1907f37794eSStanislav Mekhanoshin { "exp" , {1}, {E_ANY}},
1917f37794eSStanislav Mekhanoshin { "exp10" , {1}, {E_ANY}},
1927f37794eSStanislav Mekhanoshin { "exp2" , {1}, {E_ANY}},
1937f37794eSStanislav Mekhanoshin { "expm1" , {1}, {E_ANY}},
1947f37794eSStanislav Mekhanoshin { "fabs" , {1}, {E_ANY}},
1957f37794eSStanislav Mekhanoshin { "fast_distance" , {1}, {E_ANY,E_COPY}},
1967f37794eSStanislav Mekhanoshin { "fast_length" , {1}, {E_ANY}},
1977f37794eSStanislav Mekhanoshin { "fast_normalize" , {1}, {E_ANY}},
1987f37794eSStanislav Mekhanoshin { "fdim" , {1}, {E_ANY,E_COPY}},
1997f37794eSStanislav Mekhanoshin { "floor" , {1}, {E_ANY}},
2007f37794eSStanislav Mekhanoshin { "fma" , {1}, {E_ANY,E_COPY,E_COPY}},
2017f37794eSStanislav Mekhanoshin { "fmax" , {1}, {E_ANY,E_COPY}},
2027f37794eSStanislav Mekhanoshin { "fmin" , {1}, {E_ANY,E_COPY}},
2037f37794eSStanislav Mekhanoshin { "fmod" , {1}, {E_ANY,E_COPY}},
2047f37794eSStanislav Mekhanoshin { "fract" , {2}, {E_POINTEE,E_ANY}},
2057f37794eSStanislav Mekhanoshin { "frexp" , {1,2}, {E_ANY,E_ANY}},
2067f37794eSStanislav Mekhanoshin { "get_image_array_size" , {1}, {E_ANY}},
2077f37794eSStanislav Mekhanoshin { "get_image_channel_data_type" , {1}, {E_ANY}},
2087f37794eSStanislav Mekhanoshin { "get_image_channel_order" , {1}, {E_ANY}},
2097f37794eSStanislav Mekhanoshin { "get_image_dim" , {1}, {E_ANY}},
2107f37794eSStanislav Mekhanoshin { "get_image_height" , {1}, {E_ANY}},
2117f37794eSStanislav Mekhanoshin { "get_image_width" , {1}, {E_ANY}},
2127f37794eSStanislav Mekhanoshin { "get_pipe_max_packets" , {1}, {E_ANY}},
2137f37794eSStanislav Mekhanoshin { "get_pipe_num_packets" , {1}, {E_ANY}},
2147f37794eSStanislav Mekhanoshin { "hadd" , {1}, {E_ANY,E_COPY}},
2157f37794eSStanislav Mekhanoshin { "hypot" , {1}, {E_ANY,E_COPY}},
2167f37794eSStanislav Mekhanoshin { "ilogb" , {1}, {E_ANY}},
2177f37794eSStanislav Mekhanoshin { "isequal" , {1}, {E_ANY,E_COPY}},
2187f37794eSStanislav Mekhanoshin { "isfinite" , {1}, {E_ANY}},
2197f37794eSStanislav Mekhanoshin { "isgreater" , {1}, {E_ANY,E_COPY}},
2207f37794eSStanislav Mekhanoshin { "isgreaterequal" , {1}, {E_ANY,E_COPY}},
2217f37794eSStanislav Mekhanoshin { "isinf" , {1}, {E_ANY}},
2227f37794eSStanislav Mekhanoshin { "isless" , {1}, {E_ANY,E_COPY}},
2237f37794eSStanislav Mekhanoshin { "islessequal" , {1}, {E_ANY,E_COPY}},
2247f37794eSStanislav Mekhanoshin { "islessgreater" , {1}, {E_ANY,E_COPY}},
2257f37794eSStanislav Mekhanoshin { "isnan" , {1}, {E_ANY}},
2267f37794eSStanislav Mekhanoshin { "isnormal" , {1}, {E_ANY}},
2277f37794eSStanislav Mekhanoshin { "isnotequal" , {1}, {E_ANY,E_COPY}},
2287f37794eSStanislav Mekhanoshin { "isordered" , {1}, {E_ANY,E_COPY}},
2297f37794eSStanislav Mekhanoshin { "isunordered" , {1}, {E_ANY,E_COPY}},
2307f37794eSStanislav Mekhanoshin { "ldexp" , {1}, {E_ANY,E_SETBASE_I32}},
2317f37794eSStanislav Mekhanoshin { "length" , {1}, {E_ANY}},
2327f37794eSStanislav Mekhanoshin { "lgamma" , {1}, {E_ANY}},
2337f37794eSStanislav Mekhanoshin { "lgamma_r" , {1,2}, {E_ANY,E_ANY}},
2347f37794eSStanislav Mekhanoshin { "log" , {1}, {E_ANY}},
2357f37794eSStanislav Mekhanoshin { "log10" , {1}, {E_ANY}},
2367f37794eSStanislav Mekhanoshin { "log1p" , {1}, {E_ANY}},
2377f37794eSStanislav Mekhanoshin { "log2" , {1}, {E_ANY}},
2387f37794eSStanislav Mekhanoshin { "logb" , {1}, {E_ANY}},
2397f37794eSStanislav Mekhanoshin { "mad" , {1}, {E_ANY,E_COPY,E_COPY}},
2407f37794eSStanislav Mekhanoshin { "mad24" , {1}, {E_ANY,E_COPY,E_COPY}},
2417f37794eSStanislav Mekhanoshin { "mad_hi" , {1}, {E_ANY,E_COPY,E_COPY}},
2427f37794eSStanislav Mekhanoshin { "mad_sat" , {1}, {E_ANY,E_COPY,E_COPY}},
2437f37794eSStanislav Mekhanoshin { "max" , {1}, {E_ANY,E_COPY}},
2447f37794eSStanislav Mekhanoshin { "maxmag" , {1}, {E_ANY,E_COPY}},
2457f37794eSStanislav Mekhanoshin { "min" , {1}, {E_ANY,E_COPY}},
2467f37794eSStanislav Mekhanoshin { "minmag" , {1}, {E_ANY,E_COPY}},
2477f37794eSStanislav Mekhanoshin { "mix" , {1}, {E_ANY,E_COPY,E_COPY}},
2487f37794eSStanislav Mekhanoshin { "modf" , {2}, {E_POINTEE,E_ANY}},
2497f37794eSStanislav Mekhanoshin { "mul24" , {1}, {E_ANY,E_COPY}},
2507f37794eSStanislav Mekhanoshin { "mul_hi" , {1}, {E_ANY,E_COPY}},
2517f37794eSStanislav Mekhanoshin { "nan" , {1}, {E_ANY}},
2527f37794eSStanislav Mekhanoshin { "nextafter" , {1}, {E_ANY,E_COPY}},
2537f37794eSStanislav Mekhanoshin { "normalize" , {1}, {E_ANY}},
2547f37794eSStanislav Mekhanoshin { "popcount" , {1}, {E_ANY}},
2557f37794eSStanislav Mekhanoshin { "pow" , {1}, {E_ANY,E_COPY}},
2567f37794eSStanislav Mekhanoshin { "pown" , {1}, {E_ANY,E_SETBASE_I32}},
2577f37794eSStanislav Mekhanoshin { "powr" , {1}, {E_ANY,E_COPY}},
2587f37794eSStanislav Mekhanoshin { "prefetch" , {1}, {E_CONSTPTR_ANY,EX_SIZET}},
2597f37794eSStanislav Mekhanoshin { "radians" , {1}, {E_ANY}},
2607f37794eSStanislav Mekhanoshin { "recip" , {1}, {E_ANY}},
2617f37794eSStanislav Mekhanoshin { "remainder" , {1}, {E_ANY,E_COPY}},
2627f37794eSStanislav Mekhanoshin { "remquo" , {1,3}, {E_ANY,E_COPY,E_ANY}},
2637f37794eSStanislav Mekhanoshin { "reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
2647f37794eSStanislav Mekhanoshin { "reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
2657f37794eSStanislav Mekhanoshin { "rhadd" , {1}, {E_ANY,E_COPY}},
2667f37794eSStanislav Mekhanoshin { "rint" , {1}, {E_ANY}},
2677f37794eSStanislav Mekhanoshin { "rootn" , {1}, {E_ANY,E_SETBASE_I32}},
2687f37794eSStanislav Mekhanoshin { "rotate" , {1}, {E_ANY,E_COPY}},
2697f37794eSStanislav Mekhanoshin { "round" , {1}, {E_ANY}},
2707f37794eSStanislav Mekhanoshin { "rsqrt" , {1}, {E_ANY}},
2717f37794eSStanislav Mekhanoshin { "select" , {1,3}, {E_ANY,E_COPY,E_ANY}},
2727f37794eSStanislav Mekhanoshin { "shuffle" , {1,2}, {E_ANY,E_ANY}},
2737f37794eSStanislav Mekhanoshin { "shuffle2" , {1,3}, {E_ANY,E_COPY,E_ANY}},
2747f37794eSStanislav Mekhanoshin { "sign" , {1}, {E_ANY}},
2757f37794eSStanislav Mekhanoshin { "signbit" , {1}, {E_ANY}},
2767f37794eSStanislav Mekhanoshin { "sin" , {1}, {E_ANY}},
2777f37794eSStanislav Mekhanoshin { "sincos" , {2}, {E_POINTEE,E_ANY}},
2787f37794eSStanislav Mekhanoshin { "sinh" , {1}, {E_ANY}},
2797f37794eSStanislav Mekhanoshin { "sinpi" , {1}, {E_ANY}},
2807f37794eSStanislav Mekhanoshin { "smoothstep" , {1}, {E_ANY,E_COPY,E_COPY}},
2817f37794eSStanislav Mekhanoshin { "sqrt" , {1}, {E_ANY}},
2827f37794eSStanislav Mekhanoshin { "step" , {1}, {E_ANY,E_COPY}},
2837f37794eSStanislav Mekhanoshin { "sub_group_broadcast" , {1}, {E_ANY,EX_UINT}},
2847f37794eSStanislav Mekhanoshin { "sub_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
2857f37794eSStanislav Mekhanoshin { "sub_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
2867f37794eSStanislav Mekhanoshin { "sub_group_reduce_add" , {1}, {E_ANY}},
2877f37794eSStanislav Mekhanoshin { "sub_group_reduce_max" , {1}, {E_ANY}},
2887f37794eSStanislav Mekhanoshin { "sub_group_reduce_min" , {1}, {E_ANY}},
2897f37794eSStanislav Mekhanoshin { "sub_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
2907f37794eSStanislav Mekhanoshin { "sub_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
2917f37794eSStanislav Mekhanoshin { "sub_group_scan_exclusive_add" , {1}, {E_ANY}},
2927f37794eSStanislav Mekhanoshin { "sub_group_scan_exclusive_max" , {1}, {E_ANY}},
2937f37794eSStanislav Mekhanoshin { "sub_group_scan_exclusive_min" , {1}, {E_ANY}},
2947f37794eSStanislav Mekhanoshin { "sub_group_scan_inclusive_add" , {1}, {E_ANY}},
2957f37794eSStanislav Mekhanoshin { "sub_group_scan_inclusive_max" , {1}, {E_ANY}},
2967f37794eSStanislav Mekhanoshin { "sub_group_scan_inclusive_min" , {1}, {E_ANY}},
2977f37794eSStanislav Mekhanoshin { "sub_sat" , {1}, {E_ANY,E_COPY}},
2987f37794eSStanislav Mekhanoshin { "tan" , {1}, {E_ANY}},
2997f37794eSStanislav Mekhanoshin { "tanh" , {1}, {E_ANY}},
3007f37794eSStanislav Mekhanoshin { "tanpi" , {1}, {E_ANY}},
3017f37794eSStanislav Mekhanoshin { "tgamma" , {1}, {E_ANY}},
3027f37794eSStanislav Mekhanoshin { "trunc" , {1}, {E_ANY}},
3037f37794eSStanislav Mekhanoshin { "upsample" , {1}, {E_ANY,E_MAKEBASE_UNS}},
3047f37794eSStanislav Mekhanoshin { "vec_step" , {1}, {E_ANY}},
3057f37794eSStanislav Mekhanoshin { "vstore" , {3}, {E_POINTEE,EX_SIZET,E_ANY}},
3067f37794eSStanislav Mekhanoshin { "vstore16" , {3}, {E_V16_OF_POINTEE,EX_SIZET,E_ANY}},
3077f37794eSStanislav Mekhanoshin { "vstore2" , {3}, {E_V2_OF_POINTEE,EX_SIZET,E_ANY}},
3087f37794eSStanislav Mekhanoshin { "vstore3" , {3}, {E_V3_OF_POINTEE,EX_SIZET,E_ANY}},
3097f37794eSStanislav Mekhanoshin { "vstore4" , {3}, {E_V4_OF_POINTEE,EX_SIZET,E_ANY}},
3107f37794eSStanislav Mekhanoshin { "vstore8" , {3}, {E_V8_OF_POINTEE,EX_SIZET,E_ANY}},
3117f37794eSStanislav Mekhanoshin { "work_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
3127f37794eSStanislav Mekhanoshin { "work_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
3137f37794eSStanislav Mekhanoshin { "work_group_reduce_add" , {1}, {E_ANY}},
3147f37794eSStanislav Mekhanoshin { "work_group_reduce_max" , {1}, {E_ANY}},
3157f37794eSStanislav Mekhanoshin { "work_group_reduce_min" , {1}, {E_ANY}},
3167f37794eSStanislav Mekhanoshin { "work_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
3177f37794eSStanislav Mekhanoshin { "work_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
3187f37794eSStanislav Mekhanoshin { "work_group_scan_exclusive_add" , {1}, {E_ANY}},
3197f37794eSStanislav Mekhanoshin { "work_group_scan_exclusive_max" , {1}, {E_ANY}},
3207f37794eSStanislav Mekhanoshin { "work_group_scan_exclusive_min" , {1}, {E_ANY}},
3217f37794eSStanislav Mekhanoshin { "work_group_scan_inclusive_add" , {1}, {E_ANY}},
3227f37794eSStanislav Mekhanoshin { "work_group_scan_inclusive_max" , {1}, {E_ANY}},
3237f37794eSStanislav Mekhanoshin { "work_group_scan_inclusive_min" , {1}, {E_ANY}},
3247f37794eSStanislav Mekhanoshin { "write_imagef" , {1}, {E_ANY,E_IMAGECOORDS,EX_FLOAT4}},
3257f37794eSStanislav Mekhanoshin { "write_imagei" , {1}, {E_ANY,E_IMAGECOORDS,EX_INTV4}},
3267f37794eSStanislav Mekhanoshin { "write_imageui" , {1}, {E_ANY,E_IMAGECOORDS,EX_UINTV4}},
3277f37794eSStanislav Mekhanoshin { "ncos" , {1}, {E_ANY} },
3287f37794eSStanislav Mekhanoshin { "nexp2" , {1}, {E_ANY} },
3297f37794eSStanislav Mekhanoshin { "nfma" , {1}, {E_ANY, E_COPY, E_COPY} },
3307f37794eSStanislav Mekhanoshin { "nlog2" , {1}, {E_ANY} },
3317f37794eSStanislav Mekhanoshin { "nrcp" , {1}, {E_ANY} },
3327f37794eSStanislav Mekhanoshin { "nrsqrt" , {1}, {E_ANY} },
3337f37794eSStanislav Mekhanoshin { "nsin" , {1}, {E_ANY} },
3347f37794eSStanislav Mekhanoshin { "nsqrt" , {1}, {E_ANY} },
3357f37794eSStanislav Mekhanoshin { "ftz" , {1}, {E_ANY} },
3367f37794eSStanislav Mekhanoshin { "fldexp" , {1}, {E_ANY, EX_UINT} },
3377f37794eSStanislav Mekhanoshin { "class" , {1}, {E_ANY, EX_UINT} },
3387f37794eSStanislav Mekhanoshin { "rcbrt" , {1}, {E_ANY} },
3397f37794eSStanislav Mekhanoshin };
3407f37794eSStanislav Mekhanoshin
341fc5121a7SYaxun Liu // Library functions with unmangled name.
342fc5121a7SYaxun Liu const UnmangledFuncInfo UnmangledFuncInfo::Table[] = {
343fc5121a7SYaxun Liu {"__read_pipe_2", 4},
344fc5121a7SYaxun Liu {"__read_pipe_4", 6},
345fc5121a7SYaxun Liu {"__write_pipe_2", 4},
346fc5121a7SYaxun Liu {"__write_pipe_4", 6},
347fc5121a7SYaxun Liu };
348fc5121a7SYaxun Liu
349fc5121a7SYaxun Liu const unsigned UnmangledFuncInfo::TableSize =
350*f15014ffSBenjamin Kramer array_lengthof(UnmangledFuncInfo::Table);
3517f37794eSStanislav Mekhanoshin
getRetType(AMDGPULibFunc::EFuncId id,const AMDGPULibFunc::Param (& Leads)[2])3527f37794eSStanislav Mekhanoshin static AMDGPULibFunc::Param getRetType(AMDGPULibFunc::EFuncId id,
3537f37794eSStanislav Mekhanoshin const AMDGPULibFunc::Param (&Leads)[2]) {
3547f37794eSStanislav Mekhanoshin AMDGPULibFunc::Param Res = Leads[0];
355dc6e8dfdSJacob Lambert // TBD - This switch may require to be extended for other intrinsics
3567f37794eSStanislav Mekhanoshin switch (id) {
3577f37794eSStanislav Mekhanoshin case AMDGPULibFunc::EI_SINCOS:
3587f37794eSStanislav Mekhanoshin Res.PtrKind = AMDGPULibFunc::BYVALUE;
3597f37794eSStanislav Mekhanoshin break;
3607f37794eSStanislav Mekhanoshin default:
3617f37794eSStanislav Mekhanoshin break;
3627f37794eSStanislav Mekhanoshin }
3637f37794eSStanislav Mekhanoshin return Res;
3647f37794eSStanislav Mekhanoshin }
3657f37794eSStanislav Mekhanoshin
3667f37794eSStanislav Mekhanoshin class ParamIterator {
3677f37794eSStanislav Mekhanoshin const AMDGPULibFunc::Param (&Leads)[2];
3687f37794eSStanislav Mekhanoshin const ManglingRule& Rule;
3697f37794eSStanislav Mekhanoshin int Index;
3707f37794eSStanislav Mekhanoshin public:
ParamIterator(const AMDGPULibFunc::Param (& leads)[2],const ManglingRule & rule)3717f37794eSStanislav Mekhanoshin ParamIterator(const AMDGPULibFunc::Param (&leads)[2],
3727f37794eSStanislav Mekhanoshin const ManglingRule& rule)
3737f37794eSStanislav Mekhanoshin : Leads(leads), Rule(rule), Index(0) {}
3747f37794eSStanislav Mekhanoshin
3757f37794eSStanislav Mekhanoshin AMDGPULibFunc::Param getNextParam();
3767f37794eSStanislav Mekhanoshin };
3777f37794eSStanislav Mekhanoshin
getNextParam()3787f37794eSStanislav Mekhanoshin AMDGPULibFunc::Param ParamIterator::getNextParam() {
3797f37794eSStanislav Mekhanoshin AMDGPULibFunc::Param P;
3807f37794eSStanislav Mekhanoshin if (Index >= int(sizeof Rule.Param/sizeof Rule.Param[0])) return P;
3817f37794eSStanislav Mekhanoshin
3827f37794eSStanislav Mekhanoshin const char R = Rule.Param[Index];
3837f37794eSStanislav Mekhanoshin switch (R) {
3847f37794eSStanislav Mekhanoshin case E_NONE: break;
3857f37794eSStanislav Mekhanoshin case EX_UINT:
3867f37794eSStanislav Mekhanoshin P.ArgType = AMDGPULibFunc::U32; break;
3877f37794eSStanislav Mekhanoshin case EX_INTV4:
3887f37794eSStanislav Mekhanoshin P.ArgType = AMDGPULibFunc::I32; P.VectorSize = 4; break;
3897f37794eSStanislav Mekhanoshin case EX_UINTV4:
3907f37794eSStanislav Mekhanoshin P.ArgType = AMDGPULibFunc::U32; P.VectorSize = 4; break;
3917f37794eSStanislav Mekhanoshin case EX_FLOAT4:
3927f37794eSStanislav Mekhanoshin P.ArgType = AMDGPULibFunc::F32; P.VectorSize = 4; break;
3937f37794eSStanislav Mekhanoshin case EX_SIZET:
3947f37794eSStanislav Mekhanoshin P.ArgType = AMDGPULibFunc::U64; break;
3957f37794eSStanislav Mekhanoshin case EX_EVENT:
3967f37794eSStanislav Mekhanoshin P.ArgType = AMDGPULibFunc::EVENT; break;
3977f37794eSStanislav Mekhanoshin case EX_SAMPLER:
3987f37794eSStanislav Mekhanoshin P.ArgType = AMDGPULibFunc::SAMPLER; break;
3997f37794eSStanislav Mekhanoshin case EX_RESERVEDID: break; // TBD
4007f37794eSStanislav Mekhanoshin default:
4017f37794eSStanislav Mekhanoshin if (Index == (Rule.Lead[1] - 1)) P = Leads[1];
4027f37794eSStanislav Mekhanoshin else P = Leads[0];
4037f37794eSStanislav Mekhanoshin
4047f37794eSStanislav Mekhanoshin switch (R) {
4057f37794eSStanislav Mekhanoshin case E_ANY:
4067f37794eSStanislav Mekhanoshin case E_COPY: break;
4077f37794eSStanislav Mekhanoshin
4087f37794eSStanislav Mekhanoshin case E_POINTEE:
4097f37794eSStanislav Mekhanoshin P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4107f37794eSStanislav Mekhanoshin case E_V2_OF_POINTEE:
4117f37794eSStanislav Mekhanoshin P.VectorSize = 2; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4127f37794eSStanislav Mekhanoshin case E_V3_OF_POINTEE:
4137f37794eSStanislav Mekhanoshin P.VectorSize = 3; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4147f37794eSStanislav Mekhanoshin case E_V4_OF_POINTEE:
4157f37794eSStanislav Mekhanoshin P.VectorSize = 4; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4167f37794eSStanislav Mekhanoshin case E_V8_OF_POINTEE:
4177f37794eSStanislav Mekhanoshin P.VectorSize = 8; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4187f37794eSStanislav Mekhanoshin case E_V16_OF_POINTEE:
4197f37794eSStanislav Mekhanoshin P.VectorSize = 16; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4207f37794eSStanislav Mekhanoshin case E_CONSTPTR_ANY:
4217f37794eSStanislav Mekhanoshin P.PtrKind |= AMDGPULibFunc::CONST; break;
4227f37794eSStanislav Mekhanoshin case E_VLTLPTR_ANY:
4237f37794eSStanislav Mekhanoshin P.PtrKind |= AMDGPULibFunc::VOLATILE; break;
4247f37794eSStanislav Mekhanoshin case E_SETBASE_I32:
4257f37794eSStanislav Mekhanoshin P.ArgType = AMDGPULibFunc::I32; break;
4267f37794eSStanislav Mekhanoshin case E_SETBASE_U32:
4277f37794eSStanislav Mekhanoshin P.ArgType = AMDGPULibFunc::U32; break;
4287f37794eSStanislav Mekhanoshin
4297f37794eSStanislav Mekhanoshin case E_MAKEBASE_UNS:
4307f37794eSStanislav Mekhanoshin P.ArgType &= ~AMDGPULibFunc::BASE_TYPE_MASK;
4317f37794eSStanislav Mekhanoshin P.ArgType |= AMDGPULibFunc::UINT;
4327f37794eSStanislav Mekhanoshin break;
4337f37794eSStanislav Mekhanoshin
4347f37794eSStanislav Mekhanoshin case E_IMAGECOORDS:
4357f37794eSStanislav Mekhanoshin switch (P.ArgType) {
4367f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG1DA: P.VectorSize = 2; break;
4377f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG1DB: P.VectorSize = 1; break;
4387f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG2DA: P.VectorSize = 4; break;
4397f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG1D: P.VectorSize = 1; break;
4407f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG2D: P.VectorSize = 2; break;
4417f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG3D: P.VectorSize = 4; break;
4427f37794eSStanislav Mekhanoshin }
4437f37794eSStanislav Mekhanoshin P.PtrKind = AMDGPULibFunc::BYVALUE;
4447f37794eSStanislav Mekhanoshin P.ArgType = AMDGPULibFunc::I32;
4457f37794eSStanislav Mekhanoshin break;
4467f37794eSStanislav Mekhanoshin
4470d9673cfSYaxun Liu case E_CONSTPTR_SWAPGL: {
4480d9673cfSYaxun Liu unsigned AS = AMDGPULibFunc::getAddrSpaceFromEPtrKind(P.PtrKind);
4490d9673cfSYaxun Liu switch (AS) {
4500d9673cfSYaxun Liu case AMDGPUAS::GLOBAL_ADDRESS: AS = AMDGPUAS::LOCAL_ADDRESS; break;
4510d9673cfSYaxun Liu case AMDGPUAS::LOCAL_ADDRESS: AS = AMDGPUAS::GLOBAL_ADDRESS; break;
4527f37794eSStanislav Mekhanoshin }
4530d9673cfSYaxun Liu P.PtrKind = AMDGPULibFunc::getEPtrKindFromAddrSpace(AS);
4547f37794eSStanislav Mekhanoshin P.PtrKind |= AMDGPULibFunc::CONST;
4557f37794eSStanislav Mekhanoshin break;
4560d9673cfSYaxun Liu }
4577f37794eSStanislav Mekhanoshin
458d1f45ed5SNeubauer, Sebastian default:
459d1f45ed5SNeubauer, Sebastian llvm_unreachable("Unhandled param rule");
4607f37794eSStanislav Mekhanoshin }
4617f37794eSStanislav Mekhanoshin }
4627f37794eSStanislav Mekhanoshin ++Index;
4637f37794eSStanislav Mekhanoshin return P;
4647f37794eSStanislav Mekhanoshin }
4657f37794eSStanislav Mekhanoshin
drop_front(StringRef & str,size_t n=1)4667f37794eSStanislav Mekhanoshin inline static void drop_front(StringRef& str, size_t n = 1) {
4677f37794eSStanislav Mekhanoshin str = str.drop_front(n);
4687f37794eSStanislav Mekhanoshin }
4697f37794eSStanislav Mekhanoshin
eatTerm(StringRef & mangledName,const char c)4707f37794eSStanislav Mekhanoshin static bool eatTerm(StringRef& mangledName, const char c) {
4717f37794eSStanislav Mekhanoshin if (mangledName.front() == c) {
4727f37794eSStanislav Mekhanoshin drop_front(mangledName);
4737f37794eSStanislav Mekhanoshin return true;
4747f37794eSStanislav Mekhanoshin }
4757f37794eSStanislav Mekhanoshin return false;
4767f37794eSStanislav Mekhanoshin }
4777f37794eSStanislav Mekhanoshin
4787f37794eSStanislav Mekhanoshin template <size_t N>
eatTerm(StringRef & mangledName,const char (& str)[N])4797f37794eSStanislav Mekhanoshin static bool eatTerm(StringRef& mangledName, const char (&str)[N]) {
4807f37794eSStanislav Mekhanoshin if (mangledName.startswith(StringRef(str, N-1))) {
4817f37794eSStanislav Mekhanoshin drop_front(mangledName, N-1);
4827f37794eSStanislav Mekhanoshin return true;
4837f37794eSStanislav Mekhanoshin }
4847f37794eSStanislav Mekhanoshin return false;
4857f37794eSStanislav Mekhanoshin }
4867f37794eSStanislav Mekhanoshin
eatNumber(StringRef & s)4877f37794eSStanislav Mekhanoshin static int eatNumber(StringRef& s) {
4887f37794eSStanislav Mekhanoshin size_t const savedSize = s.size();
4897f37794eSStanislav Mekhanoshin int n = 0;
4907f37794eSStanislav Mekhanoshin while (!s.empty() && isDigit(s.front())) {
4917f37794eSStanislav Mekhanoshin n = n*10 + s.front() - '0';
4927f37794eSStanislav Mekhanoshin drop_front(s);
4937f37794eSStanislav Mekhanoshin }
4947f37794eSStanislav Mekhanoshin return s.size() < savedSize ? n : -1;
4957f37794eSStanislav Mekhanoshin }
4967f37794eSStanislav Mekhanoshin
eatLengthPrefixedName(StringRef & mangledName)4977f37794eSStanislav Mekhanoshin static StringRef eatLengthPrefixedName(StringRef& mangledName) {
4987f37794eSStanislav Mekhanoshin int const Len = eatNumber(mangledName);
4997f37794eSStanislav Mekhanoshin if (Len <= 0 || static_cast<size_t>(Len) > mangledName.size())
5007f37794eSStanislav Mekhanoshin return StringRef();
5017f37794eSStanislav Mekhanoshin StringRef Res = mangledName.substr(0, Len);
5027f37794eSStanislav Mekhanoshin drop_front(mangledName, Len);
5037f37794eSStanislav Mekhanoshin return Res;
5047f37794eSStanislav Mekhanoshin }
5057f37794eSStanislav Mekhanoshin
5067f37794eSStanislav Mekhanoshin } // end anonymous namespace
5077f37794eSStanislav Mekhanoshin
AMDGPUMangledLibFunc()508fc5121a7SYaxun Liu AMDGPUMangledLibFunc::AMDGPUMangledLibFunc() {
5097f37794eSStanislav Mekhanoshin FuncId = EI_NONE;
5107f37794eSStanislav Mekhanoshin FKind = NOPFX;
5117f37794eSStanislav Mekhanoshin Leads[0].reset();
5127f37794eSStanislav Mekhanoshin Leads[1].reset();
5137f37794eSStanislav Mekhanoshin Name.clear();
5147f37794eSStanislav Mekhanoshin }
5157f37794eSStanislav Mekhanoshin
AMDGPUUnmangledLibFunc()516fc5121a7SYaxun Liu AMDGPUUnmangledLibFunc::AMDGPUUnmangledLibFunc() {
517fc5121a7SYaxun Liu FuncId = EI_NONE;
518fc5121a7SYaxun Liu FuncTy = nullptr;
519fc5121a7SYaxun Liu }
520fc5121a7SYaxun Liu
AMDGPUMangledLibFunc(EFuncId id,const AMDGPUMangledLibFunc & copyFrom)521fc5121a7SYaxun Liu AMDGPUMangledLibFunc::AMDGPUMangledLibFunc(
522fc5121a7SYaxun Liu EFuncId id, const AMDGPUMangledLibFunc ©From) {
523fc5121a7SYaxun Liu FuncId = id;
524fc5121a7SYaxun Liu FKind = copyFrom.FKind;
525fc5121a7SYaxun Liu Leads[0] = copyFrom.Leads[0];
526fc5121a7SYaxun Liu Leads[1] = copyFrom.Leads[1];
527fc5121a7SYaxun Liu }
528fc5121a7SYaxun Liu
5297f37794eSStanislav Mekhanoshin ///////////////////////////////////////////////////////////////////////////////
5307f37794eSStanislav Mekhanoshin // Demangling
5317f37794eSStanislav Mekhanoshin
parseVecSize(StringRef & mangledName)5327f37794eSStanislav Mekhanoshin static int parseVecSize(StringRef& mangledName) {
5337f37794eSStanislav Mekhanoshin size_t const Len = eatNumber(mangledName);
5347f37794eSStanislav Mekhanoshin switch (Len) {
5357f37794eSStanislav Mekhanoshin case 2: case 3: case 4: case 8: case 16:
5367f37794eSStanislav Mekhanoshin return Len;
5377f37794eSStanislav Mekhanoshin default:
5387f37794eSStanislav Mekhanoshin break;
5397f37794eSStanislav Mekhanoshin }
5407f37794eSStanislav Mekhanoshin return 1;
5417f37794eSStanislav Mekhanoshin }
5427f37794eSStanislav Mekhanoshin
parseNamePrefix(StringRef & mangledName)5437f37794eSStanislav Mekhanoshin static AMDGPULibFunc::ENamePrefix parseNamePrefix(StringRef& mangledName) {
5447f37794eSStanislav Mekhanoshin std::pair<StringRef, StringRef> const P = mangledName.split('_');
5457f37794eSStanislav Mekhanoshin AMDGPULibFunc::ENamePrefix Pfx =
5467f37794eSStanislav Mekhanoshin StringSwitch<AMDGPULibFunc::ENamePrefix>(P.first)
5477f37794eSStanislav Mekhanoshin .Case("native", AMDGPULibFunc::NATIVE)
5487f37794eSStanislav Mekhanoshin .Case("half" , AMDGPULibFunc::HALF)
5497f37794eSStanislav Mekhanoshin .Default(AMDGPULibFunc::NOPFX);
5507f37794eSStanislav Mekhanoshin
5517f37794eSStanislav Mekhanoshin if (Pfx != AMDGPULibFunc::NOPFX)
5527f37794eSStanislav Mekhanoshin mangledName = P.second;
5537f37794eSStanislav Mekhanoshin
5547f37794eSStanislav Mekhanoshin return Pfx;
5557f37794eSStanislav Mekhanoshin }
5567f37794eSStanislav Mekhanoshin
buildManglingRulesMap()55785e2cdacSReid Kleckner StringMap<int> ManglingRule::buildManglingRulesMap() {
558*f15014ffSBenjamin Kramer StringMap<int> Map(array_lengthof(manglingRules));
55985e2cdacSReid Kleckner int Id = 0;
56085e2cdacSReid Kleckner for (auto Rule : manglingRules)
56185e2cdacSReid Kleckner Map.insert({Rule.Name, Id++});
56285e2cdacSReid Kleckner return Map;
56385e2cdacSReid Kleckner }
56485e2cdacSReid Kleckner
parseUnmangledName(StringRef FullName)565fc5121a7SYaxun Liu bool AMDGPUMangledLibFunc::parseUnmangledName(StringRef FullName) {
56685e2cdacSReid Kleckner static const StringMap<int> manglingRulesMap =
56785e2cdacSReid Kleckner ManglingRule::buildManglingRulesMap();
568fc5121a7SYaxun Liu FuncId = static_cast<EFuncId>(manglingRulesMap.lookup(FullName));
5697f37794eSStanislav Mekhanoshin return FuncId != EI_NONE;
5707f37794eSStanislav Mekhanoshin }
5717f37794eSStanislav Mekhanoshin
5727f37794eSStanislav Mekhanoshin ///////////////////////////////////////////////////////////////////////////////
5737f37794eSStanislav Mekhanoshin // Itanium Demangling
5747f37794eSStanislav Mekhanoshin
57549a49fe8SBenjamin Kramer namespace {
5767f37794eSStanislav Mekhanoshin struct ItaniumParamParser {
5777f37794eSStanislav Mekhanoshin AMDGPULibFunc::Param Prev;
5787f37794eSStanislav Mekhanoshin bool parseItaniumParam(StringRef& param, AMDGPULibFunc::Param &res);
5797f37794eSStanislav Mekhanoshin };
58049a49fe8SBenjamin Kramer } // namespace
5817f37794eSStanislav Mekhanoshin
parseItaniumParam(StringRef & param,AMDGPULibFunc::Param & res)5827f37794eSStanislav Mekhanoshin bool ItaniumParamParser::parseItaniumParam(StringRef& param,
5837f37794eSStanislav Mekhanoshin AMDGPULibFunc::Param &res) {
5847f37794eSStanislav Mekhanoshin res.reset();
5857f37794eSStanislav Mekhanoshin if (param.empty()) return false;
5867f37794eSStanislav Mekhanoshin
5877f37794eSStanislav Mekhanoshin // parse pointer prefix
5887f37794eSStanislav Mekhanoshin if (eatTerm(param, 'P')) {
5897f37794eSStanislav Mekhanoshin if (eatTerm(param, 'K')) res.PtrKind |= AMDGPULibFunc::CONST;
5907f37794eSStanislav Mekhanoshin if (eatTerm(param, 'V')) res.PtrKind |= AMDGPULibFunc::VOLATILE;
5910d9673cfSYaxun Liu unsigned AS;
5927f37794eSStanislav Mekhanoshin if (!eatTerm(param, "U3AS")) {
5930d9673cfSYaxun Liu AS = 0;
5947f37794eSStanislav Mekhanoshin } else {
5950d9673cfSYaxun Liu AS = param.front() - '0';
5967f37794eSStanislav Mekhanoshin drop_front(param, 1);
5977f37794eSStanislav Mekhanoshin }
5980d9673cfSYaxun Liu res.PtrKind |= AMDGPULibFuncBase::getEPtrKindFromAddrSpace(AS);
5997f37794eSStanislav Mekhanoshin } else {
6007f37794eSStanislav Mekhanoshin res.PtrKind = AMDGPULibFunc::BYVALUE;
6017f37794eSStanislav Mekhanoshin }
6027f37794eSStanislav Mekhanoshin
6037f37794eSStanislav Mekhanoshin // parse vector size
6047f37794eSStanislav Mekhanoshin if (eatTerm(param,"Dv")) {
6057f37794eSStanislav Mekhanoshin res.VectorSize = parseVecSize(param);
6067f37794eSStanislav Mekhanoshin if (res.VectorSize==1 || !eatTerm(param, '_')) return false;
6077f37794eSStanislav Mekhanoshin }
6087f37794eSStanislav Mekhanoshin
6097f37794eSStanislav Mekhanoshin // parse type
6107f37794eSStanislav Mekhanoshin char const TC = param.front();
6118105935dSSander de Smalen if (isDigit(TC)) {
6127f37794eSStanislav Mekhanoshin res.ArgType = StringSwitch<AMDGPULibFunc::EType>
6137f37794eSStanislav Mekhanoshin (eatLengthPrefixedName(param))
6147f37794eSStanislav Mekhanoshin .Case("ocl_image1darray" , AMDGPULibFunc::IMG1DA)
6157f37794eSStanislav Mekhanoshin .Case("ocl_image1dbuffer", AMDGPULibFunc::IMG1DB)
6167f37794eSStanislav Mekhanoshin .Case("ocl_image2darray" , AMDGPULibFunc::IMG2DA)
6177f37794eSStanislav Mekhanoshin .Case("ocl_image1d" , AMDGPULibFunc::IMG1D)
6187f37794eSStanislav Mekhanoshin .Case("ocl_image2d" , AMDGPULibFunc::IMG2D)
6197f37794eSStanislav Mekhanoshin .Case("ocl_image3d" , AMDGPULibFunc::IMG3D)
6207f37794eSStanislav Mekhanoshin .Case("ocl_event" , AMDGPULibFunc::DUMMY)
6217f37794eSStanislav Mekhanoshin .Case("ocl_sampler" , AMDGPULibFunc::DUMMY)
6227f37794eSStanislav Mekhanoshin .Default(AMDGPULibFunc::DUMMY);
6237f37794eSStanislav Mekhanoshin } else {
6247f37794eSStanislav Mekhanoshin drop_front(param);
6257f37794eSStanislav Mekhanoshin switch (TC) {
6267f37794eSStanislav Mekhanoshin case 'h': res.ArgType = AMDGPULibFunc::U8; break;
6277f37794eSStanislav Mekhanoshin case 't': res.ArgType = AMDGPULibFunc::U16; break;
6287f37794eSStanislav Mekhanoshin case 'j': res.ArgType = AMDGPULibFunc::U32; break;
6297f37794eSStanislav Mekhanoshin case 'm': res.ArgType = AMDGPULibFunc::U64; break;
6307f37794eSStanislav Mekhanoshin case 'c': res.ArgType = AMDGPULibFunc::I8; break;
6317f37794eSStanislav Mekhanoshin case 's': res.ArgType = AMDGPULibFunc::I16; break;
6327f37794eSStanislav Mekhanoshin case 'i': res.ArgType = AMDGPULibFunc::I32; break;
6337f37794eSStanislav Mekhanoshin case 'l': res.ArgType = AMDGPULibFunc::I64; break;
6347f37794eSStanislav Mekhanoshin case 'f': res.ArgType = AMDGPULibFunc::F32; break;
6357f37794eSStanislav Mekhanoshin case 'd': res.ArgType = AMDGPULibFunc::F64; break;
6367f37794eSStanislav Mekhanoshin case 'D': if (!eatTerm(param, 'h')) return false;
6377f37794eSStanislav Mekhanoshin res.ArgType = AMDGPULibFunc::F16; break;
6387f37794eSStanislav Mekhanoshin case 'S':
6397f37794eSStanislav Mekhanoshin if (!eatTerm(param, '_')) {
6407f37794eSStanislav Mekhanoshin eatNumber(param);
6417f37794eSStanislav Mekhanoshin if (!eatTerm(param, '_')) return false;
6427f37794eSStanislav Mekhanoshin }
6437f37794eSStanislav Mekhanoshin res.VectorSize = Prev.VectorSize;
6447f37794eSStanislav Mekhanoshin res.ArgType = Prev.ArgType;
6457f37794eSStanislav Mekhanoshin break;
6467f37794eSStanislav Mekhanoshin default:;
6477f37794eSStanislav Mekhanoshin }
6487f37794eSStanislav Mekhanoshin }
6497f37794eSStanislav Mekhanoshin if (res.ArgType == 0) return false;
6507f37794eSStanislav Mekhanoshin Prev.VectorSize = res.VectorSize;
6517f37794eSStanislav Mekhanoshin Prev.ArgType = res.ArgType;
6527f37794eSStanislav Mekhanoshin return true;
6537f37794eSStanislav Mekhanoshin }
6547f37794eSStanislav Mekhanoshin
parseFuncName(StringRef & mangledName)655fc5121a7SYaxun Liu bool AMDGPUMangledLibFunc::parseFuncName(StringRef &mangledName) {
6567f37794eSStanislav Mekhanoshin StringRef Name = eatLengthPrefixedName(mangledName);
6577f37794eSStanislav Mekhanoshin FKind = parseNamePrefix(Name);
658fc5121a7SYaxun Liu if (!parseUnmangledName(Name))
659fc5121a7SYaxun Liu return false;
6607f37794eSStanislav Mekhanoshin
6617f37794eSStanislav Mekhanoshin const ManglingRule& Rule = manglingRules[FuncId];
6627f37794eSStanislav Mekhanoshin ItaniumParamParser Parser;
6637f37794eSStanislav Mekhanoshin for (int I=0; I < Rule.maxLeadIndex(); ++I) {
6647f37794eSStanislav Mekhanoshin Param P;
6657f37794eSStanislav Mekhanoshin if (!Parser.parseItaniumParam(mangledName, P))
6667f37794eSStanislav Mekhanoshin return false;
6677f37794eSStanislav Mekhanoshin
6687f37794eSStanislav Mekhanoshin if ((I + 1) == Rule.Lead[0]) Leads[0] = P;
6697f37794eSStanislav Mekhanoshin if ((I + 1) == Rule.Lead[1]) Leads[1] = P;
6707f37794eSStanislav Mekhanoshin }
6717f37794eSStanislav Mekhanoshin return true;
6727f37794eSStanislav Mekhanoshin }
6737f37794eSStanislav Mekhanoshin
parseFuncName(StringRef & Name)674fc5121a7SYaxun Liu bool AMDGPUUnmangledLibFunc::parseFuncName(StringRef &Name) {
675fc5121a7SYaxun Liu if (!UnmangledFuncInfo::lookup(Name, FuncId))
6767f37794eSStanislav Mekhanoshin return false;
677fc5121a7SYaxun Liu setName(Name);
678fc5121a7SYaxun Liu return true;
6797f37794eSStanislav Mekhanoshin }
680fc5121a7SYaxun Liu
parse(StringRef FuncName,AMDGPULibFunc & F)681fc5121a7SYaxun Liu bool AMDGPULibFunc::parse(StringRef FuncName, AMDGPULibFunc &F) {
682fc5121a7SYaxun Liu if (FuncName.empty()) {
683fc5121a7SYaxun Liu F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
6847f37794eSStanislav Mekhanoshin return false;
6857f37794eSStanislav Mekhanoshin }
6867f37794eSStanislav Mekhanoshin
687fc5121a7SYaxun Liu if (eatTerm(FuncName, "_Z"))
6880eaee545SJonas Devlieghere F.Impl = std::make_unique<AMDGPUMangledLibFunc>();
689fc5121a7SYaxun Liu else
6900eaee545SJonas Devlieghere F.Impl = std::make_unique<AMDGPUUnmangledLibFunc>();
691fc5121a7SYaxun Liu if (F.Impl->parseFuncName(FuncName))
692fc5121a7SYaxun Liu return true;
693fc5121a7SYaxun Liu
694fc5121a7SYaxun Liu F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
695fc5121a7SYaxun Liu return false;
696fc5121a7SYaxun Liu }
697fc5121a7SYaxun Liu
getUnmangledName(StringRef mangledName)698fc5121a7SYaxun Liu StringRef AMDGPUMangledLibFunc::getUnmangledName(StringRef mangledName) {
6997f37794eSStanislav Mekhanoshin StringRef S = mangledName;
7007f37794eSStanislav Mekhanoshin if (eatTerm(S, "_Z"))
7017f37794eSStanislav Mekhanoshin return eatLengthPrefixedName(S);
7027f37794eSStanislav Mekhanoshin return StringRef();
7037f37794eSStanislav Mekhanoshin }
7047f37794eSStanislav Mekhanoshin
7057f37794eSStanislav Mekhanoshin ///////////////////////////////////////////////////////////////////////////////
7067f37794eSStanislav Mekhanoshin // Mangling
7077f37794eSStanislav Mekhanoshin
7087f37794eSStanislav Mekhanoshin template <typename Stream>
writeName(Stream & OS) const709fc5121a7SYaxun Liu void AMDGPUMangledLibFunc::writeName(Stream &OS) const {
7107f37794eSStanislav Mekhanoshin const char *Pfx = "";
7117f37794eSStanislav Mekhanoshin switch (FKind) {
7127f37794eSStanislav Mekhanoshin case NATIVE: Pfx = "native_"; break;
7137f37794eSStanislav Mekhanoshin case HALF: Pfx = "half_"; break;
7147f37794eSStanislav Mekhanoshin default: break;
7157f37794eSStanislav Mekhanoshin }
7167f37794eSStanislav Mekhanoshin if (!Name.empty()) {
7177f37794eSStanislav Mekhanoshin OS << Pfx << Name;
7187f37794eSStanislav Mekhanoshin } else if (FuncId != EI_NONE) {
7197f37794eSStanislav Mekhanoshin OS << Pfx;
7207f37794eSStanislav Mekhanoshin const StringRef& S = manglingRules[FuncId].Name;
7217f37794eSStanislav Mekhanoshin OS.write(S.data(), S.size());
7227f37794eSStanislav Mekhanoshin }
7237f37794eSStanislav Mekhanoshin }
7247f37794eSStanislav Mekhanoshin
mangle() const725fc5121a7SYaxun Liu std::string AMDGPUMangledLibFunc::mangle() const { return mangleNameItanium(); }
7267f37794eSStanislav Mekhanoshin
7277f37794eSStanislav Mekhanoshin ///////////////////////////////////////////////////////////////////////////////
7287f37794eSStanislav Mekhanoshin // Itanium Mangling
7297f37794eSStanislav Mekhanoshin
getItaniumTypeName(AMDGPULibFunc::EType T)7307f37794eSStanislav Mekhanoshin static const char *getItaniumTypeName(AMDGPULibFunc::EType T) {
7317f37794eSStanislav Mekhanoshin switch (T) {
7327f37794eSStanislav Mekhanoshin case AMDGPULibFunc::U8: return "h";
7337f37794eSStanislav Mekhanoshin case AMDGPULibFunc::U16: return "t";
7347f37794eSStanislav Mekhanoshin case AMDGPULibFunc::U32: return "j";
7357f37794eSStanislav Mekhanoshin case AMDGPULibFunc::U64: return "m";
7367f37794eSStanislav Mekhanoshin case AMDGPULibFunc::I8: return "c";
7377f37794eSStanislav Mekhanoshin case AMDGPULibFunc::I16: return "s";
7387f37794eSStanislav Mekhanoshin case AMDGPULibFunc::I32: return "i";
7397f37794eSStanislav Mekhanoshin case AMDGPULibFunc::I64: return "l";
7407f37794eSStanislav Mekhanoshin case AMDGPULibFunc::F16: return "Dh";
7417f37794eSStanislav Mekhanoshin case AMDGPULibFunc::F32: return "f";
7427f37794eSStanislav Mekhanoshin case AMDGPULibFunc::F64: return "d";
7437f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG1DA: return "16ocl_image1darray";
7447f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG1DB: return "17ocl_image1dbuffer";
7457f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG2DA: return "16ocl_image2darray";
7467f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG1D: return "11ocl_image1d";
7477f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG2D: return "11ocl_image2d";
7487f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG3D: return "11ocl_image3d";
7497f37794eSStanislav Mekhanoshin case AMDGPULibFunc::SAMPLER: return "11ocl_sampler";
7507f37794eSStanislav Mekhanoshin case AMDGPULibFunc::EVENT: return "9ocl_event";
751d1f45ed5SNeubauer, Sebastian default:
752d1f45ed5SNeubauer, Sebastian llvm_unreachable("Unhandled param type");
7537f37794eSStanislav Mekhanoshin }
7547f37794eSStanislav Mekhanoshin return nullptr;
7557f37794eSStanislav Mekhanoshin }
7567f37794eSStanislav Mekhanoshin
75749a49fe8SBenjamin Kramer namespace {
7587f37794eSStanislav Mekhanoshin // Itanium mangling ABI says:
7597f37794eSStanislav Mekhanoshin // "5.1.8. Compression
7607f37794eSStanislav Mekhanoshin // ... Each non-terminal in the grammar for which <substitution> appears on the
7617f37794eSStanislav Mekhanoshin // right-hand side is both a source of future substitutions and a candidate
7627f37794eSStanislav Mekhanoshin // for being substituted. There are two exceptions that appear to be
7637f37794eSStanislav Mekhanoshin // substitution candidates from the grammar, but are explicitly excluded:
7647f37794eSStanislav Mekhanoshin // 1. <builtin-type> other than vendor extended types ..."
7657f37794eSStanislav Mekhanoshin
766d1f45ed5SNeubauer, Sebastian // For the purpose of functions the following productions make sense for the
7677f37794eSStanislav Mekhanoshin // substitution:
7687f37794eSStanislav Mekhanoshin // <type> ::= <builtin-type>
7697f37794eSStanislav Mekhanoshin // ::= <class-enum-type>
7707f37794eSStanislav Mekhanoshin // ::= <array-type>
7717f37794eSStanislav Mekhanoshin // ::=<CV-qualifiers> <type>
7727f37794eSStanislav Mekhanoshin // ::= P <type> # pointer-to
7737f37794eSStanislav Mekhanoshin // ::= <substitution>
7747f37794eSStanislav Mekhanoshin //
7757f37794eSStanislav Mekhanoshin // Note that while types like images, samplers and events are by the ABI encoded
7767f37794eSStanislav Mekhanoshin // using <class-enum-type> production rule they're not used for substitution
7777f37794eSStanislav Mekhanoshin // because clang consider them as builtin types.
7787f37794eSStanislav Mekhanoshin //
779d1f45ed5SNeubauer, Sebastian // DvNN_ type is GCC extension for vectors and is a subject for the
780d1f45ed5SNeubauer, Sebastian // substitution.
7817f37794eSStanislav Mekhanoshin
7827f37794eSStanislav Mekhanoshin class ItaniumMangler {
783dc6e8dfdSJacob Lambert SmallVector<AMDGPULibFunc::Param, 10> Str; // list of accumulated substitutions
7847f37794eSStanislav Mekhanoshin bool UseAddrSpace;
7857f37794eSStanislav Mekhanoshin
findSubst(const AMDGPULibFunc::Param & P) const7867f37794eSStanislav Mekhanoshin int findSubst(const AMDGPULibFunc::Param& P) const {
7877f37794eSStanislav Mekhanoshin for(unsigned I = 0; I < Str.size(); ++I) {
7887f37794eSStanislav Mekhanoshin const AMDGPULibFunc::Param& T = Str[I];
7897f37794eSStanislav Mekhanoshin if (P.PtrKind == T.PtrKind &&
7907f37794eSStanislav Mekhanoshin P.VectorSize == T.VectorSize &&
7917f37794eSStanislav Mekhanoshin P.ArgType == T.ArgType) {
7927f37794eSStanislav Mekhanoshin return I;
7937f37794eSStanislav Mekhanoshin }
7947f37794eSStanislav Mekhanoshin }
7957f37794eSStanislav Mekhanoshin return -1;
7967f37794eSStanislav Mekhanoshin }
7977f37794eSStanislav Mekhanoshin
7987f37794eSStanislav Mekhanoshin template <typename Stream>
trySubst(Stream & os,const AMDGPULibFunc::Param & p)7997f37794eSStanislav Mekhanoshin bool trySubst(Stream& os, const AMDGPULibFunc::Param& p) {
8007f37794eSStanislav Mekhanoshin int const subst = findSubst(p);
8017f37794eSStanislav Mekhanoshin if (subst < 0) return false;
8027f37794eSStanislav Mekhanoshin // Substitutions are mangled as S(XX)?_ where XX is a hexadecimal number
8037f37794eSStanislav Mekhanoshin // 0 1 2
8047f37794eSStanislav Mekhanoshin // S_ S0_ S1_
8057f37794eSStanislav Mekhanoshin if (subst == 0) os << "S_";
8067f37794eSStanislav Mekhanoshin else os << 'S' << (subst-1) << '_';
8077f37794eSStanislav Mekhanoshin return true;
8087f37794eSStanislav Mekhanoshin }
8097f37794eSStanislav Mekhanoshin
8107f37794eSStanislav Mekhanoshin public:
ItaniumMangler(bool useAddrSpace)8117f37794eSStanislav Mekhanoshin ItaniumMangler(bool useAddrSpace)
8127f37794eSStanislav Mekhanoshin : UseAddrSpace(useAddrSpace) {}
8137f37794eSStanislav Mekhanoshin
8147f37794eSStanislav Mekhanoshin template <typename Stream>
operator ()(Stream & os,AMDGPULibFunc::Param p)8157f37794eSStanislav Mekhanoshin void operator()(Stream& os, AMDGPULibFunc::Param p) {
8167f37794eSStanislav Mekhanoshin
8177f37794eSStanislav Mekhanoshin // Itanium mangling ABI 5.1.8. Compression:
8187f37794eSStanislav Mekhanoshin // Logically, the substitutable components of a mangled name are considered
8197f37794eSStanislav Mekhanoshin // left-to-right, components before the composite structure of which they
8207f37794eSStanislav Mekhanoshin // are a part. If a component has been encountered before, it is substituted
8217f37794eSStanislav Mekhanoshin // as described below. This decision is independent of whether its components
8227f37794eSStanislav Mekhanoshin // have been substituted, so an implementation may optimize by considering
8237f37794eSStanislav Mekhanoshin // large structures for substitution before their components. If a component
8247f37794eSStanislav Mekhanoshin // has not been encountered before, its mangling is identified, and it is
8257f37794eSStanislav Mekhanoshin // added to a dictionary of substitution candidates. No entity is added to
8267f37794eSStanislav Mekhanoshin // the dictionary twice.
8277f37794eSStanislav Mekhanoshin AMDGPULibFunc::Param Ptr;
8287f37794eSStanislav Mekhanoshin
8297f37794eSStanislav Mekhanoshin if (p.PtrKind) {
8307f37794eSStanislav Mekhanoshin if (trySubst(os, p)) return;
8317f37794eSStanislav Mekhanoshin os << 'P';
8327f37794eSStanislav Mekhanoshin if (p.PtrKind & AMDGPULibFunc::CONST) os << 'K';
8337f37794eSStanislav Mekhanoshin if (p.PtrKind & AMDGPULibFunc::VOLATILE) os << 'V';
8340d9673cfSYaxun Liu unsigned AS = UseAddrSpace
8350d9673cfSYaxun Liu ? AMDGPULibFuncBase::getAddrSpaceFromEPtrKind(p.PtrKind)
8360d9673cfSYaxun Liu : 0;
83727332968SMichael Liao if (EnableOCLManglingMismatchWA || AS != 0)
83827332968SMichael Liao os << "U3AS" << AS;
8397f37794eSStanislav Mekhanoshin Ptr = p;
8407f37794eSStanislav Mekhanoshin p.PtrKind = 0;
8417f37794eSStanislav Mekhanoshin }
8427f37794eSStanislav Mekhanoshin
8437f37794eSStanislav Mekhanoshin if (p.VectorSize > 1) {
8447f37794eSStanislav Mekhanoshin if (trySubst(os, p)) goto exit;
8457f37794eSStanislav Mekhanoshin Str.push_back(p);
8467f37794eSStanislav Mekhanoshin os << "Dv" << static_cast<unsigned>(p.VectorSize) << '_';
8477f37794eSStanislav Mekhanoshin }
8487f37794eSStanislav Mekhanoshin
8497f37794eSStanislav Mekhanoshin os << getItaniumTypeName((AMDGPULibFunc::EType)p.ArgType);
8507f37794eSStanislav Mekhanoshin
8517f37794eSStanislav Mekhanoshin exit:
8527f37794eSStanislav Mekhanoshin if (Ptr.ArgType) Str.push_back(Ptr);
8537f37794eSStanislav Mekhanoshin }
8547f37794eSStanislav Mekhanoshin };
85549a49fe8SBenjamin Kramer } // namespace
8567f37794eSStanislav Mekhanoshin
mangleNameItanium() const857fc5121a7SYaxun Liu std::string AMDGPUMangledLibFunc::mangleNameItanium() const {
8587f37794eSStanislav Mekhanoshin SmallString<128> Buf;
8597f37794eSStanislav Mekhanoshin raw_svector_ostream S(Buf);
8607f37794eSStanislav Mekhanoshin SmallString<128> NameBuf;
8617f37794eSStanislav Mekhanoshin raw_svector_ostream Name(NameBuf);
8627f37794eSStanislav Mekhanoshin writeName(Name);
8637f37794eSStanislav Mekhanoshin const StringRef& NameStr = Name.str();
8647f37794eSStanislav Mekhanoshin S << "_Z" << static_cast<int>(NameStr.size()) << NameStr;
8657f37794eSStanislav Mekhanoshin
8667f37794eSStanislav Mekhanoshin ItaniumMangler Mangler(true);
8677f37794eSStanislav Mekhanoshin ParamIterator I(Leads, manglingRules[FuncId]);
8687f37794eSStanislav Mekhanoshin Param P;
8697f37794eSStanislav Mekhanoshin while ((P = I.getNextParam()).ArgType != 0)
8707f37794eSStanislav Mekhanoshin Mangler(S, P);
871adcd0268SBenjamin Kramer return std::string(S.str());
8727f37794eSStanislav Mekhanoshin }
8737f37794eSStanislav Mekhanoshin
8747f37794eSStanislav Mekhanoshin ///////////////////////////////////////////////////////////////////////////////
8757f37794eSStanislav Mekhanoshin // Misc
8767f37794eSStanislav Mekhanoshin
getIntrinsicParamType(LLVMContext & C,const AMDGPULibFunc::Param & P,bool useAddrSpace)8777f37794eSStanislav Mekhanoshin static Type* getIntrinsicParamType(
8787f37794eSStanislav Mekhanoshin LLVMContext& C,
8797f37794eSStanislav Mekhanoshin const AMDGPULibFunc::Param& P,
8807f37794eSStanislav Mekhanoshin bool useAddrSpace) {
8817f37794eSStanislav Mekhanoshin Type* T = nullptr;
8827f37794eSStanislav Mekhanoshin switch (P.ArgType) {
8837f37794eSStanislav Mekhanoshin case AMDGPULibFunc::U8:
8847f37794eSStanislav Mekhanoshin case AMDGPULibFunc::I8: T = Type::getInt8Ty(C); break;
8857f37794eSStanislav Mekhanoshin case AMDGPULibFunc::U16:
8867f37794eSStanislav Mekhanoshin case AMDGPULibFunc::I16: T = Type::getInt16Ty(C); break;
8877f37794eSStanislav Mekhanoshin case AMDGPULibFunc::U32:
8887f37794eSStanislav Mekhanoshin case AMDGPULibFunc::I32: T = Type::getInt32Ty(C); break;
8897f37794eSStanislav Mekhanoshin case AMDGPULibFunc::U64:
8907f37794eSStanislav Mekhanoshin case AMDGPULibFunc::I64: T = Type::getInt64Ty(C); break;
8917f37794eSStanislav Mekhanoshin case AMDGPULibFunc::F16: T = Type::getHalfTy(C); break;
8927f37794eSStanislav Mekhanoshin case AMDGPULibFunc::F32: T = Type::getFloatTy(C); break;
8937f37794eSStanislav Mekhanoshin case AMDGPULibFunc::F64: T = Type::getDoubleTy(C); break;
8947f37794eSStanislav Mekhanoshin
8957f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG1DA:
8967f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG1DB:
8977f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG2DA:
8987f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG1D:
8997f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG2D:
9007f37794eSStanislav Mekhanoshin case AMDGPULibFunc::IMG3D:
9017f37794eSStanislav Mekhanoshin T = StructType::create(C,"ocl_image")->getPointerTo(); break;
9027f37794eSStanislav Mekhanoshin case AMDGPULibFunc::SAMPLER:
9037f37794eSStanislav Mekhanoshin T = StructType::create(C,"ocl_sampler")->getPointerTo(); break;
9047f37794eSStanislav Mekhanoshin case AMDGPULibFunc::EVENT:
9057f37794eSStanislav Mekhanoshin T = StructType::create(C,"ocl_event")->getPointerTo(); break;
9067f37794eSStanislav Mekhanoshin default:
907d1f45ed5SNeubauer, Sebastian llvm_unreachable("Unhandled param type");
9087f37794eSStanislav Mekhanoshin return nullptr;
9097f37794eSStanislav Mekhanoshin }
9107f37794eSStanislav Mekhanoshin if (P.VectorSize > 1)
911aad93654SChristopher Tetreault T = FixedVectorType::get(T, P.VectorSize);
9127f37794eSStanislav Mekhanoshin if (P.PtrKind != AMDGPULibFunc::BYVALUE)
9137f37794eSStanislav Mekhanoshin T = useAddrSpace ? T->getPointerTo((P.PtrKind & AMDGPULibFunc::ADDR_SPACE)
9147f37794eSStanislav Mekhanoshin - 1)
9157f37794eSStanislav Mekhanoshin : T->getPointerTo();
9167f37794eSStanislav Mekhanoshin return T;
9177f37794eSStanislav Mekhanoshin }
9187f37794eSStanislav Mekhanoshin
getFunctionType(Module & M) const919fc5121a7SYaxun Liu FunctionType *AMDGPUMangledLibFunc::getFunctionType(Module &M) const {
9207f37794eSStanislav Mekhanoshin LLVMContext& C = M.getContext();
9217f37794eSStanislav Mekhanoshin std::vector<Type*> Args;
9227f37794eSStanislav Mekhanoshin ParamIterator I(Leads, manglingRules[FuncId]);
9237f37794eSStanislav Mekhanoshin Param P;
9247f37794eSStanislav Mekhanoshin while ((P=I.getNextParam()).ArgType != 0)
9257f37794eSStanislav Mekhanoshin Args.push_back(getIntrinsicParamType(C, P, true));
9267f37794eSStanislav Mekhanoshin
9277f37794eSStanislav Mekhanoshin return FunctionType::get(
9287f37794eSStanislav Mekhanoshin getIntrinsicParamType(C, getRetType(FuncId, Leads), true),
9297f37794eSStanislav Mekhanoshin Args, false);
9307f37794eSStanislav Mekhanoshin }
9317f37794eSStanislav Mekhanoshin
getNumArgs() const932fc5121a7SYaxun Liu unsigned AMDGPUMangledLibFunc::getNumArgs() const {
9337f37794eSStanislav Mekhanoshin return manglingRules[FuncId].getNumArgs();
9347f37794eSStanislav Mekhanoshin }
9357f37794eSStanislav Mekhanoshin
getNumArgs() const936fc5121a7SYaxun Liu unsigned AMDGPUUnmangledLibFunc::getNumArgs() const {
937fc5121a7SYaxun Liu return UnmangledFuncInfo::getNumArgs(FuncId);
938fc5121a7SYaxun Liu }
939fc5121a7SYaxun Liu
getName() const940fc5121a7SYaxun Liu std::string AMDGPUMangledLibFunc::getName() const {
9417f37794eSStanislav Mekhanoshin SmallString<128> Buf;
9427f37794eSStanislav Mekhanoshin raw_svector_ostream OS(Buf);
9437f37794eSStanislav Mekhanoshin writeName(OS);
944adcd0268SBenjamin Kramer return std::string(OS.str());
9457f37794eSStanislav Mekhanoshin }
9467f37794eSStanislav Mekhanoshin
getFunction(Module * M,const AMDGPULibFunc & fInfo)9477f37794eSStanislav Mekhanoshin Function *AMDGPULibFunc::getFunction(Module *M, const AMDGPULibFunc &fInfo) {
9487f37794eSStanislav Mekhanoshin std::string FuncName = fInfo.mangle();
9497f37794eSStanislav Mekhanoshin Function *F = dyn_cast_or_null<Function>(
9507f37794eSStanislav Mekhanoshin M->getValueSymbolTable().lookup(FuncName));
9517f37794eSStanislav Mekhanoshin
9527f37794eSStanislav Mekhanoshin // check formal with actual types conformance
9537f37794eSStanislav Mekhanoshin if (F && !F->isDeclaration()
9547f37794eSStanislav Mekhanoshin && !F->isVarArg()
9557f37794eSStanislav Mekhanoshin && F->arg_size() == fInfo.getNumArgs()) {
9567f37794eSStanislav Mekhanoshin return F;
9577f37794eSStanislav Mekhanoshin }
9587f37794eSStanislav Mekhanoshin return nullptr;
9597f37794eSStanislav Mekhanoshin }
9607f37794eSStanislav Mekhanoshin
getOrInsertFunction(Module * M,const AMDGPULibFunc & fInfo)96113680223SJames Y Knight FunctionCallee AMDGPULibFunc::getOrInsertFunction(Module *M,
9627f37794eSStanislav Mekhanoshin const AMDGPULibFunc &fInfo) {
9637f37794eSStanislav Mekhanoshin std::string const FuncName = fInfo.mangle();
9647f37794eSStanislav Mekhanoshin Function *F = dyn_cast_or_null<Function>(
9657f37794eSStanislav Mekhanoshin M->getValueSymbolTable().lookup(FuncName));
9667f37794eSStanislav Mekhanoshin
9677f37794eSStanislav Mekhanoshin // check formal with actual types conformance
9687f37794eSStanislav Mekhanoshin if (F && !F->isDeclaration()
9697f37794eSStanislav Mekhanoshin && !F->isVarArg()
9707f37794eSStanislav Mekhanoshin && F->arg_size() == fInfo.getNumArgs()) {
9717f37794eSStanislav Mekhanoshin return F;
9727f37794eSStanislav Mekhanoshin }
9737f37794eSStanislav Mekhanoshin
9747f37794eSStanislav Mekhanoshin FunctionType *FuncTy = fInfo.getFunctionType(*M);
9757f37794eSStanislav Mekhanoshin
9767f37794eSStanislav Mekhanoshin bool hasPtr = false;
9777f37794eSStanislav Mekhanoshin for (FunctionType::param_iterator
9787f37794eSStanislav Mekhanoshin PI = FuncTy->param_begin(),
9797f37794eSStanislav Mekhanoshin PE = FuncTy->param_end();
9807f37794eSStanislav Mekhanoshin PI != PE; ++PI) {
9817f37794eSStanislav Mekhanoshin const Type* argTy = static_cast<const Type*>(*PI);
9827f37794eSStanislav Mekhanoshin if (argTy->isPointerTy()) {
9837f37794eSStanislav Mekhanoshin hasPtr = true;
9847f37794eSStanislav Mekhanoshin break;
9857f37794eSStanislav Mekhanoshin }
9867f37794eSStanislav Mekhanoshin }
9877f37794eSStanislav Mekhanoshin
98813680223SJames Y Knight FunctionCallee C;
9897f37794eSStanislav Mekhanoshin if (hasPtr) {
9907f37794eSStanislav Mekhanoshin // Do not set extra attributes for functions with pointer arguments.
9917f37794eSStanislav Mekhanoshin C = M->getOrInsertFunction(FuncName, FuncTy);
9927f37794eSStanislav Mekhanoshin } else {
9937f37794eSStanislav Mekhanoshin AttributeList Attr;
9947f37794eSStanislav Mekhanoshin LLVMContext &Ctx = M->getContext();
995de0ae9e8SArthur Eubanks Attr = Attr.addFnAttribute(Ctx, Attribute::ReadOnly);
996de0ae9e8SArthur Eubanks Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind);
9977f37794eSStanislav Mekhanoshin C = M->getOrInsertFunction(FuncName, FuncTy, Attr);
9987f37794eSStanislav Mekhanoshin }
9997f37794eSStanislav Mekhanoshin
100013680223SJames Y Knight return C;
10017f37794eSStanislav Mekhanoshin }
1002fc5121a7SYaxun Liu
buildNameMap()100385e2cdacSReid Kleckner StringMap<unsigned> UnmangledFuncInfo::buildNameMap() {
100485e2cdacSReid Kleckner StringMap<unsigned> Map;
100585e2cdacSReid Kleckner for (unsigned I = 0; I != TableSize; ++I)
100685e2cdacSReid Kleckner Map[Table[I].Name] = I;
100785e2cdacSReid Kleckner return Map;
100885e2cdacSReid Kleckner }
100985e2cdacSReid Kleckner
lookup(StringRef Name,ID & Id)1010fc5121a7SYaxun Liu bool UnmangledFuncInfo::lookup(StringRef Name, ID &Id) {
101185e2cdacSReid Kleckner static const StringMap<unsigned> Map = buildNameMap();
1012fc5121a7SYaxun Liu auto Loc = Map.find(Name);
1013fc5121a7SYaxun Liu if (Loc != Map.end()) {
1014fc5121a7SYaxun Liu Id = toFuncId(Loc->second);
1015fc5121a7SYaxun Liu return true;
1016fc5121a7SYaxun Liu }
1017fc5121a7SYaxun Liu Id = AMDGPULibFunc::EI_NONE;
1018fc5121a7SYaxun Liu return false;
1019fc5121a7SYaxun Liu }
1020fc5121a7SYaxun Liu
AMDGPULibFunc(const AMDGPULibFunc & F)1021fc5121a7SYaxun Liu AMDGPULibFunc::AMDGPULibFunc(const AMDGPULibFunc &F) {
1022fc5121a7SYaxun Liu if (auto *MF = dyn_cast<AMDGPUMangledLibFunc>(F.Impl.get()))
1023fc5121a7SYaxun Liu Impl.reset(new AMDGPUMangledLibFunc(*MF));
1024fc5121a7SYaxun Liu else if (auto *UMF = dyn_cast<AMDGPUUnmangledLibFunc>(F.Impl.get()))
1025fc5121a7SYaxun Liu Impl.reset(new AMDGPUUnmangledLibFunc(*UMF));
1026fc5121a7SYaxun Liu else
1027fc5121a7SYaxun Liu Impl = std::unique_ptr<AMDGPULibFuncImpl>();
1028fc5121a7SYaxun Liu }
1029fc5121a7SYaxun Liu
operator =(const AMDGPULibFunc & F)1030fc5121a7SYaxun Liu AMDGPULibFunc &AMDGPULibFunc::operator=(const AMDGPULibFunc &F) {
1031fc5121a7SYaxun Liu if (this == &F)
1032fc5121a7SYaxun Liu return *this;
1033fc5121a7SYaxun Liu new (this) AMDGPULibFunc(F);
1034fc5121a7SYaxun Liu return *this;
1035fc5121a7SYaxun Liu }
1036fc5121a7SYaxun Liu
AMDGPULibFunc(EFuncId Id,const AMDGPULibFunc & CopyFrom)1037fc5121a7SYaxun Liu AMDGPULibFunc::AMDGPULibFunc(EFuncId Id, const AMDGPULibFunc &CopyFrom) {
1038fc5121a7SYaxun Liu assert(AMDGPULibFuncBase::isMangled(Id) && CopyFrom.isMangled() &&
1039fc5121a7SYaxun Liu "not supported");
1040fc5121a7SYaxun Liu Impl.reset(new AMDGPUMangledLibFunc(
1041fc5121a7SYaxun Liu Id, *cast<AMDGPUMangledLibFunc>(CopyFrom.Impl.get())));
1042fc5121a7SYaxun Liu }
1043fc5121a7SYaxun Liu
AMDGPULibFunc(StringRef Name,FunctionType * FT)1044fc5121a7SYaxun Liu AMDGPULibFunc::AMDGPULibFunc(StringRef Name, FunctionType *FT) {
1045fc5121a7SYaxun Liu Impl.reset(new AMDGPUUnmangledLibFunc(Name, FT));
1046fc5121a7SYaxun Liu }
1047fc5121a7SYaxun Liu
initMangled()1048fc5121a7SYaxun Liu void AMDGPULibFunc::initMangled() { Impl.reset(new AMDGPUMangledLibFunc()); }
1049fc5121a7SYaxun Liu
getLeads()1050fc5121a7SYaxun Liu AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() {
1051fc5121a7SYaxun Liu if (!Impl)
1052fc5121a7SYaxun Liu initMangled();
1053fc5121a7SYaxun Liu return cast<AMDGPUMangledLibFunc>(Impl.get())->Leads;
1054fc5121a7SYaxun Liu }
1055fc5121a7SYaxun Liu
getLeads() const1056fc5121a7SYaxun Liu const AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() const {
1057fc5121a7SYaxun Liu return cast<const AMDGPUMangledLibFunc>(Impl.get())->Leads;
1058fc5121a7SYaxun Liu }
1059