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 
667f37794eSStanislav Mekhanoshin    int maxLeadIndex() const { return (std::max)(Lead[0], Lead[1]); }
677f37794eSStanislav 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;
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);
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   }
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   }
106fc5121a7SYaxun Liu   static unsigned getNumArgs(ID Id) { return Table[toIndex(Id)].NumArgs; }
107fc5121a7SYaxun Liu   static StringRef getName(ID Id) { return Table[toIndex(Id)].Name; }
108fc5121a7SYaxun Liu };
109fc5121a7SYaxun Liu 
1107f37794eSStanislav 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 =
35085e2cdacSReid Kleckner     array_lengthof(UnmangledFuncInfo::Table);
3517f37794eSStanislav Mekhanoshin 
3527f37794eSStanislav Mekhanoshin static AMDGPULibFunc::Param getRetType(AMDGPULibFunc::EFuncId id,
3537f37794eSStanislav Mekhanoshin                                        const AMDGPULibFunc::Param (&Leads)[2]) {
3547f37794eSStanislav Mekhanoshin   AMDGPULibFunc::Param Res = Leads[0];
355*dc6e8dfdSJacob 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:
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 
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 
4587f37794eSStanislav Mekhanoshin     default: llvm_unreachable("Unhandeled param rule");
4597f37794eSStanislav Mekhanoshin     }
4607f37794eSStanislav Mekhanoshin   }
4617f37794eSStanislav Mekhanoshin   ++Index;
4627f37794eSStanislav Mekhanoshin   return P;
4637f37794eSStanislav Mekhanoshin }
4647f37794eSStanislav Mekhanoshin 
4657f37794eSStanislav Mekhanoshin inline static void drop_front(StringRef& str, size_t n = 1) {
4667f37794eSStanislav Mekhanoshin   str = str.drop_front(n);
4677f37794eSStanislav Mekhanoshin }
4687f37794eSStanislav Mekhanoshin 
4697f37794eSStanislav Mekhanoshin static bool eatTerm(StringRef& mangledName, const char c) {
4707f37794eSStanislav Mekhanoshin   if (mangledName.front() == c) {
4717f37794eSStanislav Mekhanoshin     drop_front(mangledName);
4727f37794eSStanislav Mekhanoshin     return true;
4737f37794eSStanislav Mekhanoshin   }
4747f37794eSStanislav Mekhanoshin   return false;
4757f37794eSStanislav Mekhanoshin }
4767f37794eSStanislav Mekhanoshin 
4777f37794eSStanislav Mekhanoshin template <size_t N>
4787f37794eSStanislav Mekhanoshin static bool eatTerm(StringRef& mangledName, const char (&str)[N]) {
4797f37794eSStanislav Mekhanoshin   if (mangledName.startswith(StringRef(str, N-1))) {
4807f37794eSStanislav Mekhanoshin     drop_front(mangledName, N-1);
4817f37794eSStanislav Mekhanoshin     return true;
4827f37794eSStanislav Mekhanoshin   }
4837f37794eSStanislav Mekhanoshin   return false;
4847f37794eSStanislav Mekhanoshin }
4857f37794eSStanislav Mekhanoshin 
4867f37794eSStanislav Mekhanoshin static int eatNumber(StringRef& s) {
4877f37794eSStanislav Mekhanoshin   size_t const savedSize = s.size();
4887f37794eSStanislav Mekhanoshin   int n = 0;
4897f37794eSStanislav Mekhanoshin   while (!s.empty() && isDigit(s.front())) {
4907f37794eSStanislav Mekhanoshin     n = n*10 + s.front() - '0';
4917f37794eSStanislav Mekhanoshin     drop_front(s);
4927f37794eSStanislav Mekhanoshin   }
4937f37794eSStanislav Mekhanoshin   return s.size() < savedSize ? n : -1;
4947f37794eSStanislav Mekhanoshin }
4957f37794eSStanislav Mekhanoshin 
4967f37794eSStanislav Mekhanoshin static StringRef eatLengthPrefixedName(StringRef& mangledName) {
4977f37794eSStanislav Mekhanoshin   int const Len = eatNumber(mangledName);
4987f37794eSStanislav Mekhanoshin   if (Len <= 0 || static_cast<size_t>(Len) > mangledName.size())
4997f37794eSStanislav Mekhanoshin     return StringRef();
5007f37794eSStanislav Mekhanoshin   StringRef Res = mangledName.substr(0, Len);
5017f37794eSStanislav Mekhanoshin   drop_front(mangledName, Len);
5027f37794eSStanislav Mekhanoshin   return Res;
5037f37794eSStanislav Mekhanoshin }
5047f37794eSStanislav Mekhanoshin 
5057f37794eSStanislav Mekhanoshin } // end anonymous namespace
5067f37794eSStanislav Mekhanoshin 
507fc5121a7SYaxun Liu AMDGPUMangledLibFunc::AMDGPUMangledLibFunc() {
5087f37794eSStanislav Mekhanoshin   FuncId = EI_NONE;
5097f37794eSStanislav Mekhanoshin   FKind = NOPFX;
5107f37794eSStanislav Mekhanoshin   Leads[0].reset();
5117f37794eSStanislav Mekhanoshin   Leads[1].reset();
5127f37794eSStanislav Mekhanoshin   Name.clear();
5137f37794eSStanislav Mekhanoshin }
5147f37794eSStanislav Mekhanoshin 
515fc5121a7SYaxun Liu AMDGPUUnmangledLibFunc::AMDGPUUnmangledLibFunc() {
516fc5121a7SYaxun Liu   FuncId = EI_NONE;
517fc5121a7SYaxun Liu   FuncTy = nullptr;
518fc5121a7SYaxun Liu }
519fc5121a7SYaxun Liu 
520fc5121a7SYaxun Liu AMDGPUMangledLibFunc::AMDGPUMangledLibFunc(
521fc5121a7SYaxun Liu     EFuncId id, const AMDGPUMangledLibFunc &copyFrom) {
522fc5121a7SYaxun Liu   FuncId = id;
523fc5121a7SYaxun Liu   FKind = copyFrom.FKind;
524fc5121a7SYaxun Liu   Leads[0] = copyFrom.Leads[0];
525fc5121a7SYaxun Liu   Leads[1] = copyFrom.Leads[1];
526fc5121a7SYaxun Liu }
527fc5121a7SYaxun Liu 
5287f37794eSStanislav Mekhanoshin ///////////////////////////////////////////////////////////////////////////////
5297f37794eSStanislav Mekhanoshin // Demangling
5307f37794eSStanislav Mekhanoshin 
5317f37794eSStanislav Mekhanoshin static int parseVecSize(StringRef& mangledName) {
5327f37794eSStanislav Mekhanoshin   size_t const Len = eatNumber(mangledName);
5337f37794eSStanislav Mekhanoshin   switch (Len) {
5347f37794eSStanislav Mekhanoshin   case 2: case 3: case 4: case 8: case 16:
5357f37794eSStanislav Mekhanoshin     return Len;
5367f37794eSStanislav Mekhanoshin   default:
5377f37794eSStanislav Mekhanoshin     break;
5387f37794eSStanislav Mekhanoshin   }
5397f37794eSStanislav Mekhanoshin   return 1;
5407f37794eSStanislav Mekhanoshin }
5417f37794eSStanislav Mekhanoshin 
5427f37794eSStanislav Mekhanoshin static AMDGPULibFunc::ENamePrefix parseNamePrefix(StringRef& mangledName) {
5437f37794eSStanislav Mekhanoshin   std::pair<StringRef, StringRef> const P = mangledName.split('_');
5447f37794eSStanislav Mekhanoshin   AMDGPULibFunc::ENamePrefix Pfx =
5457f37794eSStanislav Mekhanoshin     StringSwitch<AMDGPULibFunc::ENamePrefix>(P.first)
5467f37794eSStanislav Mekhanoshin     .Case("native", AMDGPULibFunc::NATIVE)
5477f37794eSStanislav Mekhanoshin     .Case("half"  , AMDGPULibFunc::HALF)
5487f37794eSStanislav Mekhanoshin     .Default(AMDGPULibFunc::NOPFX);
5497f37794eSStanislav Mekhanoshin 
5507f37794eSStanislav Mekhanoshin   if (Pfx != AMDGPULibFunc::NOPFX)
5517f37794eSStanislav Mekhanoshin     mangledName = P.second;
5527f37794eSStanislav Mekhanoshin 
5537f37794eSStanislav Mekhanoshin   return Pfx;
5547f37794eSStanislav Mekhanoshin }
5557f37794eSStanislav Mekhanoshin 
55685e2cdacSReid Kleckner StringMap<int> ManglingRule::buildManglingRulesMap() {
55785e2cdacSReid Kleckner   StringMap<int> Map(array_lengthof(manglingRules));
55885e2cdacSReid Kleckner   int Id = 0;
55985e2cdacSReid Kleckner   for (auto Rule : manglingRules)
56085e2cdacSReid Kleckner     Map.insert({Rule.Name, Id++});
56185e2cdacSReid Kleckner   return Map;
56285e2cdacSReid Kleckner }
56385e2cdacSReid Kleckner 
564fc5121a7SYaxun Liu bool AMDGPUMangledLibFunc::parseUnmangledName(StringRef FullName) {
56585e2cdacSReid Kleckner   static const StringMap<int> manglingRulesMap =
56685e2cdacSReid Kleckner       ManglingRule::buildManglingRulesMap();
567fc5121a7SYaxun Liu   FuncId = static_cast<EFuncId>(manglingRulesMap.lookup(FullName));
5687f37794eSStanislav Mekhanoshin   return FuncId != EI_NONE;
5697f37794eSStanislav Mekhanoshin }
5707f37794eSStanislav Mekhanoshin 
5717f37794eSStanislav Mekhanoshin ///////////////////////////////////////////////////////////////////////////////
5727f37794eSStanislav Mekhanoshin // Itanium Demangling
5737f37794eSStanislav Mekhanoshin 
57449a49fe8SBenjamin Kramer namespace {
5757f37794eSStanislav Mekhanoshin struct ItaniumParamParser {
5767f37794eSStanislav Mekhanoshin   AMDGPULibFunc::Param Prev;
5777f37794eSStanislav Mekhanoshin   bool parseItaniumParam(StringRef& param, AMDGPULibFunc::Param &res);
5787f37794eSStanislav Mekhanoshin };
57949a49fe8SBenjamin Kramer } // namespace
5807f37794eSStanislav Mekhanoshin 
5817f37794eSStanislav Mekhanoshin bool ItaniumParamParser::parseItaniumParam(StringRef& param,
5827f37794eSStanislav Mekhanoshin                                            AMDGPULibFunc::Param &res) {
5837f37794eSStanislav Mekhanoshin   res.reset();
5847f37794eSStanislav Mekhanoshin   if (param.empty()) return false;
5857f37794eSStanislav Mekhanoshin 
5867f37794eSStanislav Mekhanoshin   // parse pointer prefix
5877f37794eSStanislav Mekhanoshin   if (eatTerm(param, 'P')) {
5887f37794eSStanislav Mekhanoshin     if (eatTerm(param, 'K')) res.PtrKind |= AMDGPULibFunc::CONST;
5897f37794eSStanislav Mekhanoshin     if (eatTerm(param, 'V')) res.PtrKind |= AMDGPULibFunc::VOLATILE;
5900d9673cfSYaxun Liu     unsigned AS;
5917f37794eSStanislav Mekhanoshin     if (!eatTerm(param, "U3AS")) {
5920d9673cfSYaxun Liu       AS = 0;
5937f37794eSStanislav Mekhanoshin     } else {
5940d9673cfSYaxun Liu       AS = param.front() - '0';
5957f37794eSStanislav Mekhanoshin       drop_front(param, 1);
5967f37794eSStanislav Mekhanoshin     }
5970d9673cfSYaxun Liu     res.PtrKind |= AMDGPULibFuncBase::getEPtrKindFromAddrSpace(AS);
5987f37794eSStanislav Mekhanoshin   } else {
5997f37794eSStanislav Mekhanoshin     res.PtrKind = AMDGPULibFunc::BYVALUE;
6007f37794eSStanislav Mekhanoshin   }
6017f37794eSStanislav Mekhanoshin 
6027f37794eSStanislav Mekhanoshin   // parse vector size
6037f37794eSStanislav Mekhanoshin   if (eatTerm(param,"Dv")) {
6047f37794eSStanislav Mekhanoshin     res.VectorSize = parseVecSize(param);
6057f37794eSStanislav Mekhanoshin     if (res.VectorSize==1 || !eatTerm(param, '_')) return false;
6067f37794eSStanislav Mekhanoshin   }
6077f37794eSStanislav Mekhanoshin 
6087f37794eSStanislav Mekhanoshin   // parse type
6097f37794eSStanislav Mekhanoshin   char const TC = param.front();
6108105935dSSander de Smalen   if (isDigit(TC)) {
6117f37794eSStanislav Mekhanoshin     res.ArgType = StringSwitch<AMDGPULibFunc::EType>
6127f37794eSStanislav Mekhanoshin       (eatLengthPrefixedName(param))
6137f37794eSStanislav Mekhanoshin       .Case("ocl_image1darray" , AMDGPULibFunc::IMG1DA)
6147f37794eSStanislav Mekhanoshin       .Case("ocl_image1dbuffer", AMDGPULibFunc::IMG1DB)
6157f37794eSStanislav Mekhanoshin       .Case("ocl_image2darray" , AMDGPULibFunc::IMG2DA)
6167f37794eSStanislav Mekhanoshin       .Case("ocl_image1d"      , AMDGPULibFunc::IMG1D)
6177f37794eSStanislav Mekhanoshin       .Case("ocl_image2d"      , AMDGPULibFunc::IMG2D)
6187f37794eSStanislav Mekhanoshin       .Case("ocl_image3d"      , AMDGPULibFunc::IMG3D)
6197f37794eSStanislav Mekhanoshin       .Case("ocl_event"        , AMDGPULibFunc::DUMMY)
6207f37794eSStanislav Mekhanoshin       .Case("ocl_sampler"      , AMDGPULibFunc::DUMMY)
6217f37794eSStanislav Mekhanoshin       .Default(AMDGPULibFunc::DUMMY);
6227f37794eSStanislav Mekhanoshin   } else {
6237f37794eSStanislav Mekhanoshin     drop_front(param);
6247f37794eSStanislav Mekhanoshin     switch (TC) {
6257f37794eSStanislav Mekhanoshin     case 'h': res.ArgType =  AMDGPULibFunc::U8; break;
6267f37794eSStanislav Mekhanoshin     case 't': res.ArgType = AMDGPULibFunc::U16; break;
6277f37794eSStanislav Mekhanoshin     case 'j': res.ArgType = AMDGPULibFunc::U32; break;
6287f37794eSStanislav Mekhanoshin     case 'm': res.ArgType = AMDGPULibFunc::U64; break;
6297f37794eSStanislav Mekhanoshin     case 'c': res.ArgType =  AMDGPULibFunc::I8; break;
6307f37794eSStanislav Mekhanoshin     case 's': res.ArgType = AMDGPULibFunc::I16; break;
6317f37794eSStanislav Mekhanoshin     case 'i': res.ArgType = AMDGPULibFunc::I32; break;
6327f37794eSStanislav Mekhanoshin     case 'l': res.ArgType = AMDGPULibFunc::I64; break;
6337f37794eSStanislav Mekhanoshin     case 'f': res.ArgType = AMDGPULibFunc::F32; break;
6347f37794eSStanislav Mekhanoshin     case 'd': res.ArgType = AMDGPULibFunc::F64; break;
6357f37794eSStanislav Mekhanoshin     case 'D': if (!eatTerm(param, 'h')) return false;
6367f37794eSStanislav Mekhanoshin               res.ArgType = AMDGPULibFunc::F16; break;
6377f37794eSStanislav Mekhanoshin     case 'S':
6387f37794eSStanislav Mekhanoshin       if (!eatTerm(param, '_')) {
6397f37794eSStanislav Mekhanoshin         eatNumber(param);
6407f37794eSStanislav Mekhanoshin         if (!eatTerm(param, '_')) return false;
6417f37794eSStanislav Mekhanoshin       }
6427f37794eSStanislav Mekhanoshin       res.VectorSize = Prev.VectorSize;
6437f37794eSStanislav Mekhanoshin       res.ArgType    = Prev.ArgType;
6447f37794eSStanislav Mekhanoshin       break;
6457f37794eSStanislav Mekhanoshin     default:;
6467f37794eSStanislav Mekhanoshin     }
6477f37794eSStanislav Mekhanoshin   }
6487f37794eSStanislav Mekhanoshin   if (res.ArgType == 0) return false;
6497f37794eSStanislav Mekhanoshin   Prev.VectorSize = res.VectorSize;
6507f37794eSStanislav Mekhanoshin   Prev.ArgType    = res.ArgType;
6517f37794eSStanislav Mekhanoshin   return true;
6527f37794eSStanislav Mekhanoshin }
6537f37794eSStanislav Mekhanoshin 
654fc5121a7SYaxun Liu bool AMDGPUMangledLibFunc::parseFuncName(StringRef &mangledName) {
6557f37794eSStanislav Mekhanoshin   StringRef Name = eatLengthPrefixedName(mangledName);
6567f37794eSStanislav Mekhanoshin   FKind = parseNamePrefix(Name);
657fc5121a7SYaxun Liu   if (!parseUnmangledName(Name))
658fc5121a7SYaxun Liu     return false;
6597f37794eSStanislav Mekhanoshin 
6607f37794eSStanislav Mekhanoshin   const ManglingRule& Rule = manglingRules[FuncId];
6617f37794eSStanislav Mekhanoshin   ItaniumParamParser Parser;
6627f37794eSStanislav Mekhanoshin   for (int I=0; I < Rule.maxLeadIndex(); ++I) {
6637f37794eSStanislav Mekhanoshin     Param P;
6647f37794eSStanislav Mekhanoshin     if (!Parser.parseItaniumParam(mangledName, P))
6657f37794eSStanislav Mekhanoshin       return false;
6667f37794eSStanislav Mekhanoshin 
6677f37794eSStanislav Mekhanoshin     if ((I + 1) == Rule.Lead[0]) Leads[0] = P;
6687f37794eSStanislav Mekhanoshin     if ((I + 1) == Rule.Lead[1]) Leads[1] = P;
6697f37794eSStanislav Mekhanoshin   }
6707f37794eSStanislav Mekhanoshin   return true;
6717f37794eSStanislav Mekhanoshin }
6727f37794eSStanislav Mekhanoshin 
673fc5121a7SYaxun Liu bool AMDGPUUnmangledLibFunc::parseFuncName(StringRef &Name) {
674fc5121a7SYaxun Liu   if (!UnmangledFuncInfo::lookup(Name, FuncId))
6757f37794eSStanislav Mekhanoshin     return false;
676fc5121a7SYaxun Liu   setName(Name);
677fc5121a7SYaxun Liu   return true;
6787f37794eSStanislav Mekhanoshin }
679fc5121a7SYaxun Liu 
680fc5121a7SYaxun Liu bool AMDGPULibFunc::parse(StringRef FuncName, AMDGPULibFunc &F) {
681fc5121a7SYaxun Liu   if (FuncName.empty()) {
682fc5121a7SYaxun Liu     F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
6837f37794eSStanislav Mekhanoshin     return false;
6847f37794eSStanislav Mekhanoshin   }
6857f37794eSStanislav Mekhanoshin 
686fc5121a7SYaxun Liu   if (eatTerm(FuncName, "_Z"))
6870eaee545SJonas Devlieghere     F.Impl = std::make_unique<AMDGPUMangledLibFunc>();
688fc5121a7SYaxun Liu   else
6890eaee545SJonas Devlieghere     F.Impl = std::make_unique<AMDGPUUnmangledLibFunc>();
690fc5121a7SYaxun Liu   if (F.Impl->parseFuncName(FuncName))
691fc5121a7SYaxun Liu     return true;
692fc5121a7SYaxun Liu 
693fc5121a7SYaxun Liu   F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
694fc5121a7SYaxun Liu   return false;
695fc5121a7SYaxun Liu }
696fc5121a7SYaxun Liu 
697fc5121a7SYaxun Liu StringRef AMDGPUMangledLibFunc::getUnmangledName(StringRef mangledName) {
6987f37794eSStanislav Mekhanoshin   StringRef S = mangledName;
6997f37794eSStanislav Mekhanoshin   if (eatTerm(S, "_Z"))
7007f37794eSStanislav Mekhanoshin     return eatLengthPrefixedName(S);
7017f37794eSStanislav Mekhanoshin   return StringRef();
7027f37794eSStanislav Mekhanoshin }
7037f37794eSStanislav Mekhanoshin 
7047f37794eSStanislav Mekhanoshin ///////////////////////////////////////////////////////////////////////////////
7057f37794eSStanislav Mekhanoshin // Mangling
7067f37794eSStanislav Mekhanoshin 
7077f37794eSStanislav Mekhanoshin template <typename Stream>
708fc5121a7SYaxun Liu void AMDGPUMangledLibFunc::writeName(Stream &OS) const {
7097f37794eSStanislav Mekhanoshin   const char *Pfx = "";
7107f37794eSStanislav Mekhanoshin   switch (FKind) {
7117f37794eSStanislav Mekhanoshin   case NATIVE: Pfx = "native_"; break;
7127f37794eSStanislav Mekhanoshin   case HALF:   Pfx = "half_";   break;
7137f37794eSStanislav Mekhanoshin   default: break;
7147f37794eSStanislav Mekhanoshin   }
7157f37794eSStanislav Mekhanoshin   if (!Name.empty()) {
7167f37794eSStanislav Mekhanoshin     OS << Pfx << Name;
7177f37794eSStanislav Mekhanoshin   } else if (FuncId != EI_NONE) {
7187f37794eSStanislav Mekhanoshin     OS << Pfx;
7197f37794eSStanislav Mekhanoshin     const StringRef& S = manglingRules[FuncId].Name;
7207f37794eSStanislav Mekhanoshin     OS.write(S.data(), S.size());
7217f37794eSStanislav Mekhanoshin   }
7227f37794eSStanislav Mekhanoshin }
7237f37794eSStanislav Mekhanoshin 
724fc5121a7SYaxun Liu std::string AMDGPUMangledLibFunc::mangle() const { return mangleNameItanium(); }
7257f37794eSStanislav Mekhanoshin 
7267f37794eSStanislav Mekhanoshin ///////////////////////////////////////////////////////////////////////////////
7277f37794eSStanislav Mekhanoshin // Itanium Mangling
7287f37794eSStanislav Mekhanoshin 
7297f37794eSStanislav Mekhanoshin static const char *getItaniumTypeName(AMDGPULibFunc::EType T) {
7307f37794eSStanislav Mekhanoshin   switch (T) {
7317f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::U8:      return "h";
7327f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::U16:     return "t";
7337f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::U32:     return "j";
7347f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::U64:     return "m";
7357f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::I8:      return "c";
7367f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::I16:     return "s";
7377f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::I32:     return "i";
7387f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::I64:     return "l";
7397f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::F16:     return "Dh";
7407f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::F32:     return "f";
7417f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::F64:     return "d";
7427f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG1DA:  return "16ocl_image1darray";
7437f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG1DB:  return "17ocl_image1dbuffer";
7447f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG2DA:  return "16ocl_image2darray";
7457f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG1D:   return "11ocl_image1d";
7467f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG2D:   return "11ocl_image2d";
7477f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG3D:   return "11ocl_image3d";
7487f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::SAMPLER: return "11ocl_sampler";
7497f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::EVENT:   return "9ocl_event";
7507f37794eSStanislav Mekhanoshin   default: llvm_unreachable("Unhandeled param type");
7517f37794eSStanislav Mekhanoshin   }
7527f37794eSStanislav Mekhanoshin   return nullptr;
7537f37794eSStanislav Mekhanoshin }
7547f37794eSStanislav Mekhanoshin 
75549a49fe8SBenjamin Kramer namespace {
7567f37794eSStanislav Mekhanoshin // Itanium mangling ABI says:
7577f37794eSStanislav Mekhanoshin // "5.1.8. Compression
7587f37794eSStanislav Mekhanoshin // ... Each non-terminal in the grammar for which <substitution> appears on the
7597f37794eSStanislav Mekhanoshin // right-hand side is both a source of future substitutions and a candidate
7607f37794eSStanislav Mekhanoshin // for being substituted. There are two exceptions that appear to be
7617f37794eSStanislav Mekhanoshin // substitution candidates from the grammar, but are explicitly excluded:
7627f37794eSStanislav Mekhanoshin // 1. <builtin-type> other than vendor extended types ..."
7637f37794eSStanislav Mekhanoshin 
7647f37794eSStanislav Mekhanoshin // For the purpose of functions the following productions make sence for the
7657f37794eSStanislav Mekhanoshin // substitution:
7667f37794eSStanislav Mekhanoshin //  <type> ::= <builtin-type>
7677f37794eSStanislav Mekhanoshin //    ::= <class-enum-type>
7687f37794eSStanislav Mekhanoshin //    ::= <array-type>
7697f37794eSStanislav Mekhanoshin //    ::=<CV-qualifiers> <type>
7707f37794eSStanislav Mekhanoshin //    ::= P <type>                # pointer-to
7717f37794eSStanislav Mekhanoshin //    ::= <substitution>
7727f37794eSStanislav Mekhanoshin //
7737f37794eSStanislav Mekhanoshin // Note that while types like images, samplers and events are by the ABI encoded
7747f37794eSStanislav Mekhanoshin // using <class-enum-type> production rule they're not used for substitution
7757f37794eSStanislav Mekhanoshin // because clang consider them as builtin types.
7767f37794eSStanislav Mekhanoshin //
7777f37794eSStanislav Mekhanoshin // DvNN_ type is GCC extension for vectors and is a subject for the substitution.
7787f37794eSStanislav Mekhanoshin 
7797f37794eSStanislav Mekhanoshin 
7807f37794eSStanislav Mekhanoshin class ItaniumMangler {
781*dc6e8dfdSJacob Lambert   SmallVector<AMDGPULibFunc::Param, 10> Str; // list of accumulated substitutions
7827f37794eSStanislav Mekhanoshin   bool  UseAddrSpace;
7837f37794eSStanislav Mekhanoshin 
7847f37794eSStanislav Mekhanoshin   int findSubst(const AMDGPULibFunc::Param& P) const {
7857f37794eSStanislav Mekhanoshin     for(unsigned I = 0; I < Str.size(); ++I) {
7867f37794eSStanislav Mekhanoshin       const AMDGPULibFunc::Param& T = Str[I];
7877f37794eSStanislav Mekhanoshin       if (P.PtrKind    == T.PtrKind &&
7887f37794eSStanislav Mekhanoshin           P.VectorSize == T.VectorSize &&
7897f37794eSStanislav Mekhanoshin           P.ArgType    == T.ArgType) {
7907f37794eSStanislav Mekhanoshin         return I;
7917f37794eSStanislav Mekhanoshin       }
7927f37794eSStanislav Mekhanoshin     }
7937f37794eSStanislav Mekhanoshin     return -1;
7947f37794eSStanislav Mekhanoshin   }
7957f37794eSStanislav Mekhanoshin 
7967f37794eSStanislav Mekhanoshin   template <typename Stream>
7977f37794eSStanislav Mekhanoshin   bool trySubst(Stream& os, const AMDGPULibFunc::Param& p) {
7987f37794eSStanislav Mekhanoshin     int const subst = findSubst(p);
7997f37794eSStanislav Mekhanoshin     if (subst < 0) return false;
8007f37794eSStanislav Mekhanoshin     // Substitutions are mangled as S(XX)?_ where XX is a hexadecimal number
8017f37794eSStanislav Mekhanoshin     // 0   1    2
8027f37794eSStanislav Mekhanoshin     // S_  S0_  S1_
8037f37794eSStanislav Mekhanoshin     if (subst == 0) os << "S_";
8047f37794eSStanislav Mekhanoshin     else os << 'S' << (subst-1) << '_';
8057f37794eSStanislav Mekhanoshin     return true;
8067f37794eSStanislav Mekhanoshin   }
8077f37794eSStanislav Mekhanoshin 
8087f37794eSStanislav Mekhanoshin public:
8097f37794eSStanislav Mekhanoshin   ItaniumMangler(bool useAddrSpace)
8107f37794eSStanislav Mekhanoshin     : UseAddrSpace(useAddrSpace) {}
8117f37794eSStanislav Mekhanoshin 
8127f37794eSStanislav Mekhanoshin   template <typename Stream>
8137f37794eSStanislav Mekhanoshin   void operator()(Stream& os, AMDGPULibFunc::Param p) {
8147f37794eSStanislav Mekhanoshin 
8157f37794eSStanislav Mekhanoshin     // Itanium mangling ABI 5.1.8. Compression:
8167f37794eSStanislav Mekhanoshin     // Logically, the substitutable components of a mangled name are considered
8177f37794eSStanislav Mekhanoshin     // left-to-right, components before the composite structure of which they
8187f37794eSStanislav Mekhanoshin     // are a part. If a component has been encountered before, it is substituted
8197f37794eSStanislav Mekhanoshin     // as described below. This decision is independent of whether its components
8207f37794eSStanislav Mekhanoshin     // have been substituted, so an implementation may optimize by considering
8217f37794eSStanislav Mekhanoshin     // large structures for substitution before their components. If a component
8227f37794eSStanislav Mekhanoshin     // has not been encountered before, its mangling is identified, and it is
8237f37794eSStanislav Mekhanoshin     // added to a dictionary of substitution candidates. No entity is added to
8247f37794eSStanislav Mekhanoshin     // the dictionary twice.
8257f37794eSStanislav Mekhanoshin     AMDGPULibFunc::Param Ptr;
8267f37794eSStanislav Mekhanoshin 
8277f37794eSStanislav Mekhanoshin     if (p.PtrKind) {
8287f37794eSStanislav Mekhanoshin       if (trySubst(os, p)) return;
8297f37794eSStanislav Mekhanoshin       os << 'P';
8307f37794eSStanislav Mekhanoshin       if (p.PtrKind & AMDGPULibFunc::CONST) os << 'K';
8317f37794eSStanislav Mekhanoshin       if (p.PtrKind & AMDGPULibFunc::VOLATILE) os << 'V';
8320d9673cfSYaxun Liu       unsigned AS = UseAddrSpace
8330d9673cfSYaxun Liu                         ? AMDGPULibFuncBase::getAddrSpaceFromEPtrKind(p.PtrKind)
8340d9673cfSYaxun Liu                         : 0;
83527332968SMichael Liao       if (EnableOCLManglingMismatchWA || AS != 0)
83627332968SMichael Liao         os << "U3AS" << AS;
8377f37794eSStanislav Mekhanoshin       Ptr = p;
8387f37794eSStanislav Mekhanoshin       p.PtrKind = 0;
8397f37794eSStanislav Mekhanoshin     }
8407f37794eSStanislav Mekhanoshin 
8417f37794eSStanislav Mekhanoshin     if (p.VectorSize > 1) {
8427f37794eSStanislav Mekhanoshin       if (trySubst(os, p)) goto exit;
8437f37794eSStanislav Mekhanoshin       Str.push_back(p);
8447f37794eSStanislav Mekhanoshin       os << "Dv" << static_cast<unsigned>(p.VectorSize) << '_';
8457f37794eSStanislav Mekhanoshin     }
8467f37794eSStanislav Mekhanoshin 
8477f37794eSStanislav Mekhanoshin     os << getItaniumTypeName((AMDGPULibFunc::EType)p.ArgType);
8487f37794eSStanislav Mekhanoshin 
8497f37794eSStanislav Mekhanoshin   exit:
8507f37794eSStanislav Mekhanoshin     if (Ptr.ArgType) Str.push_back(Ptr);
8517f37794eSStanislav Mekhanoshin   }
8527f37794eSStanislav Mekhanoshin };
85349a49fe8SBenjamin Kramer } // namespace
8547f37794eSStanislav Mekhanoshin 
855fc5121a7SYaxun Liu std::string AMDGPUMangledLibFunc::mangleNameItanium() const {
8567f37794eSStanislav Mekhanoshin   SmallString<128> Buf;
8577f37794eSStanislav Mekhanoshin   raw_svector_ostream S(Buf);
8587f37794eSStanislav Mekhanoshin   SmallString<128> NameBuf;
8597f37794eSStanislav Mekhanoshin   raw_svector_ostream Name(NameBuf);
8607f37794eSStanislav Mekhanoshin   writeName(Name);
8617f37794eSStanislav Mekhanoshin   const StringRef& NameStr = Name.str();
8627f37794eSStanislav Mekhanoshin   S << "_Z" << static_cast<int>(NameStr.size()) << NameStr;
8637f37794eSStanislav Mekhanoshin 
8647f37794eSStanislav Mekhanoshin   ItaniumMangler Mangler(true);
8657f37794eSStanislav Mekhanoshin   ParamIterator I(Leads, manglingRules[FuncId]);
8667f37794eSStanislav Mekhanoshin   Param P;
8677f37794eSStanislav Mekhanoshin   while ((P = I.getNextParam()).ArgType != 0)
8687f37794eSStanislav Mekhanoshin     Mangler(S, P);
869adcd0268SBenjamin Kramer   return std::string(S.str());
8707f37794eSStanislav Mekhanoshin }
8717f37794eSStanislav Mekhanoshin 
8727f37794eSStanislav Mekhanoshin ///////////////////////////////////////////////////////////////////////////////
8737f37794eSStanislav Mekhanoshin // Misc
8747f37794eSStanislav Mekhanoshin 
8757f37794eSStanislav Mekhanoshin static Type* getIntrinsicParamType(
8767f37794eSStanislav Mekhanoshin   LLVMContext& C,
8777f37794eSStanislav Mekhanoshin   const AMDGPULibFunc::Param& P,
8787f37794eSStanislav Mekhanoshin   bool useAddrSpace) {
8797f37794eSStanislav Mekhanoshin   Type* T = nullptr;
8807f37794eSStanislav Mekhanoshin   switch (P.ArgType) {
8817f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::U8:
8827f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::I8:   T = Type::getInt8Ty(C);   break;
8837f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::U16:
8847f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::I16:  T = Type::getInt16Ty(C);  break;
8857f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::U32:
8867f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::I32:  T = Type::getInt32Ty(C);  break;
8877f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::U64:
8887f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::I64:  T = Type::getInt64Ty(C);  break;
8897f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::F16:  T = Type::getHalfTy(C);   break;
8907f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::F32:  T = Type::getFloatTy(C);  break;
8917f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::F64:  T = Type::getDoubleTy(C); break;
8927f37794eSStanislav Mekhanoshin 
8937f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG1DA:
8947f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG1DB:
8957f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG2DA:
8967f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG1D:
8977f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG2D:
8987f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::IMG3D:
8997f37794eSStanislav Mekhanoshin     T = StructType::create(C,"ocl_image")->getPointerTo(); break;
9007f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::SAMPLER:
9017f37794eSStanislav Mekhanoshin     T = StructType::create(C,"ocl_sampler")->getPointerTo(); break;
9027f37794eSStanislav Mekhanoshin   case AMDGPULibFunc::EVENT:
9037f37794eSStanislav Mekhanoshin     T = StructType::create(C,"ocl_event")->getPointerTo(); break;
9047f37794eSStanislav Mekhanoshin   default:
9057f37794eSStanislav Mekhanoshin     llvm_unreachable("Unhandeled param type");
9067f37794eSStanislav Mekhanoshin     return nullptr;
9077f37794eSStanislav Mekhanoshin   }
9087f37794eSStanislav Mekhanoshin   if (P.VectorSize > 1)
909aad93654SChristopher Tetreault     T = FixedVectorType::get(T, P.VectorSize);
9107f37794eSStanislav Mekhanoshin   if (P.PtrKind != AMDGPULibFunc::BYVALUE)
9117f37794eSStanislav Mekhanoshin     T = useAddrSpace ? T->getPointerTo((P.PtrKind & AMDGPULibFunc::ADDR_SPACE)
9127f37794eSStanislav Mekhanoshin                                        - 1)
9137f37794eSStanislav Mekhanoshin                      : T->getPointerTo();
9147f37794eSStanislav Mekhanoshin   return T;
9157f37794eSStanislav Mekhanoshin }
9167f37794eSStanislav Mekhanoshin 
917fc5121a7SYaxun Liu FunctionType *AMDGPUMangledLibFunc::getFunctionType(Module &M) const {
9187f37794eSStanislav Mekhanoshin   LLVMContext& C = M.getContext();
9197f37794eSStanislav Mekhanoshin   std::vector<Type*> Args;
9207f37794eSStanislav Mekhanoshin   ParamIterator I(Leads, manglingRules[FuncId]);
9217f37794eSStanislav Mekhanoshin   Param P;
9227f37794eSStanislav Mekhanoshin   while ((P=I.getNextParam()).ArgType != 0)
9237f37794eSStanislav Mekhanoshin     Args.push_back(getIntrinsicParamType(C, P, true));
9247f37794eSStanislav Mekhanoshin 
9257f37794eSStanislav Mekhanoshin   return FunctionType::get(
9267f37794eSStanislav Mekhanoshin     getIntrinsicParamType(C, getRetType(FuncId, Leads), true),
9277f37794eSStanislav Mekhanoshin     Args, false);
9287f37794eSStanislav Mekhanoshin }
9297f37794eSStanislav Mekhanoshin 
930fc5121a7SYaxun Liu unsigned AMDGPUMangledLibFunc::getNumArgs() const {
9317f37794eSStanislav Mekhanoshin   return manglingRules[FuncId].getNumArgs();
9327f37794eSStanislav Mekhanoshin }
9337f37794eSStanislav Mekhanoshin 
934fc5121a7SYaxun Liu unsigned AMDGPUUnmangledLibFunc::getNumArgs() const {
935fc5121a7SYaxun Liu   return UnmangledFuncInfo::getNumArgs(FuncId);
936fc5121a7SYaxun Liu }
937fc5121a7SYaxun Liu 
938fc5121a7SYaxun Liu std::string AMDGPUMangledLibFunc::getName() const {
9397f37794eSStanislav Mekhanoshin   SmallString<128> Buf;
9407f37794eSStanislav Mekhanoshin   raw_svector_ostream OS(Buf);
9417f37794eSStanislav Mekhanoshin   writeName(OS);
942adcd0268SBenjamin Kramer   return std::string(OS.str());
9437f37794eSStanislav Mekhanoshin }
9447f37794eSStanislav Mekhanoshin 
9457f37794eSStanislav Mekhanoshin Function *AMDGPULibFunc::getFunction(Module *M, const AMDGPULibFunc &fInfo) {
9467f37794eSStanislav Mekhanoshin   std::string FuncName = fInfo.mangle();
9477f37794eSStanislav Mekhanoshin   Function *F = dyn_cast_or_null<Function>(
9487f37794eSStanislav Mekhanoshin     M->getValueSymbolTable().lookup(FuncName));
9497f37794eSStanislav Mekhanoshin 
9507f37794eSStanislav Mekhanoshin   // check formal with actual types conformance
9517f37794eSStanislav Mekhanoshin   if (F && !F->isDeclaration()
9527f37794eSStanislav Mekhanoshin         && !F->isVarArg()
9537f37794eSStanislav Mekhanoshin         && F->arg_size() == fInfo.getNumArgs()) {
9547f37794eSStanislav Mekhanoshin     return F;
9557f37794eSStanislav Mekhanoshin   }
9567f37794eSStanislav Mekhanoshin   return nullptr;
9577f37794eSStanislav Mekhanoshin }
9587f37794eSStanislav Mekhanoshin 
95913680223SJames Y Knight FunctionCallee AMDGPULibFunc::getOrInsertFunction(Module *M,
9607f37794eSStanislav Mekhanoshin                                                   const AMDGPULibFunc &fInfo) {
9617f37794eSStanislav Mekhanoshin   std::string const FuncName = fInfo.mangle();
9627f37794eSStanislav Mekhanoshin   Function *F = dyn_cast_or_null<Function>(
9637f37794eSStanislav Mekhanoshin     M->getValueSymbolTable().lookup(FuncName));
9647f37794eSStanislav Mekhanoshin 
9657f37794eSStanislav Mekhanoshin   // check formal with actual types conformance
9667f37794eSStanislav Mekhanoshin   if (F && !F->isDeclaration()
9677f37794eSStanislav Mekhanoshin         && !F->isVarArg()
9687f37794eSStanislav Mekhanoshin         && F->arg_size() == fInfo.getNumArgs()) {
9697f37794eSStanislav Mekhanoshin     return F;
9707f37794eSStanislav Mekhanoshin   }
9717f37794eSStanislav Mekhanoshin 
9727f37794eSStanislav Mekhanoshin   FunctionType *FuncTy = fInfo.getFunctionType(*M);
9737f37794eSStanislav Mekhanoshin 
9747f37794eSStanislav Mekhanoshin   bool hasPtr = false;
9757f37794eSStanislav Mekhanoshin   for (FunctionType::param_iterator
9767f37794eSStanislav Mekhanoshin          PI = FuncTy->param_begin(),
9777f37794eSStanislav Mekhanoshin          PE = FuncTy->param_end();
9787f37794eSStanislav Mekhanoshin        PI != PE; ++PI) {
9797f37794eSStanislav Mekhanoshin     const Type* argTy = static_cast<const Type*>(*PI);
9807f37794eSStanislav Mekhanoshin     if (argTy->isPointerTy()) {
9817f37794eSStanislav Mekhanoshin       hasPtr = true;
9827f37794eSStanislav Mekhanoshin       break;
9837f37794eSStanislav Mekhanoshin     }
9847f37794eSStanislav Mekhanoshin   }
9857f37794eSStanislav Mekhanoshin 
98613680223SJames Y Knight   FunctionCallee C;
9877f37794eSStanislav Mekhanoshin   if (hasPtr) {
9887f37794eSStanislav Mekhanoshin     // Do not set extra attributes for functions with pointer arguments.
9897f37794eSStanislav Mekhanoshin     C = M->getOrInsertFunction(FuncName, FuncTy);
9907f37794eSStanislav Mekhanoshin   } else {
9917f37794eSStanislav Mekhanoshin     AttributeList Attr;
9927f37794eSStanislav Mekhanoshin     LLVMContext &Ctx = M->getContext();
993de0ae9e8SArthur Eubanks     Attr = Attr.addFnAttribute(Ctx, Attribute::ReadOnly);
994de0ae9e8SArthur Eubanks     Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind);
9957f37794eSStanislav Mekhanoshin     C = M->getOrInsertFunction(FuncName, FuncTy, Attr);
9967f37794eSStanislav Mekhanoshin   }
9977f37794eSStanislav Mekhanoshin 
99813680223SJames Y Knight   return C;
9997f37794eSStanislav Mekhanoshin }
1000fc5121a7SYaxun Liu 
100185e2cdacSReid Kleckner StringMap<unsigned> UnmangledFuncInfo::buildNameMap() {
100285e2cdacSReid Kleckner   StringMap<unsigned> Map;
100385e2cdacSReid Kleckner   for (unsigned I = 0; I != TableSize; ++I)
100485e2cdacSReid Kleckner     Map[Table[I].Name] = I;
100585e2cdacSReid Kleckner   return Map;
100685e2cdacSReid Kleckner }
100785e2cdacSReid Kleckner 
1008fc5121a7SYaxun Liu bool UnmangledFuncInfo::lookup(StringRef Name, ID &Id) {
100985e2cdacSReid Kleckner   static const StringMap<unsigned> Map = buildNameMap();
1010fc5121a7SYaxun Liu   auto Loc = Map.find(Name);
1011fc5121a7SYaxun Liu   if (Loc != Map.end()) {
1012fc5121a7SYaxun Liu     Id = toFuncId(Loc->second);
1013fc5121a7SYaxun Liu     return true;
1014fc5121a7SYaxun Liu   }
1015fc5121a7SYaxun Liu   Id = AMDGPULibFunc::EI_NONE;
1016fc5121a7SYaxun Liu   return false;
1017fc5121a7SYaxun Liu }
1018fc5121a7SYaxun Liu 
1019fc5121a7SYaxun Liu AMDGPULibFunc::AMDGPULibFunc(const AMDGPULibFunc &F) {
1020fc5121a7SYaxun Liu   if (auto *MF = dyn_cast<AMDGPUMangledLibFunc>(F.Impl.get()))
1021fc5121a7SYaxun Liu     Impl.reset(new AMDGPUMangledLibFunc(*MF));
1022fc5121a7SYaxun Liu   else if (auto *UMF = dyn_cast<AMDGPUUnmangledLibFunc>(F.Impl.get()))
1023fc5121a7SYaxun Liu     Impl.reset(new AMDGPUUnmangledLibFunc(*UMF));
1024fc5121a7SYaxun Liu   else
1025fc5121a7SYaxun Liu     Impl = std::unique_ptr<AMDGPULibFuncImpl>();
1026fc5121a7SYaxun Liu }
1027fc5121a7SYaxun Liu 
1028fc5121a7SYaxun Liu AMDGPULibFunc &AMDGPULibFunc::operator=(const AMDGPULibFunc &F) {
1029fc5121a7SYaxun Liu   if (this == &F)
1030fc5121a7SYaxun Liu     return *this;
1031fc5121a7SYaxun Liu   new (this) AMDGPULibFunc(F);
1032fc5121a7SYaxun Liu   return *this;
1033fc5121a7SYaxun Liu }
1034fc5121a7SYaxun Liu 
1035fc5121a7SYaxun Liu AMDGPULibFunc::AMDGPULibFunc(EFuncId Id, const AMDGPULibFunc &CopyFrom) {
1036fc5121a7SYaxun Liu   assert(AMDGPULibFuncBase::isMangled(Id) && CopyFrom.isMangled() &&
1037fc5121a7SYaxun Liu          "not supported");
1038fc5121a7SYaxun Liu   Impl.reset(new AMDGPUMangledLibFunc(
1039fc5121a7SYaxun Liu       Id, *cast<AMDGPUMangledLibFunc>(CopyFrom.Impl.get())));
1040fc5121a7SYaxun Liu }
1041fc5121a7SYaxun Liu 
1042fc5121a7SYaxun Liu AMDGPULibFunc::AMDGPULibFunc(StringRef Name, FunctionType *FT) {
1043fc5121a7SYaxun Liu   Impl.reset(new AMDGPUUnmangledLibFunc(Name, FT));
1044fc5121a7SYaxun Liu }
1045fc5121a7SYaxun Liu 
1046fc5121a7SYaxun Liu void AMDGPULibFunc::initMangled() { Impl.reset(new AMDGPUMangledLibFunc()); }
1047fc5121a7SYaxun Liu 
1048fc5121a7SYaxun Liu AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() {
1049fc5121a7SYaxun Liu   if (!Impl)
1050fc5121a7SYaxun Liu     initMangled();
1051fc5121a7SYaxun Liu   return cast<AMDGPUMangledLibFunc>(Impl.get())->Leads;
1052fc5121a7SYaxun Liu }
1053fc5121a7SYaxun Liu 
1054fc5121a7SYaxun Liu const AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() const {
1055fc5121a7SYaxun Liu   return cast<const AMDGPUMangledLibFunc>(Impl.get())->Leads;
1056fc5121a7SYaxun Liu }
1057