19
19
#![ feature( staged_api) ]
20
20
#![ cfg_attr( any( target_pointer_width="32" , target_pointer_width="16" , target_os="windows" ,
21
21
target_arch="mips64" ) ,
22
- feature( core_intrinsics, core_float) ) ]
22
+ feature( core_intrinsics, core_float, repr_simd ) ) ]
23
23
#![ feature( associated_consts) ]
24
24
#![ cfg_attr( not( stage0) , feature( i128_type) ) ]
25
25
@@ -46,6 +46,29 @@ pub mod reimpls {
46
46
#[ cfg( not( stage0) ) ]
47
47
type i128_ = i128 ;
48
48
49
+ // Unfortunately, every tool on Windows expects different
50
+ // calling conventions to be met for int128. We need to
51
+ // match here what LLVM expects from us. This is only
52
+ // required for the return type!
53
+ #[ cfg( not( stage0) ) ]
54
+ #[ cfg( windows) ]
55
+ #[ repr( simd) ]
56
+ pub struct u64x2 ( u64 , u64 ) ;
57
+
58
+ #[ cfg( not( stage0) ) ]
59
+ #[ cfg( windows) ]
60
+ type u128ret = u64x2 ;
61
+
62
+ #[ cfg( any( not( windows) , stage0) ) ]
63
+ type u128ret = u128_ ;
64
+
65
+ #[ cfg( not( stage0) ) ]
66
+ #[ cfg( windows) ]
67
+ type i128ret = u64x2 ;
68
+
69
+ #[ cfg( any( not( windows) , stage0) ) ]
70
+ type i128ret = i128_ ;
71
+
49
72
macro_rules! ashl {
50
73
( $a: expr, $b: expr, $ty: ty) => { {
51
74
let ( a, b) = ( $a, $b) ;
@@ -114,24 +137,27 @@ pub mod reimpls {
114
137
115
138
116
139
#[ export_name="__lshrti3" ]
117
- pub extern "C" fn lshr ( a : u128_ , b : u128_ ) -> u128_ {
118
- lshr ! ( a, b, u128_)
140
+ pub extern "C" fn lshr ( a : u128_ , b : u128_ ) -> u128ret {
141
+ lshr ! ( a, b, u128_) . to_ret ( )
119
142
}
120
143
121
- #[ cfg( stage0) ]
122
144
#[ export_name="__udivmodti4" ]
123
- pub extern "C" fn u128_div_mod ( n : u128_ , d : u128_ , rem : * mut u128_ ) -> u128_ {
145
+ pub extern "C" fn u128_div_mod_export ( n : u128_ , d : u128_ , rem : * mut u128_ ) -> u128ret {
146
+ u128_div_mod ( n, d, rem) . to_ret ( )
147
+ }
148
+
149
+ #[ cfg( stage0) ]
150
+ pub extern "C" fn u128_div_mod ( n : u128_ , d : u128_ , rem : * mut u128_ ) -> u128ret {
124
151
unsafe {
125
152
if !rem. is_null ( ) {
126
153
* rem = unchecked_rem ( n, d) ;
127
154
}
128
- unchecked_div ( n, d)
155
+ unchecked_div ( n, d) . to_ret ( )
129
156
}
130
157
}
131
158
132
159
#[ cfg( not( stage0) ) ]
133
- #[ export_name="__udivmodti4" ]
134
- pub extern "C" fn u128_div_mod ( n : u128_ , d : u128_ , rem : * mut u128_ ) -> u128_ {
160
+ pub extern "C" fn u128_div_mod ( n : u128_ , d : u128_ , rem : * mut u128_ ) -> u128 {
135
161
// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
136
162
unsafe {
137
163
// special cases, X is unknown, K != 0
@@ -297,43 +323,50 @@ pub mod reimpls {
297
323
}
298
324
299
325
#[ export_name="__umodti3" ]
300
- pub extern "C" fn u128_mod ( a : u128_ , b : u128_ ) -> u128_ {
326
+ pub extern "C" fn u128_mod ( a : u128_ , b : u128_ ) -> u128ret {
301
327
unsafe {
302
328
let mut r = :: core:: mem:: zeroed ( ) ;
303
329
u128_div_mod ( a, b, & mut r) ;
304
- r
330
+ r. to_ret ( )
305
331
}
306
332
}
307
333
308
334
#[ export_name="__modti3" ]
309
- pub extern "C" fn i128_mod ( a : i128_ , b : i128_ ) -> i128_ {
335
+ pub extern "C" fn i128_mod ( a : i128_ , b : i128_ ) -> i128ret {
310
336
let b = b. uabs ( ) ;
311
337
let sa = a. signum ( ) ;
312
338
let a = a. uabs ( ) ;
313
- unsafe {
339
+ ( unsafe {
314
340
let mut r = :: core:: mem:: zeroed ( ) ;
315
341
u128_div_mod ( a, b, & mut r) ;
316
342
if sa == -1 { ( r as i128_ ) . unchecked_neg ( ) } else { r as i128_ }
317
- }
343
+ } ) . to_ret ( )
318
344
}
319
345
320
346
#[ export_name="__divti3" ]
321
- pub extern "C" fn i128_div ( a : i128_ , b : i128_ ) -> i128_ {
347
+ pub extern "C" fn i128_div ( a : i128_ , b : i128_ ) -> i128ret {
322
348
let sa = a. signum ( ) ;
323
349
let sb = b. signum ( ) ;
324
350
let a = a. uabs ( ) ;
325
351
let b = b. uabs ( ) ;
326
352
let sr = sa. wrapping_mul ( sb) ; // sign of quotient
327
- if sr == -1 {
353
+ ( if sr == -1 {
328
354
( u128_div_mod ( a, b, ptr:: null_mut ( ) ) as i128_ ) . unchecked_neg ( )
329
355
} else {
330
356
u128_div_mod ( a, b, ptr:: null_mut ( ) ) as i128_
331
- }
357
+ } ) . to_ret ( )
332
358
}
333
359
360
+ #[ cfg( stage0) ]
361
+ #[ export_name="__udivti3" ]
362
+ pub extern "C" fn u128_div ( a : u128_ , b : u128_ ) -> u128ret {
363
+ ( a / b) . to_ret ( )
364
+ }
365
+
366
+ #[ cfg( not( stage0) ) ]
334
367
#[ export_name="__udivti3" ]
335
- pub extern "C" fn u128_div ( a : u128_ , b : u128_ ) -> u128_ {
336
- u128_div_mod ( a, b, ptr:: null_mut ( ) )
368
+ pub extern "C" fn u128_div ( a : u128_ , b : u128_ ) -> u128ret {
369
+ u128_div_mod ( a, b, ptr:: null_mut ( ) ) . to_ret ( )
337
370
}
338
371
339
372
macro_rules! mulo {
@@ -345,21 +378,21 @@ pub mod reimpls {
345
378
if b != 0 && b != 1 {
346
379
* overflow = 1 ;
347
380
}
348
- return result;
381
+ return result. to_ret ( ) ;
349
382
}
350
383
if b == <$ty>:: min_value( ) {
351
384
if a != 0 && a != 1 {
352
385
* overflow = 1 ;
353
386
}
354
- return result;
387
+ return result. to_ret ( ) ;
355
388
}
356
389
357
390
let sa = a. signum( ) ;
358
391
let abs_a = a. iabs( ) ;
359
392
let sb = b. signum( ) ;
360
393
let abs_b = b. iabs( ) ;
361
394
if abs_a < 2 || abs_b < 2 {
362
- return result;
395
+ return result. to_ret ( ) ;
363
396
}
364
397
unsafe {
365
398
if sa == sb {
@@ -372,27 +405,30 @@ pub mod reimpls {
372
405
}
373
406
}
374
407
}
375
- result
408
+ result. to_ret ( )
376
409
} }
377
410
}
378
411
379
412
// FIXME: i32 here should be c_int.
380
413
#[ export_name="__muloti4" ]
381
- pub extern "C" fn i128_mul_oflow ( a : i128_ , b : i128_ , o : & mut i32 ) -> i128_ {
414
+ pub extern "C" fn i128_mul_oflow ( a : i128_ , b : i128_ , o : & mut i32 ) -> i128ret {
382
415
mulo ! ( a, b, o, i128_)
383
416
}
384
417
385
418
pub trait LargeInt {
386
419
type LowHalf ;
387
420
type HighHalf ;
421
+ type Ret ;
388
422
389
423
fn low ( self ) -> Self :: LowHalf ;
390
424
fn high ( self ) -> Self :: HighHalf ;
391
425
fn from_parts ( low : Self :: LowHalf , high : Self :: HighHalf ) -> Self ;
426
+ fn to_ret ( self ) -> Self :: Ret ;
392
427
}
393
428
impl LargeInt for u64 {
394
429
type LowHalf = u32 ;
395
430
type HighHalf = u32 ;
431
+ type Ret = u64 ;
396
432
397
433
fn low ( self ) -> u32 {
398
434
self as u32
@@ -403,10 +439,14 @@ pub mod reimpls {
403
439
fn from_parts ( low : u32 , high : u32 ) -> u64 {
404
440
low as u64 | ( high as u64 ) . wrapping_shl ( 32 )
405
441
}
442
+ fn to_ret ( self ) -> u64 {
443
+ self
444
+ }
406
445
}
407
446
impl LargeInt for i64 {
408
447
type LowHalf = u32 ;
409
448
type HighHalf = i32 ;
449
+ type Ret = i64 ;
410
450
411
451
fn low ( self ) -> u32 {
412
452
self as u32
@@ -417,11 +457,15 @@ pub mod reimpls {
417
457
fn from_parts ( low : u32 , high : i32 ) -> i64 {
418
458
low as i64 | ( high as i64 ) . wrapping_shl ( 32 )
419
459
}
460
+ fn to_ret ( self ) -> i64 {
461
+ self
462
+ }
420
463
}
421
464
#[ cfg( not( stage0) ) ]
422
465
impl LargeInt for u128 {
423
466
type LowHalf = u64 ;
424
467
type HighHalf = u64 ;
468
+ type Ret = u128ret ;
425
469
426
470
fn low ( self ) -> u64 {
427
471
self as u64
@@ -433,11 +477,20 @@ pub mod reimpls {
433
477
#[ repr( C , packed) ] struct Parts ( u64 , u64 ) ;
434
478
unsafe { :: core:: mem:: transmute ( Parts ( low, high) ) }
435
479
}
480
+ #[ cfg( not( windows) ) ]
481
+ fn to_ret ( self ) -> u128ret {
482
+ self
483
+ }
484
+ #[ cfg( windows) ]
485
+ fn to_ret ( self ) -> u128ret {
486
+ u64x2 ( self . low ( ) , self . high ( ) )
487
+ }
436
488
}
437
489
#[ cfg( not( stage0) ) ]
438
490
impl LargeInt for i128 {
439
491
type LowHalf = u64 ;
440
492
type HighHalf = i64 ;
493
+ type Ret = i128ret ;
441
494
442
495
fn low ( self ) -> u64 {
443
496
self as u64
@@ -448,6 +501,14 @@ pub mod reimpls {
448
501
fn from_parts ( low : u64 , high : i64 ) -> i128 {
449
502
u128:: from_parts ( low, high as u64 ) as i128
450
503
}
504
+ #[ cfg( not( windows) ) ]
505
+ fn to_ret ( self ) -> u128ret {
506
+ self
507
+ }
508
+ #[ cfg( windows) ]
509
+ fn to_ret ( self ) -> i128ret {
510
+ u64x2 ( self . low ( ) , self . high ( ) as u64 )
511
+ }
451
512
}
452
513
453
514
macro_rules! mul {
@@ -481,14 +542,14 @@ pub mod reimpls {
481
542
482
543
#[ cfg( stage0) ]
483
544
#[ export_name="__multi3" ]
484
- pub extern "C" fn u128_mul ( a : i128_ , b : i128_ ) -> i128_ {
485
- ( a as i64 ) . wrapping_mul ( b as i64 ) as i128_
545
+ pub extern "C" fn u128_mul ( a : i128_ , b : i128_ ) -> i128ret {
546
+ ( ( a as i64 ) . wrapping_mul ( b as i64 ) as i128_ ) . to_ret ( )
486
547
}
487
548
488
549
#[ cfg( not( stage0) ) ]
489
550
#[ export_name="__multi3" ]
490
- pub extern "C" fn u128_mul ( a : i128_ , b : i128_ ) -> i128_ {
491
- mul ! ( a, b, i128_, i64 )
551
+ pub extern "C" fn u128_mul ( a : i128_ , b : i128_ ) -> i128ret {
552
+ mul ! ( a, b, i128_, i64 ) . to_ret ( )
492
553
}
493
554
494
555
trait AbsExt : Sized {
@@ -566,29 +627,29 @@ pub mod reimpls {
566
627
let exponent = $from. get_exponent( ) ;
567
628
let mantissa_fraction = repr & <$fromty as FloatStuff >:: MANTISSA_MASK ;
568
629
let mantissa = mantissa_fraction | <$fromty as FloatStuff >:: MANTISSA_LEAD_BIT ;
569
- if sign == -1.0 || exponent < 0 { return 0 ; }
630
+ if sign == -1.0 || exponent < 0 { return ( 0 as u128_ ) . to_ret ( ) ; }
570
631
if exponent > :: core:: mem:: size_of:: <$outty>( ) as i32 * 8 {
571
- return ! 0 ;
632
+ return ( ! ( 0 as u128_ ) ) . to_ret ( ) ;
572
633
}
573
- if exponent < ( <$fromty as FloatStuff >:: MANTISSA_BITS ) as i32 {
634
+ ( if exponent < ( <$fromty as FloatStuff >:: MANTISSA_BITS ) as i32 {
574
635
( mantissa as $outty)
575
636
. wrapping_shr( ( <$fromty as FloatStuff >:: MANTISSA_BITS as i32 )
576
637
. wrapping_sub( exponent) as u32 )
577
638
} else {
578
639
( mantissa as $outty)
579
640
. wrapping_shl( exponent. wrapping_sub(
580
641
<$fromty as FloatStuff >:: MANTISSA_BITS as i32 ) as u32 )
581
- }
642
+ } ) . to_ret ( )
582
643
} }
583
644
}
584
645
585
646
#[ export_name="__fixunsdfti" ]
586
- pub extern "C" fn f64_as_u128 ( a : f64 ) -> u128_ {
647
+ pub extern "C" fn f64_as_u128 ( a : f64 ) -> u128ret {
587
648
float_as_unsigned ! ( a, f64 , u128_)
588
649
}
589
650
590
651
#[ export_name="__fixunssfti" ]
591
- pub extern "C" fn f32_as_u128 ( a : f32 ) -> u128_ {
652
+ pub extern "C" fn f32_as_u128 ( a : f32 ) -> u128ret {
592
653
float_as_unsigned ! ( a, f32 , u128_)
593
654
}
594
655
@@ -601,9 +662,9 @@ pub mod reimpls {
601
662
let mantissa_fraction = repr & <$fromty as FloatStuff >:: MANTISSA_MASK ;
602
663
let mantissa = mantissa_fraction | <$fromty as FloatStuff >:: MANTISSA_LEAD_BIT ;
603
664
604
- if exponent < 0 { return 0 ; }
665
+ if exponent < 0 { return ( 0 as i128_ ) . to_ret ( ) ; }
605
666
if exponent > :: core:: mem:: size_of:: <$outty>( ) as i32 * 8 {
606
- return if sign > 0.0 { <$outty>:: max_value( ) } else { <$outty>:: min_value( ) } ;
667
+ return ( if sign > 0.0 { <$outty>:: max_value( ) } else { <$outty>:: min_value( ) } ) . to_ret ( ) ;
607
668
}
608
669
let r = if exponent < ( <$fromty as FloatStuff >:: MANTISSA_BITS ) as i32 {
609
670
( mantissa as $outty)
@@ -614,17 +675,17 @@ pub mod reimpls {
614
675
. wrapping_shl( exponent. wrapping_sub(
615
676
<$fromty as FloatStuff >:: MANTISSA_BITS as i32 ) as u32 )
616
677
} ;
617
- if sign >= 0.0 { r } else { r. unchecked_neg( ) }
678
+ ( if sign >= 0.0 { r } else { r. unchecked_neg( ) } ) . to_ret ( )
618
679
} }
619
680
}
620
681
621
682
#[ export_name="__fixdfti" ]
622
- pub extern "C" fn f64_as_i128 ( a : f64 ) -> i128_ {
683
+ pub extern "C" fn f64_as_i128 ( a : f64 ) -> i128ret {
623
684
float_as_signed ! ( a, f64 , i128_)
624
685
}
625
686
626
687
#[ export_name="__fixsfti" ]
627
- pub extern "C" fn f32_as_i128 ( a : f32 ) -> i128_ {
688
+ pub extern "C" fn f32_as_i128 ( a : f32 ) -> i128ret {
628
689
float_as_signed ! ( a, f32 , i128_)
629
690
}
630
691
0 commit comments