Auto merge of #2090 - dtolnay-contrib:addcarry, r=oli-obk
Implement llvm.x86.addcarry.64 This is the only new shim I need for https://github.com/dtolnay/precise/issues/2. It's used by the `num-bigint` crate for bigint addition.
This commit is contained in:
commit
cf5e75389d
@ -671,6 +671,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
}
|
||||
|
||||
// Architecture-specific shims
|
||||
"llvm.x86.addcarry.64" if this.tcx.sess.target.arch == "x86_64" => {
|
||||
// Computes u8+u64+u64, returning tuple (u8,u64) comprising the output carry and truncated sum.
|
||||
let &[ref c_in, ref a, ref b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
|
||||
let c_in = this.read_scalar(c_in)?.to_u8()?;
|
||||
let a = this.read_scalar(a)?.to_u64()?;
|
||||
let b = this.read_scalar(b)?.to_u64()?;
|
||||
|
||||
let wide_sum = c_in as u128 + a as u128 + b as u128;
|
||||
let (c_out, sum) = ((wide_sum >> 64) as u8, wide_sum as u64);
|
||||
|
||||
let c_out_field = this.place_field(dest, 0)?;
|
||||
this.write_scalar(Scalar::from_u8(c_out), &c_out_field)?;
|
||||
let sum_field = this.place_field(dest, 1)?;
|
||||
this.write_scalar(Scalar::from_u64(sum), &sum_field)?;
|
||||
}
|
||||
"llvm.x86.sse2.pause" if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" => {
|
||||
let &[] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
this.yield_active_thread();
|
||||
|
22
tests/run-pass/intrinsics-x86.rs
Normal file
22
tests/run-pass/intrinsics-x86.rs
Normal file
@ -0,0 +1,22 @@
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod x86_64 {
|
||||
use core::arch::x86_64 as arch;
|
||||
|
||||
fn adc(c_in: u8, a: u64, b: u64) -> (u8, u64) {
|
||||
let mut sum = 0;
|
||||
// SAFETY: There are no safety requirements for calling `_addcarry_u64`.
|
||||
// It's just unsafe for API consistency with other intrinsics.
|
||||
let c_out = unsafe { arch::_addcarry_u64(c_in, a, b, &mut sum) };
|
||||
(c_out, sum)
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
assert_eq!(adc(1, 1, 1), (0, 3));
|
||||
assert_eq!(adc(3, u64::MAX, u64::MAX), (2, 1));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
x86_64::main();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user