Line data Source code
1 : //===-- AMDGPULibFunc.cpp -------------------------------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file contains utility functions to work with Itanium mangled names
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "AMDGPU.h"
15 : #include "AMDGPULibFunc.h"
16 : #include <llvm/ADT/SmallString.h>
17 : #include <llvm/ADT/SmallVector.h>
18 : #include <llvm/ADT/StringSwitch.h>
19 : #include "llvm/IR/Attributes.h"
20 : #include "llvm/IR/DerivedTypes.h"
21 : #include "llvm/IR/Function.h"
22 : #include "llvm/IR/Module.h"
23 : #include "llvm/IR/ValueSymbolTable.h"
24 : #include <llvm/Support/raw_ostream.h>
25 : #include <string>
26 :
27 : using namespace llvm;
28 :
29 : namespace {
30 :
31 : enum EManglingParam {
32 : E_NONE,
33 : EX_EVENT,
34 : EX_FLOAT4,
35 : EX_INTV4,
36 : EX_RESERVEDID,
37 : EX_SAMPLER,
38 : EX_SIZET,
39 : EX_UINT,
40 : EX_UINTV4,
41 : E_ANY,
42 : E_CONSTPTR_ANY,
43 : E_CONSTPTR_SWAPGL,
44 : E_COPY,
45 : E_IMAGECOORDS,
46 : E_POINTEE,
47 : E_SETBASE_I32,
48 : E_SETBASE_U32,
49 : E_MAKEBASE_UNS,
50 : E_V16_OF_POINTEE,
51 : E_V2_OF_POINTEE,
52 : E_V3_OF_POINTEE,
53 : E_V4_OF_POINTEE,
54 : E_V8_OF_POINTEE,
55 : E_VLTLPTR_ANY,
56 : };
57 :
58 : struct ManglingRule {
59 : StringRef const Name;
60 : unsigned char Lead[2];
61 : unsigned char Param[5];
62 :
63 509 : int maxLeadIndex() const { return (std::max)(Lead[0], Lead[1]); }
64 : int getNumLeads() const { return (Lead[0] ? 1 : 0) + (Lead[1] ? 1 : 0); }
65 :
66 : unsigned getNumArgs() const;
67 : };
68 :
69 : // Information about library functions with unmangled names.
70 : class UnmangledFuncInfo {
71 : StringRef const Name;
72 : unsigned NumArgs;
73 :
74 : // Table for all lib functions with unmangled names.
75 : static const UnmangledFuncInfo Table[];
76 :
77 : // Number of entries in Table.
78 : static const unsigned TableSize;
79 :
80 : // Map function name to index.
81 : class NameMap : public StringMap<unsigned> {
82 : public:
83 113936 : NameMap() {
84 569680 : for (unsigned I = 0; I != TableSize; ++I)
85 455744 : (*this)[Table[I].Name] = I;
86 113936 : }
87 : };
88 : friend class NameMap;
89 : static NameMap Map;
90 :
91 : public:
92 : using ID = AMDGPULibFunc::EFuncId;
93 : UnmangledFuncInfo(StringRef _Name, unsigned _NumArgs)
94 : : Name(_Name), NumArgs(_NumArgs) {}
95 : // Get index to Table by function name.
96 : static bool lookup(StringRef Name, ID &Id);
97 : static unsigned toIndex(ID Id) {
98 : assert(static_cast<unsigned>(Id) >
99 : static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED) &&
100 : "Invalid unmangled library function");
101 : return static_cast<unsigned>(Id) - 1 -
102 39 : static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED);
103 : }
104 : static ID toFuncId(unsigned Index) {
105 : assert(Index < TableSize && "Invalid unmangled library function");
106 : return static_cast<ID>(
107 52 : Index + 1 + static_cast<unsigned>(AMDGPULibFunc::EI_LAST_MANGLED));
108 : }
109 39 : static unsigned getNumArgs(ID Id) { return Table[toIndex(Id)].NumArgs; }
110 : static StringRef getName(ID Id) { return Table[toIndex(Id)].Name; }
111 : };
112 :
113 : unsigned ManglingRule::getNumArgs() const {
114 : unsigned I=0;
115 458 : while (I < (sizeof Param/sizeof Param[0]) && Param[I]) ++I;
116 : return I;
117 : }
118 :
119 : // This table describes function formal argument type rules. The order of rules
120 : // corresponds to the EFuncId enum at AMDGPULibFunc.h
121 : //
122 : // "<func name>", { <leads> }, { <param rules> }
123 : // where:
124 : // <leads> - list of integers that are one-based indexes of formal argument
125 : // used to mangle a function name. Other argument types are derived from types
126 : // of these 'leads'. The order of integers in this list correspond to the
127 : // order in which these arguments are mangled in the EDG mangling scheme. The
128 : // same order should be preserved for arguments in the AMDGPULibFunc structure
129 : // when it is used for mangling. For example:
130 : // { "vstorea_half", {3,1}, {E_ANY,EX_SIZET,E_ANY}},
131 : // will be mangled in EDG scheme as vstorea_half_<3dparam>_<1stparam>
132 : // When mangling from code use:
133 : // AMDGPULibFunc insc;
134 : // insc.param[0] = ... // describe 3rd parameter
135 : // insc.param[1] = ... // describe 1rd parameter
136 : //
137 : // <param rules> - list of rules used to derive all of the function formal
138 : // argument types. EX_ prefixed are simple types, other derived from the
139 : // latest 'lead' argument type in the order of encoding from first to last.
140 : // E_ANY - use prev lead type, E_CONSTPTR_ANY - make const pointer out of
141 : // prev lead type, etc. see ParamIterator::getNextParam() for details.
142 :
143 : static const ManglingRule manglingRules[] = {
144 : { StringRef(), {0}, {0} },
145 : { "abs" , {1}, {E_ANY}},
146 : { "abs_diff" , {1}, {E_ANY,E_COPY}},
147 : { "acos" , {1}, {E_ANY}},
148 : { "acosh" , {1}, {E_ANY}},
149 : { "acospi" , {1}, {E_ANY}},
150 : { "add_sat" , {1}, {E_ANY,E_COPY}},
151 : { "all" , {1}, {E_ANY}},
152 : { "any" , {1}, {E_ANY}},
153 : { "asin" , {1}, {E_ANY}},
154 : { "asinh" , {1}, {E_ANY}},
155 : { "asinpi" , {1}, {E_ANY}},
156 : { "async_work_group_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_EVENT}},
157 : { "async_work_group_strided_copy" , {1}, {E_ANY,E_CONSTPTR_SWAPGL,EX_SIZET,EX_SIZET,EX_EVENT}},
158 : { "atan" , {1}, {E_ANY}},
159 : { "atan2" , {1}, {E_ANY,E_COPY}},
160 : { "atan2pi" , {1}, {E_ANY,E_COPY}},
161 : { "atanh" , {1}, {E_ANY}},
162 : { "atanpi" , {1}, {E_ANY}},
163 : { "atomic_add" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
164 : { "atomic_and" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
165 : { "atomic_cmpxchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE,E_POINTEE}},
166 : { "atomic_dec" , {1}, {E_VLTLPTR_ANY}},
167 : { "atomic_inc" , {1}, {E_VLTLPTR_ANY}},
168 : { "atomic_max" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
169 : { "atomic_min" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
170 : { "atomic_or" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
171 : { "atomic_sub" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
172 : { "atomic_xchg" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
173 : { "atomic_xor" , {1}, {E_VLTLPTR_ANY,E_POINTEE}},
174 : { "bitselect" , {1}, {E_ANY,E_COPY,E_COPY}},
175 : { "cbrt" , {1}, {E_ANY}},
176 : { "ceil" , {1}, {E_ANY}},
177 : { "clamp" , {1}, {E_ANY,E_COPY,E_COPY}},
178 : { "clz" , {1}, {E_ANY}},
179 : { "commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
180 : { "commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
181 : { "copysign" , {1}, {E_ANY,E_COPY}},
182 : { "cos" , {1}, {E_ANY}},
183 : { "cosh" , {1}, {E_ANY}},
184 : { "cospi" , {1}, {E_ANY}},
185 : { "cross" , {1}, {E_ANY,E_COPY}},
186 : { "ctz" , {1}, {E_ANY}},
187 : { "degrees" , {1}, {E_ANY}},
188 : { "distance" , {1}, {E_ANY,E_COPY}},
189 : { "divide" , {1}, {E_ANY,E_COPY}},
190 : { "dot" , {1}, {E_ANY,E_COPY}},
191 : { "erf" , {1}, {E_ANY}},
192 : { "erfc" , {1}, {E_ANY}},
193 : { "exp" , {1}, {E_ANY}},
194 : { "exp10" , {1}, {E_ANY}},
195 : { "exp2" , {1}, {E_ANY}},
196 : { "expm1" , {1}, {E_ANY}},
197 : { "fabs" , {1}, {E_ANY}},
198 : { "fast_distance" , {1}, {E_ANY,E_COPY}},
199 : { "fast_length" , {1}, {E_ANY}},
200 : { "fast_normalize" , {1}, {E_ANY}},
201 : { "fdim" , {1}, {E_ANY,E_COPY}},
202 : { "floor" , {1}, {E_ANY}},
203 : { "fma" , {1}, {E_ANY,E_COPY,E_COPY}},
204 : { "fmax" , {1}, {E_ANY,E_COPY}},
205 : { "fmin" , {1}, {E_ANY,E_COPY}},
206 : { "fmod" , {1}, {E_ANY,E_COPY}},
207 : { "fract" , {2}, {E_POINTEE,E_ANY}},
208 : { "frexp" , {1,2}, {E_ANY,E_ANY}},
209 : { "get_image_array_size" , {1}, {E_ANY}},
210 : { "get_image_channel_data_type" , {1}, {E_ANY}},
211 : { "get_image_channel_order" , {1}, {E_ANY}},
212 : { "get_image_dim" , {1}, {E_ANY}},
213 : { "get_image_height" , {1}, {E_ANY}},
214 : { "get_image_width" , {1}, {E_ANY}},
215 : { "get_pipe_max_packets" , {1}, {E_ANY}},
216 : { "get_pipe_num_packets" , {1}, {E_ANY}},
217 : { "hadd" , {1}, {E_ANY,E_COPY}},
218 : { "hypot" , {1}, {E_ANY,E_COPY}},
219 : { "ilogb" , {1}, {E_ANY}},
220 : { "isequal" , {1}, {E_ANY,E_COPY}},
221 : { "isfinite" , {1}, {E_ANY}},
222 : { "isgreater" , {1}, {E_ANY,E_COPY}},
223 : { "isgreaterequal" , {1}, {E_ANY,E_COPY}},
224 : { "isinf" , {1}, {E_ANY}},
225 : { "isless" , {1}, {E_ANY,E_COPY}},
226 : { "islessequal" , {1}, {E_ANY,E_COPY}},
227 : { "islessgreater" , {1}, {E_ANY,E_COPY}},
228 : { "isnan" , {1}, {E_ANY}},
229 : { "isnormal" , {1}, {E_ANY}},
230 : { "isnotequal" , {1}, {E_ANY,E_COPY}},
231 : { "isordered" , {1}, {E_ANY,E_COPY}},
232 : { "isunordered" , {1}, {E_ANY,E_COPY}},
233 : { "ldexp" , {1}, {E_ANY,E_SETBASE_I32}},
234 : { "length" , {1}, {E_ANY}},
235 : { "lgamma" , {1}, {E_ANY}},
236 : { "lgamma_r" , {1,2}, {E_ANY,E_ANY}},
237 : { "log" , {1}, {E_ANY}},
238 : { "log10" , {1}, {E_ANY}},
239 : { "log1p" , {1}, {E_ANY}},
240 : { "log2" , {1}, {E_ANY}},
241 : { "logb" , {1}, {E_ANY}},
242 : { "mad" , {1}, {E_ANY,E_COPY,E_COPY}},
243 : { "mad24" , {1}, {E_ANY,E_COPY,E_COPY}},
244 : { "mad_hi" , {1}, {E_ANY,E_COPY,E_COPY}},
245 : { "mad_sat" , {1}, {E_ANY,E_COPY,E_COPY}},
246 : { "max" , {1}, {E_ANY,E_COPY}},
247 : { "maxmag" , {1}, {E_ANY,E_COPY}},
248 : { "min" , {1}, {E_ANY,E_COPY}},
249 : { "minmag" , {1}, {E_ANY,E_COPY}},
250 : { "mix" , {1}, {E_ANY,E_COPY,E_COPY}},
251 : { "modf" , {2}, {E_POINTEE,E_ANY}},
252 : { "mul24" , {1}, {E_ANY,E_COPY}},
253 : { "mul_hi" , {1}, {E_ANY,E_COPY}},
254 : { "nan" , {1}, {E_ANY}},
255 : { "nextafter" , {1}, {E_ANY,E_COPY}},
256 : { "normalize" , {1}, {E_ANY}},
257 : { "popcount" , {1}, {E_ANY}},
258 : { "pow" , {1}, {E_ANY,E_COPY}},
259 : { "pown" , {1}, {E_ANY,E_SETBASE_I32}},
260 : { "powr" , {1}, {E_ANY,E_COPY}},
261 : { "prefetch" , {1}, {E_CONSTPTR_ANY,EX_SIZET}},
262 : { "radians" , {1}, {E_ANY}},
263 : { "recip" , {1}, {E_ANY}},
264 : { "remainder" , {1}, {E_ANY,E_COPY}},
265 : { "remquo" , {1,3}, {E_ANY,E_COPY,E_ANY}},
266 : { "reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
267 : { "reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
268 : { "rhadd" , {1}, {E_ANY,E_COPY}},
269 : { "rint" , {1}, {E_ANY}},
270 : { "rootn" , {1}, {E_ANY,E_SETBASE_I32}},
271 : { "rotate" , {1}, {E_ANY,E_COPY}},
272 : { "round" , {1}, {E_ANY}},
273 : { "rsqrt" , {1}, {E_ANY}},
274 : { "select" , {1,3}, {E_ANY,E_COPY,E_ANY}},
275 : { "shuffle" , {1,2}, {E_ANY,E_ANY}},
276 : { "shuffle2" , {1,3}, {E_ANY,E_COPY,E_ANY}},
277 : { "sign" , {1}, {E_ANY}},
278 : { "signbit" , {1}, {E_ANY}},
279 : { "sin" , {1}, {E_ANY}},
280 : { "sincos" , {2}, {E_POINTEE,E_ANY}},
281 : { "sinh" , {1}, {E_ANY}},
282 : { "sinpi" , {1}, {E_ANY}},
283 : { "smoothstep" , {1}, {E_ANY,E_COPY,E_COPY}},
284 : { "sqrt" , {1}, {E_ANY}},
285 : { "step" , {1}, {E_ANY,E_COPY}},
286 : { "sub_group_broadcast" , {1}, {E_ANY,EX_UINT}},
287 : { "sub_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
288 : { "sub_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
289 : { "sub_group_reduce_add" , {1}, {E_ANY}},
290 : { "sub_group_reduce_max" , {1}, {E_ANY}},
291 : { "sub_group_reduce_min" , {1}, {E_ANY}},
292 : { "sub_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
293 : { "sub_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
294 : { "sub_group_scan_exclusive_add" , {1}, {E_ANY}},
295 : { "sub_group_scan_exclusive_max" , {1}, {E_ANY}},
296 : { "sub_group_scan_exclusive_min" , {1}, {E_ANY}},
297 : { "sub_group_scan_inclusive_add" , {1}, {E_ANY}},
298 : { "sub_group_scan_inclusive_max" , {1}, {E_ANY}},
299 : { "sub_group_scan_inclusive_min" , {1}, {E_ANY}},
300 : { "sub_sat" , {1}, {E_ANY,E_COPY}},
301 : { "tan" , {1}, {E_ANY}},
302 : { "tanh" , {1}, {E_ANY}},
303 : { "tanpi" , {1}, {E_ANY}},
304 : { "tgamma" , {1}, {E_ANY}},
305 : { "trunc" , {1}, {E_ANY}},
306 : { "upsample" , {1}, {E_ANY,E_MAKEBASE_UNS}},
307 : { "vec_step" , {1}, {E_ANY}},
308 : { "vstore" , {3}, {E_POINTEE,EX_SIZET,E_ANY}},
309 : { "vstore16" , {3}, {E_V16_OF_POINTEE,EX_SIZET,E_ANY}},
310 : { "vstore2" , {3}, {E_V2_OF_POINTEE,EX_SIZET,E_ANY}},
311 : { "vstore3" , {3}, {E_V3_OF_POINTEE,EX_SIZET,E_ANY}},
312 : { "vstore4" , {3}, {E_V4_OF_POINTEE,EX_SIZET,E_ANY}},
313 : { "vstore8" , {3}, {E_V8_OF_POINTEE,EX_SIZET,E_ANY}},
314 : { "work_group_commit_read_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
315 : { "work_group_commit_write_pipe" , {1}, {E_ANY,EX_RESERVEDID}},
316 : { "work_group_reduce_add" , {1}, {E_ANY}},
317 : { "work_group_reduce_max" , {1}, {E_ANY}},
318 : { "work_group_reduce_min" , {1}, {E_ANY}},
319 : { "work_group_reserve_read_pipe" , {1}, {E_ANY,EX_UINT}},
320 : { "work_group_reserve_write_pipe" , {1}, {E_ANY,EX_UINT}},
321 : { "work_group_scan_exclusive_add" , {1}, {E_ANY}},
322 : { "work_group_scan_exclusive_max" , {1}, {E_ANY}},
323 : { "work_group_scan_exclusive_min" , {1}, {E_ANY}},
324 : { "work_group_scan_inclusive_add" , {1}, {E_ANY}},
325 : { "work_group_scan_inclusive_max" , {1}, {E_ANY}},
326 : { "work_group_scan_inclusive_min" , {1}, {E_ANY}},
327 : { "write_imagef" , {1}, {E_ANY,E_IMAGECOORDS,EX_FLOAT4}},
328 : { "write_imagei" , {1}, {E_ANY,E_IMAGECOORDS,EX_INTV4}},
329 : { "write_imageui" , {1}, {E_ANY,E_IMAGECOORDS,EX_UINTV4}},
330 : { "ncos" , {1}, {E_ANY} },
331 : { "nexp2" , {1}, {E_ANY} },
332 : { "nfma" , {1}, {E_ANY, E_COPY, E_COPY} },
333 : { "nlog2" , {1}, {E_ANY} },
334 : { "nrcp" , {1}, {E_ANY} },
335 : { "nrsqrt" , {1}, {E_ANY} },
336 : { "nsin" , {1}, {E_ANY} },
337 : { "nsqrt" , {1}, {E_ANY} },
338 : { "ftz" , {1}, {E_ANY} },
339 : { "fldexp" , {1}, {E_ANY, EX_UINT} },
340 : { "class" , {1}, {E_ANY, EX_UINT} },
341 : { "rcbrt" , {1}, {E_ANY} },
342 : };
343 :
344 : // Library functions with unmangled name.
345 : const UnmangledFuncInfo UnmangledFuncInfo::Table[] = {
346 : {"__read_pipe_2", 4},
347 : {"__read_pipe_4", 6},
348 : {"__write_pipe_2", 4},
349 : {"__write_pipe_4", 6},
350 : };
351 :
352 : const unsigned UnmangledFuncInfo::TableSize =
353 : sizeof(UnmangledFuncInfo::Table) / sizeof(UnmangledFuncInfo::Table[0]);
354 :
355 : UnmangledFuncInfo::NameMap UnmangledFuncInfo::Map;
356 :
357 : static const struct ManglingRulesMap : public StringMap<int> {
358 113936 : ManglingRulesMap()
359 113936 : : StringMap<int>(sizeof(manglingRules)/sizeof(manglingRules[0])) {
360 : int Id = 0;
361 22673264 : for (auto Rule : manglingRules)
362 22559328 : insert({ Rule.Name, Id++ });
363 113936 : }
364 : } manglingRulesMap;
365 :
366 : static AMDGPULibFunc::Param getRetType(AMDGPULibFunc::EFuncId id,
367 : const AMDGPULibFunc::Param (&Leads)[2]) {
368 63 : AMDGPULibFunc::Param Res = Leads[0];
369 : // TBD - This switch may require to be extended for other intriniscs
370 63 : switch (id) {
371 6 : case AMDGPULibFunc::EI_SINCOS:
372 : Res.PtrKind = AMDGPULibFunc::BYVALUE;
373 : break;
374 : default:
375 : break;
376 : }
377 : return Res;
378 : }
379 :
380 : class ParamIterator {
381 : const AMDGPULibFunc::Param (&Leads)[2];
382 : const ManglingRule& Rule;
383 : int Index;
384 : public:
385 : ParamIterator(const AMDGPULibFunc::Param (&leads)[2],
386 : const ManglingRule& rule)
387 170 : : Leads(leads), Rule(rule), Index(0) {}
388 :
389 : AMDGPULibFunc::Param getNextParam();
390 : };
391 :
392 364 : AMDGPULibFunc::Param ParamIterator::getNextParam() {
393 : AMDGPULibFunc::Param P;
394 364 : if (Index >= int(sizeof Rule.Param/sizeof Rule.Param[0])) return P;
395 :
396 364 : const char R = Rule.Param[Index];
397 364 : switch (R) {
398 : case E_NONE: break;
399 0 : case EX_UINT:
400 0 : P.ArgType = AMDGPULibFunc::U32; break;
401 0 : case EX_INTV4:
402 0 : P.ArgType = AMDGPULibFunc::I32; P.VectorSize = 4; break;
403 0 : case EX_UINTV4:
404 0 : P.ArgType = AMDGPULibFunc::U32; P.VectorSize = 4; break;
405 0 : case EX_FLOAT4:
406 0 : P.ArgType = AMDGPULibFunc::F32; P.VectorSize = 4; break;
407 0 : case EX_SIZET:
408 0 : P.ArgType = AMDGPULibFunc::U64; break;
409 0 : case EX_EVENT:
410 0 : P.ArgType = AMDGPULibFunc::EVENT; break;
411 0 : case EX_SAMPLER:
412 0 : P.ArgType = AMDGPULibFunc::SAMPLER; break;
413 : case EX_RESERVEDID: break; // TBD
414 194 : default:
415 194 : if (Index == (Rule.Lead[1] - 1)) P = Leads[1];
416 194 : else P = Leads[0];
417 :
418 : switch (R) {
419 : case E_ANY:
420 : case E_COPY: break;
421 :
422 18 : case E_POINTEE:
423 18 : P.PtrKind = AMDGPULibFunc::BYVALUE; break;
424 0 : case E_V2_OF_POINTEE:
425 0 : P.VectorSize = 2; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
426 0 : case E_V3_OF_POINTEE:
427 0 : P.VectorSize = 3; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
428 0 : case E_V4_OF_POINTEE:
429 0 : P.VectorSize = 4; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
430 0 : case E_V8_OF_POINTEE:
431 0 : P.VectorSize = 8; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
432 0 : case E_V16_OF_POINTEE:
433 0 : P.VectorSize = 16; P.PtrKind = AMDGPULibFunc::BYVALUE; break;
434 0 : case E_CONSTPTR_ANY:
435 0 : P.PtrKind |= AMDGPULibFunc::CONST; break;
436 0 : case E_VLTLPTR_ANY:
437 0 : P.PtrKind |= AMDGPULibFunc::VOLATILE; break;
438 0 : case E_SETBASE_I32:
439 0 : P.ArgType = AMDGPULibFunc::I32; break;
440 0 : case E_SETBASE_U32:
441 0 : P.ArgType = AMDGPULibFunc::U32; break;
442 :
443 0 : case E_MAKEBASE_UNS:
444 0 : P.ArgType &= ~AMDGPULibFunc::BASE_TYPE_MASK;
445 0 : P.ArgType |= AMDGPULibFunc::UINT;
446 0 : break;
447 :
448 0 : case E_IMAGECOORDS:
449 : switch (P.ArgType) {
450 0 : case AMDGPULibFunc::IMG1DA: P.VectorSize = 2; break;
451 0 : case AMDGPULibFunc::IMG1DB: P.VectorSize = 1; break;
452 0 : case AMDGPULibFunc::IMG2DA: P.VectorSize = 4; break;
453 0 : case AMDGPULibFunc::IMG1D: P.VectorSize = 1; break;
454 0 : case AMDGPULibFunc::IMG2D: P.VectorSize = 2; break;
455 0 : case AMDGPULibFunc::IMG3D: P.VectorSize = 4; break;
456 : }
457 : P.PtrKind = AMDGPULibFunc::BYVALUE;
458 : P.ArgType = AMDGPULibFunc::I32;
459 : break;
460 :
461 0 : case E_CONSTPTR_SWAPGL: {
462 : unsigned AS = AMDGPULibFunc::getAddrSpaceFromEPtrKind(P.PtrKind);
463 : switch (AS) {
464 0 : case AMDGPUAS::GLOBAL_ADDRESS: AS = AMDGPUAS::LOCAL_ADDRESS; break;
465 0 : case AMDGPUAS::LOCAL_ADDRESS: AS = AMDGPUAS::GLOBAL_ADDRESS; break;
466 : }
467 0 : P.PtrKind = AMDGPULibFunc::getEPtrKindFromAddrSpace(AS);
468 0 : P.PtrKind |= AMDGPULibFunc::CONST;
469 0 : break;
470 : }
471 :
472 0 : default: llvm_unreachable("Unhandeled param rule");
473 : }
474 : }
475 364 : ++Index;
476 364 : return P;
477 : }
478 :
479 1308 : inline static void drop_front(StringRef& str, size_t n = 1) {
480 1308 : str = str.drop_front(n);
481 1308 : }
482 :
483 : static bool eatTerm(StringRef& mangledName, const char c) {
484 0 : if (mangledName.front() == c) {
485 0 : drop_front(mangledName);
486 : return true;
487 : }
488 : return false;
489 : }
490 :
491 : template <size_t N>
492 1162 : static bool eatTerm(StringRef& mangledName, const char (&str)[N]) {
493 : if (mangledName.startswith(StringRef(str, N-1))) {
494 357 : drop_front(mangledName, N-1);
495 357 : return true;
496 : }
497 : return false;
498 : }
499 1159 :
500 : static inline bool isDigit(char c) { return c >= '0' && c <= '9'; }
501 357 :
502 357 : static int eatNumber(StringRef& s) {
503 : size_t const savedSize = s.size();
504 : int n = 0;
505 : while (!s.empty() && isDigit(s.front())) {
506 3 : n = n*10 + s.front() - '0';
507 : drop_front(s);
508 0 : }
509 0 : return s.size() < savedSize ? n : -1;
510 : }
511 :
512 : static StringRef eatLengthPrefixedName(StringRef& mangledName) {
513 : int const Len = eatNumber(mangledName);
514 730 : if (Len <= 0 || static_cast<size_t>(Len) > mangledName.size())
515 : return StringRef();
516 357 : StringRef Res = mangledName.substr(0, Len);
517 : drop_front(mangledName, Len);
518 : return Res;
519 730 : }
520 373 :
521 373 : } // end anonymous namespace
522 :
523 357 : AMDGPUMangledLibFunc::AMDGPUMangledLibFunc() {
524 : FuncId = EI_NONE;
525 : FKind = NOPFX;
526 297 : Leads[0].reset();
527 297 : Leads[1].reset();
528 297 : Name.clear();
529 38 : }
530 259 :
531 259 : AMDGPUUnmangledLibFunc::AMDGPUUnmangledLibFunc() {
532 259 : FuncId = EI_NONE;
533 : FuncTy = nullptr;
534 : }
535 :
536 : AMDGPUMangledLibFunc::AMDGPUMangledLibFunc(
537 1192 : EFuncId id, const AMDGPUMangledLibFunc ©From) {
538 298 : FuncId = id;
539 298 : FKind = copyFrom.FKind;
540 : Leads[0] = copyFrom.Leads[0];
541 : Leads[1] = copyFrom.Leads[1];
542 : }
543 298 :
544 : ///////////////////////////////////////////////////////////////////////////////
545 1212 : // Demangling
546 606 :
547 606 : static int parseVecSize(StringRef& mangledName) {
548 606 : size_t const Len = eatNumber(mangledName);
549 : switch (Len) {
550 55 : case 2: case 3: case 4: case 8: case 16:
551 220 : return Len;
552 55 : default:
553 55 : break;
554 55 : }
555 55 : return 1;
556 55 : }
557 :
558 : static AMDGPULibFunc::ENamePrefix parseNamePrefix(StringRef& mangledName) {
559 : std::pair<StringRef, StringRef> const P = mangledName.split('_');
560 : AMDGPULibFunc::ENamePrefix Pfx =
561 60 : StringSwitch<AMDGPULibFunc::ENamePrefix>(P.first)
562 60 : .Case("native", AMDGPULibFunc::NATIVE)
563 : .Case("half" , AMDGPULibFunc::HALF)
564 : .Default(AMDGPULibFunc::NOPFX);
565 :
566 : if (Pfx != AMDGPULibFunc::NOPFX)
567 : mangledName = P.second;
568 :
569 : return Pfx;
570 : }
571 :
572 297 : bool AMDGPUMangledLibFunc::parseUnmangledName(StringRef FullName) {
573 297 : FuncId = static_cast<EFuncId>(manglingRulesMap.lookup(FullName));
574 : return FuncId != EI_NONE;
575 255 : }
576 297 :
577 297 : ///////////////////////////////////////////////////////////////////////////////
578 : // Itanium Demangling
579 :
580 42 : namespace {
581 42 : struct ItaniumParamParser {
582 : AMDGPULibFunc::Param Prev;
583 297 : bool parseItaniumParam(StringRef& param, AMDGPULibFunc::Param &res);
584 : };
585 : } // namespace
586 297 :
587 297 : bool ItaniumParamParser::parseItaniumParam(StringRef& param,
588 297 : AMDGPULibFunc::Param &res) {
589 : res.reset();
590 : if (param.empty()) return false;
591 :
592 : // parse pointer prefix
593 : if (eatTerm(param, 'P')) {
594 : if (eatTerm(param, 'K')) res.PtrKind |= AMDGPULibFunc::CONST;
595 : if (eatTerm(param, 'V')) res.PtrKind |= AMDGPULibFunc::VOLATILE;
596 : unsigned AS;
597 : if (!eatTerm(param, "U3AS")) {
598 : AS = 0;
599 : } else {
600 : AS = param.front() - '0';
601 0 : drop_front(param, 1);
602 : }
603 : res.PtrKind |= AMDGPULibFuncBase::getEPtrKindFromAddrSpace(AS);
604 0 : } else {
605 : res.PtrKind = AMDGPULibFunc::BYVALUE;
606 : }
607 :
608 0 : // parse vector size
609 0 : if (eatTerm(param,"Dv")) {
610 : res.VectorSize = parseVecSize(param);
611 0 : if (res.VectorSize==1 || !eatTerm(param, '_')) return false;
612 : }
613 :
614 0 : // parse type
615 0 : char const TC = param.front();
616 : if (::isDigit(TC)) {
617 0 : res.ArgType = StringSwitch<AMDGPULibFunc::EType>
618 : (eatLengthPrefixedName(param))
619 : .Case("ocl_image1darray" , AMDGPULibFunc::IMG1DA)
620 : .Case("ocl_image1dbuffer", AMDGPULibFunc::IMG1DB)
621 : .Case("ocl_image2darray" , AMDGPULibFunc::IMG2DA)
622 : .Case("ocl_image1d" , AMDGPULibFunc::IMG1D)
623 0 : .Case("ocl_image2d" , AMDGPULibFunc::IMG2D)
624 0 : .Case("ocl_image3d" , AMDGPULibFunc::IMG3D)
625 0 : .Case("ocl_event" , AMDGPULibFunc::DUMMY)
626 : .Case("ocl_sampler" , AMDGPULibFunc::DUMMY)
627 : .Default(AMDGPULibFunc::DUMMY);
628 : } else {
629 0 : drop_front(param);
630 0 : switch (TC) {
631 0 : case 'h': res.ArgType = AMDGPULibFunc::U8; break;
632 : case 't': res.ArgType = AMDGPULibFunc::U16; break;
633 0 : case 'j': res.ArgType = AMDGPULibFunc::U32; break;
634 0 : case 'm': res.ArgType = AMDGPULibFunc::U64; break;
635 0 : case 'c': res.ArgType = AMDGPULibFunc::I8; break;
636 0 : case 's': res.ArgType = AMDGPULibFunc::I16; break;
637 0 : case 'i': res.ArgType = AMDGPULibFunc::I32; break;
638 0 : case 'l': res.ArgType = AMDGPULibFunc::I64; break;
639 0 : case 'f': res.ArgType = AMDGPULibFunc::F32; break;
640 0 : case 'd': res.ArgType = AMDGPULibFunc::F64; break;
641 : case 'D': if (!eatTerm(param, 'h')) return false;
642 : res.ArgType = AMDGPULibFunc::F16; break;
643 0 : case 'S':
644 0 : if (!eatTerm(param, '_')) {
645 0 : eatNumber(param);
646 0 : if (!eatTerm(param, '_')) return false;
647 0 : }
648 0 : res.VectorSize = Prev.VectorSize;
649 0 : res.ArgType = Prev.ArgType;
650 0 : break;
651 0 : default:;
652 0 : }
653 0 : }
654 0 : if (res.ArgType == 0) return false;
655 0 : Prev.VectorSize = res.VectorSize;
656 0 : Prev.ArgType = res.ArgType;
657 : return true;
658 : }
659 0 :
660 0 : bool AMDGPUMangledLibFunc::parseFuncName(StringRef &mangledName) {
661 : StringRef Name = eatLengthPrefixedName(mangledName);
662 0 : FKind = parseNamePrefix(Name);
663 0 : if (!parseUnmangledName(Name))
664 0 : return false;
665 0 :
666 : const ManglingRule& Rule = manglingRules[FuncId];
667 : ItaniumParamParser Parser;
668 0 : for (int I=0; I < Rule.maxLeadIndex(); ++I) {
669 0 : Param P;
670 0 : if (!Parser.parseItaniumParam(mangledName, P))
671 0 : return false;
672 :
673 : if ((I + 1) == Rule.Lead[0]) Leads[0] = P;
674 297 : if ((I + 1) == Rule.Lead[1]) Leads[1] = P;
675 297 : }
676 297 : return true;
677 297 : }
678 :
679 : bool AMDGPUUnmangledLibFunc::parseFuncName(StringRef &Name) {
680 253 : if (!UnmangledFuncInfo::lookup(Name, FuncId))
681 : return false;
682 765 : setName(Name);
683 : return true;
684 256 : }
685 0 :
686 : bool AMDGPULibFunc::parse(StringRef FuncName, AMDGPULibFunc &F) {
687 256 : if (FuncName.empty()) {
688 256 : F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
689 : return false;
690 : }
691 :
692 : if (eatTerm(FuncName, "_Z"))
693 606 : F.Impl = make_unique<AMDGPUMangledLibFunc>();
694 606 : else
695 : F.Impl = make_unique<AMDGPUUnmangledLibFunc>();
696 52 : if (F.Impl->parseFuncName(FuncName))
697 52 : return true;
698 :
699 : F.Impl = std::unique_ptr<AMDGPULibFuncImpl>();
700 903 : return false;
701 903 : }
702 :
703 0 : StringRef AMDGPUMangledLibFunc::getUnmangledName(StringRef mangledName) {
704 : StringRef S = mangledName;
705 : if (eatTerm(S, "_Z"))
706 903 : return eatLengthPrefixedName(S);
707 : return StringRef();
708 : }
709 :
710 903 : ///////////////////////////////////////////////////////////////////////////////
711 : // Mangling
712 :
713 : template <typename Stream>
714 : void AMDGPUMangledLibFunc::writeName(Stream &OS) const {
715 : const char *Pfx = "";
716 : switch (FKind) {
717 0 : case NATIVE: Pfx = "native_"; break;
718 0 : case HALF: Pfx = "half_"; break;
719 0 : default: break;
720 0 : }
721 0 : if (!Name.empty()) {
722 : OS << Pfx << Name;
723 : } else if (FuncId != EI_NONE) {
724 : OS << Pfx;
725 : const StringRef& S = manglingRules[FuncId].Name;
726 : OS.write(S.data(), S.size());
727 : }
728 107 : }
729 :
730 107 : std::string AMDGPUMangledLibFunc::mangle() const { return mangleNameItanium(); }
731 32 :
732 0 : ///////////////////////////////////////////////////////////////////////////////
733 : // Itanium Mangling
734 :
735 107 : static const char *getItaniumTypeName(AMDGPULibFunc::EType T) {
736 0 : switch (T) {
737 107 : case AMDGPULibFunc::U8: return "h";
738 107 : case AMDGPULibFunc::U16: return "t";
739 107 : case AMDGPULibFunc::U32: return "j";
740 107 : case AMDGPULibFunc::U64: return "m";
741 : case AMDGPULibFunc::I8: return "c";
742 107 : case AMDGPULibFunc::I16: return "s";
743 : case AMDGPULibFunc::I32: return "i";
744 107 : case AMDGPULibFunc::I64: return "l";
745 : case AMDGPULibFunc::F16: return "Dh";
746 : case AMDGPULibFunc::F32: return "f";
747 : case AMDGPULibFunc::F64: return "d";
748 : case AMDGPULibFunc::IMG1DA: return "16ocl_image1darray";
749 112 : case AMDGPULibFunc::IMG1DB: return "17ocl_image1dbuffer";
750 112 : case AMDGPULibFunc::IMG2DA: return "16ocl_image2darray";
751 : case AMDGPULibFunc::IMG1D: return "11ocl_image1d";
752 0 : case AMDGPULibFunc::IMG2D: return "11ocl_image2d";
753 0 : case AMDGPULibFunc::IMG3D: return "11ocl_image3d";
754 0 : case AMDGPULibFunc::SAMPLER: return "11ocl_sampler";
755 0 : case AMDGPULibFunc::EVENT: return "9ocl_event";
756 0 : default: llvm_unreachable("Unhandeled param type");
757 0 : }
758 0 : return nullptr;
759 0 : }
760 112 :
761 0 : namespace {
762 0 : // Itanium mangling ABI says:
763 0 : // "5.1.8. Compression
764 0 : // ... Each non-terminal in the grammar for which <substitution> appears on the
765 0 : // right-hand side is both a source of future substitutions and a candidate
766 0 : // for being substituted. There are two exceptions that appear to be
767 0 : // substitution candidates from the grammar, but are explicitly excluded:
768 0 : // 1. <builtin-type> other than vendor extended types ..."
769 0 :
770 0 : // For the purpose of functions the following productions make sence for the
771 : // substitution:
772 : // <type> ::= <builtin-type>
773 : // ::= <class-enum-type>
774 : // ::= <array-type>
775 : // ::=<CV-qualifiers> <type>
776 : // ::= P <type> # pointer-to
777 : // ::= <substitution>
778 : //
779 : // Note that while types like images, samplers and events are by the ABI encoded
780 : // using <class-enum-type> production rule they're not used for substitution
781 : // because clang consider them as builtin types.
782 : //
783 : // DvNN_ type is GCC extension for vectors and is a subject for the substitution.
784 :
785 :
786 : class ItaniumMangler {
787 : SmallVector<AMDGPULibFunc::Param, 10> Str; // list of accumulated substituions
788 : bool UseAddrSpace;
789 :
790 : int findSubst(const AMDGPULibFunc::Param& P) const {
791 : for(unsigned I = 0; I < Str.size(); ++I) {
792 : const AMDGPULibFunc::Param& T = Str[I];
793 : if (P.PtrKind == T.PtrKind &&
794 : P.VectorSize == T.VectorSize &&
795 : P.ArgType == T.ArgType) {
796 : return I;
797 : }
798 : }
799 : return -1;
800 107 : }
801 :
802 : template <typename Stream>
803 : bool trySubst(Stream& os, const AMDGPULibFunc::Param& p) {
804 : int const subst = findSubst(p);
805 72 : if (subst < 0) return false;
806 : // Substitutions are mangled as S(XX)?_ where XX is a hexadecimal number
807 20 : // 0 1 2
808 10 : // S_ S0_ S1_
809 10 : if (subst == 0) os << "S_";
810 10 : else os << 'S' << (subst-1) << '_';
811 : return true;
812 : }
813 :
814 : public:
815 : ItaniumMangler(bool useAddrSpace)
816 : : UseAddrSpace(useAddrSpace) {}
817 62 :
818 : template <typename Stream>
819 62 : void operator()(Stream& os, AMDGPULibFunc::Param p) {
820 :
821 : // Itanium mangling ABI 5.1.8. Compression:
822 : // Logically, the substitutable components of a mangled name are considered
823 10 : // left-to-right, components before the composite structure of which they
824 0 : // are a part. If a component has been encountered before, it is substituted
825 : // as described below. This decision is independent of whether its components
826 : // have been substituted, so an implementation may optimize by considering
827 : // large structures for substitution before their components. If a component
828 : // has not been encountered before, its mangling is identified, and it is
829 : // added to a dictionary of substitution candidates. No entity is added to
830 107 : // the dictionary twice.
831 : AMDGPULibFunc::Param Ptr;
832 :
833 122 : if (p.PtrKind) {
834 : if (trySubst(os, p)) return;
835 : os << 'P';
836 : if (p.PtrKind & AMDGPULibFunc::CONST) os << 'K';
837 : if (p.PtrKind & AMDGPULibFunc::VOLATILE) os << 'V';
838 : unsigned AS = UseAddrSpace
839 : ? AMDGPULibFuncBase::getAddrSpaceFromEPtrKind(p.PtrKind)
840 : : 0;
841 : if (AS != 0) os << "U3AS" << AS;
842 : Ptr = p;
843 : p.PtrKind = 0;
844 : }
845 :
846 : if (p.VectorSize > 1) {
847 122 : if (trySubst(os, p)) goto exit;
848 12 : Str.push_back(p);
849 12 : os << "Dv" << static_cast<unsigned>(p.VectorSize) << '_';
850 12 : }
851 12 :
852 12 : os << getItaniumTypeName((AMDGPULibFunc::EType)p.ArgType);
853 12 :
854 : exit:
855 12 : if (Ptr.ArgType) Str.push_back(Ptr);
856 12 : }
857 12 : };
858 : } // namespace
859 :
860 122 : std::string AMDGPUMangledLibFunc::mangleNameItanium() const {
861 50 : SmallString<128> Buf;
862 40 : raw_svector_ostream S(Buf);
863 40 : SmallString<128> NameBuf;
864 : raw_svector_ostream Name(NameBuf);
865 : writeName(Name);
866 112 : const StringRef& NameStr = Name.str();
867 : S << "_Z" << static_cast<int>(NameStr.size()) << NameStr;
868 122 :
869 122 : ItaniumMangler Mangler(true);
870 : ParamIterator I(Leads, manglingRules[FuncId]);
871 : Param P;
872 : while ((P = I.getNextParam()).ArgType != 0)
873 : Mangler(S, P);
874 107 : return S.str();
875 : }
876 :
877 : ///////////////////////////////////////////////////////////////////////////////
878 : // Misc
879 107 :
880 107 : static Type* getIntrinsicParamType(
881 107 : LLVMContext& C,
882 : const AMDGPULibFunc::Param& P,
883 : bool useAddrSpace) {
884 107 : Type* T = nullptr;
885 : switch (P.ArgType) {
886 229 : case AMDGPULibFunc::U8:
887 122 : case AMDGPULibFunc::I8: T = Type::getInt8Ty(C); break;
888 107 : case AMDGPULibFunc::U16:
889 : case AMDGPULibFunc::I16: T = Type::getInt16Ty(C); break;
890 : case AMDGPULibFunc::U32:
891 : case AMDGPULibFunc::I32: T = Type::getInt32Ty(C); break;
892 : case AMDGPULibFunc::U64:
893 : case AMDGPULibFunc::I64: T = Type::getInt64Ty(C); break;
894 135 : case AMDGPULibFunc::F16: T = Type::getHalfTy(C); break;
895 : case AMDGPULibFunc::F32: T = Type::getFloatTy(C); break;
896 : case AMDGPULibFunc::F64: T = Type::getDoubleTy(C); break;
897 :
898 : case AMDGPULibFunc::IMG1DA:
899 135 : case AMDGPULibFunc::IMG1DB:
900 0 : case AMDGPULibFunc::IMG2DA:
901 0 : case AMDGPULibFunc::IMG1D:
902 0 : case AMDGPULibFunc::IMG2D:
903 0 : case AMDGPULibFunc::IMG3D:
904 0 : T = StructType::create(C,"ocl_image")->getPointerTo(); break;
905 0 : case AMDGPULibFunc::SAMPLER:
906 0 : T = StructType::create(C,"ocl_sampler")->getPointerTo(); break;
907 0 : case AMDGPULibFunc::EVENT:
908 0 : T = StructType::create(C,"ocl_event")->getPointerTo(); break;
909 135 : default:
910 0 : llvm_unreachable("Unhandeled param type");
911 : return nullptr;
912 : }
913 : if (P.VectorSize > 1)
914 : T = VectorType::get(T, P.VectorSize);
915 : if (P.PtrKind != AMDGPULibFunc::BYVALUE)
916 : T = useAddrSpace ? T->getPointerTo((P.PtrKind & AMDGPULibFunc::ADDR_SPACE)
917 : - 1)
918 0 : : T->getPointerTo();
919 : return T;
920 0 : }
921 :
922 0 : FunctionType *AMDGPUMangledLibFunc::getFunctionType(Module &M) const {
923 0 : LLVMContext& C = M.getContext();
924 0 : std::vector<Type*> Args;
925 : ParamIterator I(Leads, manglingRules[FuncId]);
926 : Param P;
927 135 : while ((P=I.getNextParam()).ArgType != 0)
928 35 : Args.push_back(getIntrinsicParamType(C, P, true));
929 135 :
930 6 : return FunctionType::get(
931 6 : getIntrinsicParamType(C, getRetType(FuncId, Leads), true),
932 0 : Args, false);
933 : }
934 :
935 : unsigned AMDGPUMangledLibFunc::getNumArgs() const {
936 63 : return manglingRules[FuncId].getNumArgs();
937 63 : }
938 :
939 63 : unsigned AMDGPUUnmangledLibFunc::getNumArgs() const {
940 : return UnmangledFuncInfo::getNumArgs(FuncId);
941 135 : }
942 72 :
943 : std::string AMDGPUMangledLibFunc::getName() const {
944 63 : SmallString<128> Buf;
945 132 : raw_svector_ostream OS(Buf);
946 63 : writeName(OS);
947 : return OS.str();
948 : }
949 171 :
950 171 : Function *AMDGPULibFunc::getFunction(Module *M, const AMDGPULibFunc &fInfo) {
951 : std::string FuncName = fInfo.mangle();
952 : Function *F = dyn_cast_or_null<Function>(
953 39 : M->getValueSymbolTable().lookup(FuncName));
954 78 :
955 : // check formal with actual types conformance
956 : if (F && !F->isDeclaration()
957 0 : && !F->isVarArg()
958 : && F->arg_size() == fInfo.getNumArgs()) {
959 : return F;
960 0 : }
961 0 : return nullptr;
962 : }
963 :
964 18 : Function *AMDGPULibFunc::getOrInsertFunction(Module *M,
965 : const AMDGPULibFunc &fInfo) {
966 18 : std::string const FuncName = fInfo.mangle();
967 18 : Function *F = dyn_cast_or_null<Function>(
968 : M->getValueSymbolTable().lookup(FuncName));
969 :
970 11 : // check formal with actual types conformance
971 0 : if (F && !F->isDeclaration()
972 0 : && !F->isVarArg()
973 0 : && F->arg_size() == fInfo.getNumArgs()) {
974 : return F;
975 : }
976 :
977 : FunctionType *FuncTy = fInfo.getFunctionType(*M);
978 99 :
979 : bool hasPtr = false;
980 : for (FunctionType::param_iterator
981 99 : PI = FuncTy->param_begin(),
982 99 : PE = FuncTy->param_end();
983 : PI != PE; ++PI) {
984 : const Type* argTy = static_cast<const Type*>(*PI);
985 34 : if (argTy->isPointerTy()) {
986 0 : hasPtr = true;
987 0 : break;
988 : }
989 : }
990 :
991 : Constant *C = nullptr;
992 : if (hasPtr) {
993 : // Do not set extra attributes for functions with pointer arguments.
994 66 : C = M->getOrInsertFunction(FuncName, FuncTy);
995 99 : } else {
996 99 : AttributeList Attr;
997 165 : LLVMContext &Ctx = M->getContext();
998 108 : Attr.addAttribute(Ctx, AttributeList::FunctionIndex, Attribute::ReadOnly);
999 108 : Attr.addAttribute(Ctx, AttributeList::FunctionIndex, Attribute::NoUnwind);
1000 : C = M->getOrInsertFunction(FuncName, FuncTy, Attr);
1001 : }
1002 :
1003 : return cast<Function>(C);
1004 : }
1005 :
1006 99 : bool UnmangledFuncInfo::lookup(StringRef Name, ID &Id) {
1007 : auto Loc = Map.find(Name);
1008 42 : if (Loc != Map.end()) {
1009 : Id = toFuncId(Loc->second);
1010 57 : return true;
1011 57 : }
1012 57 : Id = AMDGPULibFunc::EI_NONE;
1013 57 : return false;
1014 57 : }
1015 :
1016 : AMDGPULibFunc::AMDGPULibFunc(const AMDGPULibFunc &F) {
1017 : if (auto *MF = dyn_cast<AMDGPUMangledLibFunc>(F.Impl.get()))
1018 : Impl.reset(new AMDGPUMangledLibFunc(*MF));
1019 : else if (auto *UMF = dyn_cast<AMDGPUUnmangledLibFunc>(F.Impl.get()))
1020 606 : Impl.reset(new AMDGPUUnmangledLibFunc(*UMF));
1021 606 : else
1022 1212 : Impl = std::unique_ptr<AMDGPULibFuncImpl>();
1023 104 : }
1024 52 :
1025 : AMDGPULibFunc &AMDGPULibFunc::operator=(const AMDGPULibFunc &F) {
1026 554 : if (this == &F)
1027 554 : return *this;
1028 : new (this) AMDGPULibFunc(F);
1029 : return *this;
1030 2 : }
1031 :
1032 2 : AMDGPULibFunc::AMDGPULibFunc(EFuncId Id, const AMDGPULibFunc &CopyFrom) {
1033 : assert(AMDGPULibFuncBase::isMangled(Id) && CopyFrom.isMangled() &&
1034 0 : "not supported");
1035 : Impl.reset(new AMDGPUMangledLibFunc(
1036 : Id, *cast<AMDGPUMangledLibFunc>(CopyFrom.Impl.get())));
1037 2 : }
1038 :
1039 0 : AMDGPULibFunc::AMDGPULibFunc(StringRef Name, FunctionType *FT) {
1040 0 : Impl.reset(new AMDGPUUnmangledLibFunc(Name, FT));
1041 : }
1042 0 :
1043 0 : void AMDGPULibFunc::initMangled() { Impl.reset(new AMDGPUMangledLibFunc()); }
1044 :
1045 : AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() {
1046 55 : if (!Impl)
1047 : initMangled();
1048 : return cast<AMDGPUMangledLibFunc>(Impl.get())->Leads;
1049 : }
1050 55 :
1051 55 : const AMDGPULibFunc::Param *AMDGPULibFunc::getLeads() const {
1052 : return cast<const AMDGPUMangledLibFunc>(Impl.get())->Leads;
1053 36 : }
|