Skip to content

Commit f31ee82

Browse files
committed
intrinsics: try to return everything via {u,i}128ret to match LLVM
on suggestion by nagisa.
1 parent b23391a commit f31ee82

File tree

1 file changed

+99
-38
lines changed
  • src/libcompiler_builtins

1 file changed

+99
-38
lines changed

src/libcompiler_builtins/lib.rs

Lines changed: 99 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#![feature(staged_api)]
2020
#![cfg_attr(any(target_pointer_width="32", target_pointer_width="16", target_os="windows",
2121
target_arch="mips64"),
22-
feature(core_intrinsics, core_float))]
22+
feature(core_intrinsics, core_float, repr_simd))]
2323
#![feature(associated_consts)]
2424
#![cfg_attr(not(stage0), feature(i128_type))]
2525

@@ -46,6 +46,29 @@ pub mod reimpls {
4646
#[cfg(not(stage0))]
4747
type i128_ = i128;
4848

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+
4972
macro_rules! ashl {
5073
($a:expr, $b:expr, $ty:ty) => {{
5174
let (a, b) = ($a, $b);
@@ -114,24 +137,27 @@ pub mod reimpls {
114137

115138

116139
#[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()
119142
}
120143

121-
#[cfg(stage0)]
122144
#[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 {
124151
unsafe {
125152
if !rem.is_null() {
126153
*rem = unchecked_rem(n, d);
127154
}
128-
unchecked_div(n, d)
155+
unchecked_div(n, d).to_ret()
129156
}
130157
}
131158

132159
#[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 {
135161
// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
136162
unsafe {
137163
// special cases, X is unknown, K != 0
@@ -297,43 +323,50 @@ pub mod reimpls {
297323
}
298324

299325
#[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 {
301327
unsafe {
302328
let mut r = ::core::mem::zeroed();
303329
u128_div_mod(a, b, &mut r);
304-
r
330+
r.to_ret()
305331
}
306332
}
307333

308334
#[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 {
310336
let b = b.uabs();
311337
let sa = a.signum();
312338
let a = a.uabs();
313-
unsafe {
339+
(unsafe {
314340
let mut r = ::core::mem::zeroed();
315341
u128_div_mod(a, b, &mut r);
316342
if sa == -1 { (r as i128_).unchecked_neg() } else { r as i128_ }
317-
}
343+
}).to_ret()
318344
}
319345

320346
#[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 {
322348
let sa = a.signum();
323349
let sb = b.signum();
324350
let a = a.uabs();
325351
let b = b.uabs();
326352
let sr = sa.wrapping_mul(sb); // sign of quotient
327-
if sr == -1 {
353+
(if sr == -1 {
328354
(u128_div_mod(a, b, ptr::null_mut()) as i128_).unchecked_neg()
329355
} else {
330356
u128_div_mod(a, b, ptr::null_mut()) as i128_
331-
}
357+
}).to_ret()
332358
}
333359

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))]
334367
#[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()
337370
}
338371

339372
macro_rules! mulo {
@@ -345,21 +378,21 @@ pub mod reimpls {
345378
if b != 0 && b != 1 {
346379
*overflow = 1;
347380
}
348-
return result;
381+
return result.to_ret();
349382
}
350383
if b == <$ty>::min_value() {
351384
if a != 0 && a != 1 {
352385
*overflow = 1;
353386
}
354-
return result;
387+
return result.to_ret();
355388
}
356389

357390
let sa = a.signum();
358391
let abs_a = a.iabs();
359392
let sb = b.signum();
360393
let abs_b = b.iabs();
361394
if abs_a < 2 || abs_b < 2 {
362-
return result;
395+
return result.to_ret();
363396
}
364397
unsafe {
365398
if sa == sb {
@@ -372,27 +405,30 @@ pub mod reimpls {
372405
}
373406
}
374407
}
375-
result
408+
result.to_ret()
376409
}}
377410
}
378411

379412
// FIXME: i32 here should be c_int.
380413
#[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 {
382415
mulo!(a, b, o, i128_)
383416
}
384417

385418
pub trait LargeInt {
386419
type LowHalf;
387420
type HighHalf;
421+
type Ret;
388422

389423
fn low(self) -> Self::LowHalf;
390424
fn high(self) -> Self::HighHalf;
391425
fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
426+
fn to_ret(self) -> Self::Ret;
392427
}
393428
impl LargeInt for u64 {
394429
type LowHalf = u32;
395430
type HighHalf = u32;
431+
type Ret = u64;
396432

397433
fn low(self) -> u32 {
398434
self as u32
@@ -403,10 +439,14 @@ pub mod reimpls {
403439
fn from_parts(low: u32, high: u32) -> u64 {
404440
low as u64 | (high as u64).wrapping_shl(32)
405441
}
442+
fn to_ret(self) -> u64 {
443+
self
444+
}
406445
}
407446
impl LargeInt for i64 {
408447
type LowHalf = u32;
409448
type HighHalf = i32;
449+
type Ret = i64;
410450

411451
fn low(self) -> u32 {
412452
self as u32
@@ -417,11 +457,15 @@ pub mod reimpls {
417457
fn from_parts(low: u32, high: i32) -> i64 {
418458
low as i64 | (high as i64).wrapping_shl(32)
419459
}
460+
fn to_ret(self) -> i64 {
461+
self
462+
}
420463
}
421464
#[cfg(not(stage0))]
422465
impl LargeInt for u128 {
423466
type LowHalf = u64;
424467
type HighHalf = u64;
468+
type Ret = u128ret;
425469

426470
fn low(self) -> u64 {
427471
self as u64
@@ -433,11 +477,20 @@ pub mod reimpls {
433477
#[repr(C, packed)] struct Parts(u64, u64);
434478
unsafe { ::core::mem::transmute(Parts(low, high)) }
435479
}
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+
}
436488
}
437489
#[cfg(not(stage0))]
438490
impl LargeInt for i128 {
439491
type LowHalf = u64;
440492
type HighHalf = i64;
493+
type Ret = i128ret;
441494

442495
fn low(self) -> u64 {
443496
self as u64
@@ -448,6 +501,14 @@ pub mod reimpls {
448501
fn from_parts(low: u64, high: i64) -> i128 {
449502
u128::from_parts(low, high as u64) as i128
450503
}
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+
}
451512
}
452513

453514
macro_rules! mul {
@@ -481,14 +542,14 @@ pub mod reimpls {
481542

482543
#[cfg(stage0)]
483544
#[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()
486547
}
487548

488549
#[cfg(not(stage0))]
489550
#[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()
492553
}
493554

494555
trait AbsExt: Sized {
@@ -566,29 +627,29 @@ pub mod reimpls {
566627
let exponent = $from.get_exponent();
567628
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
568629
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(); }
570631
if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
571-
return !0;
632+
return (!(0 as u128_)).to_ret();
572633
}
573-
if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
634+
(if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
574635
(mantissa as $outty)
575636
.wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
576637
.wrapping_sub(exponent) as u32)
577638
} else {
578639
(mantissa as $outty)
579640
.wrapping_shl(exponent.wrapping_sub(
580641
<$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
581-
}
642+
}).to_ret()
582643
} }
583644
}
584645

585646
#[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 {
587648
float_as_unsigned!(a, f64, u128_)
588649
}
589650

590651
#[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 {
592653
float_as_unsigned!(a, f32, u128_)
593654
}
594655

@@ -601,9 +662,9 @@ pub mod reimpls {
601662
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
602663
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
603664

604-
if exponent < 0 { return 0; }
665+
if exponent < 0 { return (0 as i128_).to_ret(); }
605666
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();
607668
}
608669
let r = if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
609670
(mantissa as $outty)
@@ -614,17 +675,17 @@ pub mod reimpls {
614675
.wrapping_shl(exponent.wrapping_sub(
615676
<$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
616677
};
617-
if sign >= 0.0 { r } else { r.unchecked_neg() }
678+
(if sign >= 0.0 { r } else { r.unchecked_neg() }).to_ret()
618679
}}
619680
}
620681

621682
#[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 {
623684
float_as_signed!(a, f64, i128_)
624685
}
625686

626687
#[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 {
628689
float_as_signed!(a, f32, i128_)
629690
}
630691

0 commit comments

Comments
 (0)