]> git.lizzy.rs Git - rust.git/blob - src/libcompiler_builtins/lib.rs
Fix invalid associated type rendering in rustdoc
[rust.git] / src / libcompiler_builtins / lib.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![feature(compiler_builtins)]
12 #![no_std]
13 #![compiler_builtins]
14 #![unstable(feature = "compiler_builtins_lib",
15             reason = "internal implementation detail of rustc right now",
16             issue = "0")]
17 #![crate_name = "compiler_builtins"]
18 #![crate_type = "rlib"]
19 #![allow(unused_features)]
20 #![feature(staged_api, core_intrinsics, repr_simd,
21            i128_type, core_float, abi_unadjusted, associated_consts)]
22 #![allow(non_camel_case_types, unused_variables, unused_imports)]
23
24 #[cfg(any(target_pointer_width="32", target_pointer_width="16", target_os="windows",
25           target_arch="mips64"))]
26 pub mod reimpls {
27
28     #![allow(unused_comparisons)]
29
30     use core::intrinsics::unchecked_div;
31     use core::intrinsics::unchecked_rem;
32     use core::ptr;
33
34     macro_rules! ashl {
35         ($a:expr, $b:expr, $ty:ty) => {{
36             let (a, b) = ($a, $b);
37             let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
38             let half_bits = bits.wrapping_shr(1);
39             if b & half_bits != 0 {
40                 <$ty>::from_parts(0, a.low().wrapping_shl(
41                                         b.wrapping_sub(half_bits) as u32))
42             } else if b == 0 {
43                 a
44             } else {
45                 <$ty>::from_parts(a.low().wrapping_shl(b as u32),
46                                   a.high().wrapping_shl(b as u32)
47                                   | a.low()
48                                      .wrapping_shr(half_bits.wrapping_sub(b) as u32))
49             }
50         }}
51     }
52
53     #[export_name="__ashlti3"]
54     pub extern "C" fn shl(a: u128, b: u128) -> u128 {
55         ashl!(a, b, u128)
56     }
57
58     macro_rules! ashr {
59         ($a: expr, $b: expr, $ty:ty) => {{
60             let (a, b) = ($a, $b);
61             let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
62             let half_bits = bits.wrapping_shr(1);
63             if b & half_bits != 0 {
64                 <$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32)
65                                   as <$ty as LargeInt>::LowHalf,
66                                   a.high().wrapping_shr(half_bits.wrapping_sub(1) as u32))
67             } else if b == 0 {
68                 a
69             } else {
70                 let high_unsigned = a.high() as <$ty as LargeInt>::LowHalf;
71                 <$ty>::from_parts(high_unsigned.wrapping_shl(half_bits.wrapping_sub(b) as u32)
72                                   | a.low().wrapping_shr(b as u32),
73                                   a.high().wrapping_shr(b as u32))
74             }
75         }}
76     }
77
78     #[export_name="__ashrti3"]
79     pub extern "C" fn shr(a: i128, b: i128) -> i128 {
80         ashr!(a, b, i128)
81     }
82
83     macro_rules! lshr {
84         ($a: expr, $b: expr, $ty:ty) => {{
85             let (a, b) = ($a, $b);
86             let bits = ::core::mem::size_of::<$ty>().wrapping_mul(8) as $ty;
87             let half_bits = bits.wrapping_shr(1);
88             if b & half_bits != 0 {
89                 <$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32), 0)
90             } else if b == 0 {
91                 a
92             } else {
93                 <$ty>::from_parts(a.high().wrapping_shl(half_bits.wrapping_sub(b) as u32)
94                                   | a.low().wrapping_shr(b as u32),
95                                   a.high().wrapping_shr(b as u32))
96             }
97         }}
98     }
99
100
101     #[export_name="__lshrti3"]
102     pub extern "C" fn lshr(a: u128, b: u128) -> u128 {
103         lshr!(a, b, u128)
104     }
105
106     pub extern "C" fn u128_div_mod(n: u128, d: u128, rem: *mut u128) -> u128 {
107         // Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
108         unsafe {
109         // special cases, X is unknown, K != 0
110         if n.high() == 0 {
111             if d.high() == 0 {
112                 // 0 X
113                 // ---
114                 // 0 X
115                 if !rem.is_null() {
116                     *rem = u128::from(unchecked_rem(n.low(), d.low()));
117                 }
118                 return u128::from(unchecked_div(n.low(), d.low()));
119             } else {
120                 // 0 X
121                 // ---
122                 // K X
123                 if !rem.is_null() {
124                     *rem = n;
125                 }
126                 return 0;
127             };
128         }
129
130         let mut sr;
131         let mut q;
132         let mut r;
133
134         if d.low() == 0 {
135             if d.high() == 0 {
136                 // K X
137                 // ---
138                 // 0 0
139                 if !rem.is_null() {
140                     *rem = u128::from(unchecked_rem(n.high(), d.low()));
141                 }
142                 return u128::from(unchecked_div(n.high(), d.low()));
143             }
144
145             if n.low() == 0 {
146                 // K 0
147                 // ---
148                 // K 0
149                 if !rem.is_null() {
150                     *rem = u128::from_parts(0, unchecked_rem(n.high(), d.high()));
151                 }
152                 return u128::from(unchecked_div(n.high(), d.high()));
153             }
154
155             // K K
156             // ---
157             // K 0
158
159             if d.high().is_power_of_two() {
160                 if !rem.is_null() {
161                     *rem = u128::from_parts(n.low(),
162                                             n.high() & (d.high().wrapping_sub(1)));
163                 }
164                 return u128::from(n.high().wrapping_shr(d.high().trailing_zeros()));
165             }
166
167             // K K
168             // ---
169             // K 0
170             sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
171
172             // D > N
173             if sr > 64 - 2 {
174                 if !rem.is_null() {
175                     *rem = n;
176                 }
177                 return 0;
178             }
179
180             sr = sr.wrapping_add(1);
181
182             // 1 <= sr <= u64::bits() - 1
183             q = n.wrapping_shl(64u32.wrapping_sub(sr));
184             r = n.wrapping_shr(sr);
185         } else {
186             if d.high() == 0 {
187                 // K X
188                 // ---
189                 // 0 K
190                 if d.low().is_power_of_two() {
191                     if !rem.is_null() {
192                         *rem = u128::from(n.low() & (d.low().wrapping_sub(1)));
193                     }
194
195                     if d.low() == 1 {
196                         return n;
197                     } else {
198                         let sr = d.low().trailing_zeros();
199                         return n.wrapping_shr(sr);
200                     };
201                 }
202
203                 sr = (1 + 64u32)
204                     .wrapping_add(d.low().leading_zeros())
205                     .wrapping_sub(n.high().leading_zeros());
206
207                 // 2 <= sr <= u64::bits() - 1
208                 q = n.wrapping_shl(128u32.wrapping_sub(sr));
209                 r = n.wrapping_shr(sr);
210                 // FIXME the C compiler-rt implementation has something here
211                 // that looks like a speed optimisation.
212                 // It would be worth a try to port it to Rust too and
213                 // compare the speed.
214             } else {
215                 // K X
216                 // ---
217                 // K K
218                 sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
219
220                 // D > N
221                 if sr > 64 - 1 {
222                     if !rem.is_null() {
223                         *rem = n;
224                     }
225                     return 0;
226                 }
227
228                 sr = sr.wrapping_add(1);
229
230                 // 1 <= sr <= u32::bits()
231                 q = n.wrapping_shl(128u32.wrapping_sub(sr));
232                 r = n.wrapping_shr(sr);
233             }
234         }
235
236         // Not a special case
237         // q and r are initialized with
238         // q = n << (u64::bits() - sr)
239         // r = n >> sr
240         // 1 <= sr <= u64::bits() - 1
241         let mut carry = 0;
242
243         // FIXME: replace this with a for loop
244         // (atm not doable as this generates call to
245         // eh_personality when optimisations are turned off,
246         // which in turn gives a linker error in later
247         // compilation steps)
248         while sr > 0 {
249             // r:q = ((r:q) << 1) | carry
250             r = r.wrapping_shl(1) | q.wrapping_shr(128 - 1);
251             q = q.wrapping_shl(1) | carry as u128;
252
253             // carry = 0
254             // if r >= d {
255             //     r -= d;
256             //     carry = 1;
257             // }
258             let s = ((d.wrapping_sub(r).wrapping_sub(1)) as i128).wrapping_shr(128 - 1);
259             carry = (s & 1) as u64;
260             r = r.wrapping_sub(d & s as u128);
261             sr = sr.wrapping_sub(1);
262         }
263
264         if !rem.is_null() {
265             *rem = r;
266         }
267         (q.wrapping_shl(1)) | carry as u128
268         }
269     }
270
271     fn i128_mod(a: i128, b: i128) -> i128 {
272         let b = b.uabs();
273         let sa = a.signum();
274         let a = a.uabs();
275         unsafe {
276             let mut r = ::core::mem::zeroed();
277             u128_div_mod(a, b, &mut r);
278             if sa == -1 { (r as i128).unchecked_neg() } else { r as i128 }
279         }
280     }
281
282     fn i128_div(a: i128, b: i128) -> i128 {
283         let sa = a.signum();
284         let sb = b.signum();
285         let a = a.uabs();
286         let b = b.uabs();
287         let sr = sa.wrapping_mul(sb); // sign of quotient
288         (if sr == -1 {
289             (u128_div_mod(a, b, ptr::null_mut()) as i128).unchecked_neg()
290         } else {
291             u128_div_mod(a, b, ptr::null_mut()) as i128
292         })
293     }
294
295     macro_rules! mulo {
296         ($a:expr, $b:expr, $o: expr, $ty: ty) => {{
297             let (a, b, overflow) = ($a, $b, $o);
298             *overflow = 0;
299             let result = a.wrapping_mul(b);
300             if a == <$ty>::min_value() {
301                 if b != 0 && b != 1 {
302                     *overflow = 1;
303                 }
304                 return result;
305             }
306             if b == <$ty>::min_value() {
307                 if a != 0 && a != 1 {
308                     *overflow = 1;
309                 }
310                 return result;
311             }
312
313             let sa = a.signum();
314             let abs_a = a.iabs();
315             let sb = b.signum();
316             let abs_b = b.iabs();
317             if abs_a < 2 || abs_b < 2 {
318                 return result;
319             }
320             if sa == sb {
321                 if abs_a > unchecked_div(<$ty>::max_value(), abs_b) {
322                     *overflow = 1;
323                 }
324             } else {
325                 if abs_a > unchecked_div(<$ty>::min_value(), abs_b.unchecked_neg()) {
326                     *overflow = 1;
327                 }
328             }
329             result
330         }}
331     }
332
333     pub trait LargeInt {
334         type LowHalf;
335         type HighHalf;
336
337         fn low(self) -> Self::LowHalf;
338         fn high(self) -> Self::HighHalf;
339         fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
340     }
341     impl LargeInt for u128 {
342         type LowHalf = u64;
343         type HighHalf = u64;
344
345         fn low(self) -> u64 {
346             self as u64
347         }
348         fn high(self) -> u64 {
349             self.wrapping_shr(64) as u64
350         }
351         fn from_parts(low: u64, high: u64) -> u128 {
352             (high as u128).wrapping_shl(64) | low as u128
353         }
354     }
355     impl LargeInt for i128 {
356         type LowHalf = u64;
357         type HighHalf = i64;
358
359         fn low(self) -> u64 {
360             self as u64
361         }
362         fn high(self) -> i64 {
363             self.wrapping_shr(64) as i64
364         }
365         fn from_parts(low: u64, high: i64) -> i128 {
366             u128::from_parts(low, high as u64) as i128
367         }
368     }
369
370     macro_rules! mul {
371         ($a:expr, $b:expr, $ty: ty, $tyh: ty) => {{
372             let (a, b) = ($a, $b);
373             let half_bits = ::core::mem::size_of::<$tyh>().wrapping_mul(4) as u32;
374             let lower_mask = (!0u64).wrapping_shr(half_bits);
375             let mut low = (a.low() & lower_mask).wrapping_mul(b.low() & lower_mask);
376             let mut t = low.wrapping_shr(half_bits);
377             low &= lower_mask;
378             t = t.wrapping_add(a.low().wrapping_shr(half_bits)
379                                       .wrapping_mul(b.low() & lower_mask));
380             low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits));
381             let mut high = t.wrapping_shr(half_bits) as $tyh;
382             t = low.wrapping_shr(half_bits);
383             low &= lower_mask;
384             t = t.wrapping_add(b.low().wrapping_shr(half_bits)
385                                       .wrapping_mul(a.low() & lower_mask));
386             low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits));
387             high = high.wrapping_add(t.wrapping_shr(half_bits) as $tyh);
388             high = high.wrapping_add(a.low().wrapping_shr(half_bits)
389                            .wrapping_mul(b.low().wrapping_shr(half_bits)) as $tyh);
390             high = high
391                 .wrapping_add(a.high()
392                 .wrapping_mul(b.low() as $tyh))
393                 .wrapping_add((a.low() as $tyh)
394                 .wrapping_mul(b.high()));
395             <$ty>::from_parts(low, high)
396         }}
397     }
398
399     #[export_name="__multi3"]
400     pub extern "C" fn u128_mul(a: i128, b: i128) -> i128 {
401         mul!(a, b, i128, i64)
402     }
403
404     trait AbsExt: Sized {
405         fn uabs(self) -> u128;
406         fn iabs(self) -> i128;
407     }
408
409     impl AbsExt for i128 {
410         fn uabs(self) -> u128 {
411             self.iabs() as u128
412         }
413         fn iabs(self) -> i128 {
414             let s = self.wrapping_shr(127);
415             ((self ^ s).wrapping_sub(s))
416         }
417     }
418
419     trait NegExt: Sized {
420         fn unchecked_neg(self) -> i128;
421     }
422
423     impl NegExt for i128 {
424         fn unchecked_neg(self) -> i128 {
425             (!self).wrapping_add(1)
426         }
427     }
428
429     trait FloatStuff: Sized {
430         type ToBytes;
431
432         const MANTISSA_BITS: u32;
433         const MAX_EXP: i32;
434         const EXP_MASK: Self::ToBytes;
435         const MANTISSA_MASK: Self::ToBytes;
436         const MANTISSA_LEAD_BIT: Self::ToBytes;
437
438         fn to_bytes(self) -> Self::ToBytes;
439         fn get_exponent(self) -> i32;
440     }
441
442     impl FloatStuff for f32 {
443         type ToBytes = u32;
444         const MANTISSA_BITS: u32 = 23;
445         const MAX_EXP: i32 = 127;
446         const EXP_MASK: u32 = 0x7F80_0000;
447         const MANTISSA_MASK: u32 = 0x007F_FFFF;
448         const MANTISSA_LEAD_BIT: u32 = 0x0080_0000;
449
450         fn to_bytes(self) -> u32 { unsafe { ::core::mem::transmute(self) } }
451         fn get_exponent(self) -> i32 {
452             ((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32)
453             .wrapping_sub(Self::MAX_EXP)
454         }
455     }
456
457     impl FloatStuff for f64 {
458         type ToBytes = u64;
459         const MANTISSA_BITS: u32 = 52;
460         const MAX_EXP: i32 = 1023;
461         const EXP_MASK: u64 = 0x7FF0_0000_0000_0000;
462         const MANTISSA_MASK: u64 = 0x000F_FFFF_FFFF_FFFF;
463         const MANTISSA_LEAD_BIT: u64 = 0x0010_0000_0000_0000;
464
465         fn to_bytes(self) -> u64 { unsafe { ::core::mem::transmute(self) } }
466         fn get_exponent(self) -> i32 {
467             ((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32)
468             .wrapping_sub(Self::MAX_EXP)
469         }
470     }
471
472     macro_rules! float_as_unsigned {
473         ($from: expr, $fromty: ty, $outty: ty) => { {
474             use core::num::Float;
475             let repr = $from.to_bytes();
476             let sign = $from.signum();
477             let exponent = $from.get_exponent();
478             let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
479             let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
480             if sign == -1.0 || exponent < 0 { return 0 as u128; }
481             if exponent > ::core::mem::size_of::<$outty>().wrapping_mul(8) as i32 {
482                 return !(0 as u128);
483             }
484             (if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
485                 (mantissa as $outty)
486                     .wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
487                                   .wrapping_sub(exponent) as u32)
488             } else {
489                 (mantissa as $outty)
490                     .wrapping_shl(exponent.wrapping_sub(
491                         <$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
492             })
493         } }
494     }
495
496     macro_rules! float_as_signed {
497         ($from: expr, $fromty: ty, $outty: ty) => {{
498             use core::num::Float;
499             let repr = $from.to_bytes();
500             let sign = $from.signum();
501             let exponent = $from.get_exponent();
502             let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
503             let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
504
505             if exponent < 0 { return 0 as i128; }
506             if exponent > ::core::mem::size_of::<$outty>().wrapping_mul(8) as i32 {
507                 let ret = if sign > 0.0 { <$outty>::max_value() } else { <$outty>::min_value() };
508                 return ret
509             }
510             let r = if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
511                 (mantissa as $outty)
512                     .wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
513                                   .wrapping_sub(exponent) as u32)
514             } else {
515                 (mantissa as $outty)
516                     .wrapping_shl(exponent.wrapping_sub(
517                         <$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
518             };
519             (if sign >= 0.0 { r } else { r.unchecked_neg() })
520         }}
521     }
522
523
524     fn i128_as_f64(a: i128) -> f64 {
525         match a.signum() {
526             1 => u128_as_f64(a.uabs()),
527             0 => 0.0,
528             _ => -u128_as_f64(a.uabs()),
529         }
530     }
531
532     fn i128_as_f32(a: i128) -> f32 {
533         match a.signum() {
534             1 => u128_as_f32(a.uabs()),
535             0 => 0.0,
536             _ => -u128_as_f32(a.uabs()),
537         }
538     }
539
540     fn u128_as_f64(mut a: u128) -> f64 {
541         use ::core::f64::MANTISSA_DIGITS;
542         if a == 0 { return 0.0; }
543         let sd = 128u32.wrapping_sub(a.leading_zeros());
544         let mut e = sd.wrapping_sub(1);
545         const MD1 : u32 = MANTISSA_DIGITS + 1;
546         const MD2 : u32 = MANTISSA_DIGITS + 2;
547
548         let negn = !0u128;
549
550         if sd > MANTISSA_DIGITS {
551             a = match sd {
552                 MD1 => a.wrapping_shl(1),
553                 MD2 => a,
554                 _ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
555                      (if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
556                                    .wrapping_sub(sd as u128))) == 0 { 0 } else { 1 })
557             };
558             a |= if (a & 4) == 0 { 0 } else { 1 };
559             a = a.wrapping_add(1);
560             a = a.wrapping_shr(2);
561             if a & (1 << MANTISSA_DIGITS) != 0 {
562                 a = a.wrapping_shr(1);
563                 e = e.wrapping_add(1);
564             }
565         } else {
566             a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd));
567         }
568         unsafe {
569             ::core::mem::transmute((e as u64).wrapping_add(1023).wrapping_shl(52)
570                                    | (a as u64 & 0x000f_ffff_ffff_ffff))
571         }
572     }
573
574     fn u128_as_f32(mut a: u128) -> f32 {
575         use ::core::f32::MANTISSA_DIGITS;
576         if a == 0 { return 0.0; }
577         let sd = 128u32.wrapping_sub(a.leading_zeros());
578         let mut e = sd.wrapping_sub(1);
579         const MD1 : u32 = MANTISSA_DIGITS + 1;
580         const MD2 : u32 = MANTISSA_DIGITS + 2;
581
582         let negn = !0u128;
583
584         if sd > MANTISSA_DIGITS {
585             a = match sd {
586                 MD1 => a.wrapping_shl(1),
587                 MD2 => a,
588                 _ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
589                      (if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
590                                    .wrapping_sub(sd as u128))) == 0 { 0 } else { 1 })
591             };
592             a |= if (a & 4) == 0 { 0 } else { 1 };
593             a = a.wrapping_add(1);
594             a = a.wrapping_shr(2);
595             if a & (1 << MANTISSA_DIGITS) != 0 {
596                 a = a.wrapping_shr(1);
597                 e = e.wrapping_add(1);
598             }
599         } else {
600             a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd));
601         }
602         unsafe {
603             ::core::mem::transmute((e as u32).wrapping_add(127).wrapping_shl(23)
604                                    | (a as u32 & 0x007f_ffff))
605         }
606     }
607
608
609     macro_rules! why_are_abi_strings_checked_by_parser { ($cret:ty, $conv:expr, $unadj:tt) => {
610     mod imp {
611         use super::{LargeInt, FloatStuff, NegExt, AbsExt};
612         use super::{i128_as_f64, i128_as_f32, u128_as_f64, u128_as_f32,
613                     i128_div, i128_mod, u128_div_mod, unchecked_div, ptr};
614         // For x64
615         // rdx:rcx, r9:r8, stack -> rdx:rax
616         // aka.
617         // define i128 @__muloti4(i128, i128, i32*)
618         #[export_name="__muloti4"]
619         pub unsafe extern $unadj fn i128_mul_oflow(a: i128, b: i128, o: *mut i32) -> i128 {
620             mulo!(a, b, o, i128)
621         }
622
623         // For x64
624         // rdx:rax -> xmm0
625         // aka.
626         // define double @__muloti4(i128)
627         #[export_name="__floattidf"]
628         pub extern $unadj fn i128_as_f64_(a: i128) -> f64 {
629             i128_as_f64(a)
630         }
631         #[export_name="__floattisf"]
632         pub extern $unadj fn i128_as_f32_(a: i128) -> f32 {
633             i128_as_f32(a)
634         }
635         #[export_name="__floatuntidf"]
636         pub extern $unadj fn u128_as_f64_(a: u128) -> f64 {
637             u128_as_f64(a)
638         }
639         #[export_name="__floatuntisf"]
640         pub extern $unadj fn u128_as_f32_(a: u128) -> f32 {
641             u128_as_f32(a)
642         }
643
644         // For x64
645         // xmm0 -> rdx:rax
646         // aka.
647         // define i128 @stuff(double)
648         #[export_name="__fixunsdfti"]
649         pub extern $unadj fn f64_as_u128(a: f64) -> u128 {
650             float_as_unsigned!(a, f64, u128)
651         }
652
653         #[export_name="__fixunssfti"]
654         pub extern $unadj fn f32_as_u128(a: f32) -> u128 {
655             float_as_unsigned!(a, f32, u128)
656         }
657
658         #[export_name="__fixdfti"]
659         pub extern $unadj fn f64_as_i128(a: f64) -> i128 {
660             float_as_signed!(a, f64, i128)
661         }
662
663         #[export_name="__fixsfti"]
664         pub extern $unadj fn f32_as_i128(a: f32) -> i128 {
665             float_as_signed!(a, f32, i128)
666         }
667
668         #[repr(simd)]
669         pub struct u64x2(u64, u64);
670
671         // For x64
672         // pointers -> xmm0
673         // aka.
674         // define <2 x u64> @stuff(i128*, i128*, i128*)
675         //
676         // That almost matches the C ABI, so we simply use the C ABI
677         #[export_name="__udivmodti4"]
678         pub extern "C" fn u128_div_mod_(n: u128, d: u128, rem: *mut u128) -> $cret {
679             let x = u128_div_mod(n, d, rem);
680             ($conv)(x)
681         }
682
683         #[export_name="__udivti3"]
684         pub extern "C" fn u128_div_(a: u128, b: u128) -> $cret {
685             let x = u128_div_mod(a, b, ptr::null_mut());
686             ($conv)(x)
687         }
688
689         #[export_name="__umodti3"]
690         pub extern "C" fn u128_mod_(a: u128, b: u128) -> $cret {
691             unsafe {
692                 let mut r = ::core::mem::zeroed();
693                 u128_div_mod(a, b, &mut r);
694                 ($conv)(r)
695             }
696         }
697
698         #[export_name="__divti3"]
699         pub extern "C" fn i128_div_(a: i128, b: i128) -> $cret {
700             let x = i128_div(a, b);
701             ($conv)(x as u128)
702         }
703
704         #[export_name="__modti3"]
705         pub extern "C" fn i128_mod_(a: i128, b: i128) -> $cret {
706             let x = i128_mod(a, b);
707             ($conv)(x as u128)
708         }
709     }
710     } }
711
712     // LLVM expectations for ABI on windows x64 are pure madness.
713     #[cfg(all(windows, target_pointer_width="64"))]
714     why_are_abi_strings_checked_by_parser!(u64x2,
715                                            |i: u128| u64x2(i.low(), i.high()),
716                                            "unadjusted");
717
718     #[cfg(not(all(windows, target_pointer_width="64")))]
719     why_are_abi_strings_checked_by_parser!(u128, |i|{ i }, "C");
720     pub use self::imp::*;
721 }