@@ -5,7 +5,6 @@ use rustc_target::spec::abi::Abi;
5
5
6
6
use crate :: * ;
7
7
use helpers:: bool_to_simd_element;
8
- use helpers:: convert:: Truncate as _;
9
8
use shims:: foreign_items:: EmulateByNameResult ;
10
9
11
10
mod sse;
@@ -26,23 +25,30 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
26
25
// Prefix should have already been checked.
27
26
let unprefixed_name = link_name. as_str ( ) . strip_prefix ( "llvm.x86." ) . unwrap ( ) ;
28
27
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
+
31
36
let [ c_in, a, b] = this. check_shim ( abi, Abi :: Unadjusted , link_name, args) ?;
32
37
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 ) ?) ?;
46
52
}
47
53
48
54
name if name. starts_with ( "sse." ) => {
0 commit comments