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 &copyFrom) {
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