Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : #include "llvm-version.h"
4 : : #include <llvm/ADT/ArrayRef.h>
5 : : #include <llvm/ADT/APInt.h>
6 : : #include <llvm/ADT/APFloat.h>
7 : : #include <llvm/Support/MathExtras.h>
8 : :
9 : : #include "APInt-C.h"
10 : : #include "julia.h"
11 : : #include "julia_assert.h"
12 : : #include "julia_internal.h"
13 : :
14 : : using namespace llvm;
15 : :
16 : 197583 : inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
17 : 197583 : return alignTo(Value, Align, Skew);
18 : : }
19 : :
20 : : const unsigned int integerPartWidth = llvm::APInt::APINT_BITS_PER_WORD;
21 : : const unsigned int host_char_bit = 8;
22 : :
23 : : /* create "APInt s" from "integerPart *ps" */
24 : : #define CREATE(s) \
25 : : APInt s; \
26 : : if ((numbits % integerPartWidth) != 0) { \
27 : : /* use LLT_ALIGN to round the memory area up to the nearest integerPart-sized chunk */ \
28 : : unsigned nbytes = RoundUpToAlignment(numbits, integerPartWidth) / host_char_bit; \
29 : : integerPart *data_a64 = (integerPart*)alloca(nbytes); \
30 : : /* TODO: this memcpy assumes little-endian,
31 : : * for big-endian, need to align the copy to the other end */ \
32 : : memcpy(data_a64, p##s, RoundUpToAlignment(numbits, host_char_bit) / host_char_bit); \
33 : : s = APInt(numbits, makeArrayRef(data_a64, nbytes / sizeof(integerPart))); \
34 : : } \
35 : : else { \
36 : : s = APInt(numbits, makeArrayRef(p##s, numbits / integerPartWidth)); \
37 : : }
38 : :
39 : : /* assign to "integerPart *pr" from "APInt a" */
40 : : #define ASSIGN(r, a) \
41 : : if (numbits <= 8) \
42 : : *(uint8_t*)p##r = a.getZExtValue(); \
43 : : else if (numbits <= 16) \
44 : : *(uint16_t*)p##r = a.getZExtValue(); \
45 : : else if (numbits <= 32) \
46 : : *(uint32_t*)p##r = a.getZExtValue(); \
47 : : else if (numbits <= 64) \
48 : : *(uint64_t*)p##r = a.getZExtValue(); \
49 : : else \
50 : : memcpy(p##r, a.getRawData(), RoundUpToAlignment(numbits, host_char_bit) / host_char_bit); \
51 : :
52 : : extern "C" JL_DLLEXPORT
53 : 0 : void LLVMNeg(unsigned numbits, integerPart *pa, integerPart *pr) {
54 : 0 : APInt z(numbits, 0);
55 [ # # ]: 0 : CREATE(a)
56 : 0 : z -= a;
57 [ # # # # : 0 : ASSIGN(r, z)
# # # # ]
58 : 0 : }
59 : :
60 : : extern "C" JL_DLLEXPORT
61 : 0 : void LLVMAdd(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
62 [ # # ]: 0 : CREATE(a)
63 [ # # ]: 0 : CREATE(b)
64 : 0 : a += b;
65 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
66 : 0 : }
67 : :
68 : : extern "C" JL_DLLEXPORT
69 : 0 : void LLVMSub(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
70 [ # # ]: 0 : CREATE(a)
71 [ # # ]: 0 : CREATE(b)
72 : 0 : a -= b;
73 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
74 : 0 : }
75 : :
76 : : extern "C" JL_DLLEXPORT
77 : 0 : void LLVMMul(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
78 [ # # ]: 0 : CREATE(a)
79 [ # # ]: 0 : CREATE(b)
80 : 0 : a *= b;
81 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
82 : 0 : }
83 : :
84 : : extern "C" JL_DLLEXPORT
85 : 0 : void LLVMSDiv(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
86 [ # # ]: 0 : if (LLVMDiv_sov(numbits, pa, pb, pr))
87 : 0 : jl_throw(jl_diverror_exception);
88 : 0 : }
89 : :
90 : : extern "C" JL_DLLEXPORT
91 : 0 : void LLVMUDiv(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
92 [ # # ]: 0 : if (LLVMDiv_uov(numbits, pa, pb, pr))
93 : 0 : jl_throw(jl_diverror_exception);
94 : 0 : }
95 : :
96 : : extern "C" JL_DLLEXPORT
97 : 0 : void LLVMSRem(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
98 [ # # ]: 0 : if (LLVMRem_sov(numbits, pa, pb, pr))
99 : 0 : jl_throw(jl_diverror_exception);
100 : 0 : }
101 : :
102 : : extern "C" JL_DLLEXPORT
103 : 0 : void LLVMURem(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
104 [ # # ]: 0 : if (LLVMRem_uov(numbits, pa, pb, pr))
105 : 0 : jl_throw(jl_diverror_exception);
106 : 0 : }
107 : :
108 : : extern "C" JL_DLLEXPORT
109 : 0 : int LLVMICmpEQ(unsigned numbits, integerPart *pa, integerPart *pb) {
110 [ # # ]: 0 : CREATE(a)
111 [ # # ]: 0 : CREATE(b)
112 : 0 : return a.eq(b);
113 : : }
114 : :
115 : : extern "C" JL_DLLEXPORT
116 : 0 : int LLVMICmpNE(unsigned numbits, integerPart *pa, integerPart *pb) {
117 [ # # ]: 0 : CREATE(a)
118 [ # # ]: 0 : CREATE(b)
119 : 0 : return a.ne(b);
120 : : }
121 : :
122 : : extern "C" JL_DLLEXPORT
123 : 0 : int LLVMICmpSLT(unsigned numbits, integerPart *pa, integerPart *pb) {
124 [ # # ]: 0 : CREATE(a)
125 [ # # ]: 0 : CREATE(b)
126 : 0 : return a.slt(b);
127 : : }
128 : :
129 : : extern "C" JL_DLLEXPORT
130 : 0 : int LLVMICmpULT(unsigned numbits, integerPart *pa, integerPart *pb) {
131 [ # # ]: 0 : CREATE(a)
132 [ # # ]: 0 : CREATE(b)
133 : 0 : return a.ult(b);
134 : : }
135 : :
136 : : extern "C" JL_DLLEXPORT
137 : 0 : int LLVMICmpSLE(unsigned numbits, integerPart *pa, integerPart *pb) {
138 [ # # ]: 0 : CREATE(a)
139 [ # # ]: 0 : CREATE(b)
140 : 0 : return a.sle(b);
141 : : }
142 : :
143 : : extern "C" JL_DLLEXPORT
144 : 0 : int LLVMICmpULE(unsigned numbits, integerPart *pa, integerPart *pb) {
145 [ # # ]: 0 : CREATE(a)
146 [ # # ]: 0 : CREATE(b)
147 : 0 : return a.ule(b);
148 : : }
149 : :
150 : : extern "C" JL_DLLEXPORT
151 : 0 : void LLVMAnd(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
152 [ # # ]: 0 : CREATE(a)
153 [ # # ]: 0 : CREATE(b)
154 : 0 : a &= b;
155 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
156 : 0 : }
157 : :
158 : : extern "C" JL_DLLEXPORT
159 : 3 : void LLVMOr(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
160 [ - + ]: 6 : CREATE(a)
161 [ - + ]: 6 : CREATE(b)
162 : 3 : a |= b;
163 [ - + - + : 3 : ASSIGN(r, a)
- + - + ]
164 : 3 : }
165 : :
166 : : extern "C" JL_DLLEXPORT
167 : 482 : void LLVMXor(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
168 [ - + ]: 964 : CREATE(a)
169 [ - + ]: 964 : CREATE(b)
170 : 482 : a ^= b;
171 [ - + - + : 482 : ASSIGN(r, a)
- + - + ]
172 : 482 : }
173 : :
174 : : extern "C" JL_DLLEXPORT
175 : 6 : void LLVMShl(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
176 [ - + ]: 12 : CREATE(a)
177 [ - + ]: 12 : CREATE(b)
178 : 6 : a = a.shl(b);
179 [ - + - + : 6 : ASSIGN(r, a)
- + - + ]
180 : 6 : }
181 : :
182 : : extern "C" JL_DLLEXPORT
183 : 5 : void LLVMLShr(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
184 [ - + ]: 10 : CREATE(a)
185 [ - + ]: 10 : CREATE(b)
186 : 5 : a = a.lshr(b);
187 [ - + - + : 5 : ASSIGN(r, a)
- + - + ]
188 : 5 : }
189 : : extern "C" JL_DLLEXPORT
190 : 2 : void LLVMAShr(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
191 [ - + ]: 4 : CREATE(a)
192 [ - + ]: 4 : CREATE(b)
193 : 2 : a = a.ashr(b);
194 [ - + - + : 2 : ASSIGN(r, a)
- + - + ]
195 : 2 : }
196 : :
197 : : extern "C" JL_DLLEXPORT
198 : 108 : void LLVMFlipAllBits(unsigned numbits, integerPart *pa, integerPart *pr) {
199 [ - + ]: 216 : CREATE(a)
200 : 108 : a.flipAllBits();
201 [ - + - + : 108 : ASSIGN(r, a)
- + - + ]
202 : 108 : }
203 : :
204 : : extern "C" JL_DLLEXPORT
205 : 0 : int LLVMAdd_uov(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
206 [ # # ]: 0 : CREATE(a)
207 [ # # ]: 0 : CREATE(b)
208 : : bool Overflow;
209 : 0 : a = a.uadd_ov(b, Overflow);
210 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
211 : 0 : return Overflow;
212 : : }
213 : :
214 : : extern "C" JL_DLLEXPORT
215 : 0 : int LLVMAdd_sov(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
216 [ # # ]: 0 : CREATE(a)
217 [ # # ]: 0 : CREATE(b)
218 : : bool Overflow;
219 : 0 : a = a.sadd_ov(b, Overflow);
220 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
221 : 0 : return Overflow;
222 : : }
223 : :
224 : : extern "C" JL_DLLEXPORT
225 : 0 : int LLVMSub_uov(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
226 [ # # ]: 0 : CREATE(a)
227 [ # # ]: 0 : CREATE(b)
228 : : bool Overflow;
229 : 0 : a = a.usub_ov(b, Overflow);
230 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
231 : 0 : return Overflow;
232 : : }
233 : :
234 : : extern "C" JL_DLLEXPORT
235 : 0 : int LLVMSub_sov(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
236 [ # # ]: 0 : CREATE(a)
237 [ # # ]: 0 : CREATE(b)
238 : : bool Overflow;
239 : 0 : a = a.ssub_ov(b, Overflow);
240 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
241 : 0 : return Overflow;
242 : : }
243 : :
244 : : extern "C" JL_DLLEXPORT
245 : 461 : int LLVMMul_sov(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
246 [ - + ]: 922 : CREATE(a)
247 [ - + ]: 461 : CREATE(b)
248 : : bool Overflow;
249 : 461 : a = a.smul_ov(b, Overflow);
250 [ - + - + : 461 : ASSIGN(r, a)
- + + - ]
251 : 461 : return Overflow;
252 : : }
253 : :
254 : : extern "C" JL_DLLEXPORT
255 : 0 : int LLVMMul_uov(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
256 [ # # ]: 0 : CREATE(a)
257 [ # # ]: 0 : CREATE(b)
258 : : bool Overflow;
259 : 0 : a = a.umul_ov(b, Overflow);
260 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
261 : 0 : return Overflow;
262 : : }
263 : :
264 : : extern "C" JL_DLLEXPORT
265 : 69 : int LLVMDiv_sov(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
266 [ - + ]: 138 : CREATE(a)
267 [ - + ]: 138 : CREATE(b)
268 [ - + ]: 69 : if (!b)
269 : 0 : return true;
270 : : bool Overflow;
271 : 69 : a = a.sdiv_ov(b, Overflow);
272 [ - + - + : 69 : ASSIGN(r, a)
- + + - ]
273 : 69 : return Overflow;
274 : : }
275 : :
276 : : extern "C" JL_DLLEXPORT
277 : 0 : int LLVMDiv_uov(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
278 [ # # ]: 0 : CREATE(a)
279 [ # # ]: 0 : CREATE(b)
280 [ # # ]: 0 : if (!b)
281 : 0 : return true;
282 : 0 : a = a.udiv(b);
283 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
284 : 0 : return false;
285 : : }
286 : :
287 : : extern "C" JL_DLLEXPORT
288 : 1807 : int LLVMRem_sov(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
289 [ - + ]: 3614 : CREATE(a)
290 [ - + ]: 3614 : CREATE(b)
291 [ - + ]: 1807 : if (!b)
292 : 0 : return true;
293 : 1807 : a = a.srem(b);
294 [ - + - + : 1807 : ASSIGN(r, a)
- + + - ]
295 : 1807 : return false;
296 : : }
297 : :
298 : : extern "C" JL_DLLEXPORT
299 : 0 : int LLVMRem_uov(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
300 [ # # ]: 0 : CREATE(a)
301 [ # # ]: 0 : CREATE(b)
302 [ # # ]: 0 : if (!b)
303 : 0 : return true;
304 : 0 : a = a.urem(b);
305 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
306 : 0 : return false;
307 : : }
308 : :
309 : : extern "C" JL_DLLEXPORT
310 : 0 : void LLVMByteSwap(unsigned numbits, integerPart *pa, integerPart *pr) {
311 [ # # ]: 0 : CREATE(a)
312 : 0 : a = a.byteSwap();
313 [ # # # # : 0 : ASSIGN(r, a)
# # # # ]
314 : 0 : }
315 : :
316 : 4 : void LLVMFPtoInt(unsigned numbits, void *pa, unsigned onumbits, integerPart *pr, bool isSigned, bool *isExact) {
317 : : double Val;
318 [ + - ]: 4 : if (numbits == 16)
319 : 4 : Val = __gnu_h2f_ieee(*(uint16_t*)pa);
320 [ # # ]: 0 : else if (numbits == 32)
321 : 0 : Val = *(float*)pa;
322 [ # # ]: 0 : else if (numbits == 64)
323 : 0 : Val = *(double*)pa;
324 : : else
325 : 0 : jl_error("FPtoSI: runtime floating point intrinsics are not implemented for bit sizes other than 16, 32 and 64");
326 : 4 : unsigned onumbytes = RoundUpToAlignment(onumbits, host_char_bit) / host_char_bit;
327 [ + - ]: 4 : if (onumbits <= 64) { // fast-path, if possible
328 [ + + ]: 4 : if (isSigned) {
329 : 2 : int64_t ia = Val;
330 : 2 : memcpy(pr, &ia, onumbytes); // TODO: assumes little-endian
331 [ - + ]: 2 : if (isExact) {
332 : : // check whether the conversion was lossless
333 [ # # ]: 0 : int64_t ia2 = ia < 0 ? -1 : 0;
334 : 0 : memcpy(&ia2, pr, onumbytes);
335 [ # # # # ]: 0 : *isExact = (Val == (double)ia2 && ia == ia2);
336 : : }
337 : : }
338 : : else {
339 : 2 : uint64_t ia = Val;
340 : 2 : memcpy(pr, &ia, onumbytes); // TODO: assumes little-endian
341 [ - + ]: 2 : if (isExact) {
342 : : // check whether the conversion was lossless
343 : 0 : uint64_t ia2 = 0;
344 : 0 : memcpy(&ia2, pr, onumbytes);
345 [ # # # # ]: 0 : *isExact = (Val == (double)ia2 && ia == ia2);
346 : : }
347 : : }
348 : : }
349 : : else {
350 : 0 : APFloat a(Val);
351 : : bool isVeryExact;
352 : 0 : APFloat::roundingMode rounding_mode = APFloat::rmNearestTiesToEven;
353 : 0 : unsigned nbytes = RoundUpToAlignment(onumbits, integerPartWidth) / host_char_bit;
354 : 0 : integerPart *parts = (integerPart*)alloca(nbytes);
355 : 0 : APFloat::opStatus status = a.convertToInteger(MutableArrayRef<integerPart>(parts, nbytes), onumbits, isSigned, rounding_mode, &isVeryExact);
356 : 0 : memcpy(pr, parts, onumbytes);
357 [ # # ]: 0 : if (isExact)
358 : 0 : *isExact = (status == APFloat::opOK);
359 : : }
360 : 4 : }
361 : :
362 : : extern "C" JL_DLLEXPORT
363 : 2 : void LLVMFPtoSI(unsigned numbits, integerPart *pa, unsigned onumbits, integerPart *pr) {
364 : 2 : LLVMFPtoInt(numbits, pa, onumbits, pr, true, NULL);
365 : 2 : }
366 : :
367 : : extern "C" JL_DLLEXPORT
368 : 2 : void LLVMFPtoUI(unsigned numbits, integerPart *pa, unsigned onumbits, integerPart *pr) {
369 : 2 : LLVMFPtoInt(numbits, pa, onumbits, pr, false, NULL);
370 : 2 : }
371 : :
372 : : extern "C" JL_DLLEXPORT
373 : 0 : int LLVMFPtoSI_exact(unsigned numbits, integerPart *pa, unsigned onumbits, integerPart *pr) {
374 : : bool isExact;
375 : 0 : LLVMFPtoInt(numbits, pa, onumbits, pr, true, &isExact);
376 : 0 : return isExact;
377 : : }
378 : :
379 : : extern "C" JL_DLLEXPORT
380 : 0 : int LLVMFPtoUI_exact(unsigned numbits, integerPart *pa, unsigned onumbits, integerPart *pr) {
381 : : bool isExact;
382 : 0 : LLVMFPtoInt(numbits, pa, onumbits, pr, false, &isExact);
383 : 0 : return isExact;
384 : : }
385 : :
386 : : extern "C" JL_DLLEXPORT
387 : 4 : void LLVMSItoFP(unsigned numbits, integerPart *pa, unsigned onumbits, integerPart *pr) {
388 : : double val;
389 : : { // end scope before jl_error call
390 [ - + ]: 8 : CREATE(a)
391 : 4 : val = a.roundToDouble(true);
392 : : }
393 [ + + ]: 4 : if (onumbits == 16)
394 : 2 : *(uint16_t*)pr = __gnu_f2h_ieee(val);
395 [ + + ]: 2 : else if (onumbits == 32)
396 : 1 : *(float*)pr = val;
397 [ + - ]: 1 : else if (onumbits == 64)
398 : 1 : *(double*)pr = val;
399 : : else
400 : 0 : jl_error("SItoFP: runtime floating point intrinsics are not implemented for bit sizes other than 16, 32 and 64");
401 : 4 : }
402 : :
403 : : extern "C" JL_DLLEXPORT
404 : 2 : void LLVMUItoFP(unsigned numbits, integerPart *pa, unsigned onumbits, integerPart *pr) {
405 : : double val;
406 : : { // end scope before jl_error call
407 [ - + ]: 4 : CREATE(a)
408 : 2 : val = a.roundToDouble(false);
409 : : }
410 [ + - ]: 2 : if (onumbits == 16)
411 : 2 : *(uint16_t*)pr = __gnu_f2h_ieee(val);
412 [ # # ]: 0 : else if (onumbits == 32)
413 : 0 : *(float*)pr = val;
414 [ # # ]: 0 : else if (onumbits == 64)
415 : 0 : *(double*)pr = val;
416 : : else
417 : 0 : jl_error("UItoFP: runtime floating point intrinsics are not implemented for bit sizes other than 32 and 64");
418 : 2 : }
419 : :
420 : : extern "C" JL_DLLEXPORT
421 : 4784 : void LLVMSExt(unsigned inumbits, integerPart *pa, unsigned onumbits, integerPart *pr) {
422 [ + + ]: 4784 : if (!(onumbits > inumbits))
423 : 2 : jl_error("SExt: output bitsize must be > input bitsize");
424 : 4782 : unsigned inumbytes = RoundUpToAlignment(inumbits, host_char_bit) / host_char_bit;
425 : 4782 : unsigned onumbytes = RoundUpToAlignment(onumbits, host_char_bit) / host_char_bit;
426 : 4782 : int bits = (0 - inumbits) % host_char_bit;
427 : 4782 : int signbit = (inumbits - 1) % host_char_bit;
428 [ + + ]: 4782 : int sign = ((unsigned char*)pa)[inumbytes - 1] & (1 << signbit) ? -1 : 0;
429 : : // copy over the input bytes
430 : 4782 : memcpy(pr, pa, inumbytes);
431 [ - + ]: 4782 : if (bits) {
432 : : // sign-extend the partial byte
433 : 0 : ((signed char*)pr)[inumbytes - 1] = ((signed char*)pa)[inumbytes - 1] << bits >> bits;
434 : : }
435 : : // sign-extend the rest of the bytes
436 : 4782 : memset((char*)pr + inumbytes, sign, onumbytes - inumbytes);
437 : 4782 : }
438 : :
439 : : extern "C" JL_DLLEXPORT
440 : 55586 : void LLVMZExt(unsigned inumbits, integerPart *pa, unsigned onumbits, integerPart *pr) {
441 [ + + ]: 55586 : if (!(onumbits > inumbits))
442 : 2 : jl_error("ZExt: output bitsize must be > input bitsize");
443 : 55584 : unsigned inumbytes = RoundUpToAlignment(inumbits, host_char_bit) / host_char_bit;
444 : 55584 : unsigned onumbytes = RoundUpToAlignment(onumbits, host_char_bit) / host_char_bit;
445 : 55584 : int bits = (0 - inumbits) % host_char_bit;
446 : : // copy over the input bytes
447 : 55584 : memcpy(pr, pa, inumbytes);
448 [ - + ]: 55584 : if (bits) {
449 : : // zero the remaining bits of the partial byte
450 : 0 : ((unsigned char*)pr)[inumbytes - 1] = ((unsigned char*)pa)[inumbytes - 1] << bits >> bits;
451 : : }
452 : : // zero-extend the rest of the bytes
453 : 55584 : memset((char*)pr + inumbytes, 0, onumbytes - inumbytes);
454 : 55584 : }
455 : :
456 : : extern "C" JL_DLLEXPORT
457 : 76243 : void LLVMTrunc(unsigned inumbits, integerPart *pa, unsigned onumbits, integerPart *pr) {
458 [ + + ]: 76243 : if (!(onumbits < inumbits))
459 : 2 : jl_error("Trunc: output bitsize must be < input bitsize");
460 : 76241 : unsigned onumbytes = RoundUpToAlignment(onumbits, host_char_bit) / host_char_bit;
461 : 76241 : memcpy(pr, pa, onumbytes);
462 : 76241 : }
463 : :
464 : : extern "C" JL_DLLEXPORT
465 : 0 : unsigned countTrailingZeros_8(uint8_t Val) {
466 : 0 : return countTrailingZeros(Val);
467 : : }
468 : :
469 : : extern "C" JL_DLLEXPORT
470 : 0 : unsigned countTrailingZeros_16(uint16_t Val) {
471 : 0 : return countTrailingZeros(Val);
472 : : }
473 : :
474 : : extern "C" JL_DLLEXPORT
475 : 0 : unsigned countTrailingZeros_32(uint32_t Val) {
476 : 0 : return countTrailingZeros(Val);
477 : : }
478 : :
479 : : extern "C" JL_DLLEXPORT
480 : 0 : unsigned countTrailingZeros_64(uint64_t Val) {
481 : 0 : return countTrailingZeros(Val);
482 : : }
483 : :
484 : : extern "C" JL_DLLEXPORT
485 : 0 : void jl_LLVMSMod(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
486 : : { // end scope before jl_error call
487 [ # # ]: 0 : CREATE(a)
488 [ # # ]: 0 : CREATE(b)
489 [ # # ]: 0 : if (!!b) {
490 : 0 : APInt r = a.srem(b);
491 [ # # ]: 0 : if (a.isNegative() != b.isNegative()) {
492 : 0 : r = (b + r).srem(b);
493 : : }
494 [ # # # # : 0 : ASSIGN(r, r)
# # # # ]
495 : 0 : return;
496 : : }
497 : : }
498 : 0 : jl_throw(jl_diverror_exception);
499 : : }
500 : :
501 : : extern "C" JL_DLLEXPORT
502 : 0 : void jl_LLVMFlipSign(unsigned numbits, integerPart *pa, integerPart *pb, integerPart *pr) {
503 : 0 : unsigned numbytes = (numbits + host_char_bit - 1) / host_char_bit;
504 : 0 : int signbit = (numbits - 1) % host_char_bit;
505 : 0 : int sign = ((unsigned char*)pb)[numbytes - 1] & (1 << signbit);
506 [ # # ]: 0 : if (sign)
507 : 0 : LLVMNeg(numbits, pa, pr);
508 : : else
509 : 0 : memcpy(pr, pa, numbytes);
510 : 0 : }
511 : :
512 : : extern "C" JL_DLLEXPORT
513 : 2057 : unsigned LLVMCountPopulation(unsigned numbits, integerPart *pa) {
514 [ - + ]: 4114 : CREATE(a)
515 : 2057 : return a.countPopulation();
516 : : }
517 : :
518 : : extern "C" JL_DLLEXPORT
519 : 0 : unsigned LLVMCountTrailingOnes(unsigned numbits, integerPart *pa) {
520 [ # # ]: 0 : CREATE(a)
521 : 0 : return a.countTrailingOnes();
522 : : }
523 : :
524 : : extern "C" JL_DLLEXPORT
525 : 9193 : unsigned LLVMCountTrailingZeros(unsigned numbits, integerPart *pa) {
526 [ - + ]: 18386 : CREATE(a)
527 : 9193 : return a.countTrailingZeros();
528 : : }
529 : :
530 : : extern "C" JL_DLLEXPORT
531 : 0 : unsigned LLVMCountLeadingOnes(unsigned numbits, integerPart *pa) {
532 [ # # ]: 0 : CREATE(a)
533 : 0 : return a.countLeadingOnes();
534 : : }
535 : :
536 : : extern "C" JL_DLLEXPORT
537 : 80 : unsigned LLVMCountLeadingZeros(unsigned numbits, integerPart *pa) {
538 [ - + ]: 160 : CREATE(a)
539 : 80 : return a.countLeadingZeros();
540 : : }
|