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:
bors 2022-04-30 09:07:16 +00:00
commit cf5e75389d
2 changed files with 37 additions and 0 deletions

View File

@ -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();

View 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();
}