compiler-builtins-zynq/build.rs

4378 lines
99 KiB
Rust

#![feature(i128_type)]
use std::env;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
let target = env::var("TARGET").unwrap();
// Emscripten's runtime includes all the builtins
if target.contains("emscripten") {
return;
}
// NOTE we are going to assume that llvm-target, what determines our codegen option, matches the
// target triple. This is usually correct for our built-in targets but can break in presence of
// custom targets, which can have arbitrary names.
let llvm_target = target.split('-').collect::<Vec<_>>();
// Build test files
#[cfg(feature = "gen-tests")]
tests::generate();
// Build missing intrinsics from compiler-rt C source code. If we're
// mangling names though we assume that we're also in test mode so we don't
// build anything and we rely on the upstream implementation of compiler-rt
// functions
if !cfg!(feature = "mangled-names") {
#[cfg(feature = "c")]
c::compile(&llvm_target);
}
// To compile intrinsics.rs for thumb targets, where there is no libc
if llvm_target[0].starts_with("thumb") {
println!("cargo:rustc-cfg=thumb")
}
// compiler-rt `cfg`s away some intrinsics for thumbv6m because that target doesn't have full
// THUMBv2 support. We have to cfg our code accordingly.
if llvm_target[0] == "thumbv6m" {
println!("cargo:rustc-cfg=thumbv6m")
}
}
#[cfg(feature = "gen-tests")]
mod tests {
extern crate cast;
extern crate rand;
use std::collections::HashSet;
use std::fmt::Write;
use std::fs::File;
use std::hash::Hash;
use std::path::PathBuf;
use std::{env, mem};
use self::cast::{f32, f64, u32, u64, u128, i32, i64, i128};
use self::rand::Rng;
const NTESTS: usize = 10_000;
macro_rules! test {
($($intrinsic:ident,)+) => {
$(
mk_file::<$intrinsic>();
)+
}
}
pub fn generate() {
// TODO move to main
test! {
// float/add.rs
Adddf3,
Addsf3,
// float/conv.rs
Fixdfdi,
Fixdfsi,
Fixsfdi,
Fixsfsi,
Fixsfti,
Fixdfti,
Fixunsdfdi,
Fixunsdfsi,
Fixunssfdi,
Fixunssfsi,
Fixunssfti,
Fixunsdfti,
Floatdidf,
Floatsidf,
Floatsisf,
Floattisf,
Floattidf,
Floatundidf,
Floatunsidf,
Floatunsisf,
Floatuntisf,
Floatuntidf,
// float/pow.rs
Powidf2,
Powisf2,
// float/sub.rs
Subdf3,
Subsf3,
// int/mul.rs
Muldi3,
Mulodi4,
Mulosi4,
Muloti4,
Multi3,
// int/sdiv.rs
Divdi3,
Divmoddi4,
Divmodsi4,
Divsi3,
Divti3,
Moddi3,
Modsi3,
Modti3,
// int/shift.rs
Ashldi3,
Ashlti3,
Ashrdi3,
Ashrti3,
Lshrdi3,
Lshrti3,
// int/udiv.rs
Udivdi3,
Udivmoddi4,
Udivmodsi4,
Udivmodti4,
Udivsi3,
Udivti3,
Umoddi3,
Umodsi3,
Umodti3,
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Adddf3 {
a: u64, // f64
b: u64, // f64
c: u64, // f64
}
impl TestCase for Adddf3 {
fn name() -> &'static str {
"adddf3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
let b = gen_f64(rng);
let c = a + b;
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() || c.is_nan() {
return None;
}
Some(
Adddf3 {
a: to_u64(a),
b: to_u64(b),
c: to_u64(c),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::add::__adddf3;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64, u64), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn adddf3() {
for &((a, b), c) in TEST_CASES {
let c_ = __adddf3(mk_f64(a), mk_f64(b));
assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Addsf3 {
a: u32, // f32
b: u32, // f32
c: u32, // f32
}
impl TestCase for Addsf3 {
fn name() -> &'static str {
"addsf3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
let b = gen_f32(rng);
let c = a + b;
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() || c.is_nan() {
return None;
}
Some(
Addsf3 {
a: to_u32(a),
b: to_u32(b),
c: to_u32(c),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::add::__addsf3;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
fn to_u32(x: f32) -> u32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32, u32), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn addsf3() {
for &((a, b), c) in TEST_CASES {
let c_ = __addsf3(mk_f32(a), mk_f32(b));
assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Ashldi3 {
a: u64,
b: u32,
c: u64,
}
impl TestCase for Ashldi3 {
fn name() -> &'static str {
"ashldi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u64(rng);
let b = (rng.gen::<u8>() % 64) as u32;
let c = a << b;
Some(Ashldi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::shift::__ashldi3;
static TEST_CASES: &[((u64, u32), u64)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn ashldi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __ashldi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Ashlti3 {
a: u128,
b: u32,
c: u128,
}
impl TestCase for Ashlti3 {
fn name() -> &'static str {
"ashlti3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u128(rng);
let b = (rng.gen::<u8>() % 128) as u32;
let c = a << b;
Some(Ashlti3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::shift::__ashlti3;
static TEST_CASES: &[((u128, u32), u128)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn ashlti3() {
for &((a, b), c) in TEST_CASES {
let c_ = __ashlti3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Ashrdi3 {
a: i64,
b: u32,
c: i64,
}
impl TestCase for Ashrdi3 {
fn name() -> &'static str {
"ashrdi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i64(rng);
let b = (rng.gen::<u8>() % 64) as u32;
let c = a >> b;
Some(Ashrdi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::shift::__ashrdi3;
static TEST_CASES: &[((i64, u32), i64)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn ashrdi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __ashrdi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Ashrti3 {
a: i128,
b: u32,
c: i128,
}
impl TestCase for Ashrti3 {
fn name() -> &'static str {
"ashrti3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i128(rng);
let b = (rng.gen::<u8>() % 128) as u32;
let c = a >> b;
Some(Ashrti3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::shift::__ashrti3;
static TEST_CASES: &[((i128, u32), i128)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn ashrti3() {
for &((a, b), c) in TEST_CASES {
let c_ = __ashrti3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Divmoddi4 {
a: i64,
b: i64,
c: i64,
rem: i64,
}
impl TestCase for Divmoddi4 {
fn name() -> &'static str {
"divmoddi4"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i64(rng);
let b = gen_i64(rng);
if b == 0 {
return None;
}
let c = a / b;
let rem = a % b;
Some(Divmoddi4 { a, b, c, rem })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), ({c}, {rem})),",
a = self.a,
b = self.b,
c = self.c,
rem = self.rem
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::sdiv::__divmoddi4;
static TEST_CASES: &[((i64, i64), (i64, i64))] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn divmoddi4() {
for &((a, b), (c, rem)) in TEST_CASES {
let mut rem_ = 0;
let c_ = __divmoddi4(a, b, &mut rem_);
assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Divdi3 {
a: i64,
b: i64,
c: i64,
}
impl TestCase for Divdi3 {
fn name() -> &'static str {
"divdi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i64(rng);
let b = gen_i64(rng);
if b == 0 {
return None;
}
let c = a / b;
Some(Divdi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::sdiv::__divdi3;
static TEST_CASES: &[((i64, i64), i64)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn divdi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __divdi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Divmodsi4 {
a: i32,
b: i32,
c: i32,
rem: i32,
}
impl TestCase for Divmodsi4 {
fn name() -> &'static str {
"divmodsi4"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i32(rng);
let b = gen_i32(rng);
if b == 0 {
return None;
}
let c = a / b;
let rem = a % b;
Some(Divmodsi4 { a, b, c, rem })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), ({c}, {rem})),",
a = self.a,
b = self.b,
c = self.c,
rem = self.rem
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::sdiv::__divmodsi4;
static TEST_CASES: &[((i32, i32), (i32, i32))] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn divmodsi4() {
for &((a, b), (c, rem)) in TEST_CASES {
let mut rem_ = 0;
let c_ = __divmodsi4(a, b, &mut rem_);
assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Divsi3 {
a: i32,
b: i32,
c: i32,
}
impl TestCase for Divsi3 {
fn name() -> &'static str {
"divsi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i32(rng);
let b = gen_i32(rng);
if b == 0 {
return None;
}
let c = a / b;
Some(Divsi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::sdiv::__divsi3;
static TEST_CASES: &[((i32, i32), i32)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn divsi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __divsi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Divti3 {
a: i128,
b: i128,
c: i128,
}
impl TestCase for Divti3 {
fn name() -> &'static str {
"divti3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i128(rng);
let b = gen_i128(rng);
if b == 0 {
return None;
}
let c = a / b;
Some(Divti3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::sdiv::__divti3;
static TEST_CASES: &[((i128, i128), i128)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn divti3() {
for &((a, b), c) in TEST_CASES {
let c_ = __divti3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixdfdi {
a: u64, // f64
b: i64,
}
impl TestCase for Fixdfdi {
fn name() -> &'static str {
"fixdfdi"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
i64(a).ok().map(|b| Fixdfdi { a: to_u64(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixdfdi;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64,), i64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixdfdi() {
for &((a,), b) in TEST_CASES {
let b_ = __fixdfdi(mk_f64(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixdfsi {
a: u64, // f64
b: i32,
}
impl TestCase for Fixdfsi {
fn name() -> &'static str {
"fixdfsi"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
i32(a).ok().map(|b| Fixdfsi { a: to_u64(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixdfsi;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64,), i32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixdfdi() {
for &((a,), b) in TEST_CASES {
let b_ = __fixdfsi(mk_f64(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixsfdi {
a: u32, // f32
b: i64,
}
impl TestCase for Fixsfdi {
fn name() -> &'static str {
"fixsfdi"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
i64(a).ok().map(|b| Fixsfdi { a: to_u32(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixsfdi;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32,), i64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixsfdi() {
for &((a,), b) in TEST_CASES {
let b_ = __fixsfdi(mk_f32(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixsfsi {
a: u32, // f32
b: i32,
}
impl TestCase for Fixsfsi {
fn name() -> &'static str {
"fixsfsi"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
i32(a).ok().map(|b| Fixsfsi { a: to_u32(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixsfsi;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32,), i32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixsfsi() {
for &((a,), b) in TEST_CASES {
let b_ = __fixsfsi(mk_f32(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixsfti {
a: u32, // f32
b: i128,
}
impl TestCase for Fixsfti {
fn name() -> &'static str {
"fixsfti"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
i128(a).ok().map(|b| Fixsfti { a: to_u32(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixsfti;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32,), i128)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixsfti() {
for &((a,), b) in TEST_CASES {
let b_ = __fixsfti(mk_f32(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixdfti {
a: u64, // f64
b: i128,
}
impl TestCase for Fixdfti {
fn name() -> &'static str {
"fixdfti"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
i128(a).ok().map(|b| Fixdfti { a: to_u64(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixdfti;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64,), i128)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixdfti() {
for &((a,), b) in TEST_CASES {
let b_ = __fixdfti(mk_f64(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixunsdfdi {
a: u64, // f64
b: u64,
}
impl TestCase for Fixunsdfdi {
fn name() -> &'static str {
"fixunsdfdi"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
u64(a).ok().map(|b| Fixunsdfdi { a: to_u64(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixunsdfdi;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64,), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixunsdfdi() {
for &((a,), b) in TEST_CASES {
let b_ = __fixunsdfdi(mk_f64(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixunsdfsi {
a: u64, // f64
b: u32,
}
impl TestCase for Fixunsdfsi {
fn name() -> &'static str {
"fixunsdfsi"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
u32(a).ok().map(|b| Fixunsdfsi { a: to_u64(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixunsdfsi;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64,), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixunsdfdi() {
for &((a,), b) in TEST_CASES {
let b_ = __fixunsdfsi(mk_f64(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixunssfdi {
a: u32, // f32
b: u64,
}
impl TestCase for Fixunssfdi {
fn name() -> &'static str {
"fixunssfdi"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
u64(a).ok().map(|b| Fixunssfdi { a: to_u32(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixunssfdi;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32,), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixunssfdi() {
for &((a,), b) in TEST_CASES {
let b_ = __fixunssfdi(mk_f32(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixunssfsi {
a: u32, // f32
b: u32,
}
impl TestCase for Fixunssfsi {
fn name() -> &'static str {
"fixunssfsi"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
u32(a).ok().map(|b| Fixunssfsi { a: to_u32(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixunssfsi;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32,), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixunssfsi() {
for &((a,), b) in TEST_CASES {
let b_ = __fixunssfsi(mk_f32(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixunssfti {
a: u32, // f32
b: u128,
}
impl TestCase for Fixunssfti {
fn name() -> &'static str {
"fixunssfti"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
u128(a).ok().map(|b| Fixunssfti { a: to_u32(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixunssfti;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32,), u128)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixunssfti() {
for &((a,), b) in TEST_CASES {
let b_ = __fixunssfti(mk_f32(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Fixunsdfti {
a: u64, // f64
b: u128,
}
impl TestCase for Fixunsdfti {
fn name() -> &'static str {
"fixunsdfti"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
u128(a).ok().map(|b| Fixunsdfti { a: to_u64(a), b })
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__fixunsdfti;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64,), u128)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn fixunsdfti() {
for &((a,), b) in TEST_CASES {
let b_ = __fixunsdfti(mk_f64(a));
assert_eq!(((a,), b), ((a,), b_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Floatdidf {
a: i64,
b: u64, // f64
}
impl TestCase for Floatdidf {
fn name() -> &'static str {
"floatdidf"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i64(rng);
Some(
Floatdidf {
a,
b: to_u64(f64(a)),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__floatdidf;
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((i64,), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn floatdidf() {
for &((a,), b) in TEST_CASES {
let b_ = __floatdidf(a);
assert_eq!(((a,), b), ((a,), to_u64(b_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Floatsidf {
a: i32,
b: u64, // f64
}
impl TestCase for Floatsidf {
fn name() -> &'static str {
"floatsidf"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i32(rng);
Some(
Floatsidf {
a,
b: to_u64(f64(a)),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__floatsidf;
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((i32,), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn floatsidf() {
for &((a,), b) in TEST_CASES {
let b_ = __floatsidf(a);
assert_eq!(((a,), b), ((a,), to_u64(b_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Floatsisf {
a: i32,
b: u32, // f32
}
impl TestCase for Floatsisf {
fn name() -> &'static str {
"floatsisf"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i32(rng);
Some(
Floatsisf {
a,
b: to_u32(f32(a)),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__floatsisf;
fn to_u32(x: f32) -> u32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((i32,), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn floatsisf() {
for &((a,), b) in TEST_CASES {
let b_ = __floatsisf(a);
assert_eq!(((a,), b), ((a,), to_u32(b_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Floattisf {
a: i128,
b: u32, // f32
}
impl TestCase for Floattisf {
fn name() -> &'static str {
"floattisf"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i128(rng);
Some(
Floattisf {
a,
b: to_u32(f32(a)),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__floattisf;
fn to_u32(x: f32) -> u32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((i128,), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn floattisf() {
for &((a,), b) in TEST_CASES {
let b_ = __floattisf(a);
assert_eq!(((a,), b), ((a,), to_u32(b_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Floattidf {
a: i128,
b: u64, // f64
}
impl TestCase for Floattidf {
fn name() -> &'static str {
"floattidf"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i128(rng);
Some(
Floattidf {
a,
b: to_u64(f64(a)),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__floattidf;
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((i128,), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn floattidf() {
for &((a,), b) in TEST_CASES {
let b_ = __floattidf(a);
let g_b = to_u64(b_);
let diff = if g_b > b { g_b - b } else { b - g_b };
assert_eq!(((a,), b, g_b, true), ((a,), b, g_b, diff <= 1));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Floatundidf {
a: u64,
b: u64, // f64
}
impl TestCase for Floatundidf {
fn name() -> &'static str {
"floatundidf"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u64(rng);
Some(
Floatundidf {
a,
b: to_u64(f64(a)),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__floatundidf;
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64,), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn floatundidf() {
for &((a,), b) in TEST_CASES {
let b_ = __floatundidf(a);
assert_eq!(((a,), b), ((a,), to_u64(b_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Floatunsidf {
a: u32,
b: u64, // f64
}
impl TestCase for Floatunsidf {
fn name() -> &'static str {
"floatunsidf"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u32(rng);
Some(
Floatunsidf {
a,
b: to_u64(f64(a)),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__floatunsidf;
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32,), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn floatunsidf() {
for &((a,), b) in TEST_CASES {
let b_ = __floatunsidf(a);
assert_eq!(((a,), b), ((a,), to_u64(b_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Floatunsisf {
a: u32,
b: u32, // f32
}
impl TestCase for Floatunsisf {
fn name() -> &'static str {
"floatunsisf"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u32(rng);
Some(
Floatunsisf {
a,
b: to_u32(f32(a)),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__floatunsisf;
fn to_u32(x: f32) -> u32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32,), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn floatunsisf() {
for &((a,), b) in TEST_CASES {
let b_ = __floatunsisf(a);
assert_eq!(((a,), b), ((a,), to_u32(b_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Floatuntisf {
a: u128,
b: u32, // f32
}
impl TestCase for Floatuntisf {
fn name() -> &'static str {
"floatuntisf"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u128(rng);
let f_a = f32(a);
f_a.ok().map(|f| {
Floatuntisf {
a,
b: to_u32(f),
}
})
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__floatuntisf;
fn to_u32(x: f32) -> u32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u128,), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn floatuntisf() {
for &((a,), b) in TEST_CASES {
let b_ = __floatuntisf(a);
assert_eq!(((a,), b), ((a,), to_u32(b_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Floatuntidf {
a: u128,
b: u64, // f64
}
impl TestCase for Floatuntidf {
fn name() -> &'static str {
"floatuntidf"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u128(rng);
Some(
Floatuntidf {
a,
b: to_u64(f64(a)),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::conv::__floatuntidf;
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u128,), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn floatuntidf() {
for &((a,), b) in TEST_CASES {
let b_ = __floatuntidf(a);
let g_b = to_u64(b_);
let diff = if g_b > b { g_b - b } else { b - g_b };
assert_eq!(((a,), b, g_b, true), ((a,), b, g_b, diff <= 1));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Moddi3 {
a: i64,
b: i64,
c: i64,
}
impl TestCase for Moddi3 {
fn name() -> &'static str {
"moddi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i64(rng);
let b = gen_i64(rng);
if b == 0 {
return None;
}
let c = a % b;
Some(Moddi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::sdiv::__moddi3;
static TEST_CASES: &[((i64, i64), i64)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn moddi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __moddi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Modsi3 {
a: i32,
b: i32,
c: i32,
}
impl TestCase for Modsi3 {
fn name() -> &'static str {
"modsi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i32(rng);
let b = gen_i32(rng);
if b == 0 {
return None;
}
let c = a % b;
Some(Modsi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::sdiv::__modsi3;
static TEST_CASES: &[((i32, i32), i32)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn modsi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __modsi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Modti3 {
a: i128,
b: i128,
c: i128,
}
impl TestCase for Modti3 {
fn name() -> &'static str {
"modti3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i128(rng);
let b = gen_i128(rng);
if b == 0 {
return None;
}
let c = a % b;
Some(Modti3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::sdiv::__modti3;
static TEST_CASES: &[((i128, i128), i128)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn modti3() {
for &((a, b), c) in TEST_CASES {
let c_ = __modti3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
struct Muldi3 {
a: u64,
b: u64,
c: u64,
}
impl TestCase for Muldi3 {
fn name() -> &'static str {
"muldi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u64(rng);
let b = gen_u64(rng);
let c = a.wrapping_mul(b);
Some(Muldi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::mul::__muldi3;
static TEST_CASES: &[((u64, u64), u64)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn muldi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __muldi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Mulodi4 {
a: i64,
b: i64,
c: i64,
overflow: u32,
}
impl TestCase for Mulodi4 {
fn name() -> &'static str {
"mulodi4"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
{
let a = gen_i64(rng);
let b = gen_i64(rng);
let c = a.wrapping_mul(b);
let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 };
Some(Mulodi4 { a, b, c, overflow })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), ({c}, {overflow})),",
a = self.a,
b = self.b,
c = self.c,
overflow = self.overflow
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::mul::__mulodi4;
static TEST_CASES: &[((i64, i64), (i64, i32))] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn mulodi4() {
let mut overflow_ = 2;
for &((a, b), (c, overflow)) in TEST_CASES {
let c_ = __mulodi4(a, b, &mut overflow_);
assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Mulosi4 {
a: i32,
b: i32,
c: i32,
overflow: u32,
}
impl TestCase for Mulosi4 {
fn name() -> &'static str {
"mulosi4"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
{
let a = gen_i32(rng);
let b = gen_i32(rng);
let c = a.wrapping_mul(b);
let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 };
Some(Mulosi4 { a, b, c, overflow })
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::mul::__mulosi4;
static TEST_CASES: &[((i32, i32), (i32, i32))] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn mulosi4() {
let mut overflow_ = 2;
for &((a, b), (c, overflow)) in TEST_CASES {
let c_ = __mulosi4(a, b, &mut overflow_);
assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_)));
}
}
"
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), ({c}, {overflow})),",
a = self.a,
b = self.b,
c = self.c,
overflow = self.overflow
)
.unwrap();
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Muloti4 {
a: i128,
b: i128,
c: i128,
overflow: u32,
}
impl TestCase for Muloti4 {
fn name() -> &'static str {
"muloti4"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
{
let a = gen_i128(rng);
let b = gen_i128(rng);
let c = a.wrapping_mul(b);
let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 };
Some(Muloti4 { a, b, c, overflow })
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::mul::__muloti4;
static TEST_CASES: &[((i128, i128), (i128, i32))] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn muloti4() {
let mut overflow_ = 2;
for &((a, b), (c, overflow)) in TEST_CASES {
let c_ = __muloti4(a, b, &mut overflow_);
assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_)));
}
}
"
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), ({c}, {overflow})),",
a = self.a,
b = self.b,
c = self.c,
overflow = self.overflow
)
.unwrap();
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Multi3 {
a: i128,
b: i128,
c: i128,
}
impl TestCase for Multi3 {
fn name() -> &'static str {
"multi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_i128(rng);
let b = gen_i128(rng);
let c = a.wrapping_mul(b);
Some(Multi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::mul::__multi3;
static TEST_CASES: &[((i128, i128), i128)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn multi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __multi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Powidf2 {
a: u64, // f64
b: i32,
c: u64, // f64
}
impl TestCase for Powidf2 {
fn name() -> &'static str {
"powidf2"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
let b = gen_i32(rng);
let c = a.powi(b);
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets
if a.is_nan() || c.is_nan() {
return None;
}
Some(
Powidf2 {
a: to_u64(a),
b,
c: to_u64(c),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::pow::__powidf2;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64, i32), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn powidf2() {
for &((a, b), c) in TEST_CASES {
let c_ = __powidf2(mk_f64(a), b);
assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Powisf2 {
a: u32, // f32
b: i32,
c: u32, // f32
}
impl TestCase for Powisf2 {
fn name() -> &'static str {
"powisf2"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
let b = gen_i32(rng);
let c = a.powi(b);
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets
if a.is_nan() || c.is_nan() {
return None;
}
Some(
Powisf2 {
a: to_u32(a),
b,
c: to_u32(c),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::pow::__powisf2;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
fn to_u32(x: f32) -> u32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32, i32), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn powisf2() {
for &((a, b), c) in TEST_CASES {
let c_ = __powisf2(mk_f32(a), b);
assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Lshrdi3 {
a: u64,
b: u32,
c: u64,
}
impl TestCase for Lshrdi3 {
fn name() -> &'static str {
"lshrdi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u64(rng);
let b = (rng.gen::<u8>() % 64) as u32;
let c = a >> b;
Some(Lshrdi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::shift::__lshrdi3;
static TEST_CASES: &[((u64, u32), u64)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn lshrdi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __lshrdi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Lshrti3 {
a: u128,
b: u32,
c: u128,
}
impl TestCase for Lshrti3 {
fn name() -> &'static str {
"lshrti3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u128(rng);
let b = (rng.gen::<u8>() % 128) as u32;
let c = a >> b;
Some(Lshrti3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::shift::__lshrti3;
static TEST_CASES: &[((u128, u32), u128)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn lshrti3() {
for &((a, b), c) in TEST_CASES {
let c_ = __lshrti3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Subdf3 {
a: u64, // f64
b: u64, // f64
c: u64, // f64
}
impl TestCase for Subdf3 {
fn name() -> &'static str {
"subdf3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
let b = gen_f64(rng);
let c = a - b;
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() || c.is_nan() {
return None;
}
Some(
Subdf3 {
a: to_u64(a),
b: to_u64(b),
c: to_u64(c),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::sub::__subdf3;
fn mk_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64, u64), u64)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn subdf3() {
for &((a, b), c) in TEST_CASES {
let c_ = __subdf3(mk_f64(a), mk_f64(b));
assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Subsf3 {
a: u32, // f32
b: u32, // f32
c: u32, // f32
}
impl TestCase for Subsf3 {
fn name() -> &'static str {
"subsf3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
let b = gen_f32(rng);
let c = a - b;
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() || c.is_nan() {
return None;
}
Some(
Subsf3 {
a: to_u32(a),
b: to_u32(b),
c: to_u32(c),
},
)
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
r#"
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
use core::mem;
#[cfg(not(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test)))]
use std::mem;
use compiler_builtins::float::sub::__subsf3;
fn mk_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
fn to_u32(x: f32) -> u32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32, u32), u32)] = &[
"#
}
fn epilogue() -> &'static str {
"
];
#[test]
fn subsf3() {
for &((a, b), c) in TEST_CASES {
let c_ = __subsf3(mk_f32(a), mk_f32(b));
assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Udivdi3 {
a: u64,
b: u64,
c: u64,
}
impl TestCase for Udivdi3 {
fn name() -> &'static str {
"udivdi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u64(rng);
let b = gen_u64(rng);
if b == 0 {
return None;
}
let c = a / b;
Some(Udivdi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::udiv::__udivdi3;
static TEST_CASES: &[((u64, u64), u64)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn udivdi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __udivdi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Udivmoddi4 {
a: u64,
b: u64,
c: u64,
rem: u64,
}
impl TestCase for Udivmoddi4 {
fn name() -> &'static str {
"udivmoddi4"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u64(rng);
let b = gen_u64(rng);
if b == 0 {
return None;
}
let c = a / b;
let rem = a % b;
Some(Udivmoddi4 { a, b, c, rem })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), ({c}, {rem})),",
a = self.a,
b = self.b,
c = self.c,
rem = self.rem
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::udiv::__udivmoddi4;
static TEST_CASES: &[((u64, u64), (u64, u64))] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn udivmoddi4() {
for &((a, b), (c, rem)) in TEST_CASES {
let mut rem_ = 0;
let c_ = __udivmoddi4(a, b, Some(&mut rem_));
assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Udivmodsi4 {
a: u32,
b: u32,
c: u32,
rem: u32,
}
impl TestCase for Udivmodsi4 {
fn name() -> &'static str {
"udivmodsi4"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u32(rng);
let b = gen_u32(rng);
if b == 0 {
return None;
}
let c = a / b;
let rem = a % b;
Some(Udivmodsi4 { a, b, c, rem })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), ({c}, {rem})),",
a = self.a,
b = self.b,
c = self.c,
rem = self.rem
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::udiv::__udivmodsi4;
static TEST_CASES: &[((u32, u32), (u32, u32))] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn udivmodsi4() {
for &((a, b), (c, rem)) in TEST_CASES {
let mut rem_ = 0;
let c_ = __udivmodsi4(a, b, Some(&mut rem_));
assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Udivmodti4 {
a: u128,
b: u128,
c: u128,
rem: u128,
}
impl TestCase for Udivmodti4 {
fn name() -> &'static str {
"udivmodti4"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u128(rng);
let b = gen_u128(rng);
if b == 0 {
return None;
}
let c = a / b;
let rem = a % b;
Some(Udivmodti4 { a, b, c, rem })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), ({c}, {rem})),",
a = self.a,
b = self.b,
c = self.c,
rem = self.rem
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::udiv::__udivmodti4;
static TEST_CASES: &[((u128, u128), (u128, u128))] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn udivmodti4() {
for &((a, b), (c, rem)) in TEST_CASES {
let mut rem_ = 0;
let c_ = __udivmodti4(a, b, Some(&mut rem_));
assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Udivsi3 {
a: u32,
b: u32,
c: u32,
}
impl TestCase for Udivsi3 {
fn name() -> &'static str {
"udivsi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u32(rng);
let b = gen_u32(rng);
if b == 0 {
return None;
}
let c = a / b;
Some(Udivsi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::udiv::__udivsi3;
static TEST_CASES: &[((u32, u32), u32)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn udivsi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __udivsi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Udivti3 {
a: u128,
b: u128,
c: u128,
}
impl TestCase for Udivti3 {
fn name() -> &'static str {
"udivti3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u128(rng);
let b = gen_u128(rng);
if b == 0 {
return None;
}
let c = a / b;
Some(Udivti3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::udiv::__udivti3;
static TEST_CASES: &[((u128, u128), u128)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn udivti3() {
for &((a, b), c) in TEST_CASES {
let c_ = __udivti3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Umoddi3 {
a: u64,
b: u64,
c: u64,
}
impl TestCase for Umoddi3 {
fn name() -> &'static str {
"umoddi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u64(rng);
let b = gen_u64(rng);
if b == 0 {
return None;
}
let c = a % b;
Some(Umoddi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::udiv::__umoddi3;
static TEST_CASES: &[((u64, u64), u64)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn umoddi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __umoddi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Umodsi3 {
a: u32,
b: u32,
c: u32,
}
impl TestCase for Umodsi3 {
fn name() -> &'static str {
"umodsi3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u32(rng);
let b = gen_u32(rng);
if b == 0 {
return None;
}
let c = a % b;
Some(Umodsi3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::udiv::__umodsi3;
static TEST_CASES: &[((u32, u32), u32)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn umodsi3() {
for &((a, b), c) in TEST_CASES {
let c_ = __umodsi3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
#[derive(Eq, Hash, PartialEq)]
pub struct Umodti3 {
a: u128,
b: u128,
c: u128,
}
impl TestCase for Umodti3 {
fn name() -> &'static str {
"umodti3"
}
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_u128(rng);
let b = gen_u128(rng);
if b == 0 {
return None;
}
let c = a % b;
Some(Umodti3 { a, b, c })
}
fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}
fn prologue() -> &'static str {
"
use compiler_builtins::int::udiv::__umodti3;
static TEST_CASES: &[((u128, u128), u128)] = &[
"
}
fn epilogue() -> &'static str {
"
];
#[test]
fn umodti3() {
for &((a, b), c) in TEST_CASES {
let c_ = __umodti3(a, b);
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}
trait TestCase {
/// Name of the intrinsic to test
fn name() -> &'static str;
/// Generates a valid test case
fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized;
/// Stringifies a test case
fn to_string(&self, buffer: &mut String);
/// Prologue of the test file
fn prologue() -> &'static str;
/// Epilogue of the test file
fn epilogue() -> &'static str;
}
const PROLOGUE: &'static str = r#"
extern crate compiler_builtins;
// test runner
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
extern crate utest_cortex_m_qemu;
// overrides `panic!`
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
#[macro_use]
extern crate utest_macros;
#[cfg(all(target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
test))]
macro_rules! panic {
($($tt:tt)*) => {
upanic!($($tt)*);
};
}
"#;
macro_rules! gen_int {
($name:ident, $ity:ident, $hty:ident) => {
fn $name<R>(rng: &mut R) -> $ity
where
R: Rng,
{
let mut mk = || if rng.gen_weighted_bool(10) {
*rng.choose(&[::std::$hty::MAX, 0, ::std::$hty::MIN]).unwrap()
} else {
rng.gen::<$hty>()
};
unsafe { mem::transmute([mk(), mk()]) }
}
}
}
gen_int!(gen_i32, i32, i16);
gen_int!(gen_i64, i64, i32);
gen_int!(gen_i128, i128, i64);
macro_rules! gen_float {
($name:ident,
$fty:ident,
$uty:ident,
$bits:expr,
$significand_bits:expr) => {
pub fn $name<R>(rng: &mut R) -> $fty
where
R: Rng,
{
const BITS: u8 = $bits;
const SIGNIFICAND_BITS: u8 = $significand_bits;
const SIGNIFICAND_MASK: $uty = (1 << SIGNIFICAND_BITS) - 1;
const SIGN_MASK: $uty = (1 << (BITS - 1));
const EXPONENT_MASK: $uty = !(SIGN_MASK | SIGNIFICAND_MASK);
fn mk_f32(sign: bool, exponent: $uty, significand: $uty) -> $fty {
unsafe {
mem::transmute(((sign as $uty) << (BITS - 1)) |
((exponent & EXPONENT_MASK) <<
SIGNIFICAND_BITS) |
(significand & SIGNIFICAND_MASK))
}
}
if rng.gen_weighted_bool(10) {
// Special values
*rng.choose(&[-0.0,
0.0,
::std::$fty::NAN,
::std::$fty::INFINITY,
-::std::$fty::INFINITY])
.unwrap()
} else if rng.gen_weighted_bool(10) {
// NaN patterns
mk_f32(rng.gen(), rng.gen(), 0)
} else if rng.gen() {
// Denormalized
mk_f32(rng.gen(), 0, rng.gen())
} else {
// Random anything
mk_f32(rng.gen(), rng.gen(), rng.gen())
}
}
}
}
gen_float!(gen_f32, f32, u32, 32, 23);
gen_float!(gen_f64, f64, u64, 64, 52);
pub fn gen_u128<R>(rng: &mut R) -> u128
where
R: Rng,
{
gen_i128(rng) as u128
}
pub fn gen_u32<R>(rng: &mut R) -> u32
where
R: Rng,
{
gen_i32(rng) as u32
}
fn gen_u64<R>(rng: &mut R) -> u64
where
R: Rng,
{
gen_i64(rng) as u64
}
pub fn to_u32(x: f32) -> u32 {
unsafe { mem::transmute(x) }
}
pub fn to_u64(x: f64) -> u64 {
unsafe { mem::transmute(x) }
}
fn mk_tests<T, R>(mut n: usize, rng: &mut R) -> String
where
T: Eq + Hash + TestCase,
R: Rng,
{
let mut buffer = PROLOGUE.to_owned();
buffer.push_str(T::prologue());
let mut cases = HashSet::new();
while n != 0 {
if let Some(case) = T::generate(rng) {
if cases.contains(&case) {
continue;
}
case.to_string(&mut buffer);
n -= 1;
cases.insert(case);
}
}
buffer.push_str(T::epilogue());
buffer
}
fn mk_file<T>()
where
T: Eq + Hash + TestCase,
{
use std::io::Write;
let rng = &mut rand::thread_rng();
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let out_file_name = format!("{}.rs", T::name());
let out_file = out_dir.join(&out_file_name);
println!("Generating {}", out_file_name);
let contents = mk_tests::<T, _>(NTESTS, rng);
File::create(out_file)
.unwrap()
.write_all(contents.as_bytes())
.unwrap();
}
}
#[cfg(feature = "c")]
mod c {
extern crate gcc;
use std::collections::BTreeMap;
use std::env;
use std::path::Path;
struct Sources {
// SYMBOL -> PATH TO SOURCE
map: BTreeMap<&'static str, &'static str>,
}
impl Sources {
fn new() -> Sources {
Sources { map: BTreeMap::new() }
}
fn extend(&mut self, sources: &[&'static str]) {
// NOTE Some intrinsics have both a generic implementation (e.g.
// `floatdidf.c`) and an arch optimized implementation
// (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized
// implementation and discard the generic implementation. If we don't
// and keep both implementations, the linker will yell at us about
// duplicate symbols!
for &src in sources {
let symbol = Path::new(src).file_stem().unwrap().to_str().unwrap();
if src.contains("/") {
// Arch-optimized implementation (preferred)
self.map.insert(symbol, src);
} else {
// Generic implementation
if !self.map.contains_key(symbol) {
self.map.insert(symbol, src);
}
}
}
}
fn remove(&mut self, symbols: &[&str]) {
for symbol in symbols {
self.map.remove(*symbol).unwrap();
}
}
}
/// Compile intrinsics from the compiler-rt C source code
pub fn compile(llvm_target: &[&str]) {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
let cfg = &mut gcc::Build::new();
cfg.warnings(false);
if target_env == "msvc" {
// Don't pull in extra libraries on MSVC
cfg.flag("/Zl");
// Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
cfg.define("__func__", Some("__FUNCTION__"));
} else {
// Turn off various features of gcc and such, mostly copying
// compiler-rt's build system already
cfg.flag("-fno-builtin");
cfg.flag("-fvisibility=hidden");
cfg.flag("-fomit-frame-pointer");
cfg.flag("-ffreestanding");
cfg.define("VISIBILITY_HIDDEN", None);
}
// NOTE Most of the ARM intrinsics are written in assembly. Tell gcc which arch we are going
// to target to make sure that the assembly implementations really work for the target. If
// the implementation is not valid for the arch, then gcc will error when compiling it.
if llvm_target[0].starts_with("thumb") {
cfg.flag("-mthumb");
if llvm_target.last() == Some(&"eabihf") {
cfg.flag("-mfloat-abi=hard");
}
}
if llvm_target[0] == "thumbv6m" {
cfg.flag("-march=armv6-m");
}
if llvm_target[0] == "thumbv7m" {
cfg.flag("-march=armv7-m");
}
if llvm_target[0] == "thumbv7em" {
cfg.flag("-march=armv7e-m");
}
let mut sources = Sources::new();
sources.extend(
&[
"absvdi2.c",
"absvsi2.c",
"addvdi3.c",
"addvsi3.c",
"apple_versioning.c",
"clzdi2.c",
"clzsi2.c",
"cmpdi2.c",
"comparedf2.c",
"comparesf2.c",
"ctzdi2.c",
"ctzsi2.c",
"divdc3.c",
"divdf3.c",
"divsc3.c",
"divsf3.c",
"divxc3.c",
"extendsfdf2.c",
"extendhfsf2.c",
"floatdisf.c",
"floatundisf.c",
"int_util.c",
"muldc3.c",
"muldf3.c",
"mulsc3.c",
"mulsf3.c",
"mulvdi3.c",
"mulvsi3.c",
"mulxc3.c",
"negdf2.c",
"negdi2.c",
"negsf2.c",
"negvdi2.c",
"negvsi2.c",
"paritydi2.c",
"paritysi2.c",
"popcountdi2.c",
"popcountsi2.c",
"powixf2.c",
"subvdi3.c",
"subvsi3.c",
"truncdfhf2.c",
"truncdfsf2.c",
"truncsfhf2.c",
"ucmpdi2.c",
],
);
// When compiling in rustbuild (the rust-lang/rust repo) this library
// also needs to satisfy intrinsics that jemalloc or C in general may
// need, so include a few more that aren't typically needed by
// LLVM/Rust.
sources.extend(&[
"ffsdi2.c",
]);
if target_os != "ios" {
sources.extend(
&[
"absvti2.c",
"addvti3.c",
"clzti2.c",
"cmpti2.c",
"ctzti2.c",
"ffsti2.c",
"mulvti3.c",
"negti2.c",
"negvti2.c",
"parityti2.c",
"popcountti2.c",
"subvti3.c",
"ucmpti2.c",
],
);
}
if target_vendor == "apple" {
sources.extend(
&[
"atomic_flag_clear.c",
"atomic_flag_clear_explicit.c",
"atomic_flag_test_and_set.c",
"atomic_flag_test_and_set_explicit.c",
"atomic_signal_fence.c",
"atomic_thread_fence.c",
],
);
}
if target_env == "msvc" {
if target_arch == "x86_64" {
sources.extend(
&[
"x86_64/floatdisf.c",
"x86_64/floatdixf.c",
],
);
}
} else {
// None of these seem to be used on x86_64 windows, and they've all
// got the wrong ABI anyway, so we want to avoid them.
if target_os != "windows" {
if target_arch == "x86_64" {
sources.extend(
&[
"x86_64/floatdisf.c",
"x86_64/floatdixf.c",
"x86_64/floatundidf.S",
"x86_64/floatundisf.S",
"x86_64/floatundixf.S",
],
);
}
}
if target_arch == "x86" {
sources.extend(
&[
"i386/ashldi3.S",
"i386/ashrdi3.S",
"i386/chkstk.S",
"i386/chkstk2.S",
"i386/divdi3.S",
"i386/floatdidf.S",
"i386/floatdisf.S",
"i386/floatdixf.S",
"i386/floatundidf.S",
"i386/floatundisf.S",
"i386/floatundixf.S",
"i386/lshrdi3.S",
"i386/moddi3.S",
"i386/muldi3.S",
"i386/udivdi3.S",
"i386/umoddi3.S",
],
);
}
}
if target_arch == "arm" && target_os != "ios" {
sources.extend(
&[
"arm/aeabi_cdcmp.S",
"arm/aeabi_cdcmpeq_check_nan.c",
"arm/aeabi_cfcmp.S",
"arm/aeabi_cfcmpeq_check_nan.c",
"arm/aeabi_dcmp.S",
"arm/aeabi_div0.c",
"arm/aeabi_drsub.c",
"arm/aeabi_fcmp.S",
"arm/aeabi_frsub.c",
"arm/bswapdi2.S",
"arm/bswapsi2.S",
"arm/clzdi2.S",
"arm/clzsi2.S",
"arm/comparesf2.S",
"arm/divmodsi4.S",
"arm/modsi3.S",
"arm/switch16.S",
"arm/switch32.S",
"arm/switch8.S",
"arm/switchu8.S",
"arm/sync_synchronize.S",
"arm/udivmodsi4.S",
"arm/umodsi3.S",
// Exclude these two files for now even though we haven't
// translated their implementation into Rust yet (#173).
// They appear... buggy? The `udivsi3` implementation was
// the one that seemed buggy, but the `divsi3` file
// references a symbol from `udivsi3` so we compile them
// both with the Rust versions.
//
// Note that if these are added back they should be removed
// from thumbv6m below.
//
// "arm/divsi3.S",
// "arm/udivsi3.S",
],
);
}
if llvm_target[0] == "armv7" {
sources.extend(
&[
"arm/sync_fetch_and_add_4.S",
"arm/sync_fetch_and_add_8.S",
"arm/sync_fetch_and_and_4.S",
"arm/sync_fetch_and_and_8.S",
"arm/sync_fetch_and_max_4.S",
"arm/sync_fetch_and_max_8.S",
"arm/sync_fetch_and_min_4.S",
"arm/sync_fetch_and_min_8.S",
"arm/sync_fetch_and_nand_4.S",
"arm/sync_fetch_and_nand_8.S",
"arm/sync_fetch_and_or_4.S",
"arm/sync_fetch_and_or_8.S",
"arm/sync_fetch_and_sub_4.S",
"arm/sync_fetch_and_sub_8.S",
"arm/sync_fetch_and_umax_4.S",
"arm/sync_fetch_and_umax_8.S",
"arm/sync_fetch_and_umin_4.S",
"arm/sync_fetch_and_umin_8.S",
"arm/sync_fetch_and_xor_4.S",
"arm/sync_fetch_and_xor_8.S",
],
);
}
if llvm_target.last().unwrap().ends_with("eabihf") {
if !llvm_target[0].starts_with("thumbv7em") {
sources.extend(
&[
"arm/adddf3vfp.S",
"arm/addsf3vfp.S",
"arm/divdf3vfp.S",
"arm/divsf3vfp.S",
"arm/eqdf2vfp.S",
"arm/eqsf2vfp.S",
"arm/extendsfdf2vfp.S",
"arm/fixdfsivfp.S",
"arm/fixsfsivfp.S",
"arm/fixunsdfsivfp.S",
"arm/fixunssfsivfp.S",
"arm/floatsidfvfp.S",
"arm/floatsisfvfp.S",
"arm/floatunssidfvfp.S",
"arm/floatunssisfvfp.S",
"arm/gedf2vfp.S",
"arm/gesf2vfp.S",
"arm/gtdf2vfp.S",
"arm/gtsf2vfp.S",
"arm/ledf2vfp.S",
"arm/lesf2vfp.S",
"arm/ltdf2vfp.S",
"arm/ltsf2vfp.S",
"arm/muldf3vfp.S",
"arm/mulsf3vfp.S",
"arm/nedf2vfp.S",
"arm/nesf2vfp.S",
"arm/restore_vfp_d8_d15_regs.S",
"arm/save_vfp_d8_d15_regs.S",
"arm/subdf3vfp.S",
"arm/subsf3vfp.S",
],
);
}
sources.extend(&["arm/negdf2vfp.S", "arm/negsf2vfp.S"]);
}
if target_arch == "aarch64" {
sources.extend(
&[
"comparetf2.c",
"extenddftf2.c",
"extendsftf2.c",
"fixtfdi.c",
"fixtfsi.c",
"fixtfti.c",
"fixunstfdi.c",
"fixunstfsi.c",
"fixunstfti.c",
"floatditf.c",
"floatsitf.c",
"floatunditf.c",
"floatunsitf.c",
"multc3.c",
"trunctfdf2.c",
"trunctfsf2.c",
],
);
}
// Remove the assembly implementations that won't compile for the target
if llvm_target[0] == "thumbv6m" {
sources.remove(
&[
"aeabi_cdcmp",
"aeabi_cfcmp",
"aeabi_dcmp",
"aeabi_fcmp",
"clzdi2",
"clzsi2",
"comparesf2",
"divmodsi4",
"modsi3",
"switch16",
"switch32",
"switch8",
"switchu8",
"udivmodsi4",
"umodsi3",
],
);
// But use some generic implementations where possible
sources.extend(&["clzdi2.c", "clzsi2.c"])
}
if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" {
sources.remove(&["aeabi_cdcmp", "aeabi_cfcmp"]);
}
let root = if env::var_os("CARGO_FEATURE_RUSTBUILD").is_some() {
Path::new("../../libcompiler_builtins")
} else {
Path::new(".")
};
let src_dir = root.join("compiler-rt/lib/builtins");
for src in sources.map.values() {
let src = src_dir.join(src);
cfg.file(&src);
println!("cargo:rerun-if-changed={}", src.display());
}
cfg.compile("libcompiler-rt.a");
}
}