12cab237bSDimitry Andric //===-- AMDGPULibFunc.cpp -------------------------------------------------===//
22cab237bSDimitry Andric //
32cab237bSDimitry Andric // The LLVM Compiler Infrastructure
42cab237bSDimitry Andric //
52cab237bSDimitry Andric // This file is distributed under the University of Illinois Open Source
62cab237bSDimitry Andric // License. See LICENSE.TXT for details.
72cab237bSDimitry Andric //
82cab237bSDimitry Andric //===----------------------------------------------------------------------===//
92cab237bSDimitry Andric //
102cab237bSDimitry Andric // This file contains utility functions to work with Itanium mangled names
112cab237bSDimitry Andric //
122cab237bSDimitry Andric //===----------------------------------------------------------------------===//
132cab237bSDimitry Andric
142cab237bSDimitry Andric #include "AMDGPU.h"
152cab237bSDimitry Andric #include "AMDGPULibFunc.h"
162cab237bSDimitry Andric #include <llvm/ADT/SmallString.h>
172cab237bSDimitry Andric #include <llvm/ADT/SmallVector.h>
182cab237bSDimitry Andric #include <llvm/ADT/StringSwitch.h>
192cab237bSDimitry Andric #include "llvm/IR/Attributes.h"
202cab237bSDimitry Andric #include "llvm/IR/DerivedTypes.h"
212cab237bSDimitry Andric #include "llvm/IR/Function.h"
222cab237bSDimitry Andric #include "llvm/IR/Module.h"
232cab237bSDimitry Andric #include "llvm/IR/ValueSymbolTable.h"
242cab237bSDimitry Andric #include <llvm/Support/raw_ostream.h>
252cab237bSDimitry Andric #include <string>
262cab237bSDimitry Andric
272cab237bSDimitry Andric using namespace llvm;
282cab237bSDimitry Andric
292cab237bSDimitry Andric namespace {
302cab237bSDimitry Andric
312cab237bSDimitry Andric enum EManglingParam {
322cab237bSDimitry Andric E_NONE,
332cab237bSDimitry Andric EX_EVENT,
342cab237bSDimitry Andric EX_FLOAT4,
352cab237bSDimitry Andric EX_INTV4,
362cab237bSDimitry Andric EX_RESERVEDID,
372cab237bSDimitry Andric EX_SAMPLER,
382cab237bSDimitry Andric EX_SIZET,
392cab237bSDimitry Andric EX_UINT,
402cab237bSDimitry Andric EX_UINTV4,
412cab237bSDimitry Andric E_ANY,
422cab237bSDimitry Andric E_CONSTPTR_ANY,
432cab237bSDimitry Andric E_CONSTPTR_SWAPGL,
442cab237bSDimitry Andric E_COPY,
452cab237bSDimitry Andric E_IMAGECOORDS,
462cab237bSDimitry Andric E_POINTEE,
472cab237bSDimitry Andric E_SETBASE_I32,
482cab237bSDimitry Andric E_SETBASE_U32,
492cab237bSDimitry Andric E_MAKEBASE_UNS,
502cab237bSDimitry Andric E_V16_OF_POINTEE,
512cab237bSDimitry Andric E_V2_OF_POINTEE,
522cab237bSDimitry Andric E_V3_OF_POINTEE,
532cab237bSDimitry Andric E_V4_OF_POINTEE,
542cab237bSDimitry Andric E_V8_OF_POINTEE,
552cab237bSDimitry Andric E_VLTLPTR_ANY,
562cab237bSDimitry Andric };
572cab237bSDimitry Andric
582cab237bSDimitry Andric struct ManglingRule {
592cab237bSDimitry Andric StringRef const Name;
602cab237bSDimitry Andric unsigned char Lead[2];
612cab237bSDimitry Andric unsigned char Param[5];
622cab237bSDimitry Andric
maxLeadIndex__anond3dc63390111::ManglingRule632cab237bSDimitry Andric int maxLeadIndex() const { return (std::max)(Lead[0], Lead[1]); }
getNumLeads__anond3dc63390111::ManglingRule642cab237bSDimitry Andric int getNumLeads() const { return (Lead[0] ? 1 : 0) + (Lead[1] ? 1 : 0); }
652cab237bSDimitry Andric
662cab237bSDimitry Andric unsigned getNumArgs() const;
672cab237bSDimitry Andric };
682cab237bSDimitry Andric
692cab237bSDimitry Andric // Information about library functions with unmangled names.
702cab237bSDimitry Andric class UnmangledFuncInfo {
712cab237bSDimitry Andric StringRef const Name;
722cab237bSDimitry Andric unsigned NumArgs;
732cab237bSDimitry Andric
742cab237bSDimitry Andric // Table for all lib functions with unmangled names.
752cab237bSDimitry Andric static const UnmangledFuncInfo Table[];
762cab237bSDimitry Andric
772cab237bSDimitry Andric // Number of entries in Table.
782cab237bSDimitry Andric static const unsigned TableSize;
792cab237bSDimitry Andric
802cab237bSDimitry Andric // Map function name to index.
812cab237bSDimitry Andric class NameMap : public StringMap<unsigned> {
822cab237bSDimitry Andric public:
NameMap()832cab237bSDimitry Andric NameMap() {
842cab237bSDimitry Andric for (unsigned I = 0; I != TableSize; ++I)
852cab237bSDimitry Andric (*this)[Table[I].Name] = I;
862cab237bSDimitry Andric }
872cab237bSDimitry Andric };
882cab237bSDimitry Andric friend class NameMap;
892cab237bSDimitry Andric static NameMap Map;
902cab237bSDimitry Andric
912cab237bSDimitry Andric public:
922cab237bSDimitry Andric using ID = AMDGPULibFunc::EFuncId;
UnmangledFuncInfo(StringRef _Name,unsigned _NumArgs)932cab237bSDimitry Andric UnmangledFuncInfo(StringRef _Name, unsigned _NumArgs)
942cab237bSDimitry Andric : Name(_Name), NumArgs(_NumArgs) {}
952cab237bSDimitry Andric // Get index to Table by function name.
962cab237bSDimitry Andric static bool lookup(StringRef Name, ID &Id);
toIndex(ID Id)972cab237bSDimitry Andric static unsigned toIndex(ID Id) {
982cab237bSDimitry Andric assert(static_cast<unsigned>(Id) >
992cab237bSDimitry Andric static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED) &&
1002cab237bSDimitry Andric "Invalid unmangled library function");
1012cab237bSDimitry Andric return static_cast<unsigned>(Id) - 1 -
1022cab237bSDimitry Andric static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED);
1032cab237bSDimitry Andric }
toFuncId(unsigned Index)1042cab237bSDimitry Andric static ID toFuncId(unsigned Index) {
1052cab237bSDimitry Andric assert(Index < TableSize && "Invalid unmangled library function");
1062cab237bSDimitry Andric return static_cast<ID>(
1072cab237bSDimitry Andric Index + 1 + static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED));
1082cab237bSDimitry Andric }
getNumArgs(ID Id)1092cab237bSDimitry Andric static unsigned getNumArgs(ID Id) { return Table[toIndex(Id)].NumArgs; }
getName(ID Id)1102cab237bSDimitry Andric static StringRef getName(ID Id) { return Table[toIndex(Id)].Name; }
1112cab237bSDimitry Andric };
1122cab237bSDimitry Andric
getNumArgs() const1132cab237bSDimitry Andric unsigned ManglingRule::getNumArgs() const {
1142cab237bSDimitry Andric unsigned I=0;
1152cab237bSDimitry Andric while (I < (sizeof Param/sizeof Param[0]) && Param[I]) ++I;
1162cab237bSDimitry Andric return I;
1172cab237bSDimitry Andric }
1182cab237bSDimitry Andric
1192cab237bSDimitry Andric // This table describes function formal argument type rules. The order of rules
1202cab237bSDimitry Andric // corresponds to the EFuncId enum at AMDGPULibFunc.h
1212cab237bSDimitry Andric //
1222cab237bSDimitry Andric // "<func name>", { <leads> }, { <param rules> }
1232cab237bSDimitry Andric // where:
1242cab237bSDimitry Andric // <leads> - list of integers that are one-based indexes of formal argument
1252cab237bSDimitry Andric // used to mangle a function name. Other argument types are derived from types
1262cab237bSDimitry Andric // of these 'leads'. The order of integers in this list correspond to the
1272cab237bSDimitry Andric // order in which these arguments are mangled in the EDG mangling scheme. The
1282cab237bSDimitry Andric // same order should be preserved for arguments in the AMDGPULibFunc structure
1292cab237bSDimitry Andric // when it is used for mangling. For example:
1302cab237bSDimitry Andric // { "vstorea_half", {3,1}, {E_ANY,EX_SIZET,E_ANY}},
1312cab237bSDimitry Andric // will be mangled in EDG scheme as vstorea_half_<3dparam>_<1stparam>
1322cab237bSDimitry Andric // When mangling from code use:
1332cab237bSDimitry Andric // AMDGPULibFunc insc;
1342cab237bSDimitry Andric // insc.param[0] = ... // describe 3rd parameter
1352cab237bSDimitry Andric // insc.param[1] = ... // describe 1rd parameter
1362cab237bSDimitry Andric //
1372cab237bSDimitry Andric // <param rules> - list of rules used to derive all of the function formal
1382cab237bSDimitry Andric // argument types. EX_ prefixed are simple types, other derived from the
1392cab237bSDimitry Andric // latest 'lead' argument type in the order of encoding from first to last.
1402cab237bSDimitry Andric // E_ANY - use prev lead type, E_CONSTPTR_ANY - make const pointer out of
1412cab237bSDimitry Andric // prev lead type, etc. see ParamIterator::getNextParam() for details.
1422cab237bSDimitry Andric
1432cab237bSDimitry Andric static const ManglingRule manglingRules[] = {
1442cab237bSDimitry Andric { StringRef(), {0}, {0} },
1452cab237bSDimitry Andric { "abs" , {1}, {E_ANY}},
1462cab237bSDimitry Andric { "abs_diff" , {1}, {E_ANY,E_COPY}},
1472cab237bSDimitry Andric { "acos" , {1}, {E_ANY}},
1482cab237bSDimitry Andric { "acosh" , {1}, {E_ANY}},
1492cab237bSDimitry Andric { "acospi" , {1}, {E_ANY}},
1502cab237bSDimitry Andric { "add_sat" , {1}, {E_ANY,E_COPY}},
1512cab237bSDimitry Andric { "all" , {1}, {E_ANY}},
1522cab237bSDimitry Andric { "any" , {1}, {E_ANY}},
1532cab237bSDimitry Andric { "asin" , {1}, {E_ANY}},
1542cab237bSDimitry Andric { "asinh" , {1}, {E_ANY}},
1552cab237bSDimitry Andric { "asinpi" , {1}, {E_ANY}},
1562cab237bSDimitry Andric { "async_work_group_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_EVENT}},
1572cab237bSDimitry Andric { "async_work_group_strided_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_SIZET,EX_EVENT}},
1582cab237bSDimitry Andric { "atan" , {1}, {E_ANY}},
1592cab237bSDimitry Andric { "atan2" , {1}, {E_ANY,E_COPY}},
1602cab237bSDimitry Andric { "atan2pi" , {1}, {E_ANY,E_COPY}},
1612cab237bSDimitry Andric { "atanh" , {1}, {E_ANY}},
1622cab237bSDimitry Andric { "atanpi" , {1}, {E_ANY}},
1632cab237bSDimitry Andric { "atomic_add" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1642cab237bSDimitry Andric { "atomic_and" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1652cab237bSDimitry Andric { "atomic_cmpxchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE,E_POINTEE}},
1662cab237bSDimitry Andric { "atomic_dec" , {1}, {E_VLTLPTR_ANY}},
1672cab237bSDimitry Andric { "atomic_inc" , {1}, {E_VLTLPTR_ANY}},
1682cab237bSDimitry Andric { "atomic_max" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1692cab237bSDimitry Andric { "atomic_min" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1702cab237bSDimitry Andric { "atomic_or" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1712cab237bSDimitry Andric { "atomic_sub" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1722cab237bSDimitry Andric { "atomic_xchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1732cab237bSDimitry Andric { "atomic_xor" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
1742cab237bSDimitry Andric { "bitselect" , {1}, {E_ANY,E_COPY,E_COPY}},
1752cab237bSDimitry Andric { "cbrt" , {1}, {E_ANY}},
1762cab237bSDimitry Andric { "ceil" , {1}, {E_ANY}},
1772cab237bSDimitry Andric { "clamp" , {1}, {E_ANY,E_COPY,E_COPY}},
1782cab237bSDimitry Andric { "clz" , {1}, {E_ANY}},
1792cab237bSDimitry Andric { "commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
1802cab237bSDimitry Andric { "commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
1812cab237bSDimitry Andric { "copysign" , {1}, {E_ANY,E_COPY}},
1822cab237bSDimitry Andric { "cos" , {1}, {E_ANY}},
1832cab237bSDimitry Andric { "cosh" , {1}, {E_ANY}},
1842cab237bSDimitry Andric { "cospi" , {1}, {E_ANY}},
1852cab237bSDimitry Andric { "cross" , {1}, {E_ANY,E_COPY}},
1862cab237bSDimitry Andric { "ctz" , {1}, {E_ANY}},
1872cab237bSDimitry Andric { "degrees" , {1}, {E_ANY}},
1882cab237bSDimitry Andric { "distance" , {1}, {E_ANY,E_COPY}},
1892cab237bSDimitry Andric { "divide" , {1}, {E_ANY,E_COPY}},
1902cab237bSDimitry Andric { "dot" , {1}, {E_ANY,E_COPY}},
1912cab237bSDimitry Andric { "erf" , {1}, {E_ANY}},
1922cab237bSDimitry Andric { "erfc" , {1}, {E_ANY}},
1932cab237bSDimitry Andric { "exp" , {1}, {E_ANY}},
1942cab237bSDimitry Andric { "exp10" , {1}, {E_ANY}},
1952cab237bSDimitry Andric { "exp2" , {1}, {E_ANY}},
1962cab237bSDimitry Andric { "expm1" , {1}, {E_ANY}},
1972cab237bSDimitry Andric { "fabs" , {1}, {E_ANY}},
1982cab237bSDimitry Andric { "fast_distance" , {1}, {E_ANY,E_COPY}},
1992cab237bSDimitry Andric { "fast_length" , {1}, {E_ANY}},
2002cab237bSDimitry Andric { "fast_normalize" , {1}, {E_ANY}},
2012cab237bSDimitry Andric { "fdim" , {1}, {E_ANY,E_COPY}},
2022cab237bSDimitry Andric { "floor" , {1}, {E_ANY}},
2032cab237bSDimitry Andric { "fma" , {1}, {E_ANY,E_COPY,E_COPY}},
2042cab237bSDimitry Andric { "fmax" , {1}, {E_ANY,E_COPY}},
2052cab237bSDimitry Andric { "fmin" , {1}, {E_ANY,E_COPY}},
2062cab237bSDimitry Andric { "fmod" , {1}, {E_ANY,E_COPY}},
2072cab237bSDimitry Andric { "fract" , {2}, {E_POINTEE,E_ANY}},
2082cab237bSDimitry Andric { "frexp" , {1,2}, {E_ANY,E_ANY}},
2092cab237bSDimitry Andric { "get_image_array_size" , {1}, {E_ANY}},
2102cab237bSDimitry Andric { "get_image_channel_data_type" , {1}, {E_ANY}},
2112cab237bSDimitry Andric { "get_image_channel_order" , {1}, {E_ANY}},
2122cab237bSDimitry Andric { "get_image_dim" , {1}, {E_ANY}},
2132cab237bSDimitry Andric { "get_image_height" , {1}, {E_ANY}},
2142cab237bSDimitry Andric { "get_image_width" , {1}, {E_ANY}},
2152cab237bSDimitry Andric { "get_pipe_max_packets" , {1}, {E_ANY}},
2162cab237bSDimitry Andric { "get_pipe_num_packets" , {1}, {E_ANY}},
2172cab237bSDimitry Andric { "hadd" , {1}, {E_ANY,E_COPY}},
2182cab237bSDimitry Andric { "hypot" , {1}, {E_ANY,E_COPY}},
2192cab237bSDimitry Andric { "ilogb" , {1}, {E_ANY}},
2202cab237bSDimitry Andric { "isequal" , {1}, {E_ANY,E_COPY}},
2212cab237bSDimitry Andric { "isfinite" , {1}, {E_ANY}},
2222cab237bSDimitry Andric { "isgreater" , {1}, {E_ANY,E_COPY}},
2232cab237bSDimitry Andric { "isgreaterequal" , {1}, {E_ANY,E_COPY}},
2242cab237bSDimitry Andric { "isinf" , {1}, {E_ANY}},
2252cab237bSDimitry Andric { "isless" , {1}, {E_ANY,E_COPY}},
2262cab237bSDimitry Andric { "islessequal" , {1}, {E_ANY,E_COPY}},
2272cab237bSDimitry Andric { "islessgreater" , {1}, {E_ANY,E_COPY}},
2282cab237bSDimitry Andric { "isnan" , {1}, {E_ANY}},
2292cab237bSDimitry Andric { "isnormal" , {1}, {E_ANY}},
2302cab237bSDimitry Andric { "isnotequal" , {1}, {E_ANY,E_COPY}},
2312cab237bSDimitry Andric { "isordered" , {1}, {E_ANY,E_COPY}},
2322cab237bSDimitry Andric { "isunordered" , {1}, {E_ANY,E_COPY}},
2332cab237bSDimitry Andric { "ldexp" , {1}, {E_ANY,E_SETBASE_I32}},
2342cab237bSDimitry Andric { "length" , {1}, {E_ANY}},
2352cab237bSDimitry Andric { "lgamma" , {1}, {E_ANY}},
2362cab237bSDimitry Andric { "lgamma_r" , {1,2}, {E_ANY,E_ANY}},
2372cab237bSDimitry Andric { "log" , {1}, {E_ANY}},
2382cab237bSDimitry Andric { "log10" , {1}, {E_ANY}},
2392cab237bSDimitry Andric { "log1p" , {1}, {E_ANY}},
2402cab237bSDimitry Andric { "log2" , {1}, {E_ANY}},
2412cab237bSDimitry Andric { "logb" , {1}, {E_ANY}},
2422cab237bSDimitry Andric { "mad" , {1}, {E_ANY,E_COPY,E_COPY}},
2432cab237bSDimitry Andric { "mad24" , {1}, {E_ANY,E_COPY,E_COPY}},
2442cab237bSDimitry Andric { "mad_hi" , {1}, {E_ANY,E_COPY,E_COPY}},
2452cab237bSDimitry Andric { "mad_sat" , {1}, {E_ANY,E_COPY,E_COPY}},
2462cab237bSDimitry Andric { "max" , {1}, {E_ANY,E_COPY}},
2472cab237bSDimitry Andric { "maxmag" , {1}, {E_ANY,E_COPY}},
2482cab237bSDimitry Andric { "min" , {1}, {E_ANY,E_COPY}},
2492cab237bSDimitry Andric { "minmag" , {1}, {E_ANY,E_COPY}},
2502cab237bSDimitry Andric { "mix" , {1}, {E_ANY,E_COPY,E_COPY}},
2512cab237bSDimitry Andric { "modf" , {2}, {E_POINTEE,E_ANY}},
2522cab237bSDimitry Andric { "mul24" , {1}, {E_ANY,E_COPY}},
2532cab237bSDimitry Andric { "mul_hi" , {1}, {E_ANY,E_COPY}},
2542cab237bSDimitry Andric { "nan" , {1}, {E_ANY}},
2552cab237bSDimitry Andric { "nextafter" , {1}, {E_ANY,E_COPY}},
2562cab237bSDimitry Andric { "normalize" , {1}, {E_ANY}},
2572cab237bSDimitry Andric { "popcount" , {1}, {E_ANY}},
2582cab237bSDimitry Andric { "pow" , {1}, {E_ANY,E_COPY}},
2592cab237bSDimitry Andric { "pown" , {1}, {E_ANY,E_SETBASE_I32}},
2602cab237bSDimitry Andric { "powr" , {1}, {E_ANY,E_COPY}},
2612cab237bSDimitry Andric { "prefetch" , {1}, {E_CONSTPTR_ANY,EX_SIZET}},
2622cab237bSDimitry Andric { "radians" , {1}, {E_ANY}},
2632cab237bSDimitry Andric { "recip" , {1}, {E_ANY}},
2642cab237bSDimitry Andric { "remainder" , {1}, {E_ANY,E_COPY}},
2652cab237bSDimitry Andric { "remquo" , {1,3}, {E_ANY,E_COPY,E_ANY}},
2662cab237bSDimitry Andric { "reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
2672cab237bSDimitry Andric { "reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
2682cab237bSDimitry Andric { "rhadd" , {1}, {E_ANY,E_COPY}},
2692cab237bSDimitry Andric { "rint" , {1}, {E_ANY}},
2702cab237bSDimitry Andric { "rootn" , {1}, {E_ANY,E_SETBASE_I32}},
2712cab237bSDimitry Andric { "rotate" , {1}, {E_ANY,E_COPY}},
2722cab237bSDimitry Andric { "round" , {1}, {E_ANY}},
2732cab237bSDimitry Andric { "rsqrt" , {1}, {E_ANY}},
2742cab237bSDimitry Andric { "select" , {1,3}, {E_ANY,E_COPY,E_ANY}},
2752cab237bSDimitry Andric { "shuffle" , {1,2}, {E_ANY,E_ANY}},
2762cab237bSDimitry Andric { "shuffle2" , {1,3}, {E_ANY,E_COPY,E_ANY}},
2772cab237bSDimitry Andric { "sign" , {1}, {E_ANY}},
2782cab237bSDimitry Andric { "signbit" , {1}, {E_ANY}},
2792cab237bSDimitry Andric { "sin" , {1}, {E_ANY}},
2802cab237bSDimitry Andric { "sincos" , {2}, {E_POINTEE,E_ANY}},
2812cab237bSDimitry Andric { "sinh" , {1}, {E_ANY}},
2822cab237bSDimitry Andric { "sinpi" , {1}, {E_ANY}},
2832cab237bSDimitry Andric { "smoothstep" , {1}, {E_ANY,E_COPY,E_COPY}},
2842cab237bSDimitry Andric { "sqrt" , {1}, {E_ANY}},
2852cab237bSDimitry Andric { "step" , {1}, {E_ANY,E_COPY}},
2862cab237bSDimitry Andric { "sub_group_broadcast" , {1}, {E_ANY,EX_UINT}},
2872cab237bSDimitry Andric { "sub_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
2882cab237bSDimitry Andric { "sub_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
2892cab237bSDimitry Andric { "sub_group_reduce_add" , {1}, {E_ANY}},
2902cab237bSDimitry Andric { "sub_group_reduce_max" , {1}, {E_ANY}},
2912cab237bSDimitry Andric { "sub_group_reduce_min" , {1}, {E_ANY}},
2922cab237bSDimitry Andric { "sub_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
2932cab237bSDimitry Andric { "sub_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
2942cab237bSDimitry Andric { "sub_group_scan_exclusive_add" , {1}, {E_ANY}},
2952cab237bSDimitry Andric { "sub_group_scan_exclusive_max" , {1}, {E_ANY}},
2962cab237bSDimitry Andric { "sub_group_scan_exclusive_min" , {1}, {E_ANY}},
2972cab237bSDimitry Andric { "sub_group_scan_inclusive_add" , {1}, {E_ANY}},
2982cab237bSDimitry Andric { "sub_group_scan_inclusive_max" , {1}, {E_ANY}},
2992cab237bSDimitry Andric { "sub_group_scan_inclusive_min" , {1}, {E_ANY}},
3002cab237bSDimitry Andric { "sub_sat" , {1}, {E_ANY,E_COPY}},
3012cab237bSDimitry Andric { "tan" , {1}, {E_ANY}},
3022cab237bSDimitry Andric { "tanh" , {1}, {E_ANY}},
3032cab237bSDimitry Andric { "tanpi" , {1}, {E_ANY}},
3042cab237bSDimitry Andric { "tgamma" , {1}, {E_ANY}},
3052cab237bSDimitry Andric { "trunc" , {1}, {E_ANY}},
3062cab237bSDimitry Andric { "upsample" , {1}, {E_ANY,E_MAKEBASE_UNS}},
3072cab237bSDimitry Andric { "vec_step" , {1}, {E_ANY}},
3082cab237bSDimitry Andric { "vstore" , {3}, {E_POINTEE,EX_SIZET,E_ANY}},
3092cab237bSDimitry Andric { "vstore16" , {3}, {E_V16_OF_POINTEE,EX_SIZET,E_ANY}},
3102cab237bSDimitry Andric { "vstore2" , {3}, {E_V2_OF_POINTEE,EX_SIZET,E_ANY}},
3112cab237bSDimitry Andric { "vstore3" , {3}, {E_V3_OF_POINTEE,EX_SIZET,E_ANY}},
3122cab237bSDimitry Andric { "vstore4" , {3}, {E_V4_OF_POINTEE,EX_SIZET,E_ANY}},
3132cab237bSDimitry Andric { "vstore8" , {3}, {E_V8_OF_POINTEE,EX_SIZET,E_ANY}},
3142cab237bSDimitry Andric { "work_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
3152cab237bSDimitry Andric { "work_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
3162cab237bSDimitry Andric { "work_group_reduce_add" , {1}, {E_ANY}},
3172cab237bSDimitry Andric { "work_group_reduce_max" , {1}, {E_ANY}},
3182cab237bSDimitry Andric { "work_group_reduce_min" , {1}, {E_ANY}},
3192cab237bSDimitry Andric { "work_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
3202cab237bSDimitry Andric { "work_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
3212cab237bSDimitry Andric { "work_group_scan_exclusive_add" , {1}, {E_ANY}},
3222cab237bSDimitry Andric { "work_group_scan_exclusive_max" , {1}, {E_ANY}},
3232cab237bSDimitry Andric { "work_group_scan_exclusive_min" , {1}, {E_ANY}},
3242cab237bSDimitry Andric { "work_group_scan_inclusive_add" , {1}, {E_ANY}},
3252cab237bSDimitry Andric { "work_group_scan_inclusive_max" , {1}, {E_ANY}},
3262cab237bSDimitry Andric { "work_group_scan_inclusive_min" , {1}, {E_ANY}},
3272cab237bSDimitry Andric { "write_imagef" , {1}, {E_ANY,E_IMAGECOORDS,EX_FLOAT4}},
3282cab237bSDimitry Andric { "write_imagei" , {1}, {E_ANY,E_IMAGECOORDS,EX_INTV4}},
3292cab237bSDimitry Andric { "write_imageui" , {1}, {E_ANY,E_IMAGECOORDS,EX_UINTV4}},
3302cab237bSDimitry Andric { "ncos" , {1}, {E_ANY} },
3312cab237bSDimitry Andric { "nexp2" , {1}, {E_ANY} },
3322cab237bSDimitry Andric { "nfma" , {1}, {E_ANY, E_COPY, E_COPY} },
3332cab237bSDimitry Andric { "nlog2" , {1}, {E_ANY} },
3342cab237bSDimitry Andric { "nrcp" , {1}, {E_ANY} },
3352cab237bSDimitry Andric { "nrsqrt" , {1}, {E_ANY} },
3362cab237bSDimitry Andric { "nsin" , {1}, {E_ANY} },
3372cab237bSDimitry Andric { "nsqrt" , {1}, {E_ANY} },
3382cab237bSDimitry Andric { "ftz" , {1}, {E_ANY} },
3392cab237bSDimitry Andric { "fldexp" , {1}, {E_ANY, EX_UINT} },
3402cab237bSDimitry Andric { "class" , {1}, {E_ANY, EX_UINT} },
3412cab237bSDimitry Andric { "rcbrt" , {1}, {E_ANY} },
3422cab237bSDimitry Andric };
3432cab237bSDimitry Andric
3442cab237bSDimitry Andric // Library functions with unmangled name.
3452cab237bSDimitry Andric const UnmangledFuncInfo UnmangledFuncInfo::Table[] = {
3462cab237bSDimitry Andric {"__read_pipe_2", 4},
3472cab237bSDimitry Andric {"__read_pipe_4", 6},
3482cab237bSDimitry Andric {"__write_pipe_2", 4},
3492cab237bSDimitry Andric {"__write_pipe_4", 6},
3502cab237bSDimitry Andric };
3512cab237bSDimitry Andric
3522cab237bSDimitry Andric const unsigned UnmangledFuncInfo::TableSize =
3532cab237bSDimitry Andric sizeof(UnmangledFuncInfo::Table) / sizeof(UnmangledFuncInfo::Table[0]);
3542cab237bSDimitry Andric
3552cab237bSDimitry Andric UnmangledFuncInfo::NameMap UnmangledFuncInfo::Map;
3562cab237bSDimitry Andric
3572cab237bSDimitry Andric static const struct ManglingRulesMap : public StringMap<int> {
ManglingRulesMap__anond3dc63390111::ManglingRulesMap3582cab237bSDimitry Andric ManglingRulesMap()
3592cab237bSDimitry Andric : StringMap<int>(sizeof(manglingRules)/sizeof(manglingRules[0])) {
3602cab237bSDimitry Andric int Id = 0;
3612cab237bSDimitry Andric for (auto Rule : manglingRules)
3622cab237bSDimitry Andric insert({ Rule.Name, Id++ });
3632cab237bSDimitry Andric }
3642cab237bSDimitry Andric } manglingRulesMap;
3652cab237bSDimitry Andric
getRetType(AMDGPULibFunc::EFuncId id,const AMDGPULibFunc::Param (& Leads)[2])3662cab237bSDimitry Andric static AMDGPULibFunc::Param getRetType(AMDGPULibFunc::EFuncId id,
3672cab237bSDimitry Andric const AMDGPULibFunc::Param (&Leads)[2]) {
3682cab237bSDimitry Andric AMDGPULibFunc::Param Res = Leads[0];
3692cab237bSDimitry Andric // TBD - This switch may require to be extended for other intriniscs
3702cab237bSDimitry Andric switch (id) {
3712cab237bSDimitry Andric case AMDGPULibFunc::EI_SINCOS:
3722cab237bSDimitry Andric Res.PtrKind = AMDGPULibFunc::BYVALUE;
3732cab237bSDimitry Andric break;
3742cab237bSDimitry Andric default:
3752cab237bSDimitry Andric break;
3762cab237bSDimitry Andric }
3772cab237bSDimitry Andric return Res;
3782cab237bSDimitry Andric }
3792cab237bSDimitry Andric
3802cab237bSDimitry Andric class ParamIterator {
3812cab237bSDimitry Andric const AMDGPULibFunc::Param (&Leads)[2];
3822cab237bSDimitry Andric const ManglingRule& Rule;
3832cab237bSDimitry Andric int Index;
3842cab237bSDimitry Andric public:
ParamIterator(const AMDGPULibFunc::Param (& leads)[2],const ManglingRule & rule)3852cab237bSDimitry Andric ParamIterator(const AMDGPULibFunc::Param (&leads)[2],
3862cab237bSDimitry Andric const ManglingRule& rule)
3872cab237bSDimitry Andric : Leads(leads), Rule(rule), Index(0) {}
3882cab237bSDimitry Andric
3892cab237bSDimitry Andric AMDGPULibFunc::Param getNextParam();
3902cab237bSDimitry Andric };
3912cab237bSDimitry Andric
getNextParam()3922cab237bSDimitry Andric AMDGPULibFunc::Param ParamIterator::getNextParam() {
3932cab237bSDimitry Andric AMDGPULibFunc::Param P;
3942cab237bSDimitry Andric if (Index >= int(sizeof Rule.Param/sizeof Rule.Param[0])) return P;
3952cab237bSDimitry Andric
3962cab237bSDimitry Andric const char R = Rule.Param[Index];
3972cab237bSDimitry Andric switch (R) {
3982cab237bSDimitry Andric case E_NONE: break;
3992cab237bSDimitry Andric case EX_UINT:
4002cab237bSDimitry Andric P.ArgType = AMDGPULibFunc::U32; break;
4012cab237bSDimitry Andric case EX_INTV4:
4022cab237bSDimitry Andric P.ArgType = AMDGPULibFunc::I32; P.VectorSize = 4; break;
4032cab237bSDimitry Andric case EX_UINTV4:
4042cab237bSDimitry Andric P.ArgType = AMDGPULibFunc::U32; P.VectorSize = 4; break;
4052cab237bSDimitry Andric case EX_FLOAT4:
4062cab237bSDimitry Andric P.ArgType = AMDGPULibFunc::F32; P.VectorSize = 4; break;
4072cab237bSDimitry Andric case EX_SIZET:
4082cab237bSDimitry Andric P.ArgType = AMDGPULibFunc::U64; break;
4092cab237bSDimitry Andric case EX_EVENT:
4102cab237bSDimitry Andric P.ArgType = AMDGPULibFunc::EVENT; break;
4112cab237bSDimitry Andric case EX_SAMPLER:
4122cab237bSDimitry Andric P.ArgType = AMDGPULibFunc::SAMPLER; break;
4132cab237bSDimitry Andric case EX_RESERVEDID: break; // TBD
4142cab237bSDimitry Andric default:
4152cab237bSDimitry Andric if (Index == (Rule.Lead[1] - 1)) P = Leads[1];
4162cab237bSDimitry Andric else P = Leads[0];
4172cab237bSDimitry Andric
4182cab237bSDimitry Andric switch (R) {
4192cab237bSDimitry Andric case E_ANY:
4202cab237bSDimitry Andric case E_COPY: break;
4212cab237bSDimitry Andric
4222cab237bSDimitry Andric case E_POINTEE:
4232cab237bSDimitry Andric P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4242cab237bSDimitry Andric case E_V2_OF_POINTEE:
4252cab237bSDimitry Andric P.VectorSize = 2; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4262cab237bSDimitry Andric case E_V3_OF_POINTEE:
4272cab237bSDimitry Andric P.VectorSize = 3; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4282cab237bSDimitry Andric case E_V4_OF_POINTEE:
4292cab237bSDimitry Andric P.VectorSize = 4; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4302cab237bSDimitry Andric case E_V8_OF_POINTEE:
4312cab237bSDimitry Andric P.VectorSize = 8; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4322cab237bSDimitry Andric case E_V16_OF_POINTEE:
4332cab237bSDimitry Andric P.VectorSize = 16; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
4342cab237bSDimitry Andric case E_CONSTPTR_ANY:
4352cab237bSDimitry Andric P.PtrKind |= AMDGPULibFunc::CONST; break;
4362cab237bSDimitry Andric case E_VLTLPTR_ANY:
4372cab237bSDimitry Andric P.PtrKind |= AMDGPULibFunc::VOLATILE; break;
4382cab237bSDimitry Andric case E_SETBASE_I32:
4392cab237bSDimitry Andric P.ArgType = AMDGPULibFunc::I32; break;
4402cab237bSDimitry Andric case E_SETBASE_U32:
4412cab237bSDimitry Andric P.ArgType = AMDGPULibFunc::U32; break;
4422cab237bSDimitry Andric
4432cab237bSDimitry Andric case E_MAKEBASE_UNS:
4442cab237bSDimitry Andric P.ArgType &= ~AMDGPULibFunc::BASE_TYPE_MASK;
4452cab237bSDimitry Andric P.ArgType |= AMDGPULibFunc::UINT;
4462cab237bSDimitry Andric break;
4472cab237bSDimitry Andric
4482cab237bSDimitry Andric case E_IMAGECOORDS:
4492cab237bSDimitry Andric switch (P.ArgType) {
4502cab237bSDimitry Andric case AMDGPULibFunc::IMG1DA: P.VectorSize = 2; break;
4512cab237bSDimitry Andric case AMDGPULibFunc::IMG1DB: P.VectorSize = 1; break;
4522cab237bSDimitry Andric case AMDGPULibFunc::IMG2DA: P.VectorSize = 4; break;
4532cab237bSDimitry Andric case AMDGPULibFunc::IMG1D: P.VectorSize = 1; break;
4542cab237bSDimitry Andric case AMDGPULibFunc::IMG2D: P.VectorSize = 2; break;
4552cab237bSDimitry Andric case AMDGPULibFunc::IMG3D: P.VectorSize = 4; break;
4562cab237bSDimitry Andric }
4572cab237bSDimitry Andric P.PtrKind = AMDGPULibFunc::BYVALUE;
4582cab237bSDimitry Andric P.ArgType = AMDGPULibFunc::I32;
4592cab237bSDimitry Andric break;
4602cab237bSDimitry Andric
4612cab237bSDimitry Andric case E_CONSTPTR_SWAPGL: {
4622cab237bSDimitry Andric unsigned AS = AMDGPULibFunc::getAddrSpaceFromEPtrKind(P.PtrKind);
4632cab237bSDimitry Andric switch (AS) {
4642cab237bSDimitry Andric case AMDGPUAS::GLOBAL_ADDRESS: AS = AMDGPUAS::LOCAL_ADDRESS; break;
4652cab237bSDimitry Andric case AMDGPUAS::LOCAL_ADDRESS: AS = AMDGPUAS::GLOBAL_ADDRESS; break;
4662cab237bSDimitry Andric }
4672cab237bSDimitry Andric P.PtrKind = AMDGPULibFunc::getEPtrKindFromAddrSpace(AS);
4682cab237bSDimitry Andric P.PtrKind |= AMDGPULibFunc::CONST;
4692cab237bSDimitry Andric break;
4702cab237bSDimitry Andric }
4712cab237bSDimitry Andric
4722cab237bSDimitry Andric default: llvm_unreachable("Unhandeled param rule");
4732cab237bSDimitry Andric }
4742cab237bSDimitry Andric }
4752cab237bSDimitry Andric ++Index;
4762cab237bSDimitry Andric return P;
4772cab237bSDimitry Andric }
4782cab237bSDimitry Andric
drop_front(StringRef & str,size_t n=1)4792cab237bSDimitry Andric inline static void drop_front(StringRef& str, size_t n = 1) {
4802cab237bSDimitry Andric str = str.drop_front(n);
4812cab237bSDimitry Andric }
4822cab237bSDimitry Andric
eatTerm(StringRef & mangledName,const char c)4832cab237bSDimitry Andric static bool eatTerm(StringRef& mangledName, const char c) {
4842cab237bSDimitry Andric if (mangledName.front() == c) {
4852cab237bSDimitry Andric drop_front(mangledName);
4862cab237bSDimitry Andric return true;
4872cab237bSDimitry Andric }
4882cab237bSDimitry Andric return false;
4892cab237bSDimitry Andric }
4902cab237bSDimitry Andric
4912cab237bSDimitry Andric template <size_t N>
eatTerm(StringRef & mangledName,const char (& str)[N])4922cab237bSDimitry Andric static bool eatTerm(StringRef& mangledName, const char (&str)[N]) {
4932cab237bSDimitry Andric if (mangledName.startswith(StringRef(str, N-1))) {
4942cab237bSDimitry Andric drop_front(mangledName, N-1);
4952cab237bSDimitry Andric return true;
4962cab237bSDimitry Andric }
4972cab237bSDimitry Andric return false;
4982cab237bSDimitry Andric }
4992cab237bSDimitry Andric
isDigit(char c)5002cab237bSDimitry Andric static inline bool isDigit(char c) { return c >= '0' && c <= '9'; }
5012cab237bSDimitry Andric
eatNumber(StringRef & s)5022cab237bSDimitry Andric static int eatNumber(StringRef& s) {
5032cab237bSDimitry Andric size_t const savedSize = s.size();
5042cab237bSDimitry Andric int n = 0;
5052cab237bSDimitry Andric while (!s.empty() && isDigit(s.front())) {
5062cab237bSDimitry Andric n = n*10 + s.front() - '0';
5072cab237bSDimitry Andric drop_front(s);
5082cab237bSDimitry Andric }
5092cab237bSDimitry Andric return s.size() < savedSize ? n : -1;
5102cab237bSDimitry Andric }
5112cab237bSDimitry Andric
eatLengthPrefixedName(StringRef & mangledName)5122cab237bSDimitry Andric static StringRef eatLengthPrefixedName(StringRef& mangledName) {
5132cab237bSDimitry Andric int const Len = eatNumber(mangledName);
5142cab237bSDimitry Andric if (Len <= 0 || static_cast<size_t>(Len) > mangledName.size())
5152cab237bSDimitry Andric return StringRef();
5162cab237bSDimitry Andric StringRef Res = mangledName.substr(0, Len);
5172cab237bSDimitry Andric drop_front(mangledName, Len);
5182cab237bSDimitry Andric return Res;
5192cab237bSDimitry Andric }
5202cab237bSDimitry Andric
5212cab237bSDimitry Andric } // end anonymous namespace
5222cab237bSDimitry Andric
AMDGPUMangledLibFunc()5232cab237bSDimitry Andric AMDGPUMangledLibFunc::AMDGPUMangledLibFunc() {
5242cab237bSDimitry Andric FuncId = EI_NONE;
5252cab237bSDimitry Andric FKind = NOPFX;
5262cab237bSDimitry Andric Leads[0].reset();
5272cab237bSDimitry Andric Leads[1].reset();
5282cab237bSDimitry Andric Name.clear();
5292cab237bSDimitry Andric }
5302cab237bSDimitry Andric
AMDGPUUnmangledLibFunc()5312cab237bSDimitry Andric AMDGPUUnmangledLibFunc::AMDGPUUnmangledLibFunc() {
5322cab237bSDimitry Andric FuncId = EI_NONE;
5332cab237bSDimitry Andric FuncTy = nullptr;
5342cab237bSDimitry Andric }
5352cab237bSDimitry Andric
AMDGPUMangledLibFunc(EFuncId id,const AMDGPUMangledLibFunc & copyFrom)5362cab237bSDimitry Andric AMDGPUMangledLibFunc::AMDGPUMangledLibFunc(
5372cab237bSDimitry Andric EFuncId id, const AMDGPUMangledLibFunc ©From) {
5382cab237bSDimitry Andric FuncId = id;
5392cab237bSDimitry Andric FKind = copyFrom.FKind;
5402cab237bSDimitry Andric Leads[0] = copyFrom.Leads[0];
5412cab237bSDimitry Andric Leads[1] = copyFrom.Leads[1];
5422cab237bSDimitry Andric }
5432cab237bSDimitry Andric
5442cab237bSDimitry Andric ///////////////////////////////////////////////////////////////////////////////
5452cab237bSDimitry Andric // Demangling
5462cab237bSDimitry Andric
parseVecSize(StringRef & mangledName)5472cab237bSDimitry Andric static int parseVecSize(StringRef& mangledName) {
5482cab237bSDimitry Andric size_t const Len = eatNumber(mangledName);
5492cab237bSDimitry Andric switch (Len) {
5502cab237bSDimitry Andric case 2: case 3: case 4: case 8: case 16:
5512cab237bSDimitry Andric return Len;
5522cab237bSDimitry Andric default:
5532cab237bSDimitry Andric break;
5542cab237bSDimitry Andric }
5552cab237bSDimitry Andric return 1;
5562cab237bSDimitry Andric }
5572cab237bSDimitry Andric
parseNamePrefix(StringRef & mangledName)5582cab237bSDimitry Andric static AMDGPULibFunc::ENamePrefix parseNamePrefix(StringRef& mangledName) {
5592cab237bSDimitry Andric std::pair<StringRef, StringRef> const P = mangledName.split('_');
5602cab237bSDimitry Andric AMDGPULibFunc::ENamePrefix Pfx =
5612cab237bSDimitry Andric StringSwitch<AMDGPULibFunc::ENamePrefix>(P.first)
5622cab237bSDimitry Andric .Case("native", AMDGPULibFunc::NATIVE)
5632cab237bSDimitry Andric .Case("half" , AMDGPULibFunc::HALF)
5642cab237bSDimitry Andric .Default(AMDGPULibFunc::NOPFX);
5652cab237bSDimitry Andric
5662cab237bSDimitry Andric if (Pfx != AMDGPULibFunc::NOPFX)
5672cab237bSDimitry Andric mangledName = P.second;
5682cab237bSDimitry Andric
5692cab237bSDimitry Andric return Pfx;
5702cab237bSDimitry Andric }
5712cab237bSDimitry Andric
parseUnmangledName(StringRef FullName)5722cab237bSDimitry Andric bool AMDGPUMangledLibFunc::parseUnmangledName(StringRef FullName) {
5732cab237bSDimitry Andric FuncId = static_cast<EFuncId>(manglingRulesMap.lookup(FullName));
5742cab237bSDimitry Andric return FuncId != EI_NONE;
5752cab237bSDimitry Andric }
5762cab237bSDimitry Andric
5772cab237bSDimitry Andric ///////////////////////////////////////////////////////////////////////////////
5782cab237bSDimitry Andric // Itanium Demangling
5792cab237bSDimitry Andric
5802cab237bSDimitry Andric namespace {
5812cab237bSDimitry Andric struct ItaniumParamParser {
5822cab237bSDimitry Andric AMDGPULibFunc::Param Prev;
5832cab237bSDimitry Andric bool parseItaniumParam(StringRef& param, AMDGPULibFunc::Param &res);
5842cab237bSDimitry Andric };
5852cab237bSDimitry Andric } // namespace
5862cab237bSDimitry Andric
parseItaniumParam(StringRef & param,AMDGPULibFunc::Param & res)5872cab237bSDimitry Andric bool ItaniumParamParser::parseItaniumParam(StringRef& param,
5882cab237bSDimitry Andric AMDGPULibFunc::Param &res) {
5892cab237bSDimitry Andric res.reset();
5902cab237bSDimitry Andric if (param.empty()) return false;
5912cab237bSDimitry Andric
5922cab237bSDimitry Andric // parse pointer prefix
5932cab237bSDimitry Andric if (eatTerm(param, 'P')) {
5942cab237bSDimitry Andric if (eatTerm(param, 'K')) res.PtrKind |= AMDGPULibFunc::CONST;
5952cab237bSDimitry Andric if (eatTerm(param, 'V')) res.PtrKind |= AMDGPULibFunc::VOLATILE;
5962cab237bSDimitry Andric unsigned AS;
5972cab237bSDimitry Andric if (!eatTerm(param, "U3AS")) {
5982cab237bSDimitry Andric AS = 0;
5992cab237bSDimitry Andric } else {
6002cab237bSDimitry Andric AS = param.front() - '0';
6012cab237bSDimitry Andric drop_front(param, 1);
6022cab237bSDimitry Andric }
6032cab237bSDimitry Andric res.PtrKind |= AMDGPULibFuncBase::getEPtrKindFromAddrSpace(AS);
6042cab237bSDimitry Andric } else {
6052cab237bSDimitry Andric res.PtrKind = AMDGPULibFunc::BYVALUE;
6062cab237bSDimitry Andric }
6072cab237bSDimitry Andric
6082cab237bSDimitry Andric // parse vector size
6092cab237bSDimitry Andric if (eatTerm(param,"Dv")) {
6102cab237bSDimitry Andric res.VectorSize = parseVecSize(param);
6112cab237bSDimitry Andric if (res.VectorSize==1 || !eatTerm(param, '_')) return false;
6122cab237bSDimitry Andric }
6132cab237bSDimitry Andric
6142cab237bSDimitry Andric // parse type
6152cab237bSDimitry Andric char const TC = param.front();
6162cab237bSDimitry Andric if (::isDigit(TC)) {
6172cab237bSDimitry Andric res.ArgType = StringSwitch<AMDGPULibFunc::EType>
6182cab237bSDimitry Andric (eatLengthPrefixedName(param))
6192cab237bSDimitry Andric .Case("ocl_image1darray" , AMDGPULibFunc::IMG1DA)
6202cab237bSDimitry Andric .Case("ocl_image1dbuffer", AMDGPULibFunc::IMG1DB)
6212cab237bSDimitry Andric .Case("ocl_image2darray" , AMDGPULibFunc::IMG2DA)
6222cab237bSDimitry Andric .Case("ocl_image1d" , AMDGPULibFunc::IMG1D)
6232cab237bSDimitry Andric .Case("ocl_image2d" , AMDGPULibFunc::IMG2D)
6242cab237bSDimitry Andric .Case("ocl_image3d" , AMDGPULibFunc::IMG3D)
6252cab237bSDimitry Andric .Case("ocl_event" , AMDGPULibFunc::DUMMY)
6262cab237bSDimitry Andric .Case("ocl_sampler" , AMDGPULibFunc::DUMMY)
6272cab237bSDimitry Andric .Default(AMDGPULibFunc::DUMMY);
6282cab237bSDimitry Andric } else {
6292cab237bSDimitry Andric drop_front(param);
6302cab237bSDimitry Andric switch (TC) {
6312cab237bSDimitry Andric case 'h': res.ArgType = AMDGPULibFunc::U8; break;
6322cab237bSDimitry Andric case 't': res.ArgType = AMDGPULibFunc::U16; break;
6332cab237bSDimitry Andric case 'j': res.ArgType = AMDGPULibFunc::U32; break;
6342cab237bSDimitry Andric case 'm': res.ArgType = AMDGPULibFunc::U64; break;
6352cab237bSDimitry Andric case 'c': res.ArgType = AMDGPULibFunc::I8; break;
6362cab237bSDimitry Andric case 's': res.ArgType = AMDGPULibFunc::I16; break;
6372cab237bSDimitry Andric case 'i': res.ArgType = AMDGPULibFunc::I32; break;
6382cab237bSDimitry Andric case 'l': res.ArgType = AMDGPULibFunc::I64; break;
6392cab237bSDimitry Andric case 'f': res.ArgType = AMDGPULibFunc::F32; break;
6402cab237bSDimitry Andric case 'd': res.ArgType = AMDGPULibFunc::F64; break;
6412cab237bSDimitry Andric case 'D': if (!eatTerm(param, 'h')) return false;
6422cab237bSDimitry Andric res.ArgType = AMDGPULibFunc::F16; break;
6432cab237bSDimitry Andric case 'S':
6442cab237bSDimitry Andric if (!eatTerm(param, '_')) {
6452cab237bSDimitry Andric eatNumber(param);
6462cab237bSDimitry Andric if (!eatTerm(param, '_')) return false;
6472cab237bSDimitry Andric }
6482cab237bSDimitry Andric res.VectorSize = Prev.VectorSize;
6492cab237bSDimitry Andric res.ArgType = Prev.ArgType;
6502cab237bSDimitry Andric break;
6512cab237bSDimitry Andric default:;
6522cab237bSDimitry Andric }
6532cab237bSDimitry Andric }
6542cab237bSDimitry Andric if (res.ArgType == 0) return false;
6552cab237bSDimitry Andric Prev.VectorSize = res.VectorSize;
6562cab237bSDimitry Andric Prev.ArgType = res.ArgType;
6572cab237bSDimitry Andric return true;
6582cab237bSDimitry Andric }
6592cab237bSDimitry Andric
parseFuncName(StringRef & mangledName)6602cab237bSDimitry Andric bool AMDGPUMangledLibFunc::parseFuncName(StringRef &mangledName) {
6612cab237bSDimitry Andric StringRef Name = eatLengthPrefixedName(mangledName);
6622cab237bSDimitry Andric FKind = parseNamePrefix(Name);
6632cab237bSDimitry Andric if (!parseUnmangledName(Name))
6642cab237bSDimitry Andric return false;
6652cab237bSDimitry Andric
6662cab237bSDimitry Andric const ManglingRule& Rule = manglingRules[FuncId];
6672cab237bSDimitry Andric ItaniumParamParser Parser;
6682cab237bSDimitry Andric for (int I=0; I < Rule.maxLeadIndex(); ++I) {
6692cab237bSDimitry Andric Param P;
6702cab237bSDimitry Andric if (!Parser.parseItaniumParam(mangledName, P))
6712cab237bSDimitry Andric return false;
6722cab237bSDimitry Andric
6732cab237bSDimitry Andric if ((I + 1) == Rule.Lead[0]) Leads[0] = P;
6742cab237bSDimitry Andric if ((I + 1) == Rule.Lead[1]) Leads[1] = P;
6752cab237bSDimitry Andric }
6762cab237bSDimitry Andric return true;
6772cab237bSDimitry Andric }
6782cab237bSDimitry Andric
parseFuncName(StringRef & Name)6792cab237bSDimitry Andric bool AMDGPUUnmangledLibFunc::parseFuncName(StringRef &Name) {
6802cab237bSDimitry Andric if (!UnmangledFuncInfo::lookup(Name, FuncId))
6812cab237bSDimitry Andric return false;
6822cab237bSDimitry Andric setName(Name);
6832cab237bSDimitry Andric return true;
6842cab237bSDimitry Andric }
6852cab237bSDimitry Andric
parse(StringRef FuncName,AMDGPULibFunc & F)6862cab237bSDimitry Andric bool AMDGPULibFunc::parse(StringRef FuncName, AMDGPULibFunc &F) {
6872cab237bSDimitry Andric if (FuncName.empty()) {
6882cab237bSDimitry Andric F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
6892cab237bSDimitry Andric return false;
6902cab237bSDimitry Andric }
6912cab237bSDimitry Andric
6922cab237bSDimitry Andric if (eatTerm(FuncName, "_Z"))
6932cab237bSDimitry Andric F.Impl = make_unique<AMDGPUMangledLibFunc>();
6942cab237bSDimitry Andric else
6952cab237bSDimitry Andric F.Impl = make_unique<AMDGPUUnmangledLibFunc>();
6962cab237bSDimitry Andric if (F.Impl->parseFuncName(FuncName))
6972cab237bSDimitry Andric return true;
6982cab237bSDimitry Andric
6992cab237bSDimitry Andric F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
7002cab237bSDimitry Andric return false;
7012cab237bSDimitry Andric }
7022cab237bSDimitry Andric
getUnmangledName(StringRef mangledName)7032cab237bSDimitry Andric StringRef AMDGPUMangledLibFunc::getUnmangledName(StringRef mangledName) {
7042cab237bSDimitry Andric StringRef S = mangledName;
7052cab237bSDimitry Andric if (eatTerm(S, "_Z"))
7062cab237bSDimitry Andric return eatLengthPrefixedName(S);
7072cab237bSDimitry Andric return StringRef();
7082cab237bSDimitry Andric }
7092cab237bSDimitry Andric
7102cab237bSDimitry Andric ///////////////////////////////////////////////////////////////////////////////
7112cab237bSDimitry Andric // Mangling
7122cab237bSDimitry Andric
7132cab237bSDimitry Andric template <typename Stream>
writeName(Stream & OS) const7142cab237bSDimitry Andric void AMDGPUMangledLibFunc::writeName(Stream &OS) const {
7152cab237bSDimitry Andric const char *Pfx = "";
7162cab237bSDimitry Andric switch (FKind) {
7172cab237bSDimitry Andric case NATIVE: Pfx = "native_"; break;
7182cab237bSDimitry Andric case HALF: Pfx = "half_"; break;
7192cab237bSDimitry Andric default: break;
7202cab237bSDimitry Andric }
7212cab237bSDimitry Andric if (!Name.empty()) {
7222cab237bSDimitry Andric OS << Pfx << Name;
7232cab237bSDimitry Andric } else if (FuncId != EI_NONE) {
7242cab237bSDimitry Andric OS << Pfx;
7252cab237bSDimitry Andric const StringRef& S = manglingRules[FuncId].Name;
7262cab237bSDimitry Andric OS.write(S.data(), S.size());
7272cab237bSDimitry Andric }
7282cab237bSDimitry Andric }
7292cab237bSDimitry Andric
mangle() const7302cab237bSDimitry Andric std::string AMDGPUMangledLibFunc::mangle() const { return mangleNameItanium(); }
7312cab237bSDimitry Andric
7322cab237bSDimitry Andric ///////////////////////////////////////////////////////////////////////////////
7332cab237bSDimitry Andric // Itanium Mangling
7342cab237bSDimitry Andric
getItaniumTypeName(AMDGPULibFunc::EType T)7352cab237bSDimitry Andric static const char *getItaniumTypeName(AMDGPULibFunc::EType T) {
7362cab237bSDimitry Andric switch (T) {
7372cab237bSDimitry Andric case AMDGPULibFunc::U8: return "h";
7382cab237bSDimitry Andric case AMDGPULibFunc::U16: return "t";
7392cab237bSDimitry Andric case AMDGPULibFunc::U32: return "j";
7402cab237bSDimitry Andric case AMDGPULibFunc::U64: return "m";
7412cab237bSDimitry Andric case AMDGPULibFunc::I8: return "c";
7422cab237bSDimitry Andric case AMDGPULibFunc::I16: return "s";
7432cab237bSDimitry Andric case AMDGPULibFunc::I32: return "i";
7442cab237bSDimitry Andric case AMDGPULibFunc::I64: return "l";
7452cab237bSDimitry Andric case AMDGPULibFunc::F16: return "Dh";
7462cab237bSDimitry Andric case AMDGPULibFunc::F32: return "f";
7472cab237bSDimitry Andric case AMDGPULibFunc::F64: return "d";
7482cab237bSDimitry Andric case AMDGPULibFunc::IMG1DA: return "16ocl_image1darray";
7492cab237bSDimitry Andric case AMDGPULibFunc::IMG1DB: return "17ocl_image1dbuffer";
7502cab237bSDimitry Andric case AMDGPULibFunc::IMG2DA: return "16ocl_image2darray";
7512cab237bSDimitry Andric case AMDGPULibFunc::IMG1D: return "11ocl_image1d";
7522cab237bSDimitry Andric case AMDGPULibFunc::IMG2D: return "11ocl_image2d";
7532cab237bSDimitry Andric case AMDGPULibFunc::IMG3D: return "11ocl_image3d";
7542cab237bSDimitry Andric case AMDGPULibFunc::SAMPLER: return "11ocl_sampler";
7552cab237bSDimitry Andric case AMDGPULibFunc::EVENT: return "9ocl_event";
7562cab237bSDimitry Andric default: llvm_unreachable("Unhandeled param type");
7572cab237bSDimitry Andric }
7582cab237bSDimitry Andric return nullptr;
7592cab237bSDimitry Andric }
7602cab237bSDimitry Andric
7612cab237bSDimitry Andric namespace {
7622cab237bSDimitry Andric // Itanium mangling ABI says:
7632cab237bSDimitry Andric // "5.1.8. Compression
7642cab237bSDimitry Andric // ... Each non-terminal in the grammar for which <substitution> appears on the
7652cab237bSDimitry Andric // right-hand side is both a source of future substitutions and a candidate
7662cab237bSDimitry Andric // for being substituted. There are two exceptions that appear to be
7672cab237bSDimitry Andric // substitution candidates from the grammar, but are explicitly excluded:
7682cab237bSDimitry Andric // 1. <builtin-type> other than vendor extended types ..."
7692cab237bSDimitry Andric
7702cab237bSDimitry Andric // For the purpose of functions the following productions make sence for the
7712cab237bSDimitry Andric // substitution:
7722cab237bSDimitry Andric // <type> ::= <builtin-type>
7732cab237bSDimitry Andric // ::= <class-enum-type>
7742cab237bSDimitry Andric // ::= <array-type>
7752cab237bSDimitry Andric // ::=<CV-qualifiers> <type>
7762cab237bSDimitry Andric // ::= P <type> # pointer-to
7772cab237bSDimitry Andric // ::= <substitution>
7782cab237bSDimitry Andric //
7792cab237bSDimitry Andric // Note that while types like images, samplers and events are by the ABI encoded
7802cab237bSDimitry Andric // using <class-enum-type> production rule they're not used for substitution
7812cab237bSDimitry Andric // because clang consider them as builtin types.
7822cab237bSDimitry Andric //
7832cab237bSDimitry Andric // DvNN_ type is GCC extension for vectors and is a subject for the substitution.
7842cab237bSDimitry Andric
7852cab237bSDimitry Andric
7862cab237bSDimitry Andric class ItaniumMangler {
7872cab237bSDimitry Andric SmallVector<AMDGPULibFunc::Param, 10> Str; // list of accumulated substituions
7882cab237bSDimitry Andric bool UseAddrSpace;
7892cab237bSDimitry Andric
findSubst(const AMDGPULibFunc::Param & P) const7902cab237bSDimitry Andric int findSubst(const AMDGPULibFunc::Param& P) const {
7912cab237bSDimitry Andric for(unsigned I = 0; I < Str.size(); ++I) {
7922cab237bSDimitry Andric const AMDGPULibFunc::Param& T = Str[I];
7932cab237bSDimitry Andric if (P.PtrKind == T.PtrKind &&
7942cab237bSDimitry Andric P.VectorSize == T.VectorSize &&
7952cab237bSDimitry Andric P.ArgType == T.ArgType) {
7962cab237bSDimitry Andric return I;
7972cab237bSDimitry Andric }
7982cab237bSDimitry Andric }
7992cab237bSDimitry Andric return -1;
8002cab237bSDimitry Andric }
8012cab237bSDimitry Andric
8022cab237bSDimitry Andric template <typename Stream>
trySubst(Stream & os,const AMDGPULibFunc::Param & p)8032cab237bSDimitry Andric bool trySubst(Stream& os, const AMDGPULibFunc::Param& p) {
8042cab237bSDimitry Andric int const subst = findSubst(p);
8052cab237bSDimitry Andric if (subst < 0) return false;
8062cab237bSDimitry Andric // Substitutions are mangled as S(XX)?_ where XX is a hexadecimal number
8072cab237bSDimitry Andric // 0 1 2
8082cab237bSDimitry Andric // S_ S0_ S1_
8092cab237bSDimitry Andric if (subst == 0) os << "S_";
8102cab237bSDimitry Andric else os << 'S' << (subst-1) << '_';
8112cab237bSDimitry Andric return true;
8122cab237bSDimitry Andric }
8132cab237bSDimitry Andric
8142cab237bSDimitry Andric public:
ItaniumMangler(bool useAddrSpace)8152cab237bSDimitry Andric ItaniumMangler(bool useAddrSpace)
8162cab237bSDimitry Andric : UseAddrSpace(useAddrSpace) {}
8172cab237bSDimitry Andric
8182cab237bSDimitry Andric template <typename Stream>
operator ()(Stream & os,AMDGPULibFunc::Param p)8192cab237bSDimitry Andric void operator()(Stream& os, AMDGPULibFunc::Param p) {
8202cab237bSDimitry Andric
8212cab237bSDimitry Andric // Itanium mangling ABI 5.1.8. Compression:
8222cab237bSDimitry Andric // Logically, the substitutable components of a mangled name are considered
8232cab237bSDimitry Andric // left-to-right, components before the composite structure of which they
8242cab237bSDimitry Andric // are a part. If a component has been encountered before, it is substituted
8252cab237bSDimitry Andric // as described below. This decision is independent of whether its components
8262cab237bSDimitry Andric // have been substituted, so an implementation may optimize by considering
8272cab237bSDimitry Andric // large structures for substitution before their components. If a component
8282cab237bSDimitry Andric // has not been encountered before, its mangling is identified, and it is
8292cab237bSDimitry Andric // added to a dictionary of substitution candidates. No entity is added to
8302cab237bSDimitry Andric // the dictionary twice.
8312cab237bSDimitry Andric AMDGPULibFunc::Param Ptr;
8322cab237bSDimitry Andric
8332cab237bSDimitry Andric if (p.PtrKind) {
8342cab237bSDimitry Andric if (trySubst(os, p)) return;
8352cab237bSDimitry Andric os << 'P';
8362cab237bSDimitry Andric if (p.PtrKind & AMDGPULibFunc::CONST) os << 'K';
8372cab237bSDimitry Andric if (p.PtrKind & AMDGPULibFunc::VOLATILE) os << 'V';
8382cab237bSDimitry Andric unsigned AS = UseAddrSpace
8392cab237bSDimitry Andric ? AMDGPULibFuncBase::getAddrSpaceFromEPtrKind(p.PtrKind)
8402cab237bSDimitry Andric : 0;
8412cab237bSDimitry Andric if (AS != 0) os << "U3AS" << AS;
8422cab237bSDimitry Andric Ptr = p;
8432cab237bSDimitry Andric p.PtrKind = 0;
8442cab237bSDimitry Andric }
8452cab237bSDimitry Andric
8462cab237bSDimitry Andric if (p.VectorSize > 1) {
8472cab237bSDimitry Andric if (trySubst(os, p)) goto exit;
8482cab237bSDimitry Andric Str.push_back(p);
8492cab237bSDimitry Andric os << "Dv" << static_cast<unsigned>(p.VectorSize) << '_';
8502cab237bSDimitry Andric }
8512cab237bSDimitry Andric
8522cab237bSDimitry Andric os << getItaniumTypeName((AMDGPULibFunc::EType)p.ArgType);
8532cab237bSDimitry Andric
8542cab237bSDimitry Andric exit:
8552cab237bSDimitry Andric if (Ptr.ArgType) Str.push_back(Ptr);
8562cab237bSDimitry Andric }
8572cab237bSDimitry Andric };
8582cab237bSDimitry Andric } // namespace
8592cab237bSDimitry Andric
mangleNameItanium() const8602cab237bSDimitry Andric std::string AMDGPUMangledLibFunc::mangleNameItanium() const {
8612cab237bSDimitry Andric SmallString<128> Buf;
8622cab237bSDimitry Andric raw_svector_ostream S(Buf);
8632cab237bSDimitry Andric SmallString<128> NameBuf;
8642cab237bSDimitry Andric raw_svector_ostream Name(NameBuf);
8652cab237bSDimitry Andric writeName(Name);
8662cab237bSDimitry Andric const StringRef& NameStr = Name.str();
8672cab237bSDimitry Andric S << "_Z" << static_cast<int>(NameStr.size()) << NameStr;
8682cab237bSDimitry Andric
8692cab237bSDimitry Andric ItaniumMangler Mangler(true);
8702cab237bSDimitry Andric ParamIterator I(Leads, manglingRules[FuncId]);
8712cab237bSDimitry Andric Param P;
8722cab237bSDimitry Andric while ((P = I.getNextParam()).ArgType != 0)
8732cab237bSDimitry Andric Mangler(S, P);
8742cab237bSDimitry Andric return S.str();
8752cab237bSDimitry Andric }
8762cab237bSDimitry Andric
8772cab237bSDimitry Andric ///////////////////////////////////////////////////////////////////////////////
8782cab237bSDimitry Andric // Misc
8792cab237bSDimitry Andric
getIntrinsicParamType(LLVMContext & C,const AMDGPULibFunc::Param & P,bool useAddrSpace)8802cab237bSDimitry Andric static Type* getIntrinsicParamType(
8812cab237bSDimitry Andric LLVMContext& C,
8822cab237bSDimitry Andric const AMDGPULibFunc::Param& P,
8832cab237bSDimitry Andric bool useAddrSpace) {
8842cab237bSDimitry Andric Type* T = nullptr;
8852cab237bSDimitry Andric switch (P.ArgType) {
8862cab237bSDimitry Andric case AMDGPULibFunc::U8:
8872cab237bSDimitry Andric case AMDGPULibFunc::I8: T = Type::getInt8Ty(C); break;
8882cab237bSDimitry Andric case AMDGPULibFunc::U16:
8892cab237bSDimitry Andric case AMDGPULibFunc::I16: T = Type::getInt16Ty(C); break;
8902cab237bSDimitry Andric case AMDGPULibFunc::U32:
8912cab237bSDimitry Andric case AMDGPULibFunc::I32: T = Type::getInt32Ty(C); break;
8922cab237bSDimitry Andric case AMDGPULibFunc::U64:
8932cab237bSDimitry Andric case AMDGPULibFunc::I64: T = Type::getInt64Ty(C); break;
8942cab237bSDimitry Andric case AMDGPULibFunc::F16: T = Type::getHalfTy(C); break;
8952cab237bSDimitry Andric case AMDGPULibFunc::F32: T = Type::getFloatTy(C); break;
8962cab237bSDimitry Andric case AMDGPULibFunc::F64: T = Type::getDoubleTy(C); break;
8972cab237bSDimitry Andric
8982cab237bSDimitry Andric case AMDGPULibFunc::IMG1DA:
8992cab237bSDimitry Andric case AMDGPULibFunc::IMG1DB:
9002cab237bSDimitry Andric case AMDGPULibFunc::IMG2DA:
9012cab237bSDimitry Andric case AMDGPULibFunc::IMG1D:
9022cab237bSDimitry Andric case AMDGPULibFunc::IMG2D:
9032cab237bSDimitry Andric case AMDGPULibFunc::IMG3D:
9042cab237bSDimitry Andric T = StructType::create(C,"ocl_image")->getPointerTo(); break;
9052cab237bSDimitry Andric case AMDGPULibFunc::SAMPLER:
9062cab237bSDimitry Andric T = StructType::create(C,"ocl_sampler")->getPointerTo(); break;
9072cab237bSDimitry Andric case AMDGPULibFunc::EVENT:
9082cab237bSDimitry Andric T = StructType::create(C,"ocl_event")->getPointerTo(); break;
9092cab237bSDimitry Andric default:
9102cab237bSDimitry Andric llvm_unreachable("Unhandeled param type");
9112cab237bSDimitry Andric return nullptr;
9122cab237bSDimitry Andric }
9132cab237bSDimitry Andric if (P.VectorSize > 1)
9142cab237bSDimitry Andric T = VectorType::get(T, P.VectorSize);
9152cab237bSDimitry Andric if (P.PtrKind != AMDGPULibFunc::BYVALUE)
9162cab237bSDimitry Andric T = useAddrSpace ? T->getPointerTo((P.PtrKind & AMDGPULibFunc::ADDR_SPACE)
9172cab237bSDimitry Andric - 1)
9182cab237bSDimitry Andric : T->getPointerTo();
9192cab237bSDimitry Andric return T;
9202cab237bSDimitry Andric }
9212cab237bSDimitry Andric
getFunctionType(Module & M) const9222cab237bSDimitry Andric FunctionType *AMDGPUMangledLibFunc::getFunctionType(Module &M) const {
9232cab237bSDimitry Andric LLVMContext& C = M.getContext();
9242cab237bSDimitry Andric std::vector<Type*> Args;
9252cab237bSDimitry Andric ParamIterator I(Leads, manglingRules[FuncId]);
9262cab237bSDimitry Andric Param P;
9272cab237bSDimitry Andric while ((P=I.getNextParam()).ArgType != 0)
9282cab237bSDimitry Andric Args.push_back(getIntrinsicParamType(C, P, true));
9292cab237bSDimitry Andric
9302cab237bSDimitry Andric return FunctionType::get(
9312cab237bSDimitry Andric getIntrinsicParamType(C, getRetType(FuncId, Leads), true),
9322cab237bSDimitry Andric Args, false);
9332cab237bSDimitry Andric }
9342cab237bSDimitry Andric
getNumArgs() const9352cab237bSDimitry Andric unsigned AMDGPUMangledLibFunc::getNumArgs() const {
9362cab237bSDimitry Andric return manglingRules[FuncId].getNumArgs();
9372cab237bSDimitry Andric }
9382cab237bSDimitry Andric
getNumArgs() const9392cab237bSDimitry Andric unsigned AMDGPUUnmangledLibFunc::getNumArgs() const {
9402cab237bSDimitry Andric return UnmangledFuncInfo::getNumArgs(FuncId);
9412cab237bSDimitry Andric }
9422cab237bSDimitry Andric
getName() const9432cab237bSDimitry Andric std::string AMDGPUMangledLibFunc::getName() const {
9442cab237bSDimitry Andric SmallString<128> Buf;
9452cab237bSDimitry Andric raw_svector_ostream OS(Buf);
9462cab237bSDimitry Andric writeName(OS);
9472cab237bSDimitry Andric return OS.str();
9482cab237bSDimitry Andric }
9492cab237bSDimitry Andric
getFunction(Module * M,const AMDGPULibFunc & fInfo)9502cab237bSDimitry Andric Function *AMDGPULibFunc::getFunction(Module *M, const AMDGPULibFunc &fInfo) {
9512cab237bSDimitry Andric std::string FuncName = fInfo.mangle();
9522cab237bSDimitry Andric Function *F = dyn_cast_or_null<Function>(
9532cab237bSDimitry Andric M->getValueSymbolTable().lookup(FuncName));
9542cab237bSDimitry Andric
9552cab237bSDimitry Andric // check formal with actual types conformance
9562cab237bSDimitry Andric if (F && !F->isDeclaration()
9572cab237bSDimitry Andric && !F->isVarArg()
9582cab237bSDimitry Andric && F->arg_size() == fInfo.getNumArgs()) {
9592cab237bSDimitry Andric return F;
9602cab237bSDimitry Andric }
9612cab237bSDimitry Andric return nullptr;
9622cab237bSDimitry Andric }
9632cab237bSDimitry Andric
getOrInsertFunction(Module * M,const AMDGPULibFunc & fInfo)9642cab237bSDimitry Andric Function *AMDGPULibFunc::getOrInsertFunction(Module *M,
9652cab237bSDimitry Andric const AMDGPULibFunc &fInfo) {
9662cab237bSDimitry Andric std::string const FuncName = fInfo.mangle();
9672cab237bSDimitry Andric Function *F = dyn_cast_or_null<Function>(
9682cab237bSDimitry Andric M->getValueSymbolTable().lookup(FuncName));
9692cab237bSDimitry Andric
9702cab237bSDimitry Andric // check formal with actual types conformance
9712cab237bSDimitry Andric if (F && !F->isDeclaration()
9722cab237bSDimitry Andric && !F->isVarArg()
9732cab237bSDimitry Andric && F->arg_size() == fInfo.getNumArgs()) {
9742cab237bSDimitry Andric return F;
9752cab237bSDimitry Andric }
9762cab237bSDimitry Andric
9772cab237bSDimitry Andric FunctionType *FuncTy = fInfo.getFunctionType(*M);
9782cab237bSDimitry Andric
9792cab237bSDimitry Andric bool hasPtr = false;
9802cab237bSDimitry Andric for (FunctionType::param_iterator
9812cab237bSDimitry Andric PI = FuncTy->param_begin(),
9822cab237bSDimitry Andric PE = FuncTy->param_end();
9832cab237bSDimitry Andric PI != PE; ++PI) {
9842cab237bSDimitry Andric const Type* argTy = static_cast<const Type*>(*PI);
9852cab237bSDimitry Andric if (argTy->isPointerTy()) {
9862cab237bSDimitry Andric hasPtr = true;
9872cab237bSDimitry Andric break;
9882cab237bSDimitry Andric }
9892cab237bSDimitry Andric }
9902cab237bSDimitry Andric
9912cab237bSDimitry Andric Constant *C = nullptr;
9922cab237bSDimitry Andric if (hasPtr) {
9932cab237bSDimitry Andric // Do not set extra attributes for functions with pointer arguments.
9942cab237bSDimitry Andric C = M->getOrInsertFunction(FuncName, FuncTy);
9952cab237bSDimitry Andric } else {
9962cab237bSDimitry Andric AttributeList Attr;
9972cab237bSDimitry Andric LLVMContext &Ctx = M->getContext();
998*b5893f02SDimitry Andric Attr = Attr.addAttribute(Ctx, AttributeList::FunctionIndex,
999*b5893f02SDimitry Andric Attribute::ReadOnly);
1000*b5893f02SDimitry Andric Attr = Attr.addAttribute(Ctx, AttributeList::FunctionIndex,
1001*b5893f02SDimitry Andric Attribute::NoUnwind);
10022cab237bSDimitry Andric C = M->getOrInsertFunction(FuncName, FuncTy, Attr);
10032cab237bSDimitry Andric }
10042cab237bSDimitry Andric
10052cab237bSDimitry Andric return cast<Function>(C);
10062cab237bSDimitry Andric }
10072cab237bSDimitry Andric
lookup(StringRef Name,ID & Id)10082cab237bSDimitry Andric bool UnmangledFuncInfo::lookup(StringRef Name, ID &Id) {
10092cab237bSDimitry Andric auto Loc = Map.find(Name);
10102cab237bSDimitry Andric if (Loc != Map.end()) {
10112cab237bSDimitry Andric Id = toFuncId(Loc->second);
10122cab237bSDimitry Andric return true;
10132cab237bSDimitry Andric }
10142cab237bSDimitry Andric Id = AMDGPULibFunc::EI_NONE;
10152cab237bSDimitry Andric return false;
10162cab237bSDimitry Andric }
10172cab237bSDimitry Andric
AMDGPULibFunc(const AMDGPULibFunc & F)10182cab237bSDimitry Andric AMDGPULibFunc::AMDGPULibFunc(const AMDGPULibFunc &F) {
10192cab237bSDimitry Andric if (auto *MF = dyn_cast<AMDGPUMangledLibFunc>(F.Impl.get()))
10202cab237bSDimitry Andric Impl.reset(new AMDGPUMangledLibFunc(*MF));
10212cab237bSDimitry Andric else if (auto *UMF = dyn_cast<AMDGPUUnmangledLibFunc>(F.Impl.get()))
10222cab237bSDimitry Andric Impl.reset(new AMDGPUUnmangledLibFunc(*UMF));
10232cab237bSDimitry Andric else
10242cab237bSDimitry Andric Impl = std::unique_ptr<AMDGPULibFuncImpl>();
10252cab237bSDimitry Andric }
10262cab237bSDimitry Andric
operator =(const AMDGPULibFunc & F)10272cab237bSDimitry Andric AMDGPULibFunc &AMDGPULibFunc::operator=(const AMDGPULibFunc &F) {
10282cab237bSDimitry Andric if (this == &F)
10292cab237bSDimitry Andric return *this;
10302cab237bSDimitry Andric new (this) AMDGPULibFunc(F);
10312cab237bSDimitry Andric return *this;
10322cab237bSDimitry Andric }
10332cab237bSDimitry Andric
AMDGPULibFunc(EFuncId Id,const AMDGPULibFunc & CopyFrom)10342cab237bSDimitry Andric AMDGPULibFunc::AMDGPULibFunc(EFuncId Id, const AMDGPULibFunc &CopyFrom) {
10352cab237bSDimitry Andric assert(AMDGPULibFuncBase::isMangled(Id) && CopyFrom.isMangled() &&
10362cab237bSDimitry Andric "not supported");
10372cab237bSDimitry Andric Impl.reset(new AMDGPUMangledLibFunc(
10382cab237bSDimitry Andric Id, *cast<AMDGPUMangledLibFunc>(CopyFrom.Impl.get())));
10392cab237bSDimitry Andric }
10402cab237bSDimitry Andric
AMDGPULibFunc(StringRef Name,FunctionType * FT)10412cab237bSDimitry Andric AMDGPULibFunc::AMDGPULibFunc(StringRef Name, FunctionType *FT) {
10422cab237bSDimitry Andric Impl.reset(new AMDGPUUnmangledLibFunc(Name, FT));
10432cab237bSDimitry Andric }
10442cab237bSDimitry Andric
initMangled()10452cab237bSDimitry Andric void AMDGPULibFunc::initMangled() { Impl.reset(new AMDGPUMangledLibFunc()); }
10462cab237bSDimitry Andric
getLeads()10472cab237bSDimitry Andric AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() {
10482cab237bSDimitry Andric if (!Impl)
10492cab237bSDimitry Andric initMangled();
10502cab237bSDimitry Andric return cast<AMDGPUMangledLibFunc>(Impl.get())->Leads;
10512cab237bSDimitry Andric }
10522cab237bSDimitry Andric
getLeads() const10532cab237bSDimitry Andric const AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() const {
10542cab237bSDimitry Andric return cast<const AMDGPUMangledLibFunc>(Impl.get())->Leads;
10552cab237bSDimitry Andric }
1056