57 unsigned char Lead[2];
58 unsigned char Param[5];
60 int maxLeadIndex()
const {
return (
std::max)(Lead[0], Lead[1]); }
61 int getNumLeads()
const {
return (Lead[0] ? 1 : 0) + (Lead[1] ? 1 : 0); }
63 unsigned getNumArgs()
const;
69 class UnmangledFuncInfo {
74 static const UnmangledFuncInfo Table[];
77 static const unsigned TableSize;
83 constexpr UnmangledFuncInfo(
const char *_Name,
unsigned _NumArgs)
84 :
Name(_Name), NumArgs(_NumArgs) {}
87 static unsigned toIndex(
ID Id) {
90 "Invalid unmangled library function");
91 return static_cast<unsigned>(
Id) - 1 -
94 static ID toFuncId(
unsigned Index) {
96 "Invalid unmangled library function");
97 return static_cast<ID>(
100 static unsigned getNumArgs(
ID Id) {
return Table[toIndex(
Id)].NumArgs; }
104 unsigned ManglingRule::getNumArgs()
const {
106 while (
I < (
sizeof Param/
sizeof Param[0]) && Param[
I]) ++
I;
134 static constexpr ManglingRule manglingRules[] = {
136 {
"abs" , {1}, {E_ANY}},
137 {
"abs_diff" , {1}, {E_ANY,E_COPY}},
138 {
"acos" , {1}, {E_ANY}},
139 {
"acosh" , {1}, {E_ANY}},
140 {
"acospi" , {1}, {E_ANY}},
141 {
"add_sat" , {1}, {E_ANY,E_COPY}},
142 {
"all" , {1}, {E_ANY}},
143 {
"any" , {1}, {E_ANY}},
144 {
"asin" , {1}, {E_ANY}},
145 {
"asinh" , {1}, {E_ANY}},
146 {
"asinpi" , {1}, {E_ANY}},
147 {
"async_work_group_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_EVENT}},
148 {
"async_work_group_strided_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_SIZET,EX_EVENT}},
149 {
"atan" , {1}, {E_ANY}},
150 {
"atan2" , {1}, {E_ANY,E_COPY}},
151 {
"atan2pi" , {1}, {E_ANY,E_COPY}},
152 {
"atanh" , {1}, {E_ANY}},
153 {
"atanpi" , {1}, {E_ANY}},
154 {
"atomic_add" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
155 {
"atomic_and" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
156 {
"atomic_cmpxchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE,E_POINTEE}},
157 {
"atomic_dec" , {1}, {E_VLTLPTR_ANY}},
158 {
"atomic_inc" , {1}, {E_VLTLPTR_ANY}},
159 {
"atomic_max" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
160 {
"atomic_min" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
161 {
"atomic_or" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
162 {
"atomic_sub" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
163 {
"atomic_xchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
164 {
"atomic_xor" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
165 {
"bitselect" , {1}, {E_ANY,E_COPY,E_COPY}},
166 {
"cbrt" , {1}, {E_ANY}},
167 {
"ceil" , {1}, {E_ANY}},
168 {
"clamp" , {1}, {E_ANY,E_COPY,E_COPY}},
169 {
"clz" , {1}, {E_ANY}},
170 {
"commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
171 {
"commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
172 {
"copysign" , {1}, {E_ANY,E_COPY}},
173 {
"cos" , {1}, {E_ANY}},
174 {
"cosh" , {1}, {E_ANY}},
175 {
"cospi" , {1}, {E_ANY}},
176 {
"cross" , {1}, {E_ANY,E_COPY}},
177 {
"ctz" , {1}, {E_ANY}},
178 {
"degrees" , {1}, {E_ANY}},
179 {
"distance" , {1}, {E_ANY,E_COPY}},
180 {
"divide" , {1}, {E_ANY,E_COPY}},
181 {
"dot" , {1}, {E_ANY,E_COPY}},
182 {
"erf" , {1}, {E_ANY}},
183 {
"erfc" , {1}, {E_ANY}},
184 {
"exp" , {1}, {E_ANY}},
185 {
"exp10" , {1}, {E_ANY}},
186 {
"exp2" , {1}, {E_ANY}},
187 {
"expm1" , {1}, {E_ANY}},
188 {
"fabs" , {1}, {E_ANY}},
189 {
"fast_distance" , {1}, {E_ANY,E_COPY}},
190 {
"fast_length" , {1}, {E_ANY}},
191 {
"fast_normalize" , {1}, {E_ANY}},
192 {
"fdim" , {1}, {E_ANY,E_COPY}},
193 {
"floor" , {1}, {E_ANY}},
194 {
"fma" , {1}, {E_ANY,E_COPY,E_COPY}},
195 {
"fmax" , {1}, {E_ANY,E_COPY}},
196 {
"fmin" , {1}, {E_ANY,E_COPY}},
197 {
"fmod" , {1}, {E_ANY,E_COPY}},
198 {
"fract" , {2}, {E_POINTEE,E_ANY}},
199 {
"frexp" , {1,2}, {E_ANY,E_ANY}},
200 {
"get_image_array_size" , {1}, {E_ANY}},
201 {
"get_image_channel_data_type" , {1}, {E_ANY}},
202 {
"get_image_channel_order" , {1}, {E_ANY}},
203 {
"get_image_dim" , {1}, {E_ANY}},
204 {
"get_image_height" , {1}, {E_ANY}},
205 {
"get_image_width" , {1}, {E_ANY}},
206 {
"get_pipe_max_packets" , {1}, {E_ANY}},
207 {
"get_pipe_num_packets" , {1}, {E_ANY}},
208 {
"hadd" , {1}, {E_ANY,E_COPY}},
209 {
"hypot" , {1}, {E_ANY,E_COPY}},
210 {
"ilogb" , {1}, {E_ANY}},
211 {
"isequal" , {1}, {E_ANY,E_COPY}},
212 {
"isfinite" , {1}, {E_ANY}},
213 {
"isgreater" , {1}, {E_ANY,E_COPY}},
214 {
"isgreaterequal" , {1}, {E_ANY,E_COPY}},
215 {
"isinf" , {1}, {E_ANY}},
216 {
"isless" , {1}, {E_ANY,E_COPY}},
217 {
"islessequal" , {1}, {E_ANY,E_COPY}},
218 {
"islessgreater" , {1}, {E_ANY,E_COPY}},
219 {
"isnan" , {1}, {E_ANY}},
220 {
"isnormal" , {1}, {E_ANY}},
221 {
"isnotequal" , {1}, {E_ANY,E_COPY}},
222 {
"isordered" , {1}, {E_ANY,E_COPY}},
223 {
"isunordered" , {1}, {E_ANY,E_COPY}},
224 {
"ldexp" , {1}, {E_ANY,E_SETBASE_I32}},
225 {
"length" , {1}, {E_ANY}},
226 {
"lgamma" , {1}, {E_ANY}},
227 {
"lgamma_r" , {1,2}, {E_ANY,E_ANY}},
228 {
"log" , {1}, {E_ANY}},
229 {
"log10" , {1}, {E_ANY}},
230 {
"log1p" , {1}, {E_ANY}},
231 {
"log2" , {1}, {E_ANY}},
232 {
"logb" , {1}, {E_ANY}},
233 {
"mad" , {1}, {E_ANY,E_COPY,E_COPY}},
234 {
"mad24" , {1}, {E_ANY,E_COPY,E_COPY}},
235 {
"mad_hi" , {1}, {E_ANY,E_COPY,E_COPY}},
236 {
"mad_sat" , {1}, {E_ANY,E_COPY,E_COPY}},
237 {
"max" , {1}, {E_ANY,E_COPY}},
238 {
"maxmag" , {1}, {E_ANY,E_COPY}},
239 {
"min" , {1}, {E_ANY,E_COPY}},
240 {
"minmag" , {1}, {E_ANY,E_COPY}},
241 {
"mix" , {1}, {E_ANY,E_COPY,E_COPY}},
242 {
"modf" , {2}, {E_POINTEE,E_ANY}},
243 {
"mul24" , {1}, {E_ANY,E_COPY}},
244 {
"mul_hi" , {1}, {E_ANY,E_COPY}},
245 {
"nan" , {1}, {E_ANY}},
246 {
"nextafter" , {1}, {E_ANY,E_COPY}},
247 {
"normalize" , {1}, {E_ANY}},
248 {
"popcount" , {1}, {E_ANY}},
249 {
"pow" , {1}, {E_ANY,E_COPY}},
250 {
"pown" , {1}, {E_ANY,E_SETBASE_I32}},
251 {
"powr" , {1}, {E_ANY,E_COPY}},
252 {
"prefetch" , {1}, {E_CONSTPTR_ANY,EX_SIZET}},
253 {
"radians" , {1}, {E_ANY}},
254 {
"recip" , {1}, {E_ANY}},
255 {
"remainder" , {1}, {E_ANY,E_COPY}},
256 {
"remquo" , {1,3}, {E_ANY,E_COPY,E_ANY}},
257 {
"reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
258 {
"reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
259 {
"rhadd" , {1}, {E_ANY,E_COPY}},
260 {
"rint" , {1}, {E_ANY}},
261 {
"rootn" , {1}, {E_ANY,E_SETBASE_I32}},
262 {
"rotate" , {1}, {E_ANY,E_COPY}},
263 {
"round" , {1}, {E_ANY}},
264 {
"rsqrt" , {1}, {E_ANY}},
265 {
"select" , {1,3}, {E_ANY,E_COPY,E_ANY}},
266 {
"shuffle" , {1,2}, {E_ANY,E_ANY}},
267 {
"shuffle2" , {1,3}, {E_ANY,E_COPY,E_ANY}},
268 {
"sign" , {1}, {E_ANY}},
269 {
"signbit" , {1}, {E_ANY}},
270 {
"sin" , {1}, {E_ANY}},
271 {
"sincos" , {2}, {E_POINTEE,E_ANY}},
272 {
"sinh" , {1}, {E_ANY}},
273 {
"sinpi" , {1}, {E_ANY}},
274 {
"smoothstep" , {1}, {E_ANY,E_COPY,E_COPY}},
275 {
"sqrt" , {1}, {E_ANY}},
276 {
"step" , {1}, {E_ANY,E_COPY}},
277 {
"sub_group_broadcast" , {1}, {E_ANY,EX_UINT}},
278 {
"sub_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
279 {
"sub_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
280 {
"sub_group_reduce_add" , {1}, {E_ANY}},
281 {
"sub_group_reduce_max" , {1}, {E_ANY}},
282 {
"sub_group_reduce_min" , {1}, {E_ANY}},
283 {
"sub_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
284 {
"sub_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
285 {
"sub_group_scan_exclusive_add" , {1}, {E_ANY}},
286 {
"sub_group_scan_exclusive_max" , {1}, {E_ANY}},
287 {
"sub_group_scan_exclusive_min" , {1}, {E_ANY}},
288 {
"sub_group_scan_inclusive_add" , {1}, {E_ANY}},
289 {
"sub_group_scan_inclusive_max" , {1}, {E_ANY}},
290 {
"sub_group_scan_inclusive_min" , {1}, {E_ANY}},
291 {
"sub_sat" , {1}, {E_ANY,E_COPY}},
292 {
"tan" , {1}, {E_ANY}},
293 {
"tanh" , {1}, {E_ANY}},
294 {
"tanpi" , {1}, {E_ANY}},
295 {
"tgamma" , {1}, {E_ANY}},
296 {
"trunc" , {1}, {E_ANY}},
297 {
"upsample" , {1}, {E_ANY,E_MAKEBASE_UNS}},
298 {
"vec_step" , {1}, {E_ANY}},
299 {
"vstore" , {3}, {E_POINTEE,EX_SIZET,E_ANY}},
300 {
"vstore16" , {3}, {E_V16_OF_POINTEE,EX_SIZET,E_ANY}},
301 {
"vstore2" , {3}, {E_V2_OF_POINTEE,EX_SIZET,E_ANY}},
302 {
"vstore3" , {3}, {E_V3_OF_POINTEE,EX_SIZET,E_ANY}},
303 {
"vstore4" , {3}, {E_V4_OF_POINTEE,EX_SIZET,E_ANY}},
304 {
"vstore8" , {3}, {E_V8_OF_POINTEE,EX_SIZET,E_ANY}},
305 {
"work_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
306 {
"work_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
307 {
"work_group_reduce_add" , {1}, {E_ANY}},
308 {
"work_group_reduce_max" , {1}, {E_ANY}},
309 {
"work_group_reduce_min" , {1}, {E_ANY}},
310 {
"work_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
311 {
"work_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
312 {
"work_group_scan_exclusive_add" , {1}, {E_ANY}},
313 {
"work_group_scan_exclusive_max" , {1}, {E_ANY}},
314 {
"work_group_scan_exclusive_min" , {1}, {E_ANY}},
315 {
"work_group_scan_inclusive_add" , {1}, {E_ANY}},
316 {
"work_group_scan_inclusive_max" , {1}, {E_ANY}},
317 {
"work_group_scan_inclusive_min" , {1}, {E_ANY}},
318 {
"write_imagef" , {1}, {E_ANY,E_IMAGECOORDS,EX_FLOAT4}},
319 {
"write_imagei" , {1}, {E_ANY,E_IMAGECOORDS,EX_INTV4}},
320 {
"write_imageui" , {1}, {E_ANY,E_IMAGECOORDS,EX_UINTV4}},
321 {
"ncos" , {1}, {E_ANY} },
322 {
"nexp2" , {1}, {E_ANY} },
323 {
"nfma" , {1}, {E_ANY, E_COPY, E_COPY} },
324 {
"nlog2" , {1}, {E_ANY} },
325 {
"nrcp" , {1}, {E_ANY} },
326 {
"nrsqrt" , {1}, {E_ANY} },
327 {
"nsin" , {1}, {E_ANY} },
328 {
"nsqrt" , {1}, {E_ANY} },
329 {
"ftz" , {1}, {E_ANY} },
330 {
"fldexp" , {1}, {E_ANY, EX_UINT} },
331 {
"class" , {1}, {E_ANY, EX_UINT} },
332 {
"rcbrt" , {1}, {E_ANY} },
336 const UnmangledFuncInfo UnmangledFuncInfo::Table[] = {
337 {
"__read_pipe_2", 4},
338 {
"__read_pipe_4", 6},
339 {
"__write_pipe_2", 4},
340 {
"__write_pipe_4", 6},
343 const unsigned UnmangledFuncInfo::TableSize =
360 class ParamIterator {
362 const ManglingRule& Rule;
366 const ManglingRule& rule)
367 : Leads(leads), Rule(rule),
Index(0) {}
374 if (
Index >=
int(
sizeof Rule.Param/
sizeof Rule.Param[0]))
return P;
376 const char R = Rule.Param[
Index];
393 case EX_RESERVEDID:
break;
395 if (
Index == (Rule.Lead[1] - 1))
P = Leads[1];
404 case E_V2_OF_POINTEE:
406 case E_V3_OF_POINTEE:
408 case E_V4_OF_POINTEE:
410 case E_V8_OF_POINTEE:
412 case E_V16_OF_POINTEE:
441 case E_CONSTPTR_SWAPGL: {
459 inline static void drop_front(
StringRef& str,
size_t n = 1) {
463 static bool eatTerm(
StringRef& mangledName,
const char c) {
464 if (mangledName.
front() ==
c) {
465 drop_front(mangledName);
472 static bool eatTerm(
StringRef& mangledName,
const char (&str)[
N]) {
474 drop_front(mangledName,
N-1);
481 size_t const savedSize =
s.size();
483 while (!
s.empty() && isDigit(
s.front())) {
484 n =
n*10 +
s.front() -
'0';
487 return s.size() < savedSize ?
n : -1;
491 int const Len = eatNumber(mangledName);
492 if (Len <= 0 ||
static_cast<size_t>(Len) > mangledName.
size())
495 drop_front(mangledName, Len);
526 size_t const Len = eatNumber(mangledName);
528 case 2:
case 3:
case 4:
case 8:
case 16:
537 std::pair<StringRef, StringRef>
const P = mangledName.
split(
'_');
545 mangledName =
P.second;
553 for (
auto Rule : manglingRules)
554 Map.insert({Rule.Name,
Id++});
558 bool AMDGPUMangledLibFunc::parseUnmangledName(
StringRef FullName) {
560 ManglingRule::buildManglingRulesMap();
569 struct ItaniumParamParser {
575 bool ItaniumParamParser::parseItaniumParam(
StringRef& param,
578 if (param.
empty())
return false;
581 if (eatTerm(param,
'P')) {
585 if (!eatTerm(param,
"U3AS")) {
588 AS = param.
front() -
'0';
589 drop_front(param, 1);
597 if (eatTerm(param,
"Dv")) {
599 if (res.VectorSize==1 || !eatTerm(param,
'_'))
return false;
603 char const TC = param.
front();
606 (eatLengthPrefixedName(param))
629 case 'D':
if (!eatTerm(param,
'h'))
return false;
632 if (!eatTerm(param,
'_')) {
634 if (!eatTerm(param,
'_'))
return false;
636 res.VectorSize = Prev.VectorSize;
637 res.ArgType = Prev.ArgType;
642 if (res.ArgType == 0)
return false;
643 Prev.VectorSize = res.VectorSize;
644 Prev.ArgType = res.ArgType;
651 if (!parseUnmangledName(
Name))
654 const ManglingRule& Rule = manglingRules[
FuncId];
655 ItaniumParamParser Parser;
656 for (
int I=0;
I < Rule.maxLeadIndex(); ++
I) {
658 if (!Parser.parseItaniumParam(mangledName,
P))
661 if ((
I + 1) == Rule.Lead[0])
Leads[0] =
P;
662 if ((
I + 1) == Rule.Lead[1])
Leads[1] =
P;
675 if (FuncName.
empty()) {
676 F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
680 if (eatTerm(FuncName,
"_Z"))
681 F.Impl = std::make_unique<AMDGPUMangledLibFunc>();
683 F.Impl = std::make_unique<AMDGPUUnmangledLibFunc>();
684 if (
F.Impl->parseFuncName(FuncName))
687 F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
693 if (eatTerm(
S,
"_Z"))
694 return eatLengthPrefixedName(
S);
701 template <
typename Stream>
702 void AMDGPUMangledLibFunc::writeName(Stream &OS)
const {
703 const char *Pfx =
"";
705 case NATIVE: Pfx =
"native_";
break;
706 case HALF: Pfx =
"half_";
break;
714 OS.write(
S.data(),
S.size());
774 class ItaniumMangler {
779 for(
unsigned I = 0;
I < Str.size(); ++
I) {
781 if (
P.PtrKind ==
T.PtrKind &&
782 P.VectorSize ==
T.VectorSize &&
783 P.ArgType ==
T.ArgType) {
790 template <
typename Stream>
792 int const subst = findSubst(
p);
793 if (subst < 0)
return false;
797 if (subst == 0) os <<
"S_";
798 else os <<
'S' << (subst-1) <<
'_';
803 ItaniumMangler(
bool useAddrSpace)
804 : UseAddrSpace(useAddrSpace) {}
806 template <
typename Stream>
822 if (trySubst(os,
p))
return;
826 unsigned AS = UseAddrSpace
829 if (AS != 0) os <<
"U3AS" << AS;
834 if (
p.VectorSize > 1) {
835 if (trySubst(os,
p))
goto exit;
837 os <<
"Dv" <<
static_cast<unsigned>(
p.VectorSize) <<
'_';
843 if (Ptr.ArgType) Str.push_back(Ptr);
848 std::string AMDGPUMangledLibFunc::mangleNameItanium()
const {
855 S <<
"_Z" <<
static_cast<int>(NameStr.
size()) << NameStr;
860 while ((
P =
I.getNextParam()).ArgType != 0)
862 return std::string(
S.str());
901 if (
P.VectorSize > 1)
912 std::vector<Type*>
Args;
915 while ((
P=
I.getNextParam()).ArgType != 0)
924 return manglingRules[
FuncId].getNumArgs();
928 return UnmangledFuncInfo::getNumArgs(
FuncId);
935 return std::string(OS.
str());
939 std::string FuncName = fInfo.
mangle();
940 Function *
F = dyn_cast_or_null<Function>(
941 M->getValueSymbolTable().lookup(FuncName));
944 if (
F && !
F->isDeclaration()
954 std::string
const FuncName = fInfo.
mangle();
955 Function *
F = dyn_cast_or_null<Function>(
956 M->getValueSymbolTable().lookup(FuncName));
959 if (
F && !
F->isDeclaration()
972 const Type* argTy =
static_cast<const Type*
>(*PI);
982 C =
M->getOrInsertFunction(FuncName, FuncTy);
989 Attribute::NoUnwind);
990 C =
M->getOrInsertFunction(FuncName, FuncTy, Attr);
998 for (
unsigned I = 0;
I != TableSize; ++
I)
1005 auto Loc = Map.find(
Name);
1006 if (Loc != Map.end()) {
1007 Id = toFuncId(Loc->second);
1015 if (
auto *MF = dyn_cast<AMDGPUMangledLibFunc>(
F.Impl.get()))
1017 else if (
auto *UMF = dyn_cast<AMDGPUUnmangledLibFunc>(
F.Impl.get()))
1020 Impl = std::unique_ptr<AMDGPULibFuncImpl>();
1034 Id, *cast<AMDGPUMangledLibFunc>(CopyFrom.Impl.get())));
1046 return cast<AMDGPUMangledLibFunc>(Impl.get())->Leads;
1050 return cast<const AMDGPUMangledLibFunc>(Impl.get())->Leads;