29 "amdgpu-enable-ocl-mangling-mismatch-workaround",
cl::init(
true),
31 cl::desc(
"Enable the workaround for OCL name mangling mismatch."));
64 unsigned char Lead[2];
65 unsigned char Param[5];
67 int maxLeadIndex()
const {
return (std::max)(Lead[0], Lead[1]); }
68 int getNumLeads()
const {
return (Lead[0] ? 1 : 0) + (Lead[1] ? 1 : 0); }
70 unsigned getNumArgs()
const;
72 static StringMap<int> buildManglingRulesMap();
76class UnmangledFuncInfo {
81 static const UnmangledFuncInfo Table[];
84 static const unsigned TableSize;
86 static StringMap<unsigned> buildNameMap();
89 using ID = AMDGPULibFunc::EFuncId;
90 constexpr UnmangledFuncInfo(
const char *_Name,
unsigned _NumArgs)
91 : Name(_Name), NumArgs(_NumArgs) {}
93 static bool lookup(StringRef Name, ID &Id);
94 static unsigned toIndex(ID Id) {
95 assert(
static_cast<unsigned>(Id) >
96 static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED) &&
97 "Invalid unmangled library function");
98 return static_cast<unsigned>(
Id) - 1 -
99 static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED);
101 static ID toFuncId(
unsigned Index) {
102 assert(Index < TableSize &&
103 "Invalid unmangled library function");
104 return static_cast<ID
>(
105 Index + 1 +
static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED));
107 static unsigned getNumArgs(ID Id) {
return Table[toIndex(Id)].NumArgs; }
108 static StringRef
getName(ID Id) {
return Table[toIndex(Id)].Name; }
111unsigned ManglingRule::getNumArgs()
const {
113 while (
I < (
sizeof Param/
sizeof Param[0]) && Param[
I]) ++
I;
141static constexpr ManglingRule manglingRules[] = {
143{
"abs" , {1}, {E_ANY}},
144{
"abs_diff" , {1}, {E_ANY,E_COPY}},
145{
"acos" , {1}, {E_ANY}},
146{
"acosh" , {1}, {E_ANY}},
147{
"acospi" , {1}, {E_ANY}},
148{
"add_sat" , {1}, {E_ANY,E_COPY}},
149{
"all" , {1}, {E_ANY}},
150{
"any" , {1}, {E_ANY}},
151{
"asin" , {1}, {E_ANY}},
152{
"asinh" , {1}, {E_ANY}},
153{
"asinpi" , {1}, {E_ANY}},
154{
"async_work_group_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_EVENT}},
155{
"async_work_group_strided_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_SIZET,EX_EVENT}},
156{
"atan" , {1}, {E_ANY}},
157{
"atan2" , {1}, {E_ANY,E_COPY}},
158{
"atan2pi" , {1}, {E_ANY,E_COPY}},
159{
"atanh" , {1}, {E_ANY}},
160{
"atanpi" , {1}, {E_ANY}},
161{
"atomic_add" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
162{
"atomic_and" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
163{
"atomic_cmpxchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE,E_POINTEE}},
164{
"atomic_dec" , {1}, {E_VLTLPTR_ANY}},
165{
"atomic_inc" , {1}, {E_VLTLPTR_ANY}},
166{
"atomic_max" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
167{
"atomic_min" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
168{
"atomic_or" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
169{
"atomic_sub" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
170{
"atomic_xchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
171{
"atomic_xor" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
172{
"bitselect" , {1}, {E_ANY,E_COPY,E_COPY}},
173{
"cbrt" , {1}, {E_ANY}},
174{
"ceil" , {1}, {E_ANY}},
175{
"clamp" , {1}, {E_ANY,E_COPY,E_COPY}},
176{
"clz" , {1}, {E_ANY}},
177{
"commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
178{
"commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
179{
"copysign" , {1}, {E_ANY,E_COPY}},
180{
"cos" , {1}, {E_ANY}},
181{
"cosh" , {1}, {E_ANY}},
182{
"cospi" , {1}, {E_ANY}},
183{
"cross" , {1}, {E_ANY,E_COPY}},
184{
"ctz" , {1}, {E_ANY}},
185{
"degrees" , {1}, {E_ANY}},
186{
"distance" , {1}, {E_ANY,E_COPY}},
187{
"divide" , {1}, {E_ANY,E_COPY}},
188{
"dot" , {1}, {E_ANY,E_COPY}},
189{
"erf" , {1}, {E_ANY}},
190{
"erfc" , {1}, {E_ANY}},
191{
"exp" , {1}, {E_ANY}},
192{
"exp10" , {1}, {E_ANY}},
193{
"exp2" , {1}, {E_ANY}},
194{
"expm1" , {1}, {E_ANY}},
195{
"fabs" , {1}, {E_ANY}},
196{
"fast_distance" , {1}, {E_ANY,E_COPY}},
197{
"fast_length" , {1}, {E_ANY}},
198{
"fast_normalize" , {1}, {E_ANY}},
199{
"fdim" , {1}, {E_ANY,E_COPY}},
200{
"floor" , {1}, {E_ANY}},
201{
"fma" , {1}, {E_ANY,E_COPY,E_COPY}},
202{
"fmax" , {1}, {E_ANY,E_COPY}},
203{
"fmin" , {1}, {E_ANY,E_COPY}},
204{
"fmod" , {1}, {E_ANY,E_COPY}},
205{
"fract" , {2}, {E_POINTEE,E_ANY}},
206{
"frexp" , {1,2}, {E_ANY,E_ANY}},
207{
"get_image_array_size" , {1}, {E_ANY}},
208{
"get_image_channel_data_type" , {1}, {E_ANY}},
209{
"get_image_channel_order" , {1}, {E_ANY}},
210{
"get_image_dim" , {1}, {E_ANY}},
211{
"get_image_height" , {1}, {E_ANY}},
212{
"get_image_width" , {1}, {E_ANY}},
213{
"get_pipe_max_packets" , {1}, {E_ANY}},
214{
"get_pipe_num_packets" , {1}, {E_ANY}},
215{
"hadd" , {1}, {E_ANY,E_COPY}},
216{
"hypot" , {1}, {E_ANY,E_COPY}},
217{
"ilogb" , {1}, {E_ANY}},
218{
"isequal" , {1}, {E_ANY,E_COPY}},
219{
"isfinite" , {1}, {E_ANY}},
220{
"isgreater" , {1}, {E_ANY,E_COPY}},
221{
"isgreaterequal" , {1}, {E_ANY,E_COPY}},
222{
"isinf" , {1}, {E_ANY}},
223{
"isless" , {1}, {E_ANY,E_COPY}},
224{
"islessequal" , {1}, {E_ANY,E_COPY}},
225{
"islessgreater" , {1}, {E_ANY,E_COPY}},
226{
"isnan" , {1}, {E_ANY}},
227{
"isnormal" , {1}, {E_ANY}},
228{
"isnotequal" , {1}, {E_ANY,E_COPY}},
229{
"isordered" , {1}, {E_ANY,E_COPY}},
230{
"isunordered" , {1}, {E_ANY,E_COPY}},
231{
"ldexp" , {1}, {E_ANY,E_SETBASE_I32}},
232{
"length" , {1}, {E_ANY}},
233{
"lgamma" , {1}, {E_ANY}},
234{
"lgamma_r" , {1,2}, {E_ANY,E_ANY}},
235{
"log" , {1}, {E_ANY}},
236{
"log10" , {1}, {E_ANY}},
237{
"log1p" , {1}, {E_ANY}},
238{
"log2" , {1}, {E_ANY}},
239{
"logb" , {1}, {E_ANY}},
240{
"mad" , {1}, {E_ANY,E_COPY,E_COPY}},
241{
"mad24" , {1}, {E_ANY,E_COPY,E_COPY}},
242{
"mad_hi" , {1}, {E_ANY,E_COPY,E_COPY}},
243{
"mad_sat" , {1}, {E_ANY,E_COPY,E_COPY}},
244{
"max" , {1}, {E_ANY,E_COPY}},
245{
"maxmag" , {1}, {E_ANY,E_COPY}},
246{
"min" , {1}, {E_ANY,E_COPY}},
247{
"minmag" , {1}, {E_ANY,E_COPY}},
248{
"mix" , {1}, {E_ANY,E_COPY,E_COPY}},
249{
"modf" , {2}, {E_POINTEE,E_ANY}},
250{
"mul24" , {1}, {E_ANY,E_COPY}},
251{
"mul_hi" , {1}, {E_ANY,E_COPY}},
252{
"nan" , {1}, {E_ANY}},
253{
"nextafter" , {1}, {E_ANY,E_COPY}},
254{
"normalize" , {1}, {E_ANY}},
255{
"popcount" , {1}, {E_ANY}},
256{
"pow" , {1}, {E_ANY,E_COPY}},
257{
"__pow_fast" , {1}, {E_ANY,E_COPY}},
258{
"pown" , {1}, {E_ANY,E_SETBASE_I32}},
259{
"__pown_fast" , {1}, {E_ANY,E_SETBASE_I32}},
260{
"powr" , {1}, {E_ANY,E_COPY}},
261{
"__powr_fast" , {1}, {E_ANY,E_COPY}},
262{
"prefetch" , {1}, {E_CONSTPTR_ANY,EX_SIZET}},
263{
"radians" , {1}, {E_ANY}},
264{
"recip" , {1}, {E_ANY}},
265{
"remainder" , {1}, {E_ANY,E_COPY}},
266{
"remquo" , {1,3}, {E_ANY,E_COPY,E_ANY}},
267{
"reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
268{
"reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
269{
"rhadd" , {1}, {E_ANY,E_COPY}},
270{
"rint" , {1}, {E_ANY}},
271{
"rootn" , {1}, {E_ANY,E_SETBASE_I32}},
272{
"__rootn_fast" , {1}, {E_ANY,E_SETBASE_I32}},
273{
"rotate" , {1}, {E_ANY,E_COPY}},
274{
"round" , {1}, {E_ANY}},
275{
"rsqrt" , {1}, {E_ANY}},
276{
"select" , {1,3}, {E_ANY,E_COPY,E_ANY}},
277{
"shuffle" , {1,2}, {E_ANY,E_ANY}},
278{
"shuffle2" , {1,3}, {E_ANY,E_COPY,E_ANY}},
279{
"sign" , {1}, {E_ANY}},
280{
"signbit" , {1}, {E_ANY}},
281{
"sin" , {1}, {E_ANY}},
282{
"sincos" , {2}, {E_POINTEE,E_ANY}},
283{
"sinh" , {1}, {E_ANY}},
284{
"sinpi" , {1}, {E_ANY}},
285{
"smoothstep" , {1}, {E_ANY,E_COPY,E_COPY}},
286{
"sqrt" , {1}, {E_ANY}},
287{
"step" , {1}, {E_ANY,E_COPY}},
288{
"sub_group_broadcast" , {1}, {E_ANY,EX_UINT}},
289{
"sub_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
290{
"sub_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
291{
"sub_group_reduce_add" , {1}, {E_ANY}},
292{
"sub_group_reduce_max" , {1}, {E_ANY}},
293{
"sub_group_reduce_min" , {1}, {E_ANY}},
294{
"sub_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
295{
"sub_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
296{
"sub_group_scan_exclusive_add" , {1}, {E_ANY}},
297{
"sub_group_scan_exclusive_max" , {1}, {E_ANY}},
298{
"sub_group_scan_exclusive_min" , {1}, {E_ANY}},
299{
"sub_group_scan_inclusive_add" , {1}, {E_ANY}},
300{
"sub_group_scan_inclusive_max" , {1}, {E_ANY}},
301{
"sub_group_scan_inclusive_min" , {1}, {E_ANY}},
302{
"sub_sat" , {1}, {E_ANY,E_COPY}},
303{
"tan" , {1}, {E_ANY}},
304{
"tanh" , {1}, {E_ANY}},
305{
"tanpi" , {1}, {E_ANY}},
306{
"tgamma" , {1}, {E_ANY}},
307{
"trunc" , {1}, {E_ANY}},
308{
"upsample" , {1}, {E_ANY,E_MAKEBASE_UNS}},
309{
"vec_step" , {1}, {E_ANY}},
310{
"vstore" , {3}, {E_POINTEE,EX_SIZET,E_ANY}},
311{
"vstore16" , {3}, {E_V16_OF_POINTEE,EX_SIZET,E_ANY}},
312{
"vstore2" , {3}, {E_V2_OF_POINTEE,EX_SIZET,E_ANY}},
313{
"vstore3" , {3}, {E_V3_OF_POINTEE,EX_SIZET,E_ANY}},
314{
"vstore4" , {3}, {E_V4_OF_POINTEE,EX_SIZET,E_ANY}},
315{
"vstore8" , {3}, {E_V8_OF_POINTEE,EX_SIZET,E_ANY}},
316{
"work_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
317{
"work_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
318{
"work_group_reduce_add" , {1}, {E_ANY}},
319{
"work_group_reduce_max" , {1}, {E_ANY}},
320{
"work_group_reduce_min" , {1}, {E_ANY}},
321{
"work_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
322{
"work_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
323{
"work_group_scan_exclusive_add" , {1}, {E_ANY}},
324{
"work_group_scan_exclusive_max" , {1}, {E_ANY}},
325{
"work_group_scan_exclusive_min" , {1}, {E_ANY}},
326{
"work_group_scan_inclusive_add" , {1}, {E_ANY}},
327{
"work_group_scan_inclusive_max" , {1}, {E_ANY}},
328{
"work_group_scan_inclusive_min" , {1}, {E_ANY}},
329{
"write_imagef" , {1}, {E_ANY,E_IMAGECOORDS,EX_FLOAT4}},
330{
"write_imagei" , {1}, {E_ANY,E_IMAGECOORDS,EX_INTV4}},
331{
"write_imageui" , {1}, {E_ANY,E_IMAGECOORDS,EX_UINTV4}},
332{
"ncos" , {1}, {E_ANY} },
333{
"nexp2" , {1}, {E_ANY} },
334{
"nfma" , {1}, {E_ANY, E_COPY, E_COPY} },
335{
"nlog2" , {1}, {E_ANY} },
336{
"nrcp" , {1}, {E_ANY} },
337{
"nrsqrt" , {1}, {E_ANY} },
338{
"nsin" , {1}, {E_ANY} },
339{
"nsqrt" , {1}, {E_ANY} },
340{
"ftz" , {1}, {E_ANY} },
341{
"fldexp" , {1}, {E_ANY, EX_UINT} },
342{
"class" , {1}, {E_ANY, EX_UINT} },
343{
"rcbrt" , {1}, {E_ANY} },
347const UnmangledFuncInfo UnmangledFuncInfo::Table[] = {
348 {
"__read_pipe_2", 4},
349 {
"__read_pipe_4", 6},
350 {
"__write_pipe_2", 4},
351 {
"__write_pipe_4", 6},
354const unsigned UnmangledFuncInfo::TableSize =
355 std::size(UnmangledFuncInfo::Table);
357static AMDGPULibFunc::Param getRetType(AMDGPULibFunc::EFuncId
id,
358 const AMDGPULibFunc::Param (&Leads)[2]) {
359 AMDGPULibFunc::Param Res = Leads[0];
362 case AMDGPULibFunc::EI_SINCOS:
363 Res.
PtrKind = AMDGPULibFunc::BYVALUE;
372 const AMDGPULibFunc::Param (&Leads)[2];
373 const ManglingRule& Rule;
376 ParamIterator(
const AMDGPULibFunc::Param (&leads)[2],
377 const ManglingRule& rule)
378 : Leads(leads), Rule(rule) {}
380 AMDGPULibFunc::Param getNextParam();
383AMDGPULibFunc::Param ParamIterator::getNextParam() {
384 AMDGPULibFunc::Param
P;
385 if (Index >=
int(
sizeof Rule.Param/
sizeof Rule.Param[0]))
return P;
387 const char R = Rule.Param[
Index];
391 P.ArgType = AMDGPULibFunc::U32;
break;
393 P.ArgType = AMDGPULibFunc::I32;
P.VectorSize = 4;
break;
395 P.ArgType = AMDGPULibFunc::U32;
P.VectorSize = 4;
break;
397 P.ArgType = AMDGPULibFunc::F32;
P.VectorSize = 4;
break;
399 P.ArgType = AMDGPULibFunc::U64;
break;
401 P.ArgType = AMDGPULibFunc::EVENT;
break;
403 P.ArgType = AMDGPULibFunc::SAMPLER;
break;
404 case EX_RESERVEDID:
break;
406 if (Index == (Rule.Lead[1] - 1))
P = Leads[1];
414 P.PtrKind = AMDGPULibFunc::BYVALUE;
break;
415 case E_V2_OF_POINTEE:
416 P.VectorSize = 2;
P.PtrKind = AMDGPULibFunc::BYVALUE;
break;
417 case E_V3_OF_POINTEE:
418 P.VectorSize = 3;
P.PtrKind = AMDGPULibFunc::BYVALUE;
break;
419 case E_V4_OF_POINTEE:
420 P.VectorSize = 4;
P.PtrKind = AMDGPULibFunc::BYVALUE;
break;
421 case E_V8_OF_POINTEE:
422 P.VectorSize = 8;
P.PtrKind = AMDGPULibFunc::BYVALUE;
break;
423 case E_V16_OF_POINTEE:
424 P.VectorSize = 16;
P.PtrKind = AMDGPULibFunc::BYVALUE;
break;
426 P.PtrKind |= AMDGPULibFunc::CONST;
break;
428 P.PtrKind |= AMDGPULibFunc::VOLATILE;
break;
430 P.ArgType = AMDGPULibFunc::I32;
break;
432 P.ArgType = AMDGPULibFunc::U32;
break;
435 P.ArgType &= ~AMDGPULibFunc::BASE_TYPE_MASK;
436 P.ArgType |= AMDGPULibFunc::UINT;
441 case AMDGPULibFunc::IMG1DA:
P.VectorSize = 2;
break;
442 case AMDGPULibFunc::IMG1DB:
P.VectorSize = 1;
break;
443 case AMDGPULibFunc::IMG2DA:
P.VectorSize = 4;
break;
444 case AMDGPULibFunc::IMG1D:
P.VectorSize = 1;
break;
445 case AMDGPULibFunc::IMG2D:
P.VectorSize = 2;
break;
446 case AMDGPULibFunc::IMG3D:
P.VectorSize = 4;
break;
448 P.PtrKind = AMDGPULibFunc::BYVALUE;
449 P.ArgType = AMDGPULibFunc::I32;
452 case E_CONSTPTR_SWAPGL: {
453 unsigned AS = AMDGPULibFunc::getAddrSpaceFromEPtrKind(
P.PtrKind);
458 P.PtrKind = AMDGPULibFunc::getEPtrKindFromAddrSpace(AS);
459 P.PtrKind |= AMDGPULibFunc::CONST;
471inline static void drop_front(StringRef& str,
size_t n = 1) {
475static bool eatTerm(StringRef& mangledName,
const char c) {
476 if (mangledName.
front() == c) {
477 drop_front(mangledName);
484static bool eatTerm(StringRef& mangledName,
const char (&str)[
N]) {
486 drop_front(mangledName,
N-1);
492static int eatNumber(StringRef& s) {
493 size_t const savedSize = s.
size();
496 n = n*10 + s.
front() -
'0';
499 return s.
size() < savedSize ? n : -1;
502static StringRef eatLengthPrefixedName(StringRef& mangledName) {
503 int const Len = eatNumber(mangledName);
504 if (Len <= 0 ||
static_cast<size_t>(Len) > mangledName.
size())
506 StringRef Res = mangledName.
substr(0, Len);
507 drop_front(mangledName, Len);
548 size_t const Len = eatNumber(mangledName);
550 case 2:
case 3:
case 4:
case 8:
case 16:
559 std::pair<StringRef, StringRef>
const P = mangledName.
split(
'_');
567 mangledName =
P.second;
572StringMap<int> ManglingRule::buildManglingRulesMap() {
573 StringMap<int>
Map(std::size(manglingRules));
575 for (
auto Rule : manglingRules)
576 Map.insert({Rule.Name,
Id++});
580bool AMDGPUMangledLibFunc::parseUnmangledName(StringRef FullName) {
581 static const StringMap<int> manglingRulesMap =
582 ManglingRule::buildManglingRulesMap();
583 FuncId =
static_cast<EFuncId
>(manglingRulesMap.
lookup(FullName));
584 return FuncId != EI_NONE;
591struct ItaniumParamParser {
592 AMDGPULibFunc::Param Prev;
593 bool parseItaniumParam(StringRef& param, AMDGPULibFunc::Param &res);
597bool ItaniumParamParser::parseItaniumParam(StringRef& param,
598 AMDGPULibFunc::Param &res) {
600 if (param.
empty())
return false;
603 if (eatTerm(param,
'P')) {
604 if (eatTerm(param,
'K')) res.
PtrKind |= AMDGPULibFunc::CONST;
605 if (eatTerm(param,
'V')) res.
PtrKind |= AMDGPULibFunc::VOLATILE;
607 if (!eatTerm(param,
"U3AS")) {
610 AS = param.
front() -
'0';
611 drop_front(param, 1);
615 res.
PtrKind = AMDGPULibFunc::BYVALUE;
619 if (eatTerm(param,
"Dv")) {
621 if (res.
VectorSize==1 || !eatTerm(param,
'_'))
return false;
625 char const TC = param.
front();
628 StringSwitch<AMDGPULibFunc::EType>(eatLengthPrefixedName(param))
629 .StartsWith(
"ocl_image1d_array", AMDGPULibFunc::IMG1DA)
630 .StartsWith(
"ocl_image1d_buffer", AMDGPULibFunc::IMG1DB)
631 .StartsWith(
"ocl_image2d_array", AMDGPULibFunc::IMG2DA)
632 .StartsWith(
"ocl_image1d", AMDGPULibFunc::IMG1D)
633 .StartsWith(
"ocl_image2d", AMDGPULibFunc::IMG2D)
634 .StartsWith(
"ocl_image3d", AMDGPULibFunc::IMG3D)
635 .Case(
"ocl_event", AMDGPULibFunc::DUMMY)
636 .Case(
"ocl_sampler", AMDGPULibFunc::DUMMY)
637 .Default(AMDGPULibFunc::DUMMY);
641 case 'h': res.
ArgType = AMDGPULibFunc::U8;
break;
642 case 't': res.
ArgType = AMDGPULibFunc::U16;
break;
643 case 'j': res.
ArgType = AMDGPULibFunc::U32;
break;
644 case 'm': res.
ArgType = AMDGPULibFunc::U64;
break;
645 case 'c': res.
ArgType = AMDGPULibFunc::I8;
break;
646 case 's': res.
ArgType = AMDGPULibFunc::I16;
break;
647 case 'i': res.
ArgType = AMDGPULibFunc::I32;
break;
648 case 'l': res.
ArgType = AMDGPULibFunc::I64;
break;
649 case 'f': res.
ArgType = AMDGPULibFunc::F32;
break;
650 case 'd': res.
ArgType = AMDGPULibFunc::F64;
break;
651 case 'D':
if (!eatTerm(param,
'h'))
return false;
652 res.
ArgType = AMDGPULibFunc::F16;
break;
654 if (!eatTerm(param,
'_')) {
656 if (!eatTerm(param,
'_'))
return false;
664 if (res.
ArgType == 0)
return false;
673 if (!parseUnmangledName(
Name))
676 const ManglingRule& Rule = manglingRules[
FuncId];
677 ItaniumParamParser Parser;
678 for (
int I=0;
I < Rule.maxLeadIndex(); ++
I) {
680 if (!Parser.parseItaniumParam(mangledName,
P))
683 if ((
I + 1) == Rule.Lead[0])
Leads[0] =
P;
684 if ((
I + 1) == Rule.Lead[1])
Leads[1] =
P;
697 if (FuncName.
empty()) {
698 F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
702 if (eatTerm(FuncName,
"_Z"))
703 F.Impl = std::make_unique<AMDGPUMangledLibFunc>();
705 F.Impl = std::make_unique<AMDGPUUnmangledLibFunc>();
706 if (
F.Impl->parseFuncName(FuncName))
709 F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
715 if (eatTerm(S,
"_Z"))
716 return eatLengthPrefixedName(S);
723template <
typename Stream>
724void AMDGPUMangledLibFunc::writeName(Stream &OS)
const {
725 const char *Pfx =
"";
727 case NATIVE: Pfx =
"native_";
break;
728 case HALF: Pfx =
"half_";
break;
733 }
else if (FuncId != EI_NONE) {
735 const StringRef& S = manglingRules[FuncId].Name;
797class ItaniumMangler {
801 int findSubst(
const AMDGPULibFunc::Param&
P)
const {
802 for(
unsigned I = 0;
I < Str.size(); ++
I) {
803 const AMDGPULibFunc::Param&
T = Str[
I];
804 if (
P.PtrKind ==
T.PtrKind &&
805 P.VectorSize ==
T.VectorSize &&
806 P.ArgType ==
T.ArgType) {
813 template <
typename Stream>
814 bool trySubst(Stream& os,
const AMDGPULibFunc::Param& p) {
815 int const subst = findSubst(p);
816 if (subst < 0)
return false;
820 if (subst == 0) os <<
"S_";
821 else os <<
'S' << (subst-1) <<
'_';
826 ItaniumMangler(
bool useAddrSpace)
827 : UseAddrSpace(useAddrSpace) {}
829 template <
typename Stream>
830 void operator()(Stream& os, AMDGPULibFunc::Param p) {
842 AMDGPULibFunc::Param Ptr;
845 if (trySubst(os, p))
return;
847 if (
p.PtrKind & AMDGPULibFunc::CONST) os <<
'K';
848 if (
p.PtrKind & AMDGPULibFunc::VOLATILE) os <<
'V';
849 unsigned AS = UseAddrSpace
858 if (
p.VectorSize > 1) {
859 if (trySubst(os, p))
goto exit;
861 os <<
"Dv" <<
static_cast<unsigned>(
p.VectorSize) <<
'_';
867 if (Ptr.
ArgType) Str.push_back(Ptr);
872std::string AMDGPUMangledLibFunc::mangleNameItanium()
const {
873 SmallString<128> Buf;
874 raw_svector_ostream S(Buf);
875 SmallString<128> NameBuf;
876 raw_svector_ostream
Name(NameBuf);
878 const StringRef& NameStr =
Name.str();
879 S <<
"_Z" <<
static_cast<int>(NameStr.
size()) << NameStr;
881 ItaniumMangler Mangler(
true);
882 ParamIterator
I(Leads, manglingRules[FuncId]);
884 while ((
P =
I.getNextParam()).ArgType != 0)
886 return std::string(S.str());
896 P.VectorSize = VT->getNumElements();
897 Ty = VT->getElementType();
900 switch (Ty->getTypeID()) {
990 if (
P.VectorSize > 1)
1000 std::vector<Type*> Args;
1003 while ((
P =
I.getNextParam()).ArgType != 0) {
1008 Args.push_back(ParamTy);
1019 return manglingRules[
FuncId].getNumArgs();
1023 return UnmangledFuncInfo::getNumArgs(
FuncId);
1030 return std::string(OS.
str());
1048 if (FuncTy == CallTy)
1051 const unsigned NumParams = FuncTy->getNumParams();
1055 for (
unsigned I = 0;
I != NumParams; ++
I) {
1056 Type *FuncArgTy = FuncTy->getParamType(
I);
1058 if (FuncArgTy == CallArgTy)
1063 if (FuncVecTy && FuncVecTy->getElementType() == CallArgTy &&
1074 std::string FuncName = fInfo.
mangle();
1076 M->getValueSymbolTable().lookup(FuncName));
1077 if (!
F ||
F->isDeclaration())
1080 if (
F->hasFnAttribute(Attribute::NoBuiltin))
1086 switch (fInfo.
getId()) {
1094 if (!M->getModuleFlag(
"amdgpu-libcall-have-fast-pow"))
1106 std::string
const FuncName = fInfo.
mangle();
1108 M->getValueSymbolTable().lookup(FuncName));
1111 if (
F->hasFnAttribute(Attribute::NoBuiltin))
1113 if (!
F->isDeclaration() &&
1121 bool hasPtr =
false;
1123 PI = FuncTy->param_begin(),
1124 PE = FuncTy->param_end();
1126 const Type* argTy =
static_cast<const Type*
>(*PI);
1136 C = M->getOrInsertFunction(FuncName, FuncTy);
1140 Attr = Attr.addFnAttribute(
1142 Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind);
1143 C = M->getOrInsertFunction(FuncName, FuncTy, Attr);
1151 for (
unsigned I = 0;
I != TableSize; ++
I)
1152 Map[Table[
I].Name] =
I;
1156bool UnmangledFuncInfo::lookup(
StringRef Name,
ID &Id) {
1158 auto Loc = Map.find(Name);
1159 if (
Loc != Map.end()) {
1160 Id = toFuncId(
Loc->second);
1163 Id = AMDGPULibFunc::EI_NONE;
1169 Impl = std::make_unique<AMDGPUMangledLibFunc>(*MF);
1171 Impl = std::make_unique<AMDGPUUnmangledLibFunc>(*UMF);
1173 Impl = std::unique_ptr<AMDGPULibFuncImpl>();
1188 Impl = std::make_unique<AMDGPUMangledLibFunc>(
1193 Impl = std::make_unique<AMDGPUMangledLibFunc>(Id, FT, SignedInts);
1197 Impl = std::make_unique<AMDGPUUnmangledLibFunc>(Name, FT);
1200void AMDGPULibFunc::initMangled() {
1201 Impl = std::make_unique<AMDGPUMangledLibFunc>();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static cl::opt< bool > EnableOCLManglingMismatchWA("amdgpu-enable-ocl-mangling-mismatch-workaround", cl::init(true), cl::ReallyHidden, cl::desc("Enable the workaround for OCL name mangling mismatch."))
static AMDGPULibFunc::ENamePrefix parseNamePrefix(StringRef &mangledName)
static const char * getItaniumTypeName(AMDGPULibFunc::EType T)
static int parseVecSize(StringRef &mangledName)
static Type * getIntrinsicParamType(LLVMContext &C, const AMDGPULibFunc::Param &P, bool UseAddrSpace)
Module.h This file contains the declarations for the Module class.
static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err)
A Lookup helper functions.
static StringRef getName(Value *V)
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
static unsigned getEPtrKindFromAddrSpace(unsigned AS)
static unsigned getAddrSpaceFromEPtrKind(unsigned Kind)
static bool isMangled(EFuncId Id)
void setName(StringRef N)
static Function * getFunction(llvm::Module *M, const AMDGPULibFunc &fInfo)
static bool parse(StringRef MangledName, AMDGPULibFunc &Ptr)
static FunctionCallee getOrInsertFunction(llvm::Module *M, const AMDGPULibFunc &fInfo)
FunctionType * getFunctionType(const Module &M) const
bool isCompatibleSignature(const Module &M, const FunctionType *FuncTy) const
bool allowsImplicitVectorSplat(int ArgIdx) const
Return true if it's legal to splat a scalar value passed in parameter ArgIdx to a vector argument.
std::string mangle() const
AMDGPULibFunc & operator=(const AMDGPULibFunc &F)
Param * getLeads()
Get leading parameters for mangled lib functions.
unsigned getNumArgs() const
static StringRef getUnmangledName(StringRef MangledName)
unsigned getNumArgs() const override
bool parseFuncName(StringRef &mangledName) override
std::string getName() const override
Get unmangled name for mangled library function and name for unmangled library function.
FunctionType * getFunctionType(const Module &M) const override
std::string mangle() const override
unsigned getNumArgs() const override
bool parseFuncName(StringRef &Name) override
static LLVM_ABI Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
Class to represent fixed width SIMD vectors.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Class to represent function types.
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Type::subtype_iterator param_iterator
Type * getParamType(unsigned i) const
Parameter type accessors.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
This is an important class for using LLVM in a threaded context.
static MemoryEffectsBase readOnly()
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
constexpr size_t size() const
size - Get the string size.
char front() const
front - Get the first character in the string.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
@ HalfTyID
16-bit floating point type
@ FloatTyID
32-bit floating point type
@ IntegerTyID
Arbitrary bit width integers.
@ DoubleTyID
64-bit floating point type
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
A raw_ostream that writes to an SmallVector or SmallString.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ LOCAL_ADDRESS
Address space for local memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_or_null(const Y &Val)
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
static Param getFromTy(Type *Ty, bool Signed)