@@ -5,7 +5,6 @@ use rustc_target::spec::abi::Abi;
55
66use crate :: * ;
77use helpers:: bool_to_simd_element;
8- use helpers:: convert:: Truncate as _;
98use shims:: foreign_items:: EmulateByNameResult ;
109
1110mod sse;
@@ -26,23 +25,30 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
2625 // Prefix should have already been checked.
2726 let unprefixed_name = link_name. as_str ( ) . strip_prefix ( "llvm.x86." ) . unwrap ( ) ;
2827 match unprefixed_name {
29- "addcarry.64" if this. tcx . sess . target . arch == "x86_64" => {
30- // Computes u8+u64+u64, returning tuple (u8,u64) comprising the output carry and truncated sum.
28+ // Used to implement the `_addcarry_u32` and `_addcarry_u64` functions.
29+ // Computes u8+uX+uX (uX is u32 or u64), returning tuple (u8,uX) comprising
30+ // the output carry and truncated sum.
31+ "addcarry.32" | "addcarry.64" => {
32+ if unprefixed_name == "addcarry.64" && this. tcx . sess . target . arch != "x86_64" {
33+ return Ok ( EmulateByNameResult :: NotSupported ) ;
34+ }
35+
3136 let [ c_in, a, b] = this. check_shim ( abi, Abi :: Unadjusted , link_name, args) ?;
3237 let c_in = this. read_scalar ( c_in) ?. to_u8 ( ) ?;
33- let a = this. read_scalar ( a) ?. to_u64 ( ) ?;
34- let b = this. read_scalar ( b) ?. to_u64 ( ) ?;
35-
36- #[ allow( clippy:: arithmetic_side_effects) ]
37- // adding two u64 and a u8 cannot wrap in a u128
38- let wide_sum = u128:: from ( c_in) + u128:: from ( a) + u128:: from ( b) ;
39- #[ allow( clippy:: arithmetic_side_effects) ] // it's a u128, we can shift by 64
40- let ( c_out, sum) = ( ( wide_sum >> 64 ) . truncate :: < u8 > ( ) , wide_sum. truncate :: < u64 > ( ) ) ;
41-
42- let c_out_field = this. project_field ( dest, 0 ) ?;
43- this. write_scalar ( Scalar :: from_u8 ( c_out) , & c_out_field) ?;
44- let sum_field = this. project_field ( dest, 1 ) ?;
45- this. write_scalar ( Scalar :: from_u64 ( sum) , & sum_field) ?;
38+ let a = this. read_immediate ( a) ?;
39+ let b = this. read_immediate ( b) ?;
40+
41+ let ( sum, overflow1) = this. overflowing_binary_op ( mir:: BinOp :: Add , & a, & b) ?;
42+ let ( sum, overflow2) = this. overflowing_binary_op (
43+ mir:: BinOp :: Add ,
44+ & sum,
45+ & ImmTy :: from_uint ( c_in, a. layout ) ,
46+ ) ?;
47+ #[ allow( clippy:: arithmetic_side_effects) ] // adding two bools into a u8
48+ let c_out = u8:: from ( overflow1) + u8:: from ( overflow2) ;
49+
50+ this. write_scalar ( Scalar :: from_u8 ( c_out) , & this. project_field ( dest, 0 ) ?) ?;
51+ this. write_immediate ( * sum, & this. project_field ( dest, 1 ) ?) ?;
4652 }
4753
4854 name if name. starts_with ( "sse." ) => {
0 commit comments