From 1703f2d4f3132ba4e2b5e6218aadeb6f8bafcd20 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 22 May 2026 09:58:01 +0100 Subject: [PATCH 1/6] Add builtin rules --- rules/builtin/ir_unsafe.json | 64 ++++++++++++++++++++++++++++++++++++ rules/builtin/src.cpp | 2 ++ rules/builtin/tgt_unsafe.rs | 6 ++++ 3 files changed, 72 insertions(+) diff --git a/rules/builtin/ir_unsafe.json b/rules/builtin/ir_unsafe.json index 08934062..4251aa52 100644 --- a/rules/builtin/ir_unsafe.json +++ b/rules/builtin/ir_unsafe.json @@ -170,5 +170,69 @@ "return_type": { "type": "u64" } + }, + "f7": { + "body": [ + { + "method_call": { + "receiver": [ + { + "placeholder": { + "arg": 0, + "access": "read" + } + } + ], + "body": [ + { + "text": ".trailing_zeros()" + } + ] + } + }, + { + "text": " as i32" + } + ], + "params": { + "a0": { + "type": "u64" + } + }, + "return_type": { + "type": "i32" + } + }, + "f8": { + "body": [ + { + "method_call": { + "receiver": [ + { + "placeholder": { + "arg": 0, + "access": "read" + } + } + ], + "body": [ + { + "text": ".count_ones()" + } + ] + } + }, + { + "text": " as i32" + } + ], + "params": { + "a0": { + "type": "u64" + } + }, + "return_type": { + "type": "i32" + } } } diff --git a/rules/builtin/src.cpp b/rules/builtin/src.cpp index b74347c3..bc4a675a 100644 --- a/rules/builtin/src.cpp +++ b/rules/builtin/src.cpp @@ -19,3 +19,5 @@ unsigned short f4(unsigned short x) { return __builtin_bswap16(x); } unsigned int f5(unsigned int x) { return __builtin_bswap32(x); } unsigned long long f6(unsigned long long x) { return __builtin_bswap64(x); } #endif +int f7(unsigned long x) { return __builtin_ctzl(x); } +int f8(unsigned long x) { return __builtin_popcountl(x); } diff --git a/rules/builtin/tgt_unsafe.rs b/rules/builtin/tgt_unsafe.rs index 077b4c5f..b0d564f3 100644 --- a/rules/builtin/tgt_unsafe.rs +++ b/rules/builtin/tgt_unsafe.rs @@ -19,3 +19,9 @@ unsafe fn f5(a0: u32) -> u32 { unsafe fn f6(a0: u64) -> u64 { a0.swap_bytes() } +unsafe fn f7(a0: u64) -> i32 { + a0.trailing_zeros() as i32 +} +unsafe fn f8(a0: u64) -> i32 { + a0.count_ones() as i32 +} From bf362c3c4ec71766c8b7ca5ec19516535c80bfa5 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 22 May 2026 10:33:22 +0100 Subject: [PATCH 2/6] Add builtin mul overflow and builtin spin lock --- rules/builtin/ir_refcount.json | 146 ++++++++++++++++++ rules/builtin/ir_unsafe.json | 129 ++++++++++++++++ rules/builtin/src.cpp | 5 + rules/builtin/tgt_refcount.rs | 15 ++ rules/builtin/tgt_unsafe.rs | 14 ++ rules/src/modules.rs | 2 + tests/unit/builtin_mul_overflow.c | 20 +++ .../unit/out/refcount/builtin_mul_overflow.rs | 46 ++++++ tests/unit/out/unsafe/builtin_mul_overflow.rs | 48 ++++++ 9 files changed, 425 insertions(+) create mode 100644 rules/builtin/ir_refcount.json create mode 100644 rules/builtin/tgt_refcount.rs create mode 100644 tests/unit/builtin_mul_overflow.c create mode 100644 tests/unit/out/refcount/builtin_mul_overflow.rs create mode 100644 tests/unit/out/unsafe/builtin_mul_overflow.rs diff --git a/rules/builtin/ir_refcount.json b/rules/builtin/ir_refcount.json new file mode 100644 index 00000000..6d2c8081 --- /dev/null +++ b/rules/builtin/ir_refcount.json @@ -0,0 +1,146 @@ +{ + "f10": { + "body": [ + { + "text": "let (val, ovf) = " + }, + { + "method_call": { + "receiver": [ + { + "placeholder": { + "arg": 0, + "access": "read" + } + } + ], + "body": [ + { + "text": ".overflowing_mul(" + }, + { + "placeholder": { + "arg": 1, + "access": "read" + } + }, + { + "text": ")" + } + ] + } + }, + { + "text": ";\n " + }, + { + "method_call": { + "receiver": [ + { + "placeholder": { + "arg": 2, + "access": "read" + } + } + ], + "body": [ + { + "text": ".write(val)" + } + ] + } + }, + { + "text": ";\n ovf" + } + ], + "multi_statement": true, + "params": { + "a0": { + "type": "i64" + }, + "a1": { + "type": "i64" + }, + "a2": { + "type": "Ptr", + "is_refcount_pointer": true + } + }, + "return_type": { + "type": "bool" + } + }, + "f9": { + "body": [ + { + "text": "let (val, ovf) = " + }, + { + "method_call": { + "receiver": [ + { + "placeholder": { + "arg": 0, + "access": "read" + } + } + ], + "body": [ + { + "text": ".overflowing_mul(" + }, + { + "placeholder": { + "arg": 1, + "access": "read" + } + }, + { + "text": ")" + } + ] + } + }, + { + "text": ";\n " + }, + { + "method_call": { + "receiver": [ + { + "placeholder": { + "arg": 2, + "access": "read" + } + } + ], + "body": [ + { + "text": ".write(val)" + } + ] + } + }, + { + "text": ";\n ovf" + } + ], + "multi_statement": true, + "params": { + "a0": { + "type": "i64" + }, + "a1": { + "type": "i64" + }, + "a2": { + "type": "Ptr", + "is_refcount_pointer": true + } + }, + "return_type": { + "type": "bool" + } + } +} diff --git a/rules/builtin/ir_unsafe.json b/rules/builtin/ir_unsafe.json index 4251aa52..f960be89 100644 --- a/rules/builtin/ir_unsafe.json +++ b/rules/builtin/ir_unsafe.json @@ -20,6 +20,74 @@ "type": "usize" } }, + "f10": { + "body": [ + { + "text": "let (val, ovf) = " + }, + { + "method_call": { + "receiver": [ + { + "placeholder": { + "arg": 0, + "access": "read" + } + } + ], + "body": [ + { + "text": ".overflowing_mul(" + }, + { + "placeholder": { + "arg": 1, + "access": "read" + } + }, + { + "text": ")" + } + ] + } + }, + { + "text": ";\n *" + }, + { + "placeholder": { + "arg": 2, + "access": "write" + } + }, + { + "text": " = val;\n ovf" + } + ], + "multi_statement": true, + "params": { + "a0": { + "type": "i64" + }, + "a1": { + "type": "i64" + }, + "a2": { + "type": "*mut i64", + "is_unsafe_pointer": true + } + }, + "return_type": { + "type": "bool" + } + }, + "f11": { + "body": [ + { + "text": "std::hint::spin_loop()" + } + ] + }, "f2": { "body": [ { @@ -234,5 +302,66 @@ "return_type": { "type": "i32" } + }, + "f9": { + "body": [ + { + "text": "let (val, ovf) = " + }, + { + "method_call": { + "receiver": [ + { + "placeholder": { + "arg": 0, + "access": "read" + } + } + ], + "body": [ + { + "text": ".overflowing_mul(" + }, + { + "placeholder": { + "arg": 1, + "access": "read" + } + }, + { + "text": ")" + } + ] + } + }, + { + "text": ";\n *" + }, + { + "placeholder": { + "arg": 2, + "access": "write" + } + }, + { + "text": " = val;\n ovf" + } + ], + "multi_statement": true, + "params": { + "a0": { + "type": "i64" + }, + "a1": { + "type": "i64" + }, + "a2": { + "type": "*mut i64", + "is_unsafe_pointer": true + } + }, + "return_type": { + "type": "bool" + } } } diff --git a/rules/builtin/src.cpp b/rules/builtin/src.cpp index bc4a675a..d7148196 100644 --- a/rules/builtin/src.cpp +++ b/rules/builtin/src.cpp @@ -21,3 +21,8 @@ unsigned long long f6(unsigned long long x) { return __builtin_bswap64(x); } #endif int f7(unsigned long x) { return __builtin_ctzl(x); } int f8(unsigned long x) { return __builtin_popcountl(x); } +bool f9(long a, long b, long *r) { return __builtin_mul_overflow(a, b, r); } +bool f10(long long a, long long b, long long *r) { return __builtin_mul_overflow(a, b, r); } +#if defined(__x86_64__) || defined(__i386__) +void f11() { return __builtin_ia32_pause(); } +#endif diff --git a/rules/builtin/tgt_refcount.rs b/rules/builtin/tgt_refcount.rs new file mode 100644 index 00000000..0f076e1c --- /dev/null +++ b/rules/builtin/tgt_refcount.rs @@ -0,0 +1,15 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +use libcc2rs::*; + +fn f9(a0: i64, a1: i64, a2: Ptr) -> bool { + let (val, ovf) = a0.overflowing_mul(a1); + a2.write(val); + ovf +} +fn f10(a0: i64, a1: i64, a2: Ptr) -> bool { + let (val, ovf) = a0.overflowing_mul(a1); + a2.write(val); + ovf +} diff --git a/rules/builtin/tgt_unsafe.rs b/rules/builtin/tgt_unsafe.rs index b0d564f3..a66b8a2b 100644 --- a/rules/builtin/tgt_unsafe.rs +++ b/rules/builtin/tgt_unsafe.rs @@ -25,3 +25,17 @@ unsafe fn f7(a0: u64) -> i32 { unsafe fn f8(a0: u64) -> i32 { a0.count_ones() as i32 } +unsafe fn f9(a0: i64, a1: i64, a2: *mut i64) -> bool { + let (val, ovf) = a0.overflowing_mul(a1); + *a2 = val; + ovf +} +unsafe fn f10(a0: i64, a1: i64, a2: *mut i64) -> bool { + let (val, ovf) = a0.overflowing_mul(a1); + *a2 = val; + ovf +} +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] +unsafe fn f11() { + std::hint::spin_loop() +} diff --git a/rules/src/modules.rs b/rules/src/modules.rs index 0da0327e..2b5d751c 100644 --- a/rules/src/modules.rs +++ b/rules/src/modules.rs @@ -16,6 +16,8 @@ pub mod assert_tgt_unsafe; pub mod brotli_tgt_refcount; #[path = r#"../brotli/tgt_unsafe.rs"#] pub mod brotli_tgt_unsafe; +#[path = r#"../builtin/tgt_refcount.rs"#] +pub mod builtin_tgt_refcount; #[path = r#"../builtin/tgt_unsafe.rs"#] pub mod builtin_tgt_unsafe; #[path = r#"../carray/tgt_refcount.rs"#] diff --git a/tests/unit/builtin_mul_overflow.c b/tests/unit/builtin_mul_overflow.c new file mode 100644 index 00000000..43544c1f --- /dev/null +++ b/tests/unit/builtin_mul_overflow.c @@ -0,0 +1,20 @@ +#include +#include + +int main() { + long a = 0; + assert(!__builtin_mul_overflow(3L, 7L, &a)); + assert(a == 21); + + long b = 0; + assert(__builtin_mul_overflow(LONG_MAX, 2L, &b)); + + long long c = 0; + assert(!__builtin_mul_overflow(1000LL, 1000LL, &c)); + assert(c == 1000000); + + long long d = 0; + assert(__builtin_mul_overflow(LLONG_MAX, 2LL, &d)); + + return 0; +} diff --git a/tests/unit/out/refcount/builtin_mul_overflow.rs b/tests/unit/out/refcount/builtin_mul_overflow.rs new file mode 100644 index 00000000..5d03ae05 --- /dev/null +++ b/tests/unit/out/refcount/builtin_mul_overflow.rs @@ -0,0 +1,46 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let a: Value = Rc::new(RefCell::new(0_i64)); + assert!( + ((!{ + let (val, ovf) = 3_i64.overflowing_mul(7_i64); + (a.as_pointer()).write(val); + ovf + } as i32) + != 0) + ); + assert!(((((*a.borrow()) == 21_i64) as i32) != 0)); + let b: Value = Rc::new(RefCell::new(0_i64)); + assert!({ + let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); + (b.as_pointer()).write(val); + ovf + }); + let c: Value = Rc::new(RefCell::new(0_i64)); + assert!( + ((!{ + let (val, ovf) = 1000_i64.overflowing_mul(1000_i64); + (c.as_pointer()).write(val); + ovf + } as i32) + != 0) + ); + assert!(((((*c.borrow()) == 1000000_i64) as i32) != 0)); + let d: Value = Rc::new(RefCell::new(0_i64)); + assert!({ + let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); + (d.as_pointer()).write(val); + ovf + }); + return 0; +} diff --git a/tests/unit/out/unsafe/builtin_mul_overflow.rs b/tests/unit/out/unsafe/builtin_mul_overflow.rs new file mode 100644 index 00000000..d78f3b5e --- /dev/null +++ b/tests/unit/out/unsafe/builtin_mul_overflow.rs @@ -0,0 +1,48 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut a: i64 = 0_i64; + assert!( + ((!{ + let (val, ovf) = 3_i64.overflowing_mul(7_i64); + *(&mut a as *mut i64) = val; + ovf + } as i32) + != 0) + ); + assert!(((((a) == (21_i64)) as i32) != 0)); + let mut b: i64 = 0_i64; + assert!({ + let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); + *(&mut b as *mut i64) = val; + ovf + }); + let mut c: i64 = 0_i64; + assert!( + ((!{ + let (val, ovf) = 1000_i64.overflowing_mul(1000_i64); + *(&mut c as *mut i64) = val; + ovf + } as i32) + != 0) + ); + assert!(((((c) == (1000000_i64)) as i32) != 0)); + let mut d: i64 = 0_i64; + assert!({ + let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); + *(&mut d as *mut i64) = val; + ovf + }); + return 0; +} From 40624d1de0a418425dcabf16bbba4261af4140ab Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 22 May 2026 10:44:14 +0100 Subject: [PATCH 3/6] Add builtin test --- tests/unit/builtin.c | 91 ++++++++++++++++++ tests/unit/builtin_mul_overflow.c | 20 ---- tests/unit/out/refcount/builtin.rs | 91 ++++++++++++++++++ .../unit/out/refcount/builtin_mul_overflow.rs | 46 --------- tests/unit/out/unsafe/builtin.rs | 93 +++++++++++++++++++ tests/unit/out/unsafe/builtin_mul_overflow.rs | 48 ---------- 6 files changed, 275 insertions(+), 114 deletions(-) create mode 100644 tests/unit/builtin.c delete mode 100644 tests/unit/builtin_mul_overflow.c create mode 100644 tests/unit/out/refcount/builtin.rs delete mode 100644 tests/unit/out/refcount/builtin_mul_overflow.rs create mode 100644 tests/unit/out/unsafe/builtin.rs delete mode 100644 tests/unit/out/unsafe/builtin_mul_overflow.rs diff --git a/tests/unit/builtin.c b/tests/unit/builtin.c new file mode 100644 index 00000000..b0d639bb --- /dev/null +++ b/tests/unit/builtin.c @@ -0,0 +1,91 @@ +#include +#include +#if defined(__linux__) +#include +#endif + +static void test_expect(void) { + int x = 42; + assert(__builtin_expect(x == 42, 1)); +} + +static void test_ctz(void) { + assert(__builtin_ctz(8U) == 3); + assert(__builtin_ctz(1U) == 0); +} + +static void test_clz(void) { + assert(__builtin_clz(1U) == 31); + assert(__builtin_clz(0x80000000U) == 0); +} + +static void test_bswap16(void) { +#if defined(__linux__) + assert(bswap_16((unsigned short)0x1234) == 0x3412); +#else + assert(__builtin_bswap16((unsigned short)0x1234) == 0x3412); +#endif +} + +static void test_bswap32(void) { +#if defined(__linux__) + assert(bswap_32(0x12345678U) == 0x78563412U); +#else + assert(__builtin_bswap32(0x12345678U) == 0x78563412U); +#endif +} + +static void test_bswap64(void) { +#if defined(__linux__) + assert(bswap_64(0x0123456789ABCDEFULL) == 0xEFCDAB8967452301ULL); +#else + assert(__builtin_bswap64(0x0123456789ABCDEFULL) == 0xEFCDAB8967452301ULL); +#endif +} + +static void test_ctzl(void) { + assert(__builtin_ctzl(8UL) == 3); + assert(__builtin_ctzl(1UL) == 0); +} + +static void test_popcountl(void) { + assert(__builtin_popcountl(0UL) == 0); + assert(__builtin_popcountl(0xFFUL) == 8); +} + +static void test_mul_overflow_long(void) { + long r = 0; + assert(!__builtin_mul_overflow(3L, 7L, &r)); + assert(r == 21); + assert(__builtin_mul_overflow(LONG_MAX, 2L, &r)); +} + +static void test_mul_overflow_long_long(void) { + long long r = 0; + assert(!__builtin_mul_overflow(1000LL, 1000LL, &r)); + assert(r == 1000000); + assert(__builtin_mul_overflow(LLONG_MAX, 2LL, &r)); +} + +#if defined(__x86_64__) || defined(__i386__) +static void test_ia32_pause(void) { + __builtin_ia32_pause(); +} +#endif + +int main(void) { + test_expect(); + test_ctz(); + test_clz(); + test_bswap16(); + test_bswap32(); + test_bswap64(); + test_ctzl(); + test_popcountl(); + test_mul_overflow_long(); + test_mul_overflow_long_long(); +#if defined(__x86_64__) || defined(__i386__) + test_ia32_pause(); +#endif + return 0; +} diff --git a/tests/unit/builtin_mul_overflow.c b/tests/unit/builtin_mul_overflow.c deleted file mode 100644 index 43544c1f..00000000 --- a/tests/unit/builtin_mul_overflow.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -int main() { - long a = 0; - assert(!__builtin_mul_overflow(3L, 7L, &a)); - assert(a == 21); - - long b = 0; - assert(__builtin_mul_overflow(LONG_MAX, 2L, &b)); - - long long c = 0; - assert(!__builtin_mul_overflow(1000LL, 1000LL, &c)); - assert(c == 1000000); - - long long d = 0; - assert(__builtin_mul_overflow(LLONG_MAX, 2LL, &d)); - - return 0; -} diff --git a/tests/unit/out/refcount/builtin.rs b/tests/unit/out/refcount/builtin.rs new file mode 100644 index 00000000..8be1d409 --- /dev/null +++ b/tests/unit/out/refcount/builtin.rs @@ -0,0 +1,91 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn test_expect_0() { + let x: Value = Rc::new(RefCell::new(42)); + assert!((((((*x.borrow()) == 42) as i32) as i64) != 0)); +} +pub fn test_ctz_1() { + assert!((((8_u32.trailing_zeros() as i32 == 3) as i32) != 0)); + assert!((((1_u32.trailing_zeros() as i32 == 0) as i32) != 0)); +} +pub fn test_clz_2() { + assert!((((1_u32.leading_zeros() as i32 == 31) as i32) != 0)); + assert!((((2147483648_u32.leading_zeros() as i32 == 0) as i32) != 0)); +} +pub fn test_bswap16_3() { + assert!((((((4660 as u16).swap_bytes() as i32) == 13330) as i32) != 0)); +} +pub fn test_bswap32_4() { + assert!((((305419896_u32.swap_bytes() == 2018915346_u32) as i32) != 0)); +} +pub fn test_bswap64_5() { + assert!((((81985529216486895_u64.swap_bytes() == 17279655951921914625_u64) as i32) != 0)); +} +pub fn test_ctzl_6() { + assert!((((8_u64.trailing_zeros() as i32 == 3) as i32) != 0)); + assert!((((1_u64.trailing_zeros() as i32 == 0) as i32) != 0)); +} +pub fn test_popcountl_7() { + assert!((((0_u64.count_ones() as i32 == 0) as i32) != 0)); + assert!((((255_u64.count_ones() as i32 == 8) as i32) != 0)); +} +pub fn test_mul_overflow_long_8() { + let r: Value = Rc::new(RefCell::new(0_i64)); + assert!( + ((!{ + let (val, ovf) = 3_i64.overflowing_mul(7_i64); + (r.as_pointer()).write(val); + ovf + } as i32) + != 0) + ); + assert!(((((*r.borrow()) == 21_i64) as i32) != 0)); + assert!({ + let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); + (r.as_pointer()).write(val); + ovf + }); +} +pub fn test_mul_overflow_long_long_9() { + let r: Value = Rc::new(RefCell::new(0_i64)); + assert!( + ((!{ + let (val, ovf) = 1000_i64.overflowing_mul(1000_i64); + (r.as_pointer()).write(val); + ovf + } as i32) + != 0) + ); + assert!(((((*r.borrow()) == 1000000_i64) as i32) != 0)); + assert!({ + let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); + (r.as_pointer()).write(val); + ovf + }); +} +pub fn test_ia32_pause_10() { + std::hint::spin_loop(); +} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + ({ test_expect_0() }); + ({ test_ctz_1() }); + ({ test_clz_2() }); + ({ test_bswap16_3() }); + ({ test_bswap32_4() }); + ({ test_bswap64_5() }); + ({ test_ctzl_6() }); + ({ test_popcountl_7() }); + ({ test_mul_overflow_long_8() }); + ({ test_mul_overflow_long_long_9() }); + ({ test_ia32_pause_10() }); + return 0; +} diff --git a/tests/unit/out/refcount/builtin_mul_overflow.rs b/tests/unit/out/refcount/builtin_mul_overflow.rs deleted file mode 100644 index 5d03ae05..00000000 --- a/tests/unit/out/refcount/builtin_mul_overflow.rs +++ /dev/null @@ -1,46 +0,0 @@ -extern crate libcc2rs; -use libcc2rs::*; -use std::cell::RefCell; -use std::collections::BTreeMap; -use std::io::prelude::*; -use std::io::{Read, Seek, Write}; -use std::os::fd::AsFd; -use std::rc::{Rc, Weak}; -pub fn main() { - std::process::exit(main_0()); -} -fn main_0() -> i32 { - let a: Value = Rc::new(RefCell::new(0_i64)); - assert!( - ((!{ - let (val, ovf) = 3_i64.overflowing_mul(7_i64); - (a.as_pointer()).write(val); - ovf - } as i32) - != 0) - ); - assert!(((((*a.borrow()) == 21_i64) as i32) != 0)); - let b: Value = Rc::new(RefCell::new(0_i64)); - assert!({ - let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); - (b.as_pointer()).write(val); - ovf - }); - let c: Value = Rc::new(RefCell::new(0_i64)); - assert!( - ((!{ - let (val, ovf) = 1000_i64.overflowing_mul(1000_i64); - (c.as_pointer()).write(val); - ovf - } as i32) - != 0) - ); - assert!(((((*c.borrow()) == 1000000_i64) as i32) != 0)); - let d: Value = Rc::new(RefCell::new(0_i64)); - assert!({ - let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); - (d.as_pointer()).write(val); - ovf - }); - return 0; -} diff --git a/tests/unit/out/unsafe/builtin.rs b/tests/unit/out/unsafe/builtin.rs new file mode 100644 index 00000000..81e9936a --- /dev/null +++ b/tests/unit/out/unsafe/builtin.rs @@ -0,0 +1,93 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn test_expect_0() { + let mut x: i32 = 42; + assert!((((((x) == (42)) as i32) as i64) != 0)); +} +pub unsafe fn test_ctz_1() { + assert!(((((8_u32.trailing_zeros() as i32) == (3)) as i32) != 0)); + assert!(((((1_u32.trailing_zeros() as i32) == (0)) as i32) != 0)); +} +pub unsafe fn test_clz_2() { + assert!(((((1_u32.leading_zeros() as i32) == (31)) as i32) != 0)); + assert!(((((2147483648_u32.leading_zeros() as i32) == (0)) as i32) != 0)); +} +pub unsafe fn test_bswap16_3() { + assert!((((((4660 as u16).swap_bytes() as i32) == (13330)) as i32) != 0)); +} +pub unsafe fn test_bswap32_4() { + assert!(((((305419896_u32.swap_bytes()) == (2018915346_u32)) as i32) != 0)); +} +pub unsafe fn test_bswap64_5() { + assert!(((((81985529216486895_u64.swap_bytes()) == (17279655951921914625_u64)) as i32) != 0)); +} +pub unsafe fn test_ctzl_6() { + assert!(((((8_u64.trailing_zeros() as i32) == (3)) as i32) != 0)); + assert!(((((1_u64.trailing_zeros() as i32) == (0)) as i32) != 0)); +} +pub unsafe fn test_popcountl_7() { + assert!(((((0_u64.count_ones() as i32) == (0)) as i32) != 0)); + assert!(((((255_u64.count_ones() as i32) == (8)) as i32) != 0)); +} +pub unsafe fn test_mul_overflow_long_8() { + let mut r: i64 = 0_i64; + assert!( + ((!{ + let (val, ovf) = 3_i64.overflowing_mul(7_i64); + *(&mut r as *mut i64) = val; + ovf + } as i32) + != 0) + ); + assert!(((((r) == (21_i64)) as i32) != 0)); + assert!({ + let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); + *(&mut r as *mut i64) = val; + ovf + }); +} +pub unsafe fn test_mul_overflow_long_long_9() { + let mut r: i64 = 0_i64; + assert!( + ((!{ + let (val, ovf) = 1000_i64.overflowing_mul(1000_i64); + *(&mut r as *mut i64) = val; + ovf + } as i32) + != 0) + ); + assert!(((((r) == (1000000_i64)) as i32) != 0)); + assert!({ + let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); + *(&mut r as *mut i64) = val; + ovf + }); +} +pub unsafe fn test_ia32_pause_10() { + std::hint::spin_loop(); +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + (unsafe { test_expect_0() }); + (unsafe { test_ctz_1() }); + (unsafe { test_clz_2() }); + (unsafe { test_bswap16_3() }); + (unsafe { test_bswap32_4() }); + (unsafe { test_bswap64_5() }); + (unsafe { test_ctzl_6() }); + (unsafe { test_popcountl_7() }); + (unsafe { test_mul_overflow_long_8() }); + (unsafe { test_mul_overflow_long_long_9() }); + (unsafe { test_ia32_pause_10() }); + return 0; +} diff --git a/tests/unit/out/unsafe/builtin_mul_overflow.rs b/tests/unit/out/unsafe/builtin_mul_overflow.rs deleted file mode 100644 index d78f3b5e..00000000 --- a/tests/unit/out/unsafe/builtin_mul_overflow.rs +++ /dev/null @@ -1,48 +0,0 @@ -extern crate libc; -use libc::*; -extern crate libcc2rs; -use libcc2rs::*; -use std::collections::BTreeMap; -use std::io::{Read, Seek, Write}; -use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; -use std::rc::Rc; -pub fn main() { - unsafe { - std::process::exit(main_0() as i32); - } -} -unsafe fn main_0() -> i32 { - let mut a: i64 = 0_i64; - assert!( - ((!{ - let (val, ovf) = 3_i64.overflowing_mul(7_i64); - *(&mut a as *mut i64) = val; - ovf - } as i32) - != 0) - ); - assert!(((((a) == (21_i64)) as i32) != 0)); - let mut b: i64 = 0_i64; - assert!({ - let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); - *(&mut b as *mut i64) = val; - ovf - }); - let mut c: i64 = 0_i64; - assert!( - ((!{ - let (val, ovf) = 1000_i64.overflowing_mul(1000_i64); - *(&mut c as *mut i64) = val; - ovf - } as i32) - != 0) - ); - assert!(((((c) == (1000000_i64)) as i32) != 0)); - let mut d: i64 = 0_i64; - assert!({ - let (val, ovf) = 9223372036854775807_i64.overflowing_mul(2_i64); - *(&mut d as *mut i64) = val; - ovf - }); - return 0; -} From 564235c83906a1a8911e47184859497c8b6e6dfe Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 22 May 2026 10:45:49 +0100 Subject: [PATCH 4/6] clang-format --- tests/unit/builtin.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/unit/builtin.c b/tests/unit/builtin.c index b0d639bb..f0ec63a9 100644 --- a/tests/unit/builtin.c +++ b/tests/unit/builtin.c @@ -68,9 +68,7 @@ static void test_mul_overflow_long_long(void) { } #if defined(__x86_64__) || defined(__i386__) -static void test_ia32_pause(void) { - __builtin_ia32_pause(); -} +static void test_ia32_pause(void) { __builtin_ia32_pause(); } #endif int main(void) { From e8baebb5cd2e10c0fecc0f0702435a07345134ea Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 22 May 2026 11:21:19 +0100 Subject: [PATCH 5/6] Delete unportable test --- tests/unit/builtin.c | 7 ------- tests/unit/out/refcount/builtin.rs | 4 ---- tests/unit/out/unsafe/builtin.rs | 4 ---- 3 files changed, 15 deletions(-) diff --git a/tests/unit/builtin.c b/tests/unit/builtin.c index f0ec63a9..a3a15328 100644 --- a/tests/unit/builtin.c +++ b/tests/unit/builtin.c @@ -67,10 +67,6 @@ static void test_mul_overflow_long_long(void) { assert(__builtin_mul_overflow(LLONG_MAX, 2LL, &r)); } -#if defined(__x86_64__) || defined(__i386__) -static void test_ia32_pause(void) { __builtin_ia32_pause(); } -#endif - int main(void) { test_expect(); test_ctz(); @@ -82,8 +78,5 @@ int main(void) { test_popcountl(); test_mul_overflow_long(); test_mul_overflow_long_long(); -#if defined(__x86_64__) || defined(__i386__) - test_ia32_pause(); -#endif return 0; } diff --git a/tests/unit/out/refcount/builtin.rs b/tests/unit/out/refcount/builtin.rs index 8be1d409..03266193 100644 --- a/tests/unit/out/refcount/builtin.rs +++ b/tests/unit/out/refcount/builtin.rs @@ -69,9 +69,6 @@ pub fn test_mul_overflow_long_long_9() { ovf }); } -pub fn test_ia32_pause_10() { - std::hint::spin_loop(); -} pub fn main() { std::process::exit(main_0()); } @@ -86,6 +83,5 @@ fn main_0() -> i32 { ({ test_popcountl_7() }); ({ test_mul_overflow_long_8() }); ({ test_mul_overflow_long_long_9() }); - ({ test_ia32_pause_10() }); return 0; } diff --git a/tests/unit/out/unsafe/builtin.rs b/tests/unit/out/unsafe/builtin.rs index 81e9936a..be8f48b9 100644 --- a/tests/unit/out/unsafe/builtin.rs +++ b/tests/unit/out/unsafe/builtin.rs @@ -69,9 +69,6 @@ pub unsafe fn test_mul_overflow_long_long_9() { ovf }); } -pub unsafe fn test_ia32_pause_10() { - std::hint::spin_loop(); -} pub fn main() { unsafe { std::process::exit(main_0() as i32); @@ -88,6 +85,5 @@ unsafe fn main_0() -> i32 { (unsafe { test_popcountl_7() }); (unsafe { test_mul_overflow_long_8() }); (unsafe { test_mul_overflow_long_long_9() }); - (unsafe { test_ia32_pause_10() }); return 0; } From fae4fc63209f52e1910ae2f8a97d08751ebbdf6f Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 22 May 2026 11:29:34 +0100 Subject: [PATCH 6/6] Delete unportable rule --- rules/builtin/ir_unsafe.json | 7 ------- rules/builtin/src.cpp | 3 --- rules/builtin/tgt_unsafe.rs | 4 ---- 3 files changed, 14 deletions(-) diff --git a/rules/builtin/ir_unsafe.json b/rules/builtin/ir_unsafe.json index f960be89..16b7c2cd 100644 --- a/rules/builtin/ir_unsafe.json +++ b/rules/builtin/ir_unsafe.json @@ -81,13 +81,6 @@ "type": "bool" } }, - "f11": { - "body": [ - { - "text": "std::hint::spin_loop()" - } - ] - }, "f2": { "body": [ { diff --git a/rules/builtin/src.cpp b/rules/builtin/src.cpp index d7148196..26da1699 100644 --- a/rules/builtin/src.cpp +++ b/rules/builtin/src.cpp @@ -23,6 +23,3 @@ int f7(unsigned long x) { return __builtin_ctzl(x); } int f8(unsigned long x) { return __builtin_popcountl(x); } bool f9(long a, long b, long *r) { return __builtin_mul_overflow(a, b, r); } bool f10(long long a, long long b, long long *r) { return __builtin_mul_overflow(a, b, r); } -#if defined(__x86_64__) || defined(__i386__) -void f11() { return __builtin_ia32_pause(); } -#endif diff --git a/rules/builtin/tgt_unsafe.rs b/rules/builtin/tgt_unsafe.rs index a66b8a2b..d2f94f66 100644 --- a/rules/builtin/tgt_unsafe.rs +++ b/rules/builtin/tgt_unsafe.rs @@ -35,7 +35,3 @@ unsafe fn f10(a0: i64, a1: i64, a2: *mut i64) -> bool { *a2 = val; ovf } -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] -unsafe fn f11() { - std::hint::spin_loop() -}