Mercurial > projects > ldc
comparison runtime/import/ldc/intrinsics.di @ 1079:4e388d9d0e25
Intrinsics overhaul:
- More error checking for pragma(intrinsic)
- Properly handle templating for real (use actual nr of bits, not .sizeof * 8)
- Template all .i* and .f* intrinsics
- The old names are deprecated aliases now
I also added a preliminary patch to make tango.math.Math use the new versions.
(I think it looks a lot nicer now)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Tue, 10 Mar 2009 04:45:32 +0100 |
parents | 39b7c32cd010 |
children | 34f2fd925de3 |
comparison
equal
deleted
inserted
replaced
1077:bb57632d27ea | 1079:4e388d9d0e25 |
---|---|
17 else | 17 else |
18 { | 18 { |
19 static assert(false, "This module is only valid for LDC"); | 19 static assert(false, "This module is only valid for LDC"); |
20 } | 20 } |
21 | 21 |
22 version(X86) | |
23 version = Reals_80Bit; | |
24 else version(X86_64) | |
25 version = Reals_80Bit; | |
26 | |
27 // | 22 // |
28 // CODE GENERATOR INTRINSICS | 23 // CODE GENERATOR INTRINSICS |
29 // | 24 // |
30 | 25 |
31 | 26 |
104 // The 'llvm.memcpy.*' intrinsics copy a block of memory from the source | 99 // The 'llvm.memcpy.*' intrinsics copy a block of memory from the source |
105 // location to the destination location. | 100 // location to the destination location. |
106 // Note that, unlike the standard libc function, the llvm.memcpy.* intrinsics do | 101 // Note that, unlike the standard libc function, the llvm.memcpy.* intrinsics do |
107 // not return a value, and takes an extra alignment argument. | 102 // not return a value, and takes an extra alignment argument. |
108 | 103 |
109 pragma(intrinsic, "llvm.memcpy.i32") | 104 pragma(intrinsic, "llvm.memcpy.i#") |
110 void llvm_memcpy_i32(void* dst, void* src, uint len, uint alignment); | 105 void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment); |
111 | 106 |
112 pragma(intrinsic, "llvm.memcpy.i64") | 107 deprecated { |
113 void llvm_memcpy_i64(void* dst, void* src, ulong len, uint alignment); | 108 alias llvm_memcpy!(uint) llvm_memcpy_i32; |
109 alias llvm_memcpy!(ulong) llvm_memcpy_i64; | |
110 } | |
114 | 111 |
115 | 112 |
116 // The 'llvm.memmove.*' intrinsics move a block of memory from the source | 113 // The 'llvm.memmove.*' intrinsics move a block of memory from the source |
117 // location to the destination location. It is similar to the 'llvm.memcpy' | 114 // location to the destination location. It is similar to the 'llvm.memcpy' |
118 // intrinsic but allows the two memory locations to overlap. | 115 // intrinsic but allows the two memory locations to overlap. |
119 // Note that, unlike the standard libc function, the llvm.memmove.* intrinsics | 116 // Note that, unlike the standard libc function, the llvm.memmove.* intrinsics |
120 // do not return a value, and takes an extra alignment argument. | 117 // do not return a value, and takes an extra alignment argument. |
121 | 118 |
122 pragma(intrinsic, "llvm.memmove.i32") | 119 pragma(intrinsic, "llvm.memmove.i#") |
123 void llvm_memmove_i32(void* dst, void* src, uint len, uint alignment); | 120 void llvm_memmove(T)(void* dst, void* src, T len, uint alignment); |
124 | 121 |
125 pragma(intrinsic, "llvm.memmove.i64") | 122 deprecated { |
126 void llvm_memmove_i64(void* dst, void* src, ulong len, int alignment); | 123 alias llvm_memmove!(uint) llvm_memmove_i32; |
124 alias llvm_memmove!(ulong) llvm_memmove_i64; | |
125 } | |
127 | 126 |
128 | 127 |
129 // The 'llvm.memset.*' intrinsics fill a block of memory with a particular byte | 128 // The 'llvm.memset.*' intrinsics fill a block of memory with a particular byte |
130 // value. | 129 // value. |
131 // Note that, unlike the standard libc function, the llvm.memset intrinsic does | 130 // Note that, unlike the standard libc function, the llvm.memset intrinsic does |
132 // not return a value, and takes an extra alignment argument. | 131 // not return a value, and takes an extra alignment argument. |
133 | 132 |
134 pragma(intrinsic, "llvm.memset.i32") | 133 pragma(intrinsic, "llvm.memset.i#") |
135 void llvm_memset_i32(void* dst, ubyte val, uint len, uint alignment); | 134 void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment); |
136 | 135 |
137 pragma(intrinsic, "llvm.memset.i64") | 136 deprecated { |
138 void llvm_memset_i64(void* dst, ubyte val, ulong len, uint alignment); | 137 alias llvm_memset!(uint) llvm_memset_i32; |
138 alias llvm_memset!(ulong) llvm_memset_i64; | |
139 } | |
139 | 140 |
140 | 141 |
141 // The 'llvm.sqrt' intrinsics return the sqrt of the specified operand, | 142 // The 'llvm.sqrt' intrinsics return the sqrt of the specified operand, |
142 // returning the same value as the libm 'sqrt' functions would. Unlike sqrt in | 143 // returning the same value as the libm 'sqrt' functions would. Unlike sqrt in |
143 // libm, however, llvm.sqrt has undefined behavior for negative numbers other | 144 // libm, however, llvm.sqrt has undefined behavior for negative numbers other |
144 // than -0.0 (which allows for better optimization, because there is no need to | 145 // than -0.0 (which allows for better optimization, because there is no need to |
145 // worry about errno being set). llvm.sqrt(-0.0) is defined to return -0.0 like | 146 // worry about errno being set). llvm.sqrt(-0.0) is defined to return -0.0 like |
146 // IEEE sqrt. | 147 // IEEE sqrt. |
147 | 148 |
148 pragma(intrinsic, "llvm.sqrt.f32") | 149 pragma(intrinsic, "llvm.sqrt.f#") |
149 float llvm_sqrt_f32(float val); | 150 T llvm_sqrt(T)(T val); |
150 | 151 |
151 pragma(intrinsic, "llvm.sqrt.f64") | 152 deprecated { |
152 double llvm_sqrt_f64(double val); | 153 alias llvm_sqrt!(float) llvm_sqrt_f32; |
153 | 154 alias llvm_sqrt!(double) llvm_sqrt_f64; |
154 version(Reals_80Bit) | 155 alias llvm_sqrt!(real) llvm_sqrt_f80; // may not actually be .f80 |
155 { | |
156 pragma(intrinsic, "llvm.sqrt.f80") | |
157 real llvm_sqrt_f80(real val); | |
158 alias llvm_sqrt_f80 llvm_sqrt_real; | |
159 } | |
160 else | |
161 { | |
162 pragma(intrinsic, "llvm.sqrt.f64") | |
163 real llvm_sqrt_real(real val); | |
164 } | 156 } |
165 | 157 |
166 | 158 |
167 // The 'llvm.sin.*' intrinsics return the sine of the operand. | 159 // The 'llvm.sin.*' intrinsics return the sine of the operand. |
168 | 160 |
169 pragma(intrinsic, "llvm.sin.f32") | 161 pragma(intrinsic, "llvm.sin.f#") |
170 float llvm_sin_f32(float val); | 162 T llvm_sin(T)(T val); |
171 | 163 |
172 pragma(intrinsic, "llvm.sin.f64") | 164 deprecated { |
173 double llvm_sin_f64(double val); | 165 alias llvm_sin!(float) llvm_sin_f32; |
174 | 166 alias llvm_sin!(double) llvm_sin_f64; |
175 version(Reals_80Bit) | 167 alias llvm_sin!(real) llvm_sin_f80; // may not actually be .f80 |
176 { | |
177 pragma(intrinsic, "llvm.sin.f80") | |
178 real llvm_sin_f80(real val); | |
179 alias llvm_sin_f80 llvm_sin_real; | |
180 } | |
181 else | |
182 { | |
183 pragma(intrinsic, "llvm.sin.f64") | |
184 real llvm_sin_real(real val); | |
185 } | 168 } |
186 | 169 |
187 | 170 |
188 // The 'llvm.cos.*' intrinsics return the cosine of the operand. | 171 // The 'llvm.cos.*' intrinsics return the cosine of the operand. |
189 | 172 |
190 pragma(intrinsic, "llvm.cos.f32") | 173 pragma(intrinsic, "llvm.cos.f#") |
191 float llvm_cos_f32(float val); | 174 T llvm_cos(T)(T val); |
192 | 175 |
193 pragma(intrinsic, "llvm.cos.f64") | 176 deprecated { |
194 double llvm_cos_f64(double val); | 177 alias llvm_cos!(float) llvm_cos_f32; |
195 | 178 alias llvm_cos!(double) llvm_cos_f64; |
196 version(Reals_80Bit) | 179 alias llvm_cos!(real) llvm_cos_f80; // may not actually be .f80 |
197 { | |
198 pragma(intrinsic, "llvm.cos.f80") | |
199 real llvm_cos_f80(real val); | |
200 alias llvm_cos_f80 llvm_cos_real; | |
201 } | |
202 else | |
203 { | |
204 pragma(intrinsic, "llvm.cos.f64") | |
205 real llvm_cos_real(real val); | |
206 } | 180 } |
207 | 181 |
208 | 182 |
209 // The 'llvm.powi.*' intrinsics return the first operand raised to the specified | 183 // The 'llvm.powi.*' intrinsics return the first operand raised to the specified |
210 // (positive or negative) power. The order of evaluation of multiplications is | 184 // (positive or negative) power. The order of evaluation of multiplications is |
211 // not defined. When a vector of floating point type is used, the second | 185 // not defined. When a vector of floating point type is used, the second |
212 // argument remains a scalar integer value. | 186 // argument remains a scalar integer value. |
213 | 187 |
214 pragma(intrinsic, "llvm.powi.f32") | 188 pragma(intrinsic, "llvm.powi.f#") |
215 float llvm_powi_f32(float val, int power); | 189 T llvm_powi(T)(T val, int power); |
216 | 190 |
217 pragma(intrinsic, "llvm.powi.f64") | 191 deprecated { |
218 double llvm_powi_f64(double val, int power); | 192 alias llvm_powi!(float) llvm_powi_f32; |
219 | 193 alias llvm_powi!(double) llvm_powi_f64; |
220 version(Reals_80Bit) | 194 alias llvm_powi!(real) llvm_powi_f80; // may not actually be .f80 |
221 { | |
222 pragma(intrinsic, "llvm.powi.f80") | |
223 real llvm_powi_f80(real val, int power); | |
224 alias llvm_powi_f80 llvm_powi_real; | |
225 } | |
226 else | |
227 { | |
228 pragma(intrinsic, "llvm.powi.f64") | |
229 real llvm_powi_real(real val, int power); | |
230 } | 195 } |
231 | 196 |
232 | 197 |
233 // The 'llvm.pow.*' intrinsics return the first operand raised to the specified | 198 // The 'llvm.pow.*' intrinsics return the first operand raised to the specified |
234 // (positive or negative) power. | 199 // (positive or negative) power. |
235 | 200 |
236 pragma(intrinsic, "llvm.pow.f32") | 201 pragma(intrinsic, "llvm.pow.f#") |
237 float llvm_pow_f32(float val, float power); | 202 T llvm_pow(T)(T val, T power); |
238 | 203 |
239 pragma(intrinsic, "llvm.pow.f64") | 204 deprecated { |
240 double llvm_pow_f64(double val, double power); | 205 alias llvm_pow!(float) llvm_pow_f32; |
241 | 206 alias llvm_pow!(double) llvm_pow_f64; |
242 version(Reals_80Bit) | 207 alias llvm_pow!(real) llvm_pow_f80; // may not actually be .f80 |
243 { | |
244 pragma(intrinsic, "llvm.pow.f80") | |
245 real llvm_pow_f80(real val, real power); | |
246 alias llvm_pow_f80 llvm_pow_real; | |
247 } | |
248 else | |
249 { | |
250 pragma(intrinsic, "llvm.pow.f64") | |
251 real llvm_pow_real(real val, real power); | |
252 } | 208 } |
253 | 209 |
254 | 210 |
255 // | 211 // |
256 // BIT MANIPULATION INTRINSICS | 212 // BIT MANIPULATION INTRINSICS |
259 // The 'llvm.bswap' family of intrinsics is used to byte swap integer values | 215 // The 'llvm.bswap' family of intrinsics is used to byte swap integer values |
260 // with an even number of bytes (positive multiple of 16 bits). These are | 216 // with an even number of bytes (positive multiple of 16 bits). These are |
261 // useful for performing operations on data that is not in the target's native | 217 // useful for performing operations on data that is not in the target's native |
262 // byte order. | 218 // byte order. |
263 | 219 |
264 pragma(intrinsic, "llvm.bswap.i16.i16") | 220 pragma(intrinsic, "llvm.bswap.i#.i#") |
265 ushort llvm_bswap_i16(ushort val); | 221 T llvm_bswap(T)(T val); |
266 | 222 |
267 pragma(intrinsic, "llvm.bswap.i32.i32") | 223 deprecated { |
268 uint llvm_bswap_i32(uint val); | 224 alias llvm_bswap!(ushort) llvm_bswap_i16; |
269 | 225 alias llvm_bswap!(uint) llvm_bswap_i32; |
270 pragma(intrinsic, "llvm.bswap.i64.i64") | 226 alias llvm_bswap!(ulong) llvm_bswap_i64; |
271 ulong llvm_bswap_i64(ulong val); | 227 } |
272 | 228 |
273 | 229 |
274 // The 'llvm.ctpop' family of intrinsics counts the number of bits set in a | 230 // The 'llvm.ctpop' family of intrinsics counts the number of bits set in a |
275 // value. | 231 // value. |
276 | 232 |
277 pragma(intrinsic, "llvm.ctpop.i8") | 233 pragma(intrinsic, "llvm.ctpop.i#") |
278 ubyte llvm_ctpop_i8(ubyte src); | 234 T llvm_ctpop(T)(T src); |
279 | 235 |
280 pragma(intrinsic, "llvm.ctpop.i16") | 236 deprecated { |
281 ushort llvm_ctpop_i16(ushort src); | 237 alias llvm_ctpop!(ubyte) llvm_ctpop_i8; |
282 | 238 alias llvm_ctpop!(ushort) llvm_ctpop_i16; |
283 pragma(intrinsic, "llvm.ctpop.i32") | 239 alias llvm_ctpop!(uint) llvm_ctpop_i32; |
284 uint llvm_ctpop_i32(uint src); | 240 alias llvm_ctpop!(ulong) llvm_ctpop_i64; |
285 | 241 } |
286 pragma(intrinsic, "llvm.ctpop.i64") | |
287 ulong llvm_ctpop_i64(ulong src); | |
288 | 242 |
289 | 243 |
290 // The 'llvm.ctlz' family of intrinsic functions counts the number of leading | 244 // The 'llvm.ctlz' family of intrinsic functions counts the number of leading |
291 // zeros in a variable. | 245 // zeros in a variable. |
292 | 246 |
293 pragma(intrinsic, "llvm.ctlz.i8") | 247 pragma(intrinsic, "llvm.ctlz.i#") |
294 ubyte llvm_ctlz_i8(ubyte src); | 248 T llvm_ctlz(T)(T src); |
295 | 249 |
296 pragma(intrinsic, "llvm.ctlz.i16") | 250 deprecated { |
297 ushort llvm_ctlz_i16(ushort src); | 251 alias llvm_ctlz!(ubyte) llvm_ctlz_i8; |
298 | 252 alias llvm_ctlz!(ushort) llvm_ctlz_i16; |
299 pragma(intrinsic, "llvm.ctlz.i32") | 253 alias llvm_ctlz!(uint) llvm_ctlz_i32; |
300 uint llvm_ctlz_i32(uint src); | 254 alias llvm_ctlz!(ulong) llvm_ctlz_i64; |
301 | 255 } |
302 pragma(intrinsic, "llvm.ctlz.i64") | |
303 ulong llvm_ctlz_i64(ulong src); | |
304 | 256 |
305 | 257 |
306 // The 'llvm.cttz' family of intrinsic functions counts the number of trailing | 258 // The 'llvm.cttz' family of intrinsic functions counts the number of trailing |
307 // zeros. | 259 // zeros. |
308 | 260 |
309 pragma(intrinsic, "llvm.cttz.i8") | 261 pragma(intrinsic, "llvm.cttz.i#") |
310 ubyte llvm_cttz_i8(ubyte src); | 262 T llvm_cttz(T)(T src); |
311 | 263 |
312 pragma(intrinsic, "llvm.cttz.i16") | 264 deprecated { |
313 ushort llvm_cttz_i16(ushort src); | 265 alias llvm_cttz!(ubyte) llvm_cttz_i8; |
314 | 266 alias llvm_cttz!(ushort) llvm_cttz_i16; |
315 pragma(intrinsic, "llvm.cttz.i32") | 267 alias llvm_cttz!(uint) llvm_cttz_i32; |
316 uint llvm_cttz_i32(uint src); | 268 alias llvm_cttz!(ulong) llvm_cttz_i64; |
317 | 269 } |
318 pragma(intrinsic, "llvm.cttz.i64") | |
319 ulong llvm_cttz_i64(ulong src); | |
320 | 270 |
321 | 271 |
322 // The 'llvm.part.select' family of intrinsic functions selects a range of bits | 272 // The 'llvm.part.select' family of intrinsic functions selects a range of bits |
323 // from an integer value and returns them in the same bit width as the original | 273 // from an integer value and returns them in the same bit width as the original |
324 // value. | 274 // value. |
325 | 275 |
326 pragma(intrinsic, "llvm.part.select.i8") | 276 pragma(intrinsic, "llvm.part.select.i#") |
327 ubyte llvm_part_select_i(ubyte val, uint loBit, uint hiBit); | 277 T llvm_part_select(T)(T val, uint loBit, uint hiBit); |
328 | 278 |
329 pragma(intrinsic, "llvm.part.select.i16") | 279 deprecated { |
330 ushort llvm_part_select_i(ushort val, uint loBit, uint hiBit); | 280 alias llvm_part_select!(ubyte) llvm_part_select_i; |
331 | 281 alias llvm_part_select!(ushort) llvm_part_select_i; |
332 pragma(intrinsic, "llvm.part.select.i32") | 282 alias llvm_part_select!(uint) llvm_part_select_i; |
333 uint llvm_part_select_i(uint val, uint loBit, uint hiBit); | 283 alias llvm_part_select!(ulong) llvm_part_select_i; |
334 | 284 } |
335 pragma(intrinsic, "llvm.part.select.i64") | |
336 ulong llvm_part_select_i(ulong val, uint loBit, uint hiBit); | |
337 | 285 |
338 | 286 |
339 // The 'llvm.part.set' family of intrinsic functions replaces a range of bits | 287 // The 'llvm.part.set' family of intrinsic functions replaces a range of bits |
340 // in an integer value with another integer value. It returns the integer with | 288 // in an integer value with another integer value. It returns the integer with |
341 // the replaced bits. | 289 // the replaced bits. |