Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : // This is in implementation of the Julia intrinsic functions against boxed types
4 : : // excluding the native function call interface (ccall, llvmcall)
5 : : //
6 : : // this file assumes a little-endian processor, although that isn't too hard to fix
7 : : // it also assumes two's complement negative numbers, which might be a bit harder to fix
8 : : //
9 : : // TODO: add half-float support
10 : :
11 : : #include "APInt-C.h"
12 : : #include "julia.h"
13 : : #include "julia_internal.h"
14 : :
15 : : const unsigned int host_char_bit = 8;
16 : :
17 : : // float16 intrinsics
18 : : // TODO: use LLVM's compiler-rt on all platforms (Xcode already links compiler-rt)
19 : :
20 : : #if !defined(_OS_DARWIN_)
21 : :
22 : 0 : static inline float half_to_float(uint16_t ival) JL_NOTSAFEPOINT
23 : : {
24 : 0 : uint32_t sign = (ival & 0x8000) >> 15;
25 : 0 : uint32_t exp = (ival & 0x7c00) >> 10;
26 : 0 : uint32_t sig = (ival & 0x3ff) >> 0;
27 : : uint32_t ret;
28 : :
29 [ # # ]: 0 : if (exp == 0) {
30 [ # # ]: 0 : if (sig == 0) {
31 : 0 : sign = sign << 31;
32 : 0 : ret = sign | exp | sig;
33 : : }
34 : : else {
35 : 0 : int n_bit = 1;
36 : 0 : uint16_t bit = 0x0200;
37 [ # # ]: 0 : while ((bit & sig) == 0) {
38 : 0 : n_bit = n_bit + 1;
39 : 0 : bit = bit >> 1;
40 : : }
41 : 0 : sign = sign << 31;
42 : 0 : exp = ((-14 - n_bit + 127) << 23);
43 : 0 : sig = ((sig & (~bit)) << n_bit) << (23 - 10);
44 : 0 : ret = sign | exp | sig;
45 : : }
46 : : }
47 [ # # ]: 0 : else if (exp == 0x1f) {
48 [ # # ]: 0 : if (sig == 0) { // Inf
49 [ # # ]: 0 : if (sign == 0)
50 : 0 : ret = 0x7f800000;
51 : : else
52 : 0 : ret = 0xff800000;
53 : : }
54 : : else // NaN
55 : 0 : ret = 0x7fc00000 | (sign << 31) | (sig << (23 - 10));
56 : : }
57 : : else {
58 : 0 : sign = sign << 31;
59 : 0 : exp = ((exp - 15 + 127) << 23);
60 : 0 : sig = sig << (23 - 10);
61 : 0 : ret = sign | exp | sig;
62 : : }
63 : :
64 : : float fret;
65 : 0 : memcpy(&fret, &ret, sizeof(float));
66 : 0 : return fret;
67 : : }
68 : :
69 : : // float to half algorithm from:
70 : : // "Fast Half Float Conversion" by Jeroen van der Zijp
71 : : // ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf
72 : : //
73 : : // With adjustments for round-to-nearest, ties to even.
74 : :
75 : : static uint16_t basetable[512] = {
76 : : 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
77 : : 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
78 : : 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
79 : : 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
80 : : 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
81 : : 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
82 : : 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
83 : : 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
84 : : 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
85 : : 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
86 : : 0x0000, 0x0000, 0x0000, 0x0400, 0x0800, 0x0c00, 0x1000, 0x1400, 0x1800, 0x1c00, 0x2000,
87 : : 0x2400, 0x2800, 0x2c00, 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x4400, 0x4800, 0x4c00,
88 : : 0x5000, 0x5400, 0x5800, 0x5c00, 0x6000, 0x6400, 0x6800, 0x6c00, 0x7000, 0x7400, 0x7800,
89 : : 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
90 : : 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
91 : : 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
92 : : 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
93 : : 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
94 : : 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
95 : : 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
96 : : 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
97 : : 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
98 : : 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
99 : : 0x7c00, 0x7c00, 0x7c00, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
100 : : 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
101 : : 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
102 : : 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
103 : : 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
104 : : 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
105 : : 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
106 : : 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
107 : : 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
108 : : 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
109 : : 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8400, 0x8800, 0x8c00, 0x9000, 0x9400,
110 : : 0x9800, 0x9c00, 0xa000, 0xa400, 0xa800, 0xac00, 0xb000, 0xb400, 0xb800, 0xbc00, 0xc000,
111 : : 0xc400, 0xc800, 0xcc00, 0xd000, 0xd400, 0xd800, 0xdc00, 0xe000, 0xe400, 0xe800, 0xec00,
112 : : 0xf000, 0xf400, 0xf800, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
113 : : 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
114 : : 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
115 : : 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
116 : : 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
117 : : 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
118 : : 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
119 : : 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
120 : : 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
121 : : 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
122 : : 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00};
123 : :
124 : : static uint8_t shifttable[512] = {
125 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
126 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
127 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
128 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
129 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
130 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
131 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
132 : : 0x19, 0x19, 0x19, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
133 : : 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
134 : : 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
135 : : 0x0d, 0x0d, 0x0d, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
136 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
137 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
138 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
139 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
140 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
141 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
142 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
143 : : 0x18, 0x18, 0x18, 0x0d, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
144 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
145 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
146 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
147 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
148 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
149 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
150 : : 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13,
151 : : 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
152 : : 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
153 : : 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
154 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
155 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
156 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
157 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
158 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
159 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
160 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
161 : : 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0d};
162 : :
163 : 0 : static inline uint16_t float_to_half(float param) JL_NOTSAFEPOINT
164 : : {
165 : : uint32_t f;
166 : 0 : memcpy(&f, ¶m, sizeof(float));
167 [ # # ]: 0 : if (isnan(param)) {
168 : 0 : uint32_t t = 0x8000 ^ (0x8000 & ((uint16_t)(f >> 0x10)));
169 : 0 : return t ^ ((uint16_t)(f >> 0xd));
170 : : }
171 : 0 : int i = ((f & ~0x007fffff) >> 23);
172 : 0 : uint8_t sh = shifttable[i];
173 : 0 : f &= 0x007fffff;
174 : : // If `val` is subnormal, the tables are set up to force the
175 : : // result to 0, so the significand has an implicit `1` in the
176 : : // cases we care about.
177 : 0 : f |= 0x007fffff + 0x1;
178 : 0 : uint16_t h = (uint16_t)(basetable[i] + ((f >> sh) & 0x03ff));
179 : : // round
180 : : // NOTE: we maybe should ignore NaNs here, but the payload is
181 : : // getting truncated anyway so "rounding" it might not matter
182 : 0 : int nextbit = (f >> (sh - 1)) & 1;
183 [ # # # # ]: 0 : if (nextbit != 0 && (h & 0x7C00) != 0x7C00) {
184 : : // Round halfway to even or check lower bits
185 [ # # # # ]: 0 : if ((h & 1) == 1 || (f & ((1 << (sh - 1)) - 1)) != 0)
186 : 0 : h += UINT16_C(1);
187 : : }
188 : 0 : return h;
189 : : }
190 : :
191 : 0 : JL_DLLEXPORT float __gnu_h2f_ieee(uint16_t param)
192 : : {
193 : 0 : return half_to_float(param);
194 : : }
195 : :
196 : 0 : JL_DLLEXPORT float __extendhfsf2(uint16_t param)
197 : : {
198 : 0 : return half_to_float(param);
199 : : }
200 : :
201 : 0 : JL_DLLEXPORT uint16_t __gnu_f2h_ieee(float param)
202 : : {
203 : 0 : return float_to_half(param);
204 : : }
205 : :
206 : 0 : JL_DLLEXPORT uint16_t __truncdfhf2(double param)
207 : : {
208 : 0 : float res = (float)param;
209 : : uint32_t resi;
210 : 0 : memcpy(&resi, &res, sizeof(res));
211 [ # # ]: 0 : if ((resi&0x7fffffffu) < 0x38800000u){ // if Float16(res) is subnormal
212 : : // shift so that the mantissa lines up where it would for normal Float16
213 : 0 : uint32_t shift = 113u-((resi & 0x7f800000u)>>23u);
214 [ # # ]: 0 : if (shift<23u) {
215 : 0 : resi |= 0x00800000; // set implicit bit
216 : 0 : resi >>= shift;
217 : : }
218 : : }
219 [ # # ]: 0 : if ((resi & 0x1fffu) == 0x1000u) { // if we are halfway between 2 Float16 values
220 : 0 : memcpy(&resi, &res, sizeof(res));
221 : : // adjust the value by 1 ULP in the direction that will make Float16(res) give the right answer
222 : 0 : resi += (fabs(res) < fabs(param)) - (fabs(param) < fabs(res));
223 : 0 : memcpy(&res, &resi, sizeof(res));
224 : : }
225 : 0 : return float_to_half(res);
226 : : }
227 : :
228 : : #endif
229 : :
230 : : // run time version of bitcast intrinsic
231 : 486531 : JL_DLLEXPORT jl_value_t *jl_bitcast(jl_value_t *ty, jl_value_t *v)
232 : : {
233 [ - + ]: 486531 : JL_TYPECHK(bitcast, datatype, ty);
234 [ + - - + ]: 486531 : if (!jl_is_concrete_type(ty) || !jl_is_primitivetype(ty))
235 : 0 : jl_error("bitcast: target type not a leaf primitive type");
236 [ - + ]: 486531 : if (!jl_is_primitivetype(jl_typeof(v)))
237 : 0 : jl_error("bitcast: value not a primitive type");
238 [ - + ]: 486531 : if (jl_datatype_size(jl_typeof(v)) != jl_datatype_size(ty))
239 : 0 : jl_error("bitcast: argument size does not match size of target type");
240 [ - + ]: 486531 : if (ty == jl_typeof(v))
241 : 0 : return v;
242 [ - + ]: 486531 : if (ty == (jl_value_t*)jl_bool_type)
243 [ # # ]: 0 : return *(uint8_t*)jl_data_ptr(v) & 1 ? jl_true : jl_false;
244 : 486531 : return jl_new_bits(ty, jl_data_ptr(v));
245 : : }
246 : :
247 : : // run time version of pointerref intrinsic (warning: i is not rooted)
248 : 4749 : JL_DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i, jl_value_t *align)
249 : : {
250 [ - + ]: 4749 : JL_TYPECHK(pointerref, pointer, p);
251 [ - + ]: 4749 : JL_TYPECHK(pointerref, long, i)
252 [ - + ]: 4749 : JL_TYPECHK(pointerref, long, align);
253 : 4749 : jl_value_t *ety = jl_tparam0(jl_typeof(p));
254 [ - + ]: 4749 : if (ety == (jl_value_t*)jl_any_type) {
255 : 0 : jl_value_t **pp = (jl_value_t**)(jl_unbox_long(p) + (jl_unbox_long(i)-1)*sizeof(void*));
256 : 0 : return *pp;
257 : : }
258 : : else {
259 [ - + ]: 4749 : if (!is_valid_intrinsic_elptr(ety))
260 : 0 : jl_error("pointerref: invalid pointer");
261 : 4749 : size_t nb = LLT_ALIGN(jl_datatype_size(ety), jl_datatype_align(ety));
262 : 4749 : char *pp = (char*)jl_unbox_long(p) + (jl_unbox_long(i)-1)*nb;
263 : 4749 : return jl_new_bits(ety, pp);
264 : : }
265 : : }
266 : :
267 : : // run time version of pointerset intrinsic (warning: x is not gc-rooted)
268 : 0 : JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t *i, jl_value_t *align)
269 : : {
270 [ # # ]: 0 : JL_TYPECHK(pointerset, pointer, p);
271 [ # # ]: 0 : JL_TYPECHK(pointerset, long, i);
272 [ # # ]: 0 : JL_TYPECHK(pointerset, long, align);
273 : 0 : jl_value_t *ety = jl_tparam0(jl_typeof(p));
274 [ # # ]: 0 : if (ety == (jl_value_t*)jl_any_type) {
275 : 0 : jl_value_t **pp = (jl_value_t**)(jl_unbox_long(p) + (jl_unbox_long(i)-1)*sizeof(void*));
276 : 0 : *pp = x;
277 : : }
278 : : else {
279 [ # # ]: 0 : if (!is_valid_intrinsic_elptr(ety))
280 : 0 : jl_error("pointerset: invalid pointer");
281 [ # # ]: 0 : if (jl_typeof(x) != ety)
282 : 0 : jl_type_error("pointerset", ety, x);
283 : 0 : size_t elsz = jl_datatype_size(ety);
284 : 0 : size_t nb = LLT_ALIGN(elsz, jl_datatype_align(ety));
285 : 0 : char *pp = (char*)jl_unbox_long(p) + (jl_unbox_long(i)-1)*nb;
286 : 0 : memcpy(pp, x, elsz);
287 : : }
288 : 0 : return p;
289 : : }
290 : :
291 : 0 : JL_DLLEXPORT jl_value_t *jl_atomic_pointerref(jl_value_t *p, jl_value_t *order)
292 : : {
293 [ # # ]: 0 : JL_TYPECHK(atomic_pointerref, pointer, p);
294 [ # # ]: 0 : JL_TYPECHK(atomic_pointerref, symbol, order)
295 : 0 : (void)jl_get_atomic_order_checked((jl_sym_t*)order, 1, 0);
296 : 0 : jl_value_t *ety = jl_tparam0(jl_typeof(p));
297 : 0 : char *pp = (char*)jl_unbox_long(p);
298 [ # # ]: 0 : if (ety == (jl_value_t*)jl_any_type) {
299 : 0 : return jl_atomic_load((_Atomic(jl_value_t*)*)pp);
300 : : }
301 : : else {
302 [ # # ]: 0 : if (!is_valid_intrinsic_elptr(ety))
303 : 0 : jl_error("atomic_pointerref: invalid pointer");
304 : 0 : size_t nb = jl_datatype_size(ety);
305 [ # # # # ]: 0 : if ((nb & (nb - 1)) != 0 || nb > MAX_POINTERATOMIC_SIZE)
306 : 0 : jl_error("atomic_pointerref: invalid pointer for atomic operation");
307 : 0 : return jl_atomic_new_bits(ety, pp);
308 : : }
309 : : }
310 : :
311 : 0 : JL_DLLEXPORT jl_value_t *jl_atomic_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t *order)
312 : : {
313 [ # # ]: 0 : JL_TYPECHK(atomic_pointerset, pointer, p);
314 [ # # ]: 0 : JL_TYPECHK(atomic_pointerset, symbol, order);
315 : 0 : (void)jl_get_atomic_order_checked((jl_sym_t*)order, 0, 1);
316 : 0 : jl_value_t *ety = jl_tparam0(jl_typeof(p));
317 : 0 : char *pp = (char*)jl_unbox_long(p);
318 [ # # ]: 0 : if (ety == (jl_value_t*)jl_any_type) {
319 : 0 : jl_atomic_store((_Atomic(jl_value_t*)*)pp, x);
320 : : }
321 : : else {
322 [ # # ]: 0 : if (!is_valid_intrinsic_elptr(ety))
323 : 0 : jl_error("atomic_pointerset: invalid pointer");
324 [ # # ]: 0 : if (jl_typeof(x) != ety)
325 : 0 : jl_type_error("atomic_pointerset", ety, x);
326 : 0 : size_t nb = jl_datatype_size(ety);
327 [ # # # # ]: 0 : if ((nb & (nb - 1)) != 0 || nb > MAX_POINTERATOMIC_SIZE)
328 : 0 : jl_error("atomic_pointerset: invalid pointer for atomic operation");
329 : 0 : jl_atomic_store_bits(pp, x, nb);
330 : : }
331 : 0 : return p;
332 : : }
333 : :
334 : 0 : JL_DLLEXPORT jl_value_t *jl_atomic_pointerswap(jl_value_t *p, jl_value_t *x, jl_value_t *order)
335 : : {
336 [ # # ]: 0 : JL_TYPECHK(atomic_pointerswap, pointer, p);
337 [ # # ]: 0 : JL_TYPECHK(atomic_pointerswap, symbol, order);
338 : 0 : (void)jl_get_atomic_order_checked((jl_sym_t*)order, 1, 1);
339 : 0 : jl_value_t *ety = jl_tparam0(jl_typeof(p));
340 : : jl_value_t *y;
341 : 0 : char *pp = (char*)jl_unbox_long(p);
342 [ # # ]: 0 : if (ety == (jl_value_t*)jl_any_type) {
343 : 0 : y = jl_atomic_exchange((_Atomic(jl_value_t*)*)pp, x);
344 : : }
345 : : else {
346 [ # # ]: 0 : if (!is_valid_intrinsic_elptr(ety))
347 : 0 : jl_error("atomic_pointerswap: invalid pointer");
348 [ # # ]: 0 : if (jl_typeof(x) != ety)
349 : 0 : jl_type_error("atomic_pointerswap", ety, x);
350 : 0 : size_t nb = jl_datatype_size(ety);
351 [ # # # # ]: 0 : if ((nb & (nb - 1)) != 0 || nb > MAX_POINTERATOMIC_SIZE)
352 : 0 : jl_error("atomic_pointerswap: invalid pointer for atomic operation");
353 : 0 : y = jl_atomic_swap_bits(ety, pp, x, nb);
354 : : }
355 : 0 : return y;
356 : : }
357 : :
358 : 0 : JL_DLLEXPORT jl_value_t *jl_atomic_pointermodify(jl_value_t *p, jl_value_t *f, jl_value_t *x, jl_value_t *order)
359 : : {
360 [ # # ]: 0 : JL_TYPECHK(atomic_pointermodify, pointer, p);
361 [ # # ]: 0 : JL_TYPECHK(atomic_pointermodify, symbol, order)
362 : 0 : (void)jl_get_atomic_order_checked((jl_sym_t*)order, 1, 1);
363 : 0 : jl_value_t *ety = jl_tparam0(jl_typeof(p));
364 : 0 : char *pp = (char*)jl_unbox_long(p);
365 : : jl_value_t *expected;
366 [ # # ]: 0 : if (ety == (jl_value_t*)jl_any_type) {
367 : 0 : expected = jl_atomic_load((_Atomic(jl_value_t*)*)pp);
368 : : }
369 : : else {
370 [ # # ]: 0 : if (!is_valid_intrinsic_elptr(ety))
371 : 0 : jl_error("atomic_pointermodify: invalid pointer");
372 : 0 : size_t nb = jl_datatype_size(ety);
373 [ # # # # ]: 0 : if ((nb & (nb - 1)) != 0 || nb > MAX_POINTERATOMIC_SIZE)
374 : 0 : jl_error("atomic_pointermodify: invalid pointer for atomic operation");
375 : 0 : expected = jl_atomic_new_bits(ety, pp);
376 : : }
377 : : jl_value_t **args;
378 : 0 : JL_GC_PUSHARGS(args, 2);
379 : 0 : args[0] = expected;
380 : 0 : while (1) {
381 : 0 : args[1] = x;
382 : 0 : jl_value_t *y = jl_apply_generic(f, args, 2);
383 : 0 : args[1] = y;
384 [ # # ]: 0 : if (ety == (jl_value_t*)jl_any_type) {
385 [ # # ]: 0 : if (jl_atomic_cmpswap((_Atomic(jl_value_t*)*)pp, &expected, y))
386 : 0 : break;
387 : : }
388 : : else {
389 : : //if (!is_valid_intrinsic_elptr(ety)) // handled by jl_atomic_pointerref earlier
390 : : // jl_error("atomic_pointermodify: invalid pointer");
391 [ # # ]: 0 : if (jl_typeof(y) != ety)
392 : 0 : jl_type_error("atomic_pointermodify", ety, y);
393 : 0 : size_t nb = jl_datatype_size(ety);
394 [ # # ]: 0 : if (jl_atomic_bool_cmpswap_bits(pp, expected, y, nb))
395 : 0 : break;
396 : 0 : expected = jl_atomic_new_bits(ety, pp);
397 : : }
398 : 0 : args[0] = expected;
399 : 0 : jl_gc_safepoint();
400 : : }
401 : : // args[0] == expected (old)
402 : : // args[1] == y (new)
403 : 0 : jl_datatype_t *rettyp = jl_apply_modify_type(ety);
404 : : JL_GC_PROMISE_ROOTED(rettyp); // (JL_ALWAYS_LEAFTYPE)
405 : 0 : args[0] = jl_new_struct(rettyp, args[0], args[1]);
406 : 0 : JL_GC_POP();
407 : 0 : return args[0];
408 : : }
409 : :
410 : :
411 : 0 : JL_DLLEXPORT jl_value_t *jl_atomic_pointerreplace(jl_value_t *p, jl_value_t *expected, jl_value_t *x, jl_value_t *success_order_sym, jl_value_t *failure_order_sym)
412 : : {
413 [ # # ]: 0 : JL_TYPECHK(atomic_pointerreplace, pointer, p);
414 [ # # ]: 0 : JL_TYPECHK(atomic_pointerreplace, symbol, success_order_sym);
415 [ # # ]: 0 : JL_TYPECHK(atomic_pointerreplace, symbol, failure_order_sym);
416 : 0 : enum jl_memory_order success_order = jl_get_atomic_order_checked((jl_sym_t*)success_order_sym, 1, 1);
417 : 0 : enum jl_memory_order failure_order = jl_get_atomic_order_checked((jl_sym_t*)failure_order_sym, 1, 0);
418 [ # # ]: 0 : if (failure_order > success_order)
419 : 0 : jl_atomic_error("atomic_pointerreplace: invalid atomic ordering");
420 : : // TODO: filter other invalid orderings
421 : 0 : jl_value_t *ety = jl_tparam0(jl_typeof(p));
422 : 0 : char *pp = (char*)jl_unbox_long(p);
423 : 0 : jl_datatype_t *rettyp = jl_apply_cmpswap_type(ety);
424 : : JL_GC_PROMISE_ROOTED(rettyp); // (JL_ALWAYS_LEAFTYPE)
425 [ # # ]: 0 : if (ety == (jl_value_t*)jl_any_type) {
426 : : jl_value_t *result;
427 : 0 : JL_GC_PUSH1(&result);
428 : 0 : result = expected;
429 : : int success;
430 : : while (1) {
431 : 0 : success = jl_atomic_cmpswap((_Atomic(jl_value_t*)*)pp, &result, x);
432 [ # # # # ]: 0 : if (success || !jl_egal(result, expected))
433 : : break;
434 : : }
435 [ # # ]: 0 : result = jl_new_struct(rettyp, result, success ? jl_true : jl_false);
436 : 0 : JL_GC_POP();
437 : 0 : return result;
438 : : }
439 : : else {
440 [ # # ]: 0 : if (!is_valid_intrinsic_elptr(ety))
441 : 0 : jl_error("atomic_pointerreplace: invalid pointer");
442 [ # # ]: 0 : if (jl_typeof(x) != ety)
443 : 0 : jl_type_error("atomic_pointerreplace", ety, x);
444 : 0 : size_t nb = jl_datatype_size(ety);
445 [ # # # # ]: 0 : if ((nb & (nb - 1)) != 0 || nb > MAX_POINTERATOMIC_SIZE)
446 : 0 : jl_error("atomic_pointerreplace: invalid pointer for atomic operation");
447 : 0 : return jl_atomic_cmpswap_bits((jl_datatype_t*)ety, rettyp, pp, expected, x, nb);
448 : : }
449 : : }
450 : :
451 : 10 : JL_DLLEXPORT jl_value_t *jl_atomic_fence(jl_value_t *order_sym)
452 : : {
453 [ - + ]: 10 : JL_TYPECHK(fence, symbol, order_sym);
454 : 10 : enum jl_memory_order order = jl_get_atomic_order_checked((jl_sym_t*)order_sym, 1, 1);
455 [ + - ]: 10 : if (order > jl_memory_order_monotonic)
456 : 10 : jl_fence();
457 : 10 : return jl_nothing;
458 : : }
459 : :
460 : 0 : JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty)
461 : : {
462 [ # # ]: 0 : JL_TYPECHK(cglobal, type, ty);
463 : 0 : JL_GC_PUSH1(&v);
464 : 0 : jl_value_t *rt =
465 [ # # ]: 0 : ty == (jl_value_t*)jl_nothing_type ? (jl_value_t*)jl_voidpointer_type : // a common case
466 : 0 : (jl_value_t*)jl_apply_type1((jl_value_t*)jl_pointer_type, ty);
467 : : JL_GC_PROMISE_ROOTED(rt); // (JL_ALWAYS_LEAFTYPE)
468 : :
469 [ # # ]: 0 : if (!jl_is_concrete_type(rt))
470 : 0 : jl_error("cglobal: type argument not concrete");
471 : :
472 [ # # # # ]: 0 : if (jl_is_tuple(v) && jl_nfields(v) == 1)
473 : 0 : v = jl_fieldref(v, 0);
474 : :
475 [ # # ]: 0 : if (jl_is_pointer(v)) {
476 : 0 : v = jl_bitcast(rt, v);
477 : 0 : JL_GC_POP();
478 : 0 : return v;
479 : : }
480 : :
481 : 0 : char *f_lib = NULL;
482 [ # # # # ]: 0 : if (jl_is_tuple(v) && jl_nfields(v) > 1) {
483 : 0 : jl_value_t *t1 = jl_fieldref_noalloc(v, 1);
484 : 0 : v = jl_fieldref(v, 0);
485 [ # # ]: 0 : if (jl_is_symbol(t1))
486 : 0 : f_lib = jl_symbol_name((jl_sym_t*)t1);
487 [ # # ]: 0 : else if (jl_is_string(t1))
488 : 0 : f_lib = jl_string_data(t1);
489 : : else
490 [ # # ]: 0 : JL_TYPECHK(cglobal, symbol, t1)
491 : : }
492 : :
493 : 0 : char *f_name = NULL;
494 [ # # ]: 0 : if (jl_is_symbol(v))
495 : 0 : f_name = jl_symbol_name((jl_sym_t*)v);
496 [ # # ]: 0 : else if (jl_is_string(v))
497 : 0 : f_name = jl_string_data(v);
498 : : else
499 [ # # ]: 0 : JL_TYPECHK(cglobal, symbol, v)
500 : :
501 : : #ifdef _OS_WINDOWS_
502 : : if (!f_lib)
503 : : f_lib = (char*)jl_dlfind_win32(f_name);
504 : : #endif
505 : :
506 : : void *ptr;
507 : 0 : jl_dlsym(jl_get_library(f_lib), f_name, &ptr, 1);
508 : 0 : jl_value_t *jv = jl_gc_alloc_1w();
509 : 0 : jl_set_typeof(jv, rt);
510 : 0 : *(void**)jl_data_ptr(jv) = ptr;
511 : 0 : JL_GC_POP();
512 : 0 : return jv;
513 : : }
514 : :
515 : 0 : JL_DLLEXPORT jl_value_t *jl_cglobal_auto(jl_value_t *v) {
516 : 0 : return jl_cglobal(v, (jl_value_t*)jl_nothing_type);
517 : : }
518 : :
519 : 0 : static inline char signbitbyte(void *a, unsigned bytes) JL_NOTSAFEPOINT
520 : : {
521 : : // sign bit of an signed number of n bytes, as a byte
522 [ # # ]: 0 : return (((signed char*)a)[bytes - 1] < 0) ? ~0 : 0;
523 : : }
524 : :
525 : 0 : static inline char usignbitbyte(void *a, unsigned bytes) JL_NOTSAFEPOINT
526 : : {
527 : : // sign bit of an unsigned number
528 : 0 : return 0;
529 : : }
530 : :
531 : 29352400 : static inline unsigned select_by_size(unsigned sz) JL_NOTSAFEPOINT
532 : : {
533 : : /* choose the right sized function specialization */
534 [ - + + + : 29352400 : switch (sz) {
+ + ]
535 : 0 : default: return 0;
536 : 1030420 : case 1: return 1;
537 : 506 : case 2: return 2;
538 : 741036 : case 4: return 3;
539 : 27580400 : case 8: return 4;
540 : 21 : case 16: return 5;
541 : : }
542 : : }
543 : :
544 : : #define SELECTOR_FUNC(intrinsic) \
545 : : typedef intrinsic##_t select_##intrinsic##_t[6]; \
546 : : static inline intrinsic##_t select_##intrinsic(unsigned sz, const select_##intrinsic##_t list) JL_NOTSAFEPOINT \
547 : : { \
548 : : intrinsic##_t thunk = list[select_by_size(sz)]; \
549 : : if (!thunk) thunk = list[0]; \
550 : : return thunk; \
551 : : }
552 : :
553 : : #define fp_select(a, func) \
554 : : sizeof(a) == sizeof(float) ? func##f((float)a) : func(a)
555 : : #define fp_select2(a, b, func) \
556 : : sizeof(a) == sizeof(float) ? func##f(a, b) : func(a, b)
557 : :
558 : : // fast-function generators //
559 : :
560 : : // integer input
561 : : // OP::Function macro(input)
562 : : // name::unique string
563 : : // nbits::number of bits
564 : : // c_type::c_type corresponding to nbits
565 : : #define un_iintrinsic_ctype(OP, name, nbits, c_type) \
566 : : static inline void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pr) JL_NOTSAFEPOINT \
567 : : { \
568 : : c_type a = *(c_type*)pa; \
569 : : *(c_type*)pr = OP(a); \
570 : : }
571 : :
572 : : // integer input, unsigned output
573 : : // OP::Function macro(input)
574 : : // name::unique string
575 : : // nbits::number of bits
576 : : // c_type::c_type corresponding to nbits
577 : : #define uu_iintrinsic_ctype(OP, name, nbits, c_type) \
578 : : static inline unsigned jl_##name##nbits(unsigned runtime_nbits, void *pa) JL_NOTSAFEPOINT \
579 : : { \
580 : : c_type a = *(c_type*)pa; \
581 : : return OP(a); \
582 : : }
583 : :
584 : : // floating point
585 : : // OP::Function macro(output pointer, input)
586 : : // name::unique string
587 : : // nbits::number of bits in the *input*
588 : : // c_type::c_type corresponding to nbits
589 : : #define un_fintrinsic_ctype(OP, name, c_type) \
590 : : static inline void name(unsigned osize, void *pa, void *pr) JL_NOTSAFEPOINT \
591 : : { \
592 : : c_type a = *(c_type*)pa; \
593 : : OP((c_type*)pr, a); \
594 : : }
595 : :
596 : : #define un_fintrinsic_half(OP, name) \
597 : : static inline void name(unsigned osize, void *pa, void *pr) JL_NOTSAFEPOINT \
598 : : { \
599 : : uint16_t a = *(uint16_t*)pa; \
600 : : float A = __gnu_h2f_ieee(a); \
601 : : if (osize == 16) { \
602 : : float R; \
603 : : OP(&R, A); \
604 : : *(uint16_t*)pr = __gnu_f2h_ieee(R); \
605 : : } else { \
606 : : OP((uint16_t*)pr, A); \
607 : : } \
608 : : }
609 : :
610 : : // float or integer inputs
611 : : // OP::Function macro(inputa, inputb)
612 : : // name::unique string
613 : : // nbits::number of bits
614 : : // c_type::c_type corresponding to nbits
615 : : #define bi_intrinsic_ctype(OP, name, nbits, c_type) \
616 : : static void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *pr) JL_NOTSAFEPOINT \
617 : : { \
618 : : c_type a = *(c_type*)pa; \
619 : : c_type b = *(c_type*)pb; \
620 : : *(c_type*)pr = (c_type)OP(a, b); \
621 : : }
622 : :
623 : : #define bi_intrinsic_half(OP, name) \
624 : : static void jl_##name##16(unsigned runtime_nbits, void *pa, void *pb, void *pr) JL_NOTSAFEPOINT \
625 : : { \
626 : : uint16_t a = *(uint16_t*)pa; \
627 : : uint16_t b = *(uint16_t*)pb; \
628 : : float A = __gnu_h2f_ieee(a); \
629 : : float B = __gnu_h2f_ieee(b); \
630 : : runtime_nbits = 16; \
631 : : float R = OP(A, B); \
632 : : *(uint16_t*)pr = __gnu_f2h_ieee(R); \
633 : : }
634 : :
635 : : // float or integer inputs, bool output
636 : : // OP::Function macro(inputa, inputb)
637 : : // name::unique string
638 : : // nbits::number of bits
639 : : // c_type::c_type corresponding to nbits
640 : : #define bool_intrinsic_ctype(OP, name, nbits, c_type) \
641 : : static int jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb) JL_NOTSAFEPOINT \
642 : : { \
643 : : c_type a = *(c_type*)pa; \
644 : : c_type b = *(c_type*)pb; \
645 : : return OP(a, b); \
646 : : }
647 : :
648 : : #define bool_intrinsic_half(OP, name) \
649 : : static int jl_##name##16(unsigned runtime_nbits, void *pa, void *pb) JL_NOTSAFEPOINT \
650 : : { \
651 : : uint16_t a = *(uint16_t*)pa; \
652 : : uint16_t b = *(uint16_t*)pb; \
653 : : float A = __gnu_h2f_ieee(a); \
654 : : float B = __gnu_h2f_ieee(b); \
655 : : runtime_nbits = 16; \
656 : : return OP(A, B); \
657 : : }
658 : :
659 : :
660 : : // integer inputs, with precondition test
661 : : // OP::Function macro(inputa, inputb)
662 : : // name::unique string
663 : : // nbits::number of bits
664 : : // c_type::c_type corresponding to nbits
665 : : #define checked_intrinsic_ctype(CHECK_OP, OP, name, nbits, c_type) \
666 : : static int jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *pr) JL_NOTSAFEPOINT \
667 : : { \
668 : : c_type a = *(c_type*)pa; \
669 : : c_type b = *(c_type*)pb; \
670 : : *(c_type*)pr = (c_type)OP(a, b); \
671 : : return CHECK_OP(c_type, a, b); \
672 : : }
673 : :
674 : : // float inputs
675 : : // OP::Function macro(inputa, inputb, inputc)
676 : : // name::unique string
677 : : // nbits::number of bits
678 : : // c_type::c_type corresponding to nbits
679 : : #define ter_intrinsic_ctype(OP, name, nbits, c_type) \
680 : : static void jl_##name##nbits(unsigned runtime_nbits, void *pa, void *pb, void *pc, void *pr) JL_NOTSAFEPOINT \
681 : : { \
682 : : c_type a = *(c_type*)pa; \
683 : : c_type b = *(c_type*)pb; \
684 : : c_type c = *(c_type*)pc; \
685 : : *(c_type*)pr = (c_type)OP(a, b, c); \
686 : : }
687 : :
688 : : #define ter_intrinsic_half(OP, name) \
689 : : static void jl_##name##16(unsigned runtime_nbits, void *pa, void *pb, void *pc, void *pr) JL_NOTSAFEPOINT \
690 : : { \
691 : : uint16_t a = *(uint16_t*)pa; \
692 : : uint16_t b = *(uint16_t*)pb; \
693 : : uint16_t c = *(uint16_t*)pc; \
694 : : float A = __gnu_h2f_ieee(a); \
695 : : float B = __gnu_h2f_ieee(b); \
696 : : float C = __gnu_h2f_ieee(c); \
697 : : runtime_nbits = 16; \
698 : : float R = OP(A, B, C); \
699 : : *(uint16_t*)pr = __gnu_f2h_ieee(R); \
700 : : }
701 : :
702 : :
703 : : // unary operator generator //
704 : :
705 : : typedef void (*intrinsic_1_t)(unsigned, void*, void*);
706 [ - + ]: 116766 : SELECTOR_FUNC(intrinsic_1)
707 : : #define un_iintrinsic(name, u) \
708 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a) \
709 : : { \
710 : : return jl_iintrinsic_1(jl_typeof(a), a, #name, u##signbitbyte, jl_intrinsiclambda_ty1, name##_list); \
711 : : }
712 : : #define un_iintrinsic_fast(LLVMOP, OP, name, u) \
713 : : un_iintrinsic_ctype(OP, name, 8, u##int##8_t) \
714 : : un_iintrinsic_ctype(OP, name, 16, u##int##16_t) \
715 : : un_iintrinsic_ctype(OP, name, 32, u##int##32_t) \
716 : : un_iintrinsic_ctype(OP, name, 64, u##int##64_t) \
717 : : static const select_intrinsic_1_t name##_list = { \
718 : : LLVMOP, \
719 : : jl_##name##8, \
720 : : jl_##name##16, \
721 : : jl_##name##32, \
722 : : jl_##name##64, \
723 : : }; \
724 : : un_iintrinsic(name, u)
725 : : #define un_iintrinsic_slow(LLVMOP, name, u) \
726 : : static const select_intrinsic_1_t name##_list = { \
727 : : LLVMOP \
728 : : }; \
729 : : un_iintrinsic(name, u)
730 : :
731 : : typedef unsigned (*intrinsic_u1_t)(unsigned, void*);
732 [ + - ]: 11330 : SELECTOR_FUNC(intrinsic_u1)
733 : : #define uu_iintrinsic(name, u) \
734 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a) \
735 : : { \
736 : : return jl_iintrinsic_1(jl_typeof(a), a, #name, u##signbitbyte, jl_intrinsiclambda_u1, name##_list); \
737 : : }
738 : : #define uu_iintrinsic_fast(LLVMOP, OP, name, u) \
739 : : uu_iintrinsic_ctype(OP, name, 8, u##int##8_t) \
740 : : uu_iintrinsic_ctype(OP, name, 16, u##int##16_t) \
741 : : uu_iintrinsic_ctype(OP, name, 32, u##int##32_t) \
742 : : uu_iintrinsic_ctype(OP, name, 64, u##int##64_t) \
743 : : static const select_intrinsic_u1_t name##_list = { \
744 : : LLVMOP, \
745 : : jl_##name##8, \
746 : : jl_##name##16, \
747 : : jl_##name##32, \
748 : : jl_##name##64, \
749 : : }; \
750 : : uu_iintrinsic(name, u)
751 : : #define uu_iintrinsic_slow(LLVMOP, name, u) \
752 : : static const select_intrinsic_u1_t name##_list = { \
753 : : LLVMOP \
754 : : }; \
755 : : uu_iintrinsic(name, u)
756 : :
757 : : static inline
758 : 128096 : jl_value_t *jl_iintrinsic_1(jl_value_t *ty, jl_value_t *a, const char *name,
759 : : char (*getsign)(void*, unsigned),
760 : : jl_value_t *(*lambda1)(jl_value_t*, void*, unsigned, unsigned, const void*), const void *list)
761 : : {
762 [ - + ]: 128096 : if (!jl_is_primitivetype(jl_typeof(a)))
763 : 0 : jl_errorf("%s: value is not a primitive type", name);
764 [ - + ]: 128096 : if (!jl_is_primitivetype(ty))
765 : 0 : jl_errorf("%s: type is not a primitive type", name);
766 : 128096 : void *pa = jl_data_ptr(a);
767 : 128096 : unsigned isize = jl_datatype_size(jl_typeof(a));
768 : 128096 : unsigned isize2 = next_power_of_two(isize);
769 : 128096 : unsigned osize = jl_datatype_size(ty);
770 : 128096 : unsigned osize2 = next_power_of_two(osize);
771 [ - + ]: 128096 : if (isize2 > osize2)
772 : 0 : osize2 = isize2;
773 [ + - - + ]: 128096 : if (osize2 > isize || isize2 > isize) {
774 : : /* if needed, round type up to a real c-type and set/clear the unused bits */
775 : : void *pa2;
776 : 0 : pa2 = alloca(osize2);
777 : : /* TODO: this memcpy assumes little-endian,
778 : : * for big-endian, need to align the copy to the other end */ \
779 : 0 : memcpy(pa2, pa, isize);
780 : 0 : memset((char*)pa2 + isize, getsign(pa, isize), osize2 - isize);
781 : 0 : pa = pa2;
782 : : }
783 : 128096 : jl_value_t *newv = lambda1(ty, pa, osize, osize2, list);
784 [ + + ]: 128096 : if (ty == (jl_value_t*)jl_bool_type)
785 [ + + ]: 6083 : return *(uint8_t*)jl_data_ptr(newv) & 1 ? jl_true : jl_false;
786 : 122013 : return newv;
787 : : }
788 : :
789 : 116766 : static inline jl_value_t *jl_intrinsiclambda_ty1(jl_value_t *ty, void *pa, unsigned osize, unsigned osize2, const void *voidlist)
790 : : {
791 : 116766 : intrinsic_1_t op = select_intrinsic_1(osize2, (const intrinsic_1_t*)voidlist);
792 : 116766 : void *pr = alloca(osize2);
793 : 116766 : op(osize * host_char_bit, pa, pr);
794 : 116766 : return jl_new_bits(ty, pr);
795 : : }
796 : :
797 : 11330 : static inline jl_value_t *jl_intrinsiclambda_u1(jl_value_t *ty, void *pa, unsigned osize, unsigned osize2, const void *voidlist)
798 : : {
799 : 11330 : jl_task_t *ct = jl_current_task;
800 : 11330 : intrinsic_u1_t op = select_intrinsic_u1(osize2, (const intrinsic_u1_t*)voidlist);
801 : 11330 : uint64_t cnt = op(osize * host_char_bit, pa);
802 : : // TODO: the following assume little-endian
803 : : // for big-endian, need to copy from the other end of cnt
804 [ + - ]: 11330 : if (osize <= sizeof(cnt)) {
805 : 11330 : return jl_new_bits(ty, &cnt);
806 : : }
807 : 0 : jl_value_t *newv = jl_gc_alloc(ct->ptls, osize, ty);
808 : : // perform zext, if needed
809 : 0 : memset((char*)jl_data_ptr(newv) + sizeof(cnt), 0, osize - sizeof(cnt));
810 : 0 : memcpy(jl_data_ptr(newv), &cnt, sizeof(cnt));
811 : 0 : return newv;
812 : : }
813 : :
814 : : // conversion operator
815 : :
816 : : typedef void (*intrinsic_cvt_t)(unsigned, void*, unsigned, void*);
817 : : typedef unsigned (*intrinsic_cvt_check_t)(unsigned, unsigned, void*);
818 : : #define cvt_iintrinsic(LLVMOP, name) \
819 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *ty, jl_value_t *a) \
820 : : { \
821 : : return jl_intrinsic_cvt(ty, a, #name, LLVMOP); \
822 : : }
823 : :
824 : 123170 : static inline jl_value_t *jl_intrinsic_cvt(jl_value_t *ty, jl_value_t *a, const char *name, intrinsic_cvt_t op)
825 : : {
826 : 123170 : jl_value_t *aty = jl_typeof(a);
827 [ - + ]: 123170 : if (!jl_is_primitivetype(aty))
828 : 0 : jl_errorf("%s: value is not a primitive type", name);
829 [ - + ]: 123170 : if (!jl_is_primitivetype(ty))
830 : 0 : jl_errorf("%s: type is not a primitive type", name);
831 : 123170 : void *pa = jl_data_ptr(a);
832 : 123170 : unsigned isize = jl_datatype_size(aty);
833 : 123170 : unsigned osize = jl_datatype_size(ty);
834 : 123170 : void *pr = alloca(osize);
835 : 123170 : unsigned isize_bits = isize * host_char_bit;
836 : 123170 : unsigned osize_bits = osize * host_char_bit;
837 : 123170 : op(isize_bits, pa, osize_bits, pr);
838 : 123170 : return jl_new_bits(ty, pr);
839 : : }
840 : :
841 : : // floating point
842 : :
843 : : #define un_fintrinsic_withtype(OP, name) \
844 : : un_fintrinsic_half(OP, jl_##name##16) \
845 : : un_fintrinsic_ctype(OP, jl_##name##32, float) \
846 : : un_fintrinsic_ctype(OP, jl_##name##64, double) \
847 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *ty, jl_value_t *a) \
848 : : { \
849 : : return jl_fintrinsic_1(ty, a, #name, jl_##name##16, jl_##name##32, jl_##name##64); \
850 : : }
851 : :
852 : : #define un_fintrinsic(OP, name) \
853 : : un_fintrinsic_withtype(OP, name##_withtype) \
854 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a) \
855 : : { \
856 : : return jl_##name##_withtype(jl_typeof(a), a); \
857 : : }
858 : :
859 : : typedef void (fintrinsic_op1)(unsigned, void*, void*);
860 : :
861 : 0 : static inline jl_value_t *jl_fintrinsic_1(jl_value_t *ty, jl_value_t *a, const char *name, fintrinsic_op1 *halfop, fintrinsic_op1 *floatop, fintrinsic_op1 *doubleop)
862 : : {
863 : 0 : jl_task_t *ct = jl_current_task;
864 [ # # ]: 0 : if (!jl_is_primitivetype(jl_typeof(a)))
865 : 0 : jl_errorf("%s: value is not a primitive type", name);
866 [ # # ]: 0 : if (!jl_is_primitivetype(ty))
867 : 0 : jl_errorf("%s: type is not a primitive type", name);
868 : 0 : unsigned sz2 = jl_datatype_size(ty);
869 : 0 : jl_value_t *newv = jl_gc_alloc(ct->ptls, sz2, ty);
870 : 0 : void *pa = jl_data_ptr(a), *pr = jl_data_ptr(newv);
871 : 0 : unsigned sz = jl_datatype_size(jl_typeof(a));
872 [ # # # # ]: 0 : switch (sz) {
873 : : /* choose the right size c-type operation based on the input */
874 : 0 : case 2:
875 : 0 : halfop(sz2 * host_char_bit, pa, pr);
876 : 0 : break;
877 : 0 : case 4:
878 : 0 : floatop(sz2 * host_char_bit, pa, pr);
879 : 0 : break;
880 : 0 : case 8:
881 : 0 : doubleop(sz2 * host_char_bit, pa, pr);
882 : 0 : break;
883 : 0 : default:
884 : 0 : jl_errorf("%s: runtime floating point intrinsics are not implemented for bit sizes other than 16, 32 and 64", name);
885 : : }
886 : 0 : return newv;
887 : : }
888 : :
889 : : // binary operator generator //
890 : :
891 : : // integer
892 : :
893 : : typedef void (*intrinsic_2_t)(unsigned, void*, void*, void*);
894 [ + + ]: 23724400 : SELECTOR_FUNC(intrinsic_2)
895 : : #define bi_iintrinsic(name, u, cvtb) \
896 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a, jl_value_t *b) \
897 : : { \
898 : : return jl_iintrinsic_2(a, b, #name, u##signbitbyte, jl_intrinsiclambda_2, name##_list, cvtb); \
899 : : }
900 : : #define bi_iintrinsic_cnvtb_fast(LLVMOP, OP, name, u, cvtb) \
901 : : bi_intrinsic_ctype(OP, name, 8, u##int##8_t) \
902 : : bi_intrinsic_ctype(OP, name, 16, u##int##16_t) \
903 : : bi_intrinsic_ctype(OP, name, 32, u##int##32_t) \
904 : : bi_intrinsic_ctype(OP, name, 64, u##int##64_t) \
905 : : static const select_intrinsic_2_t name##_list = { \
906 : : LLVMOP, \
907 : : jl_##name##8, \
908 : : jl_##name##16, \
909 : : jl_##name##32, \
910 : : jl_##name##64, \
911 : : }; \
912 : : bi_iintrinsic(name, u, cvtb)
913 : : #define bi_iintrinsic_fast(LLVMOP, OP, name, u) \
914 : : bi_iintrinsic_cnvtb_fast(LLVMOP, OP, name, u, 0)
915 : :
916 : : typedef int (*intrinsic_cmp_t)(unsigned, void*, void*);
917 [ - + ]: 5497580 : SELECTOR_FUNC(intrinsic_cmp)
918 : : #define cmp_iintrinsic(name, u) \
919 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a, jl_value_t *b) \
920 : : { \
921 : : return jl_iintrinsic_2(a, b, #name, u##signbitbyte, jl_intrinsiclambda_cmp, name##_list, 0); \
922 : : }
923 : : #define bool_iintrinsic_fast(LLVMOP, OP, name, u) \
924 : : bool_intrinsic_ctype(OP, name, 8, u##int##8_t) \
925 : : bool_intrinsic_ctype(OP, name, 16, u##int##16_t) \
926 : : bool_intrinsic_ctype(OP, name, 32, u##int##32_t) \
927 : : bool_intrinsic_ctype(OP, name, 64, u##int##64_t) \
928 : : static const select_intrinsic_cmp_t name##_list = { \
929 : : LLVMOP, \
930 : : jl_##name##8, \
931 : : jl_##name##16, \
932 : : jl_##name##32, \
933 : : jl_##name##64, \
934 : : }; \
935 : : cmp_iintrinsic(name, u)
936 : :
937 : : typedef int (*intrinsic_checked_t)(unsigned, void*, void*, void*) JL_NOTSAFEPOINT;
938 [ + - ]: 2325 : SELECTOR_FUNC(intrinsic_checked)
939 : : #define checked_iintrinsic(name, u, lambda_checked) \
940 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a, jl_value_t *b) \
941 : : { \
942 : : return jl_iintrinsic_2(a, b, #name, u##signbitbyte, lambda_checked, name##_list, 0); \
943 : : }
944 : : #define checked_iintrinsic_fast(LLVMOP, CHECK_OP, OP, name, u) \
945 : : checked_intrinsic_ctype(CHECK_OP, OP, name, 8, u##int##8_t) \
946 : : checked_intrinsic_ctype(CHECK_OP, OP, name, 16, u##int##16_t) \
947 : : checked_intrinsic_ctype(CHECK_OP, OP, name, 32, u##int##32_t) \
948 : : checked_intrinsic_ctype(CHECK_OP, OP, name, 64, u##int##64_t) \
949 : : static const select_intrinsic_checked_t name##_list = { \
950 : : LLVMOP, \
951 : : jl_##name##8, \
952 : : jl_##name##16, \
953 : : jl_##name##32, \
954 : : jl_##name##64, \
955 : : }; \
956 : : checked_iintrinsic(name, u, jl_intrinsiclambda_checked)
957 : : #define checked_iintrinsic_slow(LLVMOP, name, u) \
958 : : static const select_intrinsic_checked_t name##_list = { \
959 : : LLVMOP \
960 : : }; \
961 : : checked_iintrinsic(name, u, jl_intrinsiclambda_checked)
962 : : #define checked_iintrinsic_div(LLVMOP, name, u) \
963 : : static const select_intrinsic_checked_t name##_list = { \
964 : : LLVMOP \
965 : : }; \
966 : : checked_iintrinsic(name, u, jl_intrinsiclambda_checkeddiv)
967 : :
968 : : static inline
969 : 29224300 : jl_value_t *jl_iintrinsic_2(jl_value_t *a, jl_value_t *b, const char *name,
970 : : char (*getsign)(void*, unsigned),
971 : : jl_value_t *(*lambda2)(jl_value_t*, void*, void*, unsigned, unsigned, const void*),
972 : : const void *list, int cvtb)
973 : : {
974 : 29224300 : jl_value_t *ty = jl_typeof(a);
975 : 29224300 : jl_value_t *tyb = jl_typeof(b);
976 [ + + ]: 29224300 : if (tyb != ty) {
977 [ - + ]: 431532 : if (!cvtb)
978 : 0 : jl_errorf("%s: types of a and b must match", name);
979 [ - + ]: 431532 : if (!jl_is_primitivetype(tyb))
980 : 0 : jl_errorf("%s: b is not a primitive type", name);
981 : : }
982 [ - + ]: 29224300 : if (!jl_is_primitivetype(ty))
983 : 0 : jl_errorf("%s: a is not a primitive type", name);
984 : 29224300 : void *pa = jl_data_ptr(a), *pb = jl_data_ptr(b);
985 : 29224300 : unsigned sz = jl_datatype_size(ty);
986 : 29224300 : unsigned sz2 = next_power_of_two(sz);
987 [ + + ]: 29224300 : unsigned szb = cvtb ? jl_datatype_size(tyb) : sz;
988 [ - + ]: 29224300 : if (sz2 > sz) {
989 : : /* round type up to the appropriate c-type and set/clear the unused bits */
990 : 0 : void *pa2 = alloca(sz2);
991 : 0 : memcpy(pa2, pa, sz);
992 : 0 : memset((char*)pa2 + sz, getsign(pa, sz), sz2 - sz);
993 : 0 : pa = pa2;
994 : : }
995 [ + + ]: 29224300 : if (sz2 > szb) {
996 : : /* round type up to the appropriate c-type and set/clear/truncate the unused bits
997 : : * (zero-extend if cvtb is set, since in that case b is unsigned while the sign of a comes from the op)
998 : : */
999 : 38630 : void *pb2 = alloca(sz2);
1000 : 38630 : memcpy(pb2, pb, szb);
1001 [ - + ]: 38630 : memset((char*)pb2 + szb, cvtb ? 0 : getsign(pb, szb), sz2 - szb);
1002 : 38630 : pb = pb2;
1003 : : }
1004 : 29224300 : jl_value_t *newv = lambda2(ty, pa, pb, sz, sz2, list);
1005 : 29224300 : return newv;
1006 : : }
1007 : :
1008 : 23724400 : static inline jl_value_t *jl_intrinsiclambda_2(jl_value_t *ty, void *pa, void *pb, unsigned sz, unsigned sz2, const void *voidlist)
1009 : : {
1010 : 23724400 : void *pr = alloca(sz2);
1011 : 23724400 : intrinsic_2_t op = select_intrinsic_2(sz2, (const intrinsic_2_t*)voidlist);
1012 : 23724400 : op(sz * host_char_bit, pa, pb, pr);
1013 : 23724400 : return jl_new_bits(ty, pr);
1014 : : }
1015 : :
1016 : 5497580 : static inline jl_value_t *jl_intrinsiclambda_cmp(jl_value_t *ty, void *pa, void *pb, unsigned sz, unsigned sz2, const void *voidlist)
1017 : : {
1018 : 5497580 : intrinsic_cmp_t op = select_intrinsic_cmp(sz2, (const intrinsic_cmp_t*)voidlist);
1019 : 5497580 : int cmp = op(sz * host_char_bit, pa, pb);
1020 [ + + ]: 5497580 : return cmp ? jl_true : jl_false;
1021 : : }
1022 : :
1023 : 459 : static inline jl_value_t *jl_intrinsiclambda_checked(jl_value_t *ty, void *pa, void *pb, unsigned sz, unsigned sz2, const void *voidlist)
1024 : : {
1025 : : jl_value_t *params[2];
1026 : 459 : params[0] = ty;
1027 : 459 : params[1] = (jl_value_t*)jl_bool_type;
1028 : 459 : jl_datatype_t *tuptyp = jl_apply_tuple_type_v(params, 2);
1029 : : JL_GC_PROMISE_ROOTED(tuptyp); // (JL_ALWAYS_LEAFTYPE)
1030 : 459 : jl_task_t *ct = jl_current_task;
1031 : 459 : jl_value_t *newv = jl_gc_alloc(ct->ptls, ((jl_datatype_t*)tuptyp)->size, tuptyp);
1032 : :
1033 : 459 : intrinsic_checked_t op = select_intrinsic_checked(sz2, (const intrinsic_checked_t*)voidlist);
1034 : 459 : int ovflw = op(sz * host_char_bit, pa, pb, jl_data_ptr(newv));
1035 : :
1036 : 459 : char *ao = (char*)jl_data_ptr(newv) + sz;
1037 : 459 : *ao = (char)ovflw;
1038 : 459 : return newv;
1039 : : }
1040 : 1866 : static inline jl_value_t *jl_intrinsiclambda_checkeddiv(jl_value_t *ty, void *pa, void *pb, unsigned sz, unsigned sz2, const void *voidlist)
1041 : : {
1042 : 1866 : void *pr = alloca(sz2);
1043 : 1866 : intrinsic_checked_t op = select_intrinsic_checked(sz2, (const intrinsic_checked_t*)voidlist);
1044 : 1866 : int ovflw = op(sz * host_char_bit, pa, pb, pr);
1045 [ - + ]: 1866 : if (ovflw)
1046 : 0 : jl_throw(jl_diverror_exception);
1047 : 1866 : return jl_new_bits(ty, pr);
1048 : : }
1049 : :
1050 : : // floating point
1051 : :
1052 : : #define bi_fintrinsic(OP, name) \
1053 : : bi_intrinsic_half(OP, name) \
1054 : : bi_intrinsic_ctype(OP, name, 32, float) \
1055 : : bi_intrinsic_ctype(OP, name, 64, double) \
1056 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a, jl_value_t *b) \
1057 : : { \
1058 : : jl_task_t *ct = jl_current_task; \
1059 : : jl_value_t *ty = jl_typeof(a); \
1060 : : if (jl_typeof(b) != ty) \
1061 : : jl_error(#name ": types of a and b must match"); \
1062 : : if (!jl_is_primitivetype(ty)) \
1063 : : jl_error(#name ": values are not primitive types"); \
1064 : : int sz = jl_datatype_size(ty); \
1065 : : jl_value_t *newv = jl_gc_alloc(ct->ptls, sz, ty); \
1066 : : void *pa = jl_data_ptr(a), *pb = jl_data_ptr(b), *pr = jl_data_ptr(newv); \
1067 : : switch (sz) { \
1068 : : /* choose the right size c-type operation */ \
1069 : : case 2: \
1070 : : jl_##name##16(16, pa, pb, pr); \
1071 : : break; \
1072 : : case 4: \
1073 : : jl_##name##32(32, pa, pb, pr); \
1074 : : break; \
1075 : : case 8: \
1076 : : jl_##name##64(64, pa, pb, pr); \
1077 : : break; \
1078 : : default: \
1079 : : jl_error(#name ": runtime floating point intrinsics are not implemented for bit sizes other than 16, 32 and 64"); \
1080 : : } \
1081 : : return newv; \
1082 : : }
1083 : :
1084 : : #define bool_fintrinsic(OP, name) \
1085 : : bool_intrinsic_half(OP, name) \
1086 : : bool_intrinsic_ctype(OP, name, 32, float) \
1087 : : bool_intrinsic_ctype(OP, name, 64, double) \
1088 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a, jl_value_t *b) \
1089 : : { \
1090 : : jl_value_t *ty = jl_typeof(a); \
1091 : : if (jl_typeof(b) != ty) \
1092 : : jl_error(#name ": types of a and b must match"); \
1093 : : if (!jl_is_primitivetype(ty)) \
1094 : : jl_error(#name ": values are not primitive types"); \
1095 : : void *pa = jl_data_ptr(a), *pb = jl_data_ptr(b); \
1096 : : int sz = jl_datatype_size(ty); \
1097 : : int cmp; \
1098 : : switch (sz) { \
1099 : : /* choose the right size c-type operation */ \
1100 : : case 2: \
1101 : : cmp = jl_##name##16(16, pa, pb); \
1102 : : break; \
1103 : : case 4: \
1104 : : cmp = jl_##name##32(32, pa, pb); \
1105 : : break; \
1106 : : case 8: \
1107 : : cmp = jl_##name##64(64, pa, pb); \
1108 : : break; \
1109 : : default: \
1110 : : jl_error(#name ": runtime floating point intrinsics are not implemented for bit sizes other than 32 and 64"); \
1111 : : } \
1112 : : return cmp ? jl_true : jl_false; \
1113 : : }
1114 : :
1115 : : #define ter_fintrinsic(OP, name) \
1116 : : ter_intrinsic_half(OP, name) \
1117 : : ter_intrinsic_ctype(OP, name, 32, float) \
1118 : : ter_intrinsic_ctype(OP, name, 64, double) \
1119 : : JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a, jl_value_t *b, jl_value_t *c) \
1120 : : { \
1121 : : jl_task_t *ct = jl_current_task; \
1122 : : jl_value_t *ty = jl_typeof(a); \
1123 : : if (jl_typeof(b) != ty || jl_typeof(c) != ty) \
1124 : : jl_error(#name ": types of a, b, and c must match"); \
1125 : : if (!jl_is_primitivetype(ty)) \
1126 : : jl_error(#name ": values are not primitive types"); \
1127 : : int sz = jl_datatype_size(ty); \
1128 : : jl_value_t *newv = jl_gc_alloc(ct->ptls, sz, ty); \
1129 : : void *pa = jl_data_ptr(a), *pb = jl_data_ptr(b), *pc = jl_data_ptr(c), *pr = jl_data_ptr(newv); \
1130 : : switch (sz) { \
1131 : : /* choose the right size c-type operation */ \
1132 : : case 2: \
1133 : : jl_##name##16(16, pa, pb, pc, pr); \
1134 : : break; \
1135 : : case 4: \
1136 : : jl_##name##32(32, pa, pb, pc, pr); \
1137 : : break; \
1138 : : case 8: \
1139 : : jl_##name##64(64, pa, pb, pc, pr); \
1140 : : break; \
1141 : : default: \
1142 : : jl_error(#name ": runtime floating point intrinsics are not implemented for bit sizes other than 16, 32 and 64"); \
1143 : : } \
1144 : : return newv; \
1145 : : }
1146 : :
1147 : : // arithmetic
1148 : : #define neg(a) -a
1149 : : #define neg_float(pr, a) *pr = -a
1150 : 33856 : un_iintrinsic_fast(LLVMNeg, neg, neg_int, u)
1151 : : #define add(a,b) a + b
1152 : 38813634 : bi_iintrinsic_fast(LLVMAdd, add, add_int, u)
1153 : 107528 : bi_iintrinsic_fast(LLVMAdd, add, add_ptr, u)
1154 : : #define sub(a,b) a - b
1155 : 4608180 : bi_iintrinsic_fast(LLVMSub, sub, sub_int, u)
1156 : 0 : bi_iintrinsic_fast(LLVMSub, sub, sub_ptr, u)
1157 : : #define mul(a,b) a * b
1158 : 420130 : bi_iintrinsic_fast(LLVMMul, mul, mul_int, u)
1159 : : #define div(a,b) a / b
1160 : 0 : bi_iintrinsic_fast(LLVMSDiv, div, sdiv_int, )
1161 : 0 : bi_iintrinsic_fast(LLVMUDiv, div, udiv_int, u)
1162 : : #define rem(a,b) a % b
1163 : 0 : bi_iintrinsic_fast(LLVMSRem, rem, srem_int, )
1164 : 0 : bi_iintrinsic_fast(LLVMURem, rem, urem_int, u)
1165 : : #define smod(a,b) ((a < 0) == (b < 0)) ? a % b : (b + (a % b)) % b
1166 [ # # ]: 0 : bi_iintrinsic_fast(jl_LLVMSMod, smod, smod_int, )
1167 : : #define frem(a, b) \
1168 : : fp_select2(a, b, fmod)
1169 : :
1170 [ # # ]: 0 : un_fintrinsic(neg_float,neg_float)
1171 [ # # # # : 0 : bi_fintrinsic(add,add_float)
# # # # ]
1172 [ - + - + : 2 : bi_fintrinsic(sub,sub_float)
- - + - ]
1173 [ # # # # : 0 : bi_fintrinsic(mul,mul_float)
# # # # ]
1174 [ # # # # : 0 : bi_fintrinsic(div,div_float)
# # # # ]
1175 [ # # # # : 0 : bi_fintrinsic(frem,rem_float)
# # # # ]
1176 : :
1177 : : // ternary operators //
1178 : : // runtime fma is broken on windows, define julia_fma(f) ourself with fma_emulated as reference.
1179 : : #if defined(_OS_WINDOWS_)
1180 : : // reinterpret(UInt64, ::Float64)
1181 : : uint64_t bitcast_d2u(double d) {
1182 : : uint64_t r;
1183 : : memcpy(&r, &d, 8);
1184 : : return r;
1185 : : }
1186 : : // reinterpret(Float64, ::UInt64)
1187 : : double bitcast_u2d(uint64_t d) {
1188 : : double r;
1189 : : memcpy(&r, &d, 8);
1190 : : return r;
1191 : : }
1192 : : // Base.splitbits(::Float64)
1193 : : void splitbits(double *hi, double *lo, double d) {
1194 : : *hi = bitcast_u2d(bitcast_d2u(d) & 0xfffffffff8000000);
1195 : : *lo = d - *hi;
1196 : : }
1197 : : // Base.exponent(::Float64)
1198 : : int exponent(double a) {
1199 : : int e;
1200 : : frexp(a, &e);
1201 : : return e - 1;
1202 : : }
1203 : : // Base.fma_emulated(::Float32, ::Float32, ::Float32)
1204 : : float julia_fmaf(float a, float b, float c) {
1205 : : double ab, res;
1206 : : ab = (double)a * b;
1207 : : res = ab + (double)c;
1208 : : if ((bitcast_d2u(res) & 0x1fffffff) == 0x10000000){
1209 : : double reslo = fabsf(c) > fabs(ab) ? ab-(res - c) : c-(res - ab);
1210 : : if (reslo != 0)
1211 : : res = nextafter(res, copysign(1.0/0.0, reslo));
1212 : : }
1213 : : return (float)res;
1214 : : }
1215 : : // Base.twomul(::Float64, ::Float64)
1216 : : void two_mul(double *abhi, double *ablo, double a, double b) {
1217 : : double ahi, alo, bhi, blo, blohi, blolo;
1218 : : splitbits(&ahi, &alo, a);
1219 : : splitbits(&bhi, &blo, b);
1220 : : splitbits(&blohi, &blolo, blo);
1221 : : *abhi = a*b;
1222 : : *ablo = alo*blohi - (((*abhi - ahi*bhi) - alo*bhi) - ahi*blo) + blolo*alo;
1223 : : }
1224 : : // Base.issubnormal(::Float64) (Win32's fpclassify seems broken)
1225 : : int issubnormal(double d) {
1226 : : uint64_t y = bitcast_d2u(d);
1227 : : return ((y & 0x7ff0000000000000) == 0) & ((y & 0x000fffffffffffff) != 0);
1228 : : }
1229 : : #if defined(_WIN32)
1230 : : // Win32 needs volatile (avoid over optimization?)
1231 : : #define VDOUBLE volatile double
1232 : : #else
1233 : : #define VDOUBLE double
1234 : : #endif
1235 : :
1236 : : // Base.fma_emulated(::Float64, ::Float64, ::Float64)
1237 : : double julia_fma(double a, double b, double c) {
1238 : : double abhi, ablo, r, s;
1239 : : two_mul(&abhi, &ablo, a, b);
1240 : : if (!isfinite(abhi+c) || fabs(abhi) < 2.0041683600089732e-292 ||
1241 : : issubnormal(a) || issubnormal(b)) {
1242 : : int aandbfinite = isfinite(a) && isfinite(b);
1243 : : if (!(aandbfinite && isfinite(c)))
1244 : : return aandbfinite ? c : abhi+c;
1245 : : if (a == 0 || b == 0)
1246 : : return abhi+c;
1247 : : int bias = exponent(a) + exponent(b);
1248 : : VDOUBLE c_denorm = ldexp(c, -bias);
1249 : : if (isfinite(c_denorm)) {
1250 : : if (issubnormal(a))
1251 : : a *= 4.503599627370496e15;
1252 : : if (issubnormal(b))
1253 : : b *= 4.503599627370496e15;
1254 : : a = bitcast_u2d((bitcast_d2u(a) & 0x800fffffffffffff) | 0x3ff0000000000000);
1255 : : b = bitcast_u2d((bitcast_d2u(b) & 0x800fffffffffffff) | 0x3ff0000000000000);
1256 : : c = c_denorm;
1257 : : two_mul(&abhi, &ablo, a, b);
1258 : : r = abhi+c;
1259 : : s = (fabs(abhi) > fabs(c)) ? (abhi-r+c+ablo) : (c-r+abhi+ablo);
1260 : : double sumhi = r+s;
1261 : : if (issubnormal(ldexp(sumhi, bias))) {
1262 : : double sumlo = r-sumhi+s;
1263 : : int bits_lost = -bias-exponent(sumhi)-1022;
1264 : : if ((bits_lost != 1) ^ ((bitcast_d2u(sumhi)&1) == 1))
1265 : : if (sumlo != 0)
1266 : : sumhi = nextafter(sumhi, copysign(1.0/0.0, sumlo));
1267 : : }
1268 : : return ldexp(sumhi, bias);
1269 : : }
1270 : : if (isinf(abhi) && signbit(c) == signbit(a*b))
1271 : : return abhi;
1272 : : }
1273 : : r = abhi+c;
1274 : : s = (fabs(abhi) > fabs(c)) ? (abhi-r+c+ablo) : (c-r+abhi+ablo);
1275 : : return r+s;
1276 : : }
1277 : : #define fma(a, b, c) \
1278 : : sizeof(a) == sizeof(float) ? julia_fmaf(a, b, c) : julia_fma(a, b, c)
1279 : : #else // On other systems use fma(f) directly
1280 : : #define fma(a, b, c) \
1281 : : sizeof(a) == sizeof(float) ? fmaf(a, b, c) : fma(a, b, c)
1282 : : #endif
1283 : :
1284 : : #define muladd(a, b, c) a * b + c
1285 [ # # # # : 0 : ter_fintrinsic(fma,fma_float)
# # # # #
# ]
1286 [ # # # # : 0 : ter_fintrinsic(muladd,muladd_float)
# # # # #
# ]
1287 : :
1288 : : // same-type comparisons
1289 : : #define eq(a,b) a == b
1290 : 139000 : bool_iintrinsic_fast(LLVMICmpEQ, eq, eq_int, u)
1291 : : #define ne(a,b) a != b
1292 : 0 : bool_iintrinsic_fast(LLVMICmpNE, ne, ne_int, u)
1293 : : #define lt(a,b) a < b
1294 : 4962860 : bool_iintrinsic_fast(LLVMICmpSLT, lt, slt_int, )
1295 : 833560 : bool_iintrinsic_fast(LLVMICmpULT, lt, ult_int, u)
1296 : : #define le(a,b) a <= b
1297 : 4655120 : bool_iintrinsic_fast(LLVMICmpSLE, le, sle_int, )
1298 : 404624 : bool_iintrinsic_fast(LLVMICmpULE, le, ule_int, u)
1299 : :
1300 : : typedef union {
1301 : : float f;
1302 : : int32_t d;
1303 : : uint32_t ud;
1304 : : } bits32;
1305 : : typedef union {
1306 : : double f;
1307 : : int64_t d;
1308 : : uint64_t ud;
1309 : : } bits64;
1310 : :
1311 : : #define fpiseq_n(c_type, nbits) \
1312 : : static inline int fpiseq##nbits(c_type a, c_type b) JL_NOTSAFEPOINT { \
1313 : : bits##nbits ua, ub; \
1314 : : ua.f = a; \
1315 : : ub.f = b; \
1316 : : return (isnan(a) && isnan(b)) || ua.d == ub.d; \
1317 : : }
1318 [ # # # # : 0 : fpiseq_n(float, 32)
# # ]
1319 [ # # # # : 0 : fpiseq_n(double, 64)
# # ]
1320 : : #define fpiseq(a,b) \
1321 : : sizeof(a) == sizeof(float) ? fpiseq32(a, b) : fpiseq64(a, b)
1322 : :
1323 [ # # # # : 0 : bool_fintrinsic(eq,eq_float)
# # # # #
# ]
1324 [ # # # # : 0 : bool_fintrinsic(ne,ne_float)
# # # # #
# ]
1325 [ # # # # : 0 : bool_fintrinsic(lt,lt_float)
# # # # #
# ]
1326 [ # # # # : 0 : bool_fintrinsic(le,le_float)
# # # # #
# ]
1327 [ # # # # : 0 : bool_fintrinsic(fpiseq,fpiseq)
# # # # #
# ]
1328 : :
1329 : : // bitwise operators
1330 : : #define and_op(a,b) a & b
1331 : 2191365 : bi_iintrinsic_fast(LLVMAnd, and_op, and_int, u)
1332 : : #define or_op(a,b) a | b
1333 : 276955 : bi_iintrinsic_fast(LLVMOr, or_op, or_int, u)
1334 : : #define xor_op(a,b) a ^ b
1335 : 3732 : bi_iintrinsic_fast(LLVMXor, xor_op, xor_int, u)
1336 : : #define shl_op(a,b) b >= 8 * sizeof(a) ? 0 : a << b
1337 [ + + ]: 475053 : bi_iintrinsic_cnvtb_fast(LLVMShl, shl_op, shl_int, u, 1)
1338 : : #define lshr_op(a,b) (b >= 8 * sizeof(a)) ? 0 : a >> b
1339 [ + + ]: 471430 : bi_iintrinsic_cnvtb_fast(LLVMLShr, lshr_op, lshr_int, u, 1)
1340 : : #define ashr_op(a,b) ((b < 0 || b >= 8 * sizeof(a)) ? a >> (8 * sizeof(a) - 1) : a >> b)
1341 [ + + - + ]: 80761 : bi_iintrinsic_cnvtb_fast(LLVMAShr, ashr_op, ashr_int, , 1)
1342 : : //#define bswap_op(a) __builtin_bswap(a)
1343 : : //un_iintrinsic_fast(LLVMByteSwap, bswap_op, bswap_int, u)
1344 : 0 : un_iintrinsic_slow(LLVMByteSwap, bswap_int, u)
1345 : : //#define ctpop_op(a) __builtin_ctpop(a)
1346 : : //uu_iintrinsic_fast(LLVMCountPopulation, ctpop_op, ctpop_int, u)
1347 : 2057 : uu_iintrinsic_slow(LLVMCountPopulation, ctpop_int, u)
1348 : : //#define ctlz_op(a) __builtin_ctlz(a)
1349 : : //uu_iintrinsic_fast(LLVMCountLeadingZeros, ctlz_op, ctlz_int, u)
1350 : 80 : uu_iintrinsic_slow(LLVMCountLeadingZeros, ctlz_int, u)
1351 : : //#define cttz_op(a) __builtin_cttz(a)
1352 : : //uu_iintrinsic_fast(LLVMCountTrailingZeros, cttz_op, cttz_int, u)
1353 : 9193 : uu_iintrinsic_slow(LLVMCountTrailingZeros, cttz_int, u)
1354 : : #define not_op(a) ~a
1355 : 199676 : un_iintrinsic_fast(LLVMFlipAllBits, not_op, not_int, u)
1356 : :
1357 : : // conversions
1358 : 69517 : cvt_iintrinsic(LLVMTrunc, trunc_int)
1359 : 4782 : cvt_iintrinsic(LLVMSExt, sext_int)
1360 : 48871 : cvt_iintrinsic(LLVMZExt, zext_int)
1361 : 0 : cvt_iintrinsic(LLVMSItoFP, sitofp)
1362 : 0 : cvt_iintrinsic(LLVMUItoFP, uitofp)
1363 : 0 : cvt_iintrinsic(LLVMFPtoSI, fptosi)
1364 : 0 : cvt_iintrinsic(LLVMFPtoUI, fptoui)
1365 : :
1366 : : #define fptrunc(pr, a) \
1367 : : if (!(osize < 8 * sizeof(a))) \
1368 : : jl_error("fptrunc: output bitsize must be < input bitsize"); \
1369 : : else if (osize == 16) \
1370 : : *(uint16_t*)pr = __gnu_f2h_ieee(a); \
1371 : : else if (osize == 32) \
1372 : : *(float*)pr = a; \
1373 : : else if (osize == 64) \
1374 : : *(double*)pr = a; \
1375 : : else \
1376 : : jl_error("fptrunc: runtime floating point intrinsics are not implemented for bit sizes other than 16, 32 and 64");
1377 : : #define fpext(pr, a) \
1378 : : if (!(osize >= 8 * sizeof(a))) \
1379 : : jl_error("fpext: output bitsize must be >= input bitsize"); \
1380 : : if (osize == 32) \
1381 : : *(float*)pr = a; \
1382 : : else if (osize == 64) \
1383 : : *(double*)pr = a; \
1384 : : else \
1385 : : jl_error("fpext: runtime floating point intrinsics are not implemented for bit sizes other than 32 and 64");
1386 [ # # # # : 0 : un_fintrinsic_withtype(fptrunc,fptrunc)
# # # # #
# # # # #
# # # # ]
1387 [ # # # # : 0 : un_fintrinsic_withtype(fpext,fpext)
# # # # #
# # # #
# ]
1388 : :
1389 : : // checked arithmetic
1390 : : /**
1391 : : * s_typemin = - s_typemax - 1
1392 : : * s_typemax = ((t)1 << (runtime_nbits - 1)) - 1
1393 : : * u_typemin = 0
1394 : : * u_typemax = ((t)1 << runtime_nbits) - 1
1395 : : **/
1396 : : #define sTYPEMIN(t) -sTYPEMAX(t) - 1
1397 : : #define sTYPEMAX(t) \
1398 : : ((t)(8 * sizeof(a) == runtime_nbits \
1399 : : ? ((((((t)1) << (8 * sizeof(t) - 2)) - 1) << 1) + 1) \
1400 : : : ( (((t)1) << (runtime_nbits - 1)) - 1)))
1401 : :
1402 : : #define uTYPEMIN(t) ((t)0)
1403 : : #define uTYPEMAX(t) \
1404 : : ((t)(8 * sizeof(t) == runtime_nbits \
1405 : : ? (~((t)0)) : (~(((t)~((t)0)) << runtime_nbits))))
1406 : : #define check_sadd_int(t, a, b) \
1407 : : /* this test checks for (b >= 0) ? (a + b > typemax) : (a + b < typemin) ==> overflow */ \
1408 : : (b >= 0) ? (a > sTYPEMAX(t) - b) : (a < sTYPEMIN(t) - b)
1409 [ # # # # : 0 : checked_iintrinsic_fast(LLVMAdd_sov, check_sadd_int, add, checked_sadd_int, )
# # ]
1410 : : #define check_uadd_int(t, a, b) \
1411 : : /* this test checks for (a + b) > typemax(a) ==> overflow */ \
1412 : : a > uTYPEMAX(t) - b
1413 [ # # ]: 0 : checked_iintrinsic_fast(LLVMAdd_uov, check_uadd_int, add, checked_uadd_int, u)
1414 : : #define check_ssub_int(t, a, b) \
1415 : : /* this test checks for (b >= 0) ? (a - b < typemin) : (a - b > typemax) ==> overflow */ \
1416 : : (b >= 0) ? (a < sTYPEMIN(t) + b) : (a > sTYPEMAX(t) + b)
1417 [ # # # # : 0 : checked_iintrinsic_fast(LLVMSub_sov, check_ssub_int, sub, checked_ssub_int, )
# # ]
1418 : : #define check_usub_int(t, a, b) \
1419 : : /* this test checks for (a - b) < typemin ==> overflow */ \
1420 : : a < uTYPEMIN(t) + b
1421 : 0 : checked_iintrinsic_fast(LLVMSub_uov, check_usub_int, sub, checked_usub_int, u)
1422 : 459 : checked_iintrinsic_slow(LLVMMul_sov, checked_smul_int, )
1423 : 0 : checked_iintrinsic_slow(LLVMMul_uov, checked_umul_int, u)
1424 : :
1425 : 64 : checked_iintrinsic_div(LLVMDiv_sov, checked_sdiv_int, )
1426 : 0 : checked_iintrinsic_div(LLVMDiv_uov, checked_udiv_int, u)
1427 : 1802 : checked_iintrinsic_div(LLVMRem_sov, checked_srem_int, )
1428 : 0 : checked_iintrinsic_div(LLVMRem_uov, checked_urem_int, u)
1429 : :
1430 : : // functions
1431 : : #define flipsign(a, b) \
1432 : : (b >= 0) ? a : -a
1433 [ # # ]: 0 : bi_iintrinsic_fast(jl_LLVMFlipSign, flipsign, flipsign_int, )
1434 : : #define abs_float(pr, a) *pr = fp_select(a, fabs)
1435 : : #define ceil_float(pr, a) *pr = fp_select(a, ceil)
1436 : : #define floor_float(pr, a) *pr = fp_select(a, floor)
1437 : : #define trunc_float(pr, a) *pr = fp_select(a, trunc)
1438 : : #define rint_float(pr, a) *pr = fp_select(a, rint)
1439 : : #define sqrt_float(pr, a) *pr = fp_select(a, sqrt)
1440 : : #define copysign_float(a, b) fp_select2(a, b, copysign)
1441 : :
1442 [ # # ]: 0 : un_fintrinsic(abs_float,abs_float)
1443 [ # # # # : 0 : bi_fintrinsic(copysign_float,copysign_float)
# # # # ]
1444 [ # # ]: 0 : un_fintrinsic(ceil_float,ceil_llvm)
1445 [ # # ]: 0 : un_fintrinsic(floor_float,floor_llvm)
1446 [ # # ]: 0 : un_fintrinsic(trunc_float,trunc_llvm)
1447 [ # # ]: 0 : un_fintrinsic(rint_float,rint_llvm)
1448 [ # # ]: 0 : un_fintrinsic(sqrt_float,sqrt_llvm)
1449 [ # # ]: 0 : un_fintrinsic(sqrt_float,sqrt_llvm_fast)
1450 : :
1451 : 0 : JL_DLLEXPORT jl_value_t *jl_arraylen(jl_value_t *a)
1452 : : {
1453 [ # # ]: 0 : JL_TYPECHK(arraylen, array, a);
1454 : 0 : return jl_box_long(jl_array_len((jl_array_t*)a));
1455 : : }
1456 : :
1457 : 0 : JL_DLLEXPORT jl_value_t *jl_have_fma(jl_value_t *typ)
1458 : : {
1459 [ # # ]: 0 : JL_TYPECHK(have_fma, datatype, typ);
1460 : : // TODO: run-time feature check?
1461 : 0 : return jl_false;
1462 : : }
|