diff --git a/.cargo/config b/.cargo/config deleted file mode 100644 index b538953..0000000 --- a/.cargo/config +++ /dev/null @@ -1,11 +0,0 @@ -[target.thumbv6m-none-eabi] -rustflags = ["-C", "link-arg=-nostartfiles"] - -[target.thumbv7m-none-eabi] -rustflags = ["-C", "link-arg=-nostartfiles"] - -[target.thumbv7em-none-eabi] -rustflags = ["-C", "link-arg=-nostartfiles"] - -[target.thumbv7em-none-eabihf] -rustflags = ["-C", "link-arg=-nostartfiles"] \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index d86b9fa..bbdcf70 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "compiler-rt/compiler-rt-cdylib/compiler-rt"] - path = compiler-rt/compiler-rt-cdylib/compiler-rt + path = compiler-rt url = https://github.com/rust-lang/compiler-rt diff --git a/.travis.yml b/.travis.yml index 96bd24a..108b12a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,10 +22,10 @@ matrix: - env: TARGET=powerpc-unknown-linux-gnu - env: TARGET=powerpc64-unknown-linux-gnu - env: TARGET=powerpc64le-unknown-linux-gnu - - env: TARGET=thumbv6m-none-eabi - - env: TARGET=thumbv7em-none-eabi - - env: TARGET=thumbv7em-none-eabihf - - env: TARGET=thumbv7m-none-eabi + - env: TARGET=thumbv6m-linux-eabi + - env: TARGET=thumbv7em-linux-eabi + - env: TARGET=thumbv7em-linux-eabihf + - env: TARGET=thumbv7m-linux-eabi - env: TARGET=x86_64-apple-darwin os: osx env: TARGET=x86_64-unknown-linux-gnu @@ -34,11 +34,9 @@ before_install: - test "$TRAVIS_OS_NAME" = "osx" || docker run --rm --privileged multiarch/qemu-user-static:register install: - - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $TRAVIS_RUST_VERSION - - source ~/.cargo/env - case $TARGET in x86_64-apple-darwin | x86_64-unknown-linux-gnu) ;; - thumbv*-none-eabi*) rustup component add rust-src ;; + thumbv*eabi*) rustup component add rust-src ;; *) rustup target add $TARGET;; esac diff --git a/Cargo.toml b/Cargo.toml index a82aad5..59f6b40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,26 +5,27 @@ name = "compiler_builtins" version = "0.1.0" [build-dependencies] -rustc-cfg = "0.3.0" +cast = { version = "0.2.0", optional = true } +rand = { version = "0.3.15", optional = true } [build-dependencies.gcc] optional = true version = "0.3.36" -[dev-dependencies] -quickcheck = "0.3.1" -rand = "0.3.14" -gcc_s = { path = "gcc_s" } -compiler-rt = { path = "compiler-rt" } - [features] -# Build the missing intrinsics from compiler-rt C source code c = ["gcc"] -# Mark this crate as the #![compiler_builtins] crate compiler-builtins = [] default = ["compiler-builtins"] -# Include implementations of memory operations like memcpy mem = [] rustbuild = ["compiler-builtins"] +# generate tests +gen-tests = ["cast", "rand"] + +[target.'cfg(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")), target_os = "linux"))'.dev-dependencies] +test = { git = "https://github.com/japaric/utest" } +utest-cortex-m-qemu = { default-features = false, git = "https://github.com/japaric/utest" } +utest-macros = { git = "https://github.com/japaric/utest" } + + [workspace] diff --git a/appveyor.yml b/appveyor.yml index c05bfdf..f5a4c62 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,8 +6,9 @@ environment: install: - git submodule update --init - curl -sSf -o rustup-init.exe https://win.rustup.rs - - rustup-init.exe --default-host %TARGET% --default-toolchain nightly -y + - rustup-init.exe --default-host x86_64-pc-windows-msvc --default-toolchain nightly -y - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + - if "%TARGET%"=="i686-pc-windows-msvc" ( rustup target add %TARGET% ) - rustc -Vv - cargo -V @@ -16,5 +17,5 @@ build: false test_script: - cargo build --target %TARGET% - cargo build --release --target %TARGET% - - cargo test --no-default-features --target %TARGET% - - cargo test --no-default-features --release --target %TARGET% + - cargo test --no-default-features --features gen-tests --target %TARGET% + - cargo test --no-default-features --features gen-tests --release --target %TARGET% diff --git a/build.rs b/build.rs index 6c96284..ac75e6e 100644 --- a/build.rs +++ b/build.rs @@ -1,55 +1,6 @@ -#[cfg(feature = "c")] -extern crate gcc; -extern crate rustc_cfg; +#![feature(i128_type)] -#[cfg(feature = "c")] -use std::collections::BTreeMap; -use std::io::Write; -#[cfg(feature = "c")] -use std::path::Path; -use std::{env, io, process}; - -use rustc_cfg::Cfg; - -#[cfg(feature = "c")] -struct Sources { - // SYMBOL -> PATH TO SOURCE - map: BTreeMap<&'static str, &'static str>, -} - -#[cfg(feature = "c")] -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(); - } - } -} +use std::env; fn main() { println!("cargo:rerun-if-changed=build.rs"); @@ -61,367 +12,18 @@ fn main() { return; } - let Cfg { ref target_arch, ref target_os, ref target_env, ref target_vendor, .. } = - Cfg::new(&target).unwrap_or_else(|e| { - writeln!(io::stderr(), "{}", e).ok(); - process::exit(1) - }); // 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::>(); + // Build test files + #[cfg(feature = "gen-tests")] + tests::generate(); + // Build missing intrinsics from compiler-rt C source code - match () { - #[cfg(feature = "c")] - () => { - let target_vendor = target_vendor.as_ref().unwrap(); - let cfg = &mut gcc::Config::new(); - - 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", - "ffsdi2.c", - "fixdfdi.c", - "fixdfsi.c", - "fixsfdi.c", - "fixsfsi.c", - "fixunsdfdi.c", - "fixunsdfsi.c", - "fixunssfdi.c", - "fixunssfsi.c", - "fixunsxfdi.c", - "fixunsxfsi.c", - "fixxfdi.c", - "floatdidf.c", - "floatdisf.c", - "floatdixf.c", - "floatsidf.c", - "floatsisf.c", - "floatundidf.c", - "floatundisf.c", - "floatundixf.c", - "floatunsidf.c", - "floatunsisf.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"]); - - if target_os != "ios" { - sources.extend(&["absvti2.c", - "addvti3.c", - "clzti2.c", - "cmpti2.c", - "ctzti2.c", - "ffsti2.c", - "fixdfti.c", - "fixsfti.c", - "fixunsdfti.c", - "fixunssfti.c", - "fixunsxfti.c", - "fixxfti.c", - "floattidf.c", - "floattisf.c", - "floattixf.c", - "floatuntidf.c", - "floatuntisf.c", - "floatuntixf.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/floatdidf.c", "x86_64/floatdisf.c", "x86_64/floatdixf.c"]); - } - } else { - if target_os != "freebsd" && target_os != "netbsd" { - sources.extend(&["gcc_personality_v0.c"]); - } - - if target_arch == "x86_64" { - sources.extend(&["x86_64/chkstk.S", - "x86_64/chkstk2.S", - "x86_64/floatdidf.c", - "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/divsi3.S", - "arm/modsi3.S", - "arm/switch16.S", - "arm/switch32.S", - "arm/switch8.S", - "arm/switchu8.S", - "arm/sync_synchronize.S", - "arm/udivmodsi4.S", - "arm/udivsi3.S", - "arm/umodsi3.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", - "divsi3", - "modsi3", - "switch16", - "switch32", - "switch8", - "switchu8", - "udivmodsi4", - "udivsi3", - "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/compiler-rt-cdylib/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"); - } - #[cfg(not(feature = "c"))] - () => {} - } - - // To filter away some flaky test (see src/float/add.rs for details) - if llvm_target[0].starts_with("arm") && - llvm_target.last().unwrap().contains("gnueabi") { - println!("cargo:rustc-cfg=arm_linux") - } + #[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") { @@ -434,3 +36,3831 @@ fn main() { 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, i32, i64}; + 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, + Fixunsdfdi, + Fixunsdfsi, + Fixunssfdi, + Fixunssfsi, + Floatdidf, + Floatsidf, + Floatsisf, + Floatundidf, + Floatunsidf, + Floatunsisf, + + // 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u64(rng); + let b = (rng.gen::() % 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(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = (rng.gen::() % 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(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i64(rng); + let b = (rng.gen::() % 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(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_i128(rng); + let b = (rng.gen::() % 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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 fixsfdi() { + for &((a,), b) in TEST_CASES { + let b_ = __fixsfsi(mk_f32(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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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 Floatdidf { + a: i64, + b: u64, // f64 + } + + impl TestCase for Floatdidf { + fn name() -> &'static str { + "floatdidf" + } + + fn generate(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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 Floatundidf { + a: u64, + b: u64, // f64 + } + + impl TestCase for Floatundidf { + fn name() -> &'static str { + "floatundidf" + } + + fn generate(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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 Moddi3 { + a: i64, + b: i64, + c: i64, + } + + impl TestCase for Moddi3 { + fn name() -> &'static str { + "moddi3" + } + + fn generate(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u64(rng); + let b = (rng.gen::() % 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(rng: &mut R) -> Option + where + R: Rng, + Self: Sized, + { + let a = gen_u128(rng); + let b = (rng.gen::() % 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(rng: &mut R) -> Option + 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(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(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(rng: &mut R) -> u128 + where + R: Rng, + { + gen_i128(rng) as u128 + } + + pub fn gen_u32(rng: &mut R) -> u32 + where + R: Rng, + { + gen_i32(rng) as u32 + } + + fn gen_u64(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(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() + 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 = out_dir.join(format!("{}.rs", T::name())); + let contents = mk_tests::(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::Config::new(); + + 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", + "ffsdi2.c", + "fixdfdi.c", + "fixdfsi.c", + "fixsfdi.c", + "fixsfsi.c", + "fixunsdfdi.c", + "fixunsdfsi.c", + "fixunssfdi.c", + "fixunssfsi.c", + "fixunsxfdi.c", + "fixunsxfsi.c", + "fixxfdi.c", + "floatdidf.c", + "floatdisf.c", + "floatdixf.c", + "floatsidf.c", + "floatsisf.c", + "floatundidf.c", + "floatundisf.c", + "floatundixf.c", + "floatunsidf.c", + "floatunsisf.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", + ], + ); + + if target_os != "ios" { + sources.extend( + &[ + "absvti2.c", + "addvti3.c", + "clzti2.c", + "cmpti2.c", + "ctzti2.c", + "ffsti2.c", + "fixdfti.c", + "fixsfti.c", + "fixunsdfti.c", + "fixunssfti.c", + "fixunsxfti.c", + "fixxfti.c", + "floattidf.c", + "floattisf.c", + "floattixf.c", + "floatuntidf.c", + "floatuntisf.c", + "floatuntixf.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/floatdidf.c", + "x86_64/floatdisf.c", + "x86_64/floatdixf.c", + ], + ); + } + } else { + if target_os != "freebsd" && target_os != "netbsd" { + sources.extend(&["gcc_personality_v0.c"]); + } + + if target_arch == "x86_64" { + sources.extend( + &[ + "x86_64/chkstk.S", + "x86_64/chkstk2.S", + "x86_64/floatdidf.c", + "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/divsi3.S", + "arm/modsi3.S", + "arm/switch16.S", + "arm/switch32.S", + "arm/switch8.S", + "arm/switchu8.S", + "arm/sync_synchronize.S", + "arm/udivmodsi4.S", + "arm/udivsi3.S", + "arm/umodsi3.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", + "divsi3", + "modsi3", + "switch16", + "switch32", + "switch8", + "switchu8", + "udivmodsi4", + "udivsi3", + "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"); + } +} diff --git a/ci/docker/thumbv7m-none-eabi/Dockerfile b/ci/docker/thumbv6m-linux-eabi/Dockerfile similarity index 59% rename from ci/docker/thumbv7m-none-eabi/Dockerfile rename to ci/docker/thumbv6m-linux-eabi/Dockerfile index e09c020..d260356 100644 --- a/ci/docker/thumbv7m-none-eabi/Dockerfile +++ b/ci/docker/thumbv6m-linux-eabi/Dockerfile @@ -1,9 +1,9 @@ FROM ubuntu:16.04 RUN apt-get update && \ apt-get install -y --no-install-recommends \ - ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev + ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev qemu-user-static RUN curl -LSfs https://japaric.github.io/trust/install.sh | \ sh -s -- --git japaric/xargo --tag v0.3.1 --target x86_64-unknown-linux-gnu --to /usr/bin -ENV AR_thumbv7m_none_eabi=arm-none-eabi-ar \ - CARGO_TARGET_THUMBV7M_NONE_EABI_LINKER=arm-none-eabi-gcc \ - CC_thumbv7m_none_eabi=arm-none-eabi-gcc \ +ENV AR_thumbv6m_linux_eabi=arm-none-eabi-ar \ + CARGO_TARGET_THUMBV6M_LINUX_EABI_LINKER=arm-none-eabi-gcc \ + CC_thumbv6m_linux_eabi=arm-none-eabi-gcc \ diff --git a/ci/docker/thumbv7em-none-eabi/Dockerfile b/ci/docker/thumbv7em-linux-eabi/Dockerfile similarity index 59% rename from ci/docker/thumbv7em-none-eabi/Dockerfile rename to ci/docker/thumbv7em-linux-eabi/Dockerfile index fda5dcb..d630352 100644 --- a/ci/docker/thumbv7em-none-eabi/Dockerfile +++ b/ci/docker/thumbv7em-linux-eabi/Dockerfile @@ -1,9 +1,9 @@ FROM ubuntu:16.04 RUN apt-get update && \ apt-get install -y --no-install-recommends \ - ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev + ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev qemu-user-static RUN curl -LSfs https://japaric.github.io/trust/install.sh | \ sh -s -- --git japaric/xargo --tag v0.3.1 --target x86_64-unknown-linux-gnu --to /usr/bin -ENV AR_thumbv7em_none_eabi=arm-none-eabi-ar \ - CARGO_TARGET_THUMBV7EM_NONE_EABI_LINKER=arm-none-eabi-gcc \ - CC_thumbv7em_none_eabi=arm-none-eabi-gcc \ +ENV AR_thumbv7em_linux_eabi=arm-none-eabi-ar \ + CARGO_TARGET_THUMBV7EM_LINUX_EABI_LINKER=arm-none-eabi-gcc \ + CC_thumbv7em_linux_eabi=arm-none-eabi-gcc \ diff --git a/ci/docker/thumbv7em-none-eabihf/Dockerfile b/ci/docker/thumbv7em-linux-eabihf/Dockerfile similarity index 58% rename from ci/docker/thumbv7em-none-eabihf/Dockerfile rename to ci/docker/thumbv7em-linux-eabihf/Dockerfile index 5395e74..6f30729 100644 --- a/ci/docker/thumbv7em-none-eabihf/Dockerfile +++ b/ci/docker/thumbv7em-linux-eabihf/Dockerfile @@ -1,9 +1,9 @@ FROM ubuntu:16.04 RUN apt-get update && \ apt-get install -y --no-install-recommends \ - ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev + ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev qemu-user-static RUN curl -LSfs https://japaric.github.io/trust/install.sh | \ sh -s -- --git japaric/xargo --tag v0.3.1 --target x86_64-unknown-linux-gnu --to /usr/bin -ENV AR_thumbv7em_none_eabihf=arm-none-eabi-ar \ - CARGO_TARGET_THUMBV7EM_NONE_EABIHF_LINKER=arm-none-eabi-gcc \ - CC_thumbv7em_none_eabihf=arm-none-eabi-gcc \ +ENV AR_thumbv7em_linux_eabihf=arm-none-eabi-ar \ + CARGO_TARGET_THUMBV7EM_LINUX_EABIHF_LINKER=arm-none-eabi-gcc \ + CC_thumbv7em_linux_eabihf=arm-none-eabi-gcc \ diff --git a/ci/docker/thumbv6m-none-eabi/Dockerfile b/ci/docker/thumbv7m-linux-eabi/Dockerfile similarity index 59% rename from ci/docker/thumbv6m-none-eabi/Dockerfile rename to ci/docker/thumbv7m-linux-eabi/Dockerfile index 2a2d127..a7dbad6 100644 --- a/ci/docker/thumbv6m-none-eabi/Dockerfile +++ b/ci/docker/thumbv7m-linux-eabi/Dockerfile @@ -1,9 +1,9 @@ FROM ubuntu:16.04 RUN apt-get update && \ apt-get install -y --no-install-recommends \ - ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev + ca-certificates curl gcc gcc-arm-none-eabi libc6-dev libcurl4-openssl-dev libssh2-1 libnewlib-dev qemu-user-static RUN curl -LSfs https://japaric.github.io/trust/install.sh | \ sh -s -- --git japaric/xargo --tag v0.3.1 --target x86_64-unknown-linux-gnu --to /usr/bin -ENV AR_thumbv6m_none_eabi=arm-none-eabi-ar \ - CARGO_TARGET_THUMBV6M_NONE_EABI_LINKER=arm-none-eabi-gcc \ - CC_thumbv6m_none_eabi=arm-none-eabi-gcc \ +ENV AR_thumbv7m_linux_eabi=arm-none-eabi-ar \ + CARGO_TARGET_THUMBV7M_LINUX_EABI_LINKER=arm-none-eabi-gcc \ + CC_thumbv7m_linux_eabi=arm-none-eabi-gcc \ diff --git a/ci/run.sh b/ci/run.sh index b30fad1..771f881 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -3,12 +3,38 @@ set -ex # Test our implementation case $1 in thumb*) - xargo build --target $1 - xargo build --target $1 --release + for t in $(ls tests); do + t=${t%.rs} + + # TODO(#154) enable these tests when aeabi_*mul are implemented + case $t in + powi*f2) + continue + ;; + esac + + # FIXME(#150) debug assertion in divmoddi4 + case $1 in + thumbv6m-*) + case $t in + divdi3 | divmoddi4 | moddi3 | modsi3 | udivmoddi4 | udivmodsi4 | umoddi3 | \ + umodsi3) + continue + ;; + esac + ;; + esac + + xargo test --test $t --target $1 --features 'mem gen-tests' --no-run + qemu-arm-static target/${1}/debug/$t-* + + xargo test --test $t --target $1 --features 'mem gen-tests' --no-run --release + qemu-arm-static target/${1}/release/$t-* + done ;; *) - cargo test --no-default-features --target $1 - cargo test --no-default-features --target $1 --release + cargo test --no-default-features --features gen-tests --target $1 + cargo test --no-default-features --features gen-tests --target $1 --release ;; esac diff --git a/compiler-rt/compiler-rt-cdylib/compiler-rt b/compiler-rt similarity index 100% rename from compiler-rt/compiler-rt-cdylib/compiler-rt rename to compiler-rt diff --git a/compiler-rt/Cargo.toml b/compiler-rt/Cargo.toml deleted file mode 100644 index cac8773..0000000 --- a/compiler-rt/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "compiler-rt" -version = "0.1.0" -authors = ["Alex Crichton "] - -[dependencies] -compiler-rt-cdylib = { path = "compiler-rt-cdylib" } -libloading = "0.3" diff --git a/compiler-rt/compiler-rt-cdylib/Cargo.toml b/compiler-rt/compiler-rt-cdylib/Cargo.toml deleted file mode 100644 index ec9c6af..0000000 --- a/compiler-rt/compiler-rt-cdylib/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "compiler-rt-cdylib" -version = "0.1.0" -authors = ["Alex Crichton "] -build = "build.rs" - -[lib] -crate-type = ["cdylib"] - -[build-dependencies] -gcc = "0.3.36" - diff --git a/compiler-rt/compiler-rt-cdylib/build.rs b/compiler-rt/compiler-rt-cdylib/build.rs deleted file mode 100644 index c07ea70..0000000 --- a/compiler-rt/compiler-rt-cdylib/build.rs +++ /dev/null @@ -1,104 +0,0 @@ -extern crate gcc; - -use std::env; -use std::path::Path; -use std::process::Command; - -struct Sources { - files: Vec<&'static str>, -} - -impl Sources { - fn new() -> Sources { - Sources { files: Vec::new() } - } - - fn extend(&mut self, sources: &[&'static str]) { - self.files.extend(sources); - } -} - -fn main() { - if !Path::new("compiler-rt/.git").exists() { - let _ = Command::new("git").args(&["submodule", "update", "--init"]) - .status(); - } - - let target = env::var("TARGET").expect("TARGET was not set"); - let cfg = &mut gcc::Config::new(); - - if target.contains("msvc") { - cfg.define("__func__", Some("__FUNCTION__")); - } else { - cfg.flag("-fno-builtin"); - cfg.flag("-fomit-frame-pointer"); - cfg.flag("-ffreestanding"); - } - - let mut sources = Sources::new(); - - sources.extend(&[ - "muldi3.c", - "mulosi4.c", - "mulodi4.c", - "divsi3.c", - "divdi3.c", - "modsi3.c", - "moddi3.c", - "divmodsi4.c", - "divmoddi4.c", - "ashldi3.c", - "ashrdi3.c", - "lshrdi3.c", - "udivdi3.c", - "umoddi3.c", - "udivmoddi4.c", - "udivsi3.c", - "umodsi3.c", - "udivmodsi4.c", - "adddf3.c", - "addsf3.c", - "powidf2.c", - "powisf2.c", - "subdf3.c", - "subsf3.c", - "floatsisf.c", - "floatsidf.c", - "floatdidf.c", - "floatunsisf.c", - "floatunsidf.c", - "floatundidf.c", - "fixsfsi.c", - "fixsfdi.c", - "fixdfsi.c", - "fixdfdi.c", - "fixunssfsi.c", - "fixunssfdi.c", - "fixunsdfsi.c", - "fixunsdfdi.c", - // 128 bit integers - "lshrti3.c", - "modti3.c", - "muloti4.c", - "multi3.c", - "udivmodti4.c", - "udivti3.c", - "umodti3.c", - "ashlti3.c", - "ashrti3.c", - "divti3.c", - ]); - - let builtins_dir = Path::new("compiler-rt/lib/builtins"); - for src in sources.files.iter() { - cfg.file(builtins_dir.join(src)); - } - - cfg.compile("libcompiler-rt.a"); - - println!("cargo:rerun-if-changed=build.rs"); - - for source in sources.files.iter() { - println!("cargo:rerun-if-changed={}", builtins_dir.join(source).display()); - } -} diff --git a/compiler-rt/compiler-rt-cdylib/src/lib.rs b/compiler-rt/compiler-rt-cdylib/src/lib.rs deleted file mode 100644 index 2f08314..0000000 --- a/compiler-rt/compiler-rt-cdylib/src/lib.rs +++ /dev/null @@ -1,126 +0,0 @@ -#![feature(lang_items)] -#![no_std] - -extern { - fn __ashldi3(); - fn __ashrdi3(); - fn __divdi3(); - fn __divmoddi4(); - fn __divmodsi4(); - fn __divsi3(); - fn __lshrdi3(); - fn __moddi3(); - fn __modsi3(); - fn __muldi3(); - fn __mulodi4(); - fn __mulosi4(); - fn __udivdi3(); - fn __udivmoddi4(); - fn __udivmodsi4(); - fn __udivsi3(); - fn __umoddi3(); - fn __umodsi3(); - fn __addsf3(); - fn __adddf3(); - fn __powisf2(); - fn __powidf2(); - fn __subsf3(); - fn __subdf3(); - fn __floatsisf(); - fn __floatsidf(); - fn __floatdidf(); - fn __floatunsisf(); - fn __floatunsidf(); - fn __floatundidf(); - fn __fixsfsi(); - fn __fixsfdi(); - fn __fixdfsi(); - fn __fixdfdi(); - fn __fixunssfsi(); - fn __fixunssfdi(); - fn __fixunsdfsi(); - fn __fixunsdfdi(); -} - -macro_rules! declare { - ($func:ident, $sym:ident) => { - #[no_mangle] - pub extern fn $func() -> usize { - $sym as usize - } - } -} - -declare!(___ashldi3, __ashldi3); -declare!(___ashrdi3, __ashrdi3); -declare!(___divdi3, __divdi3); -declare!(___divmoddi4, __divmoddi4); -declare!(___divmodsi4, __divmodsi4); -declare!(___divsi3, __divsi3); -declare!(___lshrdi3, __lshrdi3); -declare!(___moddi3, __moddi3); -declare!(___modsi3, __modsi3); -declare!(___muldi3, __muldi3); -declare!(___mulodi4, __mulodi4); -declare!(___mulosi4, __mulosi4); -declare!(___udivdi3, __udivdi3); -declare!(___udivmoddi4, __udivmoddi4); -declare!(___udivmodsi4, __udivmodsi4); -declare!(___udivsi3, __udivsi3); -declare!(___umoddi3, __umoddi3); -declare!(___umodsi3, __umodsi3); -declare!(___addsf3, __addsf3); -declare!(___adddf3, __adddf3); -declare!(___powisf2, __powisf2); -declare!(___powidf2, __powidf2); -declare!(___subsf3, __subsf3); -declare!(___subdf3, __subdf3); -declare!(___floatsisf, __floatsisf); -declare!(___floatsidf, __floatsidf); -declare!(___floatdidf, __floatdidf); -declare!(___floatunsisf, __floatunsisf); -declare!(___floatunsidf, __floatunsidf); -declare!(___floatundidf, __floatundidf); -declare!(___fixsfsi, __fixsfsi); -declare!(___fixsfdi, __fixsfdi); -declare!(___fixdfsi, __fixdfsi); -declare!(___fixdfdi, __fixdfdi); -declare!(___fixunssfsi, __fixunssfsi); -declare!(___fixunssfdi, __fixunssfdi); -declare!(___fixunsdfsi, __fixunsdfsi); -declare!(___fixunsdfdi, __fixunsdfdi); - -#[cfg(all(not(windows), - not(target_arch = "mips64"), - not(target_arch = "mips64el"), - target_pointer_width="64"))] -pub mod int_128 { - extern { - fn __lshrti3(); - fn __modti3(); - fn __muloti4(); - fn __multi3(); - fn __udivmodti4(); - fn __udivti3(); - fn __umodti3(); - fn __ashlti3(); - fn __ashrti3(); - fn __divti3(); - } - - declare!(___lshrti3, __lshrti3); - declare!(___modti3, __modti3); - declare!(___muloti4, __muloti4); - declare!(___multi3, __multi3); - declare!(___udivmodti4, __udivmodti4); - declare!(___udivti3, __udivti3); - declare!(___umodti3, __umodti3); - declare!(___ashlti3, __ashlti3); - declare!(___ashrti3, __ashrti3); - declare!(___divti3, __divti3); -} - -#[lang = "eh_personality"] -fn eh_personality() {} -#[lang = "panic_fmt"] -fn panic_fmt() {} diff --git a/compiler-rt/src/lib.rs b/compiler-rt/src/lib.rs deleted file mode 100644 index ca99f39..0000000 --- a/compiler-rt/src/lib.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![feature(drop_types_in_const)] - -extern crate libloading; - -use std::sync::{Once, ONCE_INIT}; -use std::env; - -use libloading::Library; - -fn compiler_rt() -> &'static Library { - let dir = env::current_exe().unwrap(); - let cdylib = dir.parent().unwrap().read_dir().unwrap().map(|c| { - c.unwrap().path() - }).find(|path| { - path.file_name().unwrap().to_str().unwrap().contains("compiler_rt_cdylib") - }).unwrap(); - - unsafe { - static mut COMPILER_RT: Option = None; - static INIT: Once = ONCE_INIT; - - INIT.call_once(|| { - COMPILER_RT = Some(Library::new(&cdylib).unwrap()); - }); - COMPILER_RT.as_ref().unwrap() - } -} - -pub fn get(sym: &str) -> usize { - unsafe { - let sym = format!("_{}", sym); - let f: fn() -> usize = *compiler_rt().get(sym.as_bytes()).unwrap(); - f() - } -} diff --git a/gcc_s/Cargo.toml b/gcc_s/Cargo.toml deleted file mode 100644 index 4e3080f..0000000 --- a/gcc_s/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -authors = ["Jorge Aparicio "] -name = "gcc_s" -version = "0.1.0" - -[dependencies] -libloading = "0.3.0" diff --git a/gcc_s/src/lib.rs b/gcc_s/src/lib.rs deleted file mode 100644 index e3417ff..0000000 --- a/gcc_s/src/lib.rs +++ /dev/null @@ -1,39 +0,0 @@ -#![feature(drop_types_in_const)] - -extern crate libloading; - -use std::sync::{Once, ONCE_INIT}; - -use libloading::Library; - -static mut GCC_S: Option = None; - -#[cfg(not(windows))] -fn gcc_s() -> &'static Library { - #[cfg(not(target_os = "macos"))] - const LIBGCC_S: &'static str = "libgcc_s.so.1"; - - #[cfg(target_os = "macos")] - const LIBGCC_S: &'static str = "libgcc_s.1.dylib"; - - unsafe { - static INIT: Once = ONCE_INIT; - - INIT.call_once(|| { - GCC_S = Some(Library::new(LIBGCC_S).unwrap()); - }); - GCC_S.as_ref().unwrap() - } -} - -#[cfg(windows)] -pub fn get(_sym: &str) -> Option { - None -} - -#[cfg(not(windows))] -pub fn get(sym: &str) -> Option { - unsafe { - gcc_s().get(sym.as_bytes()).ok().map(|s| *s) - } -} diff --git a/src/arm.rs b/src/arm.rs index 63f5250..cf960c5 100755 --- a/src/arm.rs +++ b/src/arm.rs @@ -180,84 +180,3 @@ pub unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) { pub unsafe extern "aapcs" fn __aeabi_memclr8(dest: *mut u8, n: usize) { memset(dest, 0, n); } - - -#[cfg(test)] -mod tests { - use quickcheck::TestResult; - use qc::{U32, U64}; - - quickcheck!{ - fn uldivmod(n: U64, d: U64) -> TestResult { - let (n, d) = (n.0, d.0); - if d == 0 { - TestResult::discard() - } else { - let q: u64; - let r: u64; - unsafe { - // The inline asm is a bit tricky here, LLVM will allocate - // both r0 and r1 when we specify a 64-bit value for {r0}. - asm!("bl __aeabi_uldivmod" - : "={r0}" (q), "={r2}" (r) - : "{r0}" (n), "{r2}" (d) - : "r12", "lr", "flags"); - } - TestResult::from_bool(q == n / d && r == n % d) - } - } - - fn uidivmod(n: U32, d: U32) -> TestResult { - let (n, d) = (n.0, d.0); - if d == 0 { - TestResult::discard() - } else { - let q: u32; - let r: u32; - unsafe { - asm!("bl __aeabi_uidivmod" - : "={r0}" (q), "={r1}" (r) - : "{r0}" (n), "{r1}" (d) - : "r2", "r3", "r12", "lr", "flags"); - } - TestResult::from_bool(q == n / d && r == n % d) - } - } - - fn ldivmod(n: U64, d: U64) -> TestResult { - let (n, d) = (n.0 as i64, d.0 as i64); - if d == 0 { - TestResult::discard() - } else { - let q: i64; - let r: i64; - unsafe { - // The inline asm is a bit tricky here, LLVM will allocate - // both r0 and r1 when we specify a 64-bit value for {r0}. - asm!("bl __aeabi_ldivmod" - : "={r0}" (q), "={r2}" (r) - : "{r0}" (n), "{r2}" (d) - : "r12", "lr", "flags"); - } - TestResult::from_bool(q == n / d && r == n % d) - } - } - - fn idivmod(n: U32, d: U32) -> TestResult { - let (n, d) = (n.0 as i32, d.0 as i32); - if d == 0 || (n == i32::min_value() && d == -1) { - TestResult::discard() - } else { - let q: i32; - let r: i32; - unsafe { - asm!("bl __aeabi_idivmod" - : "={r0}" (q), "={r1}" (r) - : "{r0}" (n), "{r1}" (d) - : "r2", "r3", "r12", "lr", "flags"); - } - TestResult::from_bool(q == n / d && r == n % d) - } - } - } -} diff --git a/src/float/add.rs b/src/float/add.rs index 992d149..5024a72 100644 --- a/src/float/add.rs +++ b/src/float/add.rs @@ -192,28 +192,3 @@ add!("aapcs", __adddf3: f64); #[cfg(not(target_arch = "arm"))] add!("C", __adddf3: f64); - -// NOTE(cfg) for some reason, on arm*-unknown-linux-gnueabi*, our implementation doesn't -// match the output of its gcc_s or compiler-rt counterpart. Until we investigate further, we'll -// just avoid testing against them on those targets. Do note that our implementation gives the -// correct answer; gcc_s and compiler-rt are incorrect in this case. -#[cfg(all(test, not(arm_linux)))] -mod tests { - use core::{f32, f64}; - use qc::{F32, F64}; - - check! { - fn __addsf3(f: extern "C" fn(f32, f32) -> f32, - a: F32, - b: F32) - -> Option { - Some(F32(f(a.0, b.0))) - } - - fn __adddf3(f: extern "C" fn(f64, f64) -> f64, - a: F64, - b: F64) -> Option { - Some(F64(f(a.0, b.0))) - } - } -} diff --git a/src/float/conv.rs b/src/float/conv.rs index 2781ff5..efe590a 100755 --- a/src/float/conv.rs +++ b/src/float/conv.rs @@ -94,6 +94,7 @@ enum Sign { Positive, Negative } + macro_rules! fp_fix { ($intrinsic:ident: $fty:ty, $ity:ty) => { pub extern "C" fn $intrinsic(f: $fty) -> $ity { @@ -155,112 +156,3 @@ fp_fix!(__fixunssfsi: f32, u32); fp_fix!(__fixunssfdi: f32, u64); fp_fix!(__fixunsdfsi: f64, u32); fp_fix!(__fixunsdfdi: f64, u64); - -// NOTE(cfg) for some reason, on arm*-unknown-linux-gnueabihf, our implementation doesn't -// match the output of its gcc_s or compiler-rt counterpart. Until we investigate further, we'll -// just avoid testing against them on those targets. Do note that our implementation gives the -// correct answer; gcc_s and compiler-rt are incorrect in this case. -// -#[cfg(all(test, not(arm_linux)))] -mod tests { - use qc::{I32, U32, I64, U64, F32, F64}; - - check! { - fn __floatsisf(f: extern "C" fn(i32) -> f32, - a: I32) - -> Option { - Some(F32(f(a.0))) - } - fn __floatsidf(f: extern "C" fn(i32) -> f64, - a: I32) - -> Option { - Some(F64(f(a.0))) - } - fn __floatdidf(f: extern "C" fn(i64) -> f64, - a: I64) - -> Option { - Some(F64(f(a.0))) - } - fn __floatunsisf(f: extern "C" fn(u32) -> f32, - a: U32) - -> Option { - Some(F32(f(a.0))) - } - fn __floatunsidf(f: extern "C" fn(u32) -> f64, - a: U32) - -> Option { - Some(F64(f(a.0))) - } - fn __floatundidf(f: extern "C" fn(u64) -> f64, - a: U64) - -> Option { - Some(F64(f(a.0))) - } - - fn __fixsfsi(f: extern "C" fn(f32) -> i32, - a: F32) - -> Option { - if (a.0 as f64) > (i32::max_value() as f64) || - (a.0 as f64) < (i32::min_value() as f64) || a.0.is_nan() { - None - } else { Some(I32(f(a.0))) } - } - fn __fixsfdi(f: extern "C" fn(f32) -> i64, - a: F32) - -> Option { - if (a.0 as f64) > (i64::max_value() as f64) || - (a.0 as f64) < (i64::min_value() as f64) || a.0.is_nan() { - None - } else { Some(I64(f(a.0))) } - } - fn __fixdfsi(f: extern "C" fn(f64) -> i32, - a: F64) - -> Option { - if a.0 > (i32::max_value() as f64) || - a.0 < (i32::min_value() as f64) || a.0.is_nan() { - None - } else { Some(I32(f(a.0))) } - } - fn __fixdfdi(f: extern "C" fn(f64) -> i64, - a: F64) - -> Option { - if a.0 > (i64::max_value() as f64) || - a.0 < (i64::min_value() as f64) || a.0.is_nan() { - None - } else { Some(I64(f(a.0))) } - } - - fn __fixunssfsi(f: extern "C" fn(f32) -> u32, - a: F32) - -> Option { - if (a.0 as f64) > (u32::max_value() as f64) || - (a.0 as f64) < (u32::min_value() as f64) || a.0.is_nan() { - None - } else { Some(U32(f(a.0))) } - } - fn __fixunssfdi(f: extern "C" fn(f32) -> u64, - a: F32) - -> Option { - if (a.0 as f64) > (u64::max_value() as f64) || - (a.0 as f64) < (u64::min_value() as f64) || a.0.is_nan() { - None - } else { Some(U64(f(a.0))) } - } - fn __fixunsdfsi(f: extern "C" fn(f64) -> u32, - a: F64) - -> Option { - if a.0 > (u32::max_value() as f64) || - a.0 < (u32::min_value() as f64) || a.0.is_nan() { - None - } else { Some(U32(f(a.0))) } - } - fn __fixunsdfdi(f: extern "C" fn(f64) -> u64, - a: F64) - -> Option { - if a.0 <= (u64::max_value() as f64) || - a.0 >= (u64::min_value() as f64) || a.0.is_nan() { - None - } else { Some(U64(f(a.0))) } - } - } -} diff --git a/src/float/pow.rs b/src/float/pow.rs index 52aba5d..5e28d95 100644 --- a/src/float/pow.rs +++ b/src/float/pow.rs @@ -28,22 +28,3 @@ macro_rules! pow { pow!(__powisf2: f32, i32); pow!(__powidf2: f64, i32); - -#[cfg(test)] -mod tests { - use qc::{I32, F32, F64}; - - check! { - fn __powisf2(f: extern "C" fn(f32, i32) -> f32, - a: F32, - b: I32) -> Option { - Some(F32(f(a.0, b.0))) - } - - fn __powidf2(f: extern "C" fn(f64, i32) -> f64, - a: F64, - b: I32) -> Option { - Some(F64(f(a.0, b.0))) - } - } -} diff --git a/src/float/sub.rs b/src/float/sub.rs index 928d738..a4fd884 100644 --- a/src/float/sub.rs +++ b/src/float/sub.rs @@ -18,28 +18,3 @@ sub!(#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] sub!(#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)] #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))] | __subdf3: f64); - -// NOTE(cfg) for some reason, on arm*-unknown-linux-gnueabi*, our implementation doesn't -// match the output of its gcc_s or compiler-rt counterpart. Until we investigate further, we'll -// just avoid testing against them on those targets. Do note that our implementation gives the -// correct answer; gcc_s and compiler-rt are incorrect in this case. -#[cfg(all(test, not(arm_linux)))] -mod tests { - use core::{f32, f64}; - use qc::{F32, F64}; - - check! { - fn __subsf3(f: extern "C" fn(f32, f32) -> f32, - a: F32, - b: F32) - -> Option { - Some(F32(f(a.0, b.0))) - } - - fn __subdf3(f: extern "C" fn(f64, f64) -> f64, - a: F64, - b: F64) -> Option { - Some(F64(f(a.0, b.0))) - } - } -} diff --git a/src/int/mul.rs b/src/int/mul.rs index 7b0d033..5381edd 100644 --- a/src/int/mul.rs +++ b/src/int/mul.rs @@ -93,66 +93,3 @@ mulo!(__mulodi4: i64); mulo!(__muloti4: i128, "unadjusted"); #[cfg(not(all(windows, target_pointer_width="64")))] mulo!(__muloti4: i128); - -#[cfg(test)] -mod tests { - use qc::{I32, I64, U64}; - - check! { - fn __muldi3(f: extern "C" fn(u64, u64) -> u64, a: U64, b: U64) - -> Option { - Some(f(a.0, b.0)) - } - - fn __mulosi4(f: extern "C" fn(i32, i32, &mut i32) -> i32, - a: I32, - b: I32) -> Option<(i32, i32)> { - let (a, b) = (a.0, b.0); - let mut overflow = 2; - let r = f(a, b, &mut overflow); - if overflow != 0 && overflow != 1 { - panic!("Invalid value {} for overflow", overflow); - } - Some((r, overflow)) - } - - fn __mulodi4(f: extern "C" fn(i64, i64, &mut i32) -> i64, - a: I64, - b: I64) -> Option<(i64, i32)> { - let (a, b) = (a.0, b.0); - let mut overflow = 2; - let r = f(a, b, &mut overflow); - if overflow != 0 && overflow != 1 { - panic!("Invalid value {} for overflow", overflow); - } - Some((r, overflow)) - } - } -} - -#[cfg(test)] -#[cfg(all(not(windows), - not(target_arch = "mips64"), - not(target_arch = "mips64el"), - target_pointer_width="64"))] -mod tests_i128 { - use qc::I128; - - check! { - fn __multi3(f: extern "C" fn(i128, i128) -> i128, a: I128, b: I128) - -> Option { - Some(f(a.0, b.0)) - } - fn __muloti4(f: extern "C" fn(i128, i128, &mut i32) -> i128, - a: I128, - b: I128) -> Option<(i128, i32)> { - let (a, b) = (a.0, b.0); - let mut overflow = 2; - let r = f(a, b, &mut overflow); - if overflow != 0 && overflow != 1 { - panic!("Invalid value {} for overflow", overflow); - } - Some((r, overflow)) - } - } -} diff --git a/src/int/sdiv.rs b/src/int/sdiv.rs index 1906560..5576898 100644 --- a/src/int/sdiv.rs +++ b/src/int/sdiv.rs @@ -100,120 +100,3 @@ divmod!("aapcs", __divmoddi4, __divdi3: i64); #[cfg(not(target_arch = "arm"))] divmod!("C", __divmoddi4, __divdi3: i64); - -#[cfg(test)] -mod tests { - use qc::{U32, U64}; - - check! { - fn __divdi3(f: extern "C" fn(i64, i64) -> i64, n: U64, d: U64) -> Option { - let (n, d) = (n.0 as i64, d.0 as i64); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - fn __moddi3(f: extern "C" fn(i64, i64) -> i64, n: U64, d: U64) -> Option { - let (n, d) = (n.0 as i64, d.0 as i64); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - #[cfg(target_arch = "arm")] - fn __divmoddi4(f: extern "aapcs" fn(i64, i64, &mut i64) -> i64, - n: U64, - d: U64) -> Option<(i64, i64)> { - let (n, d) = (n.0 as i64, d.0 as i64); - if d == 0 { - None - } else { - let mut r = 0; - let q = f(n, d, &mut r); - Some((q, r)) - } - } - - #[cfg(not(target_arch = "arm"))] - fn __divmoddi4(f: extern "C" fn(i64, i64, &mut i64) -> i64, - n: U64, - d: U64) -> Option<(i64, i64)> { - let (n, d) = (n.0 as i64, d.0 as i64); - if d == 0 { - None - } else { - let mut r = 0; - let q = f(n, d, &mut r); - Some((q, r)) - } - } - - fn __divsi3(f: extern "C" fn(i32, i32) -> i32, - n: U32, - d: U32) -> Option { - let (n, d) = (n.0 as i32, d.0 as i32); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - fn __modsi3(f: extern "C" fn(i32, i32) -> i32, - n: U32, - d: U32) -> Option { - let (n, d) = (n.0 as i32, d.0 as i32); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - fn __divmodsi4(f: extern "C" fn(i32, i32, &mut i32) -> i32, - n: U32, - d: U32) -> Option<(i32, i32)> { - let (n, d) = (n.0 as i32, d.0 as i32); - if d == 0 { - None - } else { - let mut r = 0; - let q = f(n, d, &mut r); - Some((q, r)) - } - } - } -} - -#[cfg(test)] -#[cfg(all(not(windows), - not(target_arch = "mips64"), - not(target_arch = "mips64el"), - target_pointer_width="64"))] -mod tests_i128 { - use qc::U128; - check! { - - fn __divti3(f: extern "C" fn(i128, i128) -> i128, n: U128, d: U128) -> Option { - let (n, d) = (n.0 as i128, d.0 as i128); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - fn __modti3(f: extern "C" fn(i128, i128) -> i128, n: U128, d: U128) -> Option { - let (n, d) = (n.0 as i128, d.0 as i128); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - } -} diff --git a/src/int/shift.rs b/src/int/shift.rs index fdd2f6c..8b5c4a1 100644 --- a/src/int/shift.rs +++ b/src/int/shift.rs @@ -72,77 +72,3 @@ ashr!(__ashrti3: i128); lshr!(__lshrdi3: u64); lshr!(__lshrti3: u128); - -#[cfg(test)] -mod tests { - use qc::{I64, U64}; - - // NOTE We purposefully stick to `u32` for `b` here because we want "small" values (b < 64) - check! { - fn __ashldi3(f: extern "C" fn(u64, u32) -> u64, a: U64, b: u32) -> Option { - let a = a.0; - if b >= 64 { - None - } else { - Some(f(a, b)) - } - } - - fn __ashrdi3(f: extern "C" fn(i64, u32) -> i64, a: I64, b: u32) -> Option { - let a = a.0; - if b >= 64 { - None - } else { - Some(f(a, b)) - } - } - - fn __lshrdi3(f: extern "C" fn(u64, u32) -> u64, a: U64, b: u32) -> Option { - let a = a.0; - if b >= 64 { - None - } else { - Some(f(a, b)) - } - } - } -} - -#[cfg(test)] -#[cfg(all(not(windows), - not(target_arch = "mips64"), - not(target_arch = "mips64el"), - target_pointer_width="64"))] -mod tests_i128 { - use qc::{I128, U128}; - - // NOTE We purposefully stick to `u32` for `b` here because we want "small" values (b < 64) - check! { - fn __ashlti3(f: extern "C" fn(u128, u32) -> u128, a: U128, b: u32) -> Option { - let a = a.0; - if b >= 64 { - None - } else { - Some(f(a, b)) - } - } - - fn __ashrti3(f: extern "C" fn(i128, u32) -> i128, a: I128, b: u32) -> Option { - let a = a.0; - if b >= 64 { - None - } else { - Some(f(a, b)) - } - } - - fn __lshrti3(f: extern "C" fn(u128, u32) -> u128, a: U128, b: u32) -> Option { - let a = a.0; - if b >= 128 { - None - } else { - Some(f(a, b)) - } - } - } -} diff --git a/src/int/udiv.rs b/src/int/udiv.rs index 6c125bb..e8db746 100644 --- a/src/int/udiv.rs +++ b/src/int/udiv.rs @@ -312,120 +312,3 @@ udivmodti4!(::U64x2, ::conv); #[cfg(not(all(windows, target_pointer_width="64")))] udivmodti4!(u128, |i|{ i }); - -#[cfg(test)] -mod tests { - use qc::{U32, U64}; - - check! { - fn __udivdi3(f: extern "C" fn(u64, u64) -> u64, n: U64, d: U64) -> Option { - let (n, d) = (n.0, d.0); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - fn __umoddi3(f: extern "C" fn(u64, u64) -> u64, n: U64, d: U64) -> Option { - let (n, d) = (n.0, d.0); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - fn __udivmoddi4(f: extern "C" fn(u64, u64, Option<&mut u64>) -> u64, - n: U64, - d: U64) -> Option<(u64, u64)> { - let (n, d) = (n.0, d.0); - if d == 0 { - None - } else { - let mut r = 0; - let q = f(n, d, Some(&mut r)); - Some((q, r)) - } - } - - fn __udivsi3(f: extern "C" fn(u32, u32) -> u32, n: U32, d: U32) -> Option { - let (n, d) = (n.0, d.0); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - fn __umodsi3(f: extern "C" fn(u32, u32) -> u32, n: U32, d: U32) -> Option { - let (n, d) = (n.0, d.0); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - fn __udivmodsi4(f: extern "C" fn(u32, u32, Option<&mut u32>) -> u32, - n: U32, - d: U32) -> Option<(u32, u32)> { - let (n, d) = (n.0, d.0); - if d == 0 { - None - } else { - let mut r = 0; - let q = f(n, d, Some(&mut r)); - Some((q, r)) - } - } - } -} - -#[cfg(test)] -#[cfg(all(not(windows), - not(target_arch = "mips64"), - not(target_arch = "mips64el"), - target_pointer_width="64"))] -mod tests_i128 { - use qc::U128; - - check! { - fn __udivti3(f: extern "C" fn(u128, u128) -> u128, - n: U128, - d: U128) -> Option { - let (n, d) = (n.0, d.0); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - fn __umodti3(f: extern "C" fn(u128, u128) -> u128, - n: U128, - d: U128) -> Option { - let (n, d) = (n.0, d.0); - if d == 0 { - None - } else { - Some(f(n, d)) - } - } - - fn __udivmodti4(f: extern "C" fn(u128, u128, Option<&mut u128>) -> u128, - n: U128, - d: U128) -> Option { - let (n, d) = (n.0, d.0); - if d == 0 { - None - } else { - // FIXME fix the segfault when the remainder is requested - /*let mut r = 0; - let q = f(n, d, Some(&mut r)); - Some((q, r))*/ - Some(f(n, d, None)) - } - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 0da336e..8c7820b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,26 +111,9 @@ fn sconv(i: i128) -> U64x2 { U64x2(j.low(), j.high()) } -#[cfg(test)] -#[cfg_attr(target_arch = "arm", macro_use)] -extern crate quickcheck; - #[cfg(test)] extern crate core; -#[cfg(test)] -extern crate gcc_s; - -#[cfg(test)] -extern crate compiler_rt; - -#[cfg(test)] -extern crate rand; - -#[cfg(test)] -#[macro_use] -mod qc; - pub mod int; pub mod float; diff --git a/tests/adddf3.rs b/tests/adddf3.rs new file mode 100644 index 0000000..3129330 --- /dev/null +++ b/tests/adddf3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/adddf3.rs")); diff --git a/tests/addsf3.rs b/tests/addsf3.rs new file mode 100644 index 0000000..b5c9c3d --- /dev/null +++ b/tests/addsf3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/addsf3.rs")); diff --git a/tests/ashldi3.rs b/tests/ashldi3.rs new file mode 100644 index 0000000..1116375 --- /dev/null +++ b/tests/ashldi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/ashldi3.rs")); diff --git a/tests/ashlti3.rs b/tests/ashlti3.rs new file mode 100644 index 0000000..4c799cf --- /dev/null +++ b/tests/ashlti3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/ashlti3.rs")); diff --git a/tests/ashrdi3.rs b/tests/ashrdi3.rs new file mode 100644 index 0000000..a0a2b6c --- /dev/null +++ b/tests/ashrdi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/ashrdi3.rs")); diff --git a/tests/ashrti3.rs b/tests/ashrti3.rs new file mode 100644 index 0000000..b147051 --- /dev/null +++ b/tests/ashrti3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/ashrti3.rs")); diff --git a/tests/divdi3.rs b/tests/divdi3.rs new file mode 100644 index 0000000..4bdce54 --- /dev/null +++ b/tests/divdi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/divdi3.rs")); diff --git a/tests/divmoddi4.rs b/tests/divmoddi4.rs new file mode 100644 index 0000000..9ddd85a --- /dev/null +++ b/tests/divmoddi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/divmoddi4.rs")); diff --git a/tests/divmodsi4.rs b/tests/divmodsi4.rs new file mode 100644 index 0000000..6fe80e9 --- /dev/null +++ b/tests/divmodsi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/divmodsi4.rs")); diff --git a/tests/divsi3.rs b/tests/divsi3.rs new file mode 100644 index 0000000..e6440d7 --- /dev/null +++ b/tests/divsi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/divsi3.rs")); diff --git a/tests/divti3.rs b/tests/divti3.rs new file mode 100644 index 0000000..c86785f --- /dev/null +++ b/tests/divti3.rs @@ -0,0 +1,11 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +// FIXME(#158) +#[cfg(not(any(target_arch = "mips", windows)))] +include!(concat!(env!("OUT_DIR"), "/divti3.rs")); diff --git a/tests/fixdfdi.rs b/tests/fixdfdi.rs new file mode 100644 index 0000000..b664775 --- /dev/null +++ b/tests/fixdfdi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixdfdi.rs")); diff --git a/tests/fixdfsi.rs b/tests/fixdfsi.rs new file mode 100644 index 0000000..2677eec --- /dev/null +++ b/tests/fixdfsi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixdfsi.rs")); diff --git a/tests/fixsfdi.rs b/tests/fixsfdi.rs new file mode 100644 index 0000000..e38952b --- /dev/null +++ b/tests/fixsfdi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixsfdi.rs")); diff --git a/tests/fixsfsi.rs b/tests/fixsfsi.rs new file mode 100644 index 0000000..242b4c1 --- /dev/null +++ b/tests/fixsfsi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixsfsi.rs")); diff --git a/tests/fixunsdfdi.rs b/tests/fixunsdfdi.rs new file mode 100644 index 0000000..13b35ba --- /dev/null +++ b/tests/fixunsdfdi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixunsdfdi.rs")); diff --git a/tests/fixunsdfsi.rs b/tests/fixunsdfsi.rs new file mode 100644 index 0000000..32faf36 --- /dev/null +++ b/tests/fixunsdfsi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixunsdfsi.rs")); diff --git a/tests/fixunssfdi.rs b/tests/fixunssfdi.rs new file mode 100644 index 0000000..24e6f6e --- /dev/null +++ b/tests/fixunssfdi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixunssfdi.rs")); diff --git a/tests/fixunssfsi.rs b/tests/fixunssfsi.rs new file mode 100644 index 0000000..da02cd9 --- /dev/null +++ b/tests/fixunssfsi.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/fixunssfsi.rs")); diff --git a/tests/floatdidf.rs b/tests/floatdidf.rs new file mode 100644 index 0000000..2b3dcb5 --- /dev/null +++ b/tests/floatdidf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatdidf.rs")); diff --git a/tests/floatsidf.rs b/tests/floatsidf.rs new file mode 100644 index 0000000..ffee7e2 --- /dev/null +++ b/tests/floatsidf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatsidf.rs")); diff --git a/tests/floatsisf.rs b/tests/floatsisf.rs new file mode 100644 index 0000000..c03ab7f --- /dev/null +++ b/tests/floatsisf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatsisf.rs")); diff --git a/tests/floatundidf.rs b/tests/floatundidf.rs new file mode 100644 index 0000000..0b83385 --- /dev/null +++ b/tests/floatundidf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatundidf.rs")); diff --git a/tests/floatunsidf.rs b/tests/floatunsidf.rs new file mode 100644 index 0000000..e25a69f --- /dev/null +++ b/tests/floatunsidf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatunsidf.rs")); diff --git a/tests/floatunsisf.rs b/tests/floatunsisf.rs new file mode 100644 index 0000000..c0b9fd8 --- /dev/null +++ b/tests/floatunsisf.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/floatunsisf.rs")); diff --git a/tests/lshrdi3.rs b/tests/lshrdi3.rs new file mode 100644 index 0000000..b1a2331 --- /dev/null +++ b/tests/lshrdi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/lshrdi3.rs")); diff --git a/tests/lshrti3.rs b/tests/lshrti3.rs new file mode 100644 index 0000000..2ee32ce --- /dev/null +++ b/tests/lshrti3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/lshrti3.rs")); diff --git a/tests/moddi3.rs b/tests/moddi3.rs new file mode 100644 index 0000000..6a58a77 --- /dev/null +++ b/tests/moddi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/moddi3.rs")); diff --git a/tests/modsi3.rs b/tests/modsi3.rs new file mode 100644 index 0000000..46ad8cd --- /dev/null +++ b/tests/modsi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/modsi3.rs")); diff --git a/tests/modti3.rs b/tests/modti3.rs new file mode 100644 index 0000000..2ce42ac --- /dev/null +++ b/tests/modti3.rs @@ -0,0 +1,11 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +// FIXME(#158) +#[cfg(not(any(target_arch = "mips", windows)))] +include!(concat!(env!("OUT_DIR"), "/modti3.rs")); diff --git a/tests/muldi3.rs b/tests/muldi3.rs new file mode 100644 index 0000000..d771e8a --- /dev/null +++ b/tests/muldi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/muldi3.rs")); diff --git a/tests/mulodi4.rs b/tests/mulodi4.rs new file mode 100644 index 0000000..071a295 --- /dev/null +++ b/tests/mulodi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/mulodi4.rs")); diff --git a/tests/mulosi4.rs b/tests/mulosi4.rs new file mode 100644 index 0000000..3ec4336 --- /dev/null +++ b/tests/mulosi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/mulosi4.rs")); diff --git a/tests/muloti4.rs b/tests/muloti4.rs new file mode 100644 index 0000000..358c57e --- /dev/null +++ b/tests/muloti4.rs @@ -0,0 +1,10 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +#[cfg(not(target_arch = "mips"))] +include!(concat!(env!("OUT_DIR"), "/muloti4.rs")); diff --git a/tests/multi3.rs b/tests/multi3.rs new file mode 100644 index 0000000..db52538 --- /dev/null +++ b/tests/multi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/multi3.rs")); diff --git a/tests/powidf2.rs b/tests/powidf2.rs new file mode 100644 index 0000000..dde5f03 --- /dev/null +++ b/tests/powidf2.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/powidf2.rs")); diff --git a/tests/powisf2.rs b/tests/powisf2.rs new file mode 100644 index 0000000..3e0baeb --- /dev/null +++ b/tests/powisf2.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/powisf2.rs")); diff --git a/tests/subdf3.rs b/tests/subdf3.rs new file mode 100644 index 0000000..13f6957 --- /dev/null +++ b/tests/subdf3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/subdf3.rs")); diff --git a/tests/subsf3.rs b/tests/subsf3.rs new file mode 100644 index 0000000..7be426c --- /dev/null +++ b/tests/subsf3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/subsf3.rs")); diff --git a/tests/udivdi3.rs b/tests/udivdi3.rs new file mode 100644 index 0000000..d87091c --- /dev/null +++ b/tests/udivdi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/udivdi3.rs")); diff --git a/tests/udivmoddi4.rs b/tests/udivmoddi4.rs new file mode 100644 index 0000000..a9444c1 --- /dev/null +++ b/tests/udivmoddi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/udivmoddi4.rs")); diff --git a/tests/udivmodsi4.rs b/tests/udivmodsi4.rs new file mode 100644 index 0000000..e93bfe1 --- /dev/null +++ b/tests/udivmodsi4.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/udivmodsi4.rs")); diff --git a/tests/udivmodti4.rs b/tests/udivmodti4.rs new file mode 100644 index 0000000..5629d61 --- /dev/null +++ b/tests/udivmodti4.rs @@ -0,0 +1,11 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +// FIXME(#158) +#[cfg(not(any(target_arch = "mips", windows)))] +include!(concat!(env!("OUT_DIR"), "/udivmodti4.rs")); diff --git a/tests/udivsi3.rs b/tests/udivsi3.rs new file mode 100644 index 0000000..d6433e7 --- /dev/null +++ b/tests/udivsi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/udivsi3.rs")); diff --git a/tests/udivti3.rs b/tests/udivti3.rs new file mode 100644 index 0000000..3509225 --- /dev/null +++ b/tests/udivti3.rs @@ -0,0 +1,11 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +// FIXME(#158) +#[cfg(not(any(target_arch = "mips", windows)))] +include!(concat!(env!("OUT_DIR"), "/udivti3.rs")); diff --git a/tests/umoddi3.rs b/tests/umoddi3.rs new file mode 100644 index 0000000..09a114e --- /dev/null +++ b/tests/umoddi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/umoddi3.rs")); diff --git a/tests/umodsi3.rs b/tests/umodsi3.rs new file mode 100644 index 0000000..aa56e81 --- /dev/null +++ b/tests/umodsi3.rs @@ -0,0 +1,8 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +include!(concat!(env!("OUT_DIR"), "/umodsi3.rs")); diff --git a/tests/umodti3.rs b/tests/umodti3.rs new file mode 100644 index 0000000..5807bcf --- /dev/null +++ b/tests/umodti3.rs @@ -0,0 +1,11 @@ +#![feature(compiler_builtins_lib)] +#![feature(i128_type)] +#![cfg_attr(all(target_arch = "arm", + not(any(target_env = "gnu", target_env = "musl")), + target_os = "linux", + test), no_std)] + +// FIXME(#137) +// FIXME(#158) +#[cfg(not(any(target_arch = "mips", windows)))] +include!(concat!(env!("OUT_DIR"), "/umodti3.rs")); diff --git a/thumbv6m-linux-eabi.json b/thumbv6m-linux-eabi.json new file mode 100644 index 0000000..dd0cb61 --- /dev/null +++ b/thumbv6m-linux-eabi.json @@ -0,0 +1,27 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "win64", + "sysv64" + ], + "arch": "arm", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "env": "", + "executables": true, + "features": "+strict-align", + "linker": "arm-none-eabi-gcc", + "linker-flavor": "gcc", + "llvm-target": "thumbv6m-none-eabi", + "max-atomic-width": 0, + "os": "linux", + "panic-strategy": "abort", + "pre-link-args": { + "gcc": ["-nostartfiles"] + }, + "relocation-model": "static", + "target-endian": "little", + "target-pointer-width": "32", + "vendor": "" +} diff --git a/thumbv7em-linux-eabi.json b/thumbv7em-linux-eabi.json new file mode 100644 index 0000000..eef29f5 --- /dev/null +++ b/thumbv7em-linux-eabi.json @@ -0,0 +1,26 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "win64", + "sysv64" + ], + "arch": "arm", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "env": "", + "executables": true, + "linker": "arm-none-eabi-gcc", + "linker-flavor": "gcc", + "llvm-target": "thumbv7em-none-eabi", + "max-atomic-width": 32, + "os": "linux", + "panic-strategy": "abort", + "pre-link-args": { + "gcc": ["-nostartfiles"] + }, + "relocation-model": "static", + "target-endian": "little", + "target-pointer-width": "32", + "vendor": "" +} diff --git a/thumbv7em-linux-eabihf.json b/thumbv7em-linux-eabihf.json new file mode 100644 index 0000000..5d72ec3 --- /dev/null +++ b/thumbv7em-linux-eabihf.json @@ -0,0 +1,27 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "win64", + "sysv64" + ], + "arch": "arm", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "env": "", + "executables": true, + "features": "+vfp4,+d16,+fp-only-sp", + "linker": "arm-none-eabi-gcc", + "linker-flavor": "gcc", + "llvm-target": "thumbv7em-none-eabihf", + "max-atomic-width": 32, + "os": "linux", + "panic-strategy": "abort", + "pre-link-args": { + "gcc": ["-nostartfiles"] + }, + "relocation-model": "static", + "target-endian": "little", + "target-pointer-width": "32", + "vendor": "" +} diff --git a/thumbv7m-linux-eabi.json b/thumbv7m-linux-eabi.json new file mode 100644 index 0000000..1e8a7f0 --- /dev/null +++ b/thumbv7m-linux-eabi.json @@ -0,0 +1,26 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "win64", + "sysv64" + ], + "arch": "arm", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "env": "", + "executables": true, + "linker": "arm-none-eabi-gcc", + "linker-flavor": "gcc", + "llvm-target": "thumbv7m-none-eabi", + "max-atomic-width": 32, + "os": "linux", + "panic-strategy": "abort", + "pre-link-args": { + "gcc": ["-nostartfiles"] + }, + "relocation-model": "static", + "target-endian": "little", + "target-pointer-width": "32", + "vendor": "" +}