about summary refs log tree commit diff
path: root/library/compiler-builtins/builtins-test/tests/lse.rs
blob: 5d59fbb7f44d24adf4dbdaf063d63f28e3da7556 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#![feature(decl_macro)] // so we can use pub(super)
#![feature(macro_metavar_expr_concat)]
#![cfg(all(target_arch = "aarch64", target_os = "linux"))]

/// Translate a byte size to a Rust type.
macro int_ty {
    (1) => { i8 },
    (2) => { i16 },
    (4) => { i32 },
    (8) => { i64 },
    (16) => { i128 }
}

mod cas {
    pub(super) macro test($_ordering:ident, $bytes:tt, $name:ident) {
        #[test]
        fn $name() {
            builtins_test::fuzz_2(10000, |expected: super::int_ty!($bytes), new| {
                let mut target = expected.wrapping_add(10);
                assert_eq!(
                    unsafe {
                        compiler_builtins::aarch64_linux::$name::$name(expected, new, &mut target)
                    },
                    expected.wrapping_add(10),
                    "return value should always be the previous value",
                );
                assert_eq!(
                    target,
                    expected.wrapping_add(10),
                    "shouldn't have changed target"
                );

                target = expected;
                assert_eq!(
                    unsafe {
                        compiler_builtins::aarch64_linux::$name::$name(expected, new, &mut target)
                    },
                    expected
                );
                assert_eq!(target, new, "should have updated target");
            });
        }
    }
}

macro test_cas16($_ordering:ident, $name:ident) {
    cas::test!($_ordering, 16, $name);
}

mod swap {
    pub(super) macro test($_ordering:ident, $bytes:tt, $name:ident) {
        #[test]
        fn $name() {
            builtins_test::fuzz_2(10000, |left: super::int_ty!($bytes), mut right| {
                let orig_right = right;
                assert_eq!(
                    unsafe { compiler_builtins::aarch64_linux::$name::$name(left, &mut right) },
                    orig_right
                );
                assert_eq!(left, right);
            });
        }
    }
}

macro_rules! test_op {
    ($mod:ident, $( $op:tt )* ) => {
        mod $mod {
            pub(super) macro test {
                ($_ordering:ident, $bytes:tt, $name:ident) => {
                    #[test]
                    fn $name() {
                        builtins_test::fuzz_2(10000, |old, val| {
                            let mut target = old;
                            let op: fn(super::int_ty!($bytes), super::int_ty!($bytes)) -> _ = $($op)*;
                            let expected = op(old, val);
                            assert_eq!(old, unsafe { compiler_builtins::aarch64_linux::$name::$name(val, &mut target) }, "{} should return original value", stringify!($name));
                            assert_eq!(expected, target, "{} should store to target", stringify!($name));
                        });
                    }
                }
            }
        }
    };
}

test_op!(add, |left, right| left.wrapping_add(right));
test_op!(clr, |left, right| left & !right);
test_op!(xor, std::ops::BitXor::bitxor);
test_op!(or, std::ops::BitOr::bitor);
use compiler_builtins::{foreach_bytes, foreach_ordering};
compiler_builtins::foreach_cas!(cas::test);
compiler_builtins::foreach_cas16!(test_cas16);
compiler_builtins::foreach_swp!(swap::test);
compiler_builtins::foreach_ldadd!(add::test);
compiler_builtins::foreach_ldclr!(clr::test);
compiler_builtins::foreach_ldeor!(xor::test);
compiler_builtins::foreach_ldset!(or::test);