|
@@ -1,436 +1,3866 @@
|
|
|
-#[cfg(feature = "c")]
|
|
|
-extern crate gcc;
|
|
|
-extern crate rustc_cfg;
|
|
|
+#![feature(i128_type)]
|
|
|
+
|
|
|
+use std::env;
|
|
|
+
|
|
|
+fn main() {
|
|
|
+ println!("cargo:rerun-if-changed=build.rs");
|
|
|
+
|
|
|
+ let target = env::var("TARGET").unwrap();
|
|
|
+
|
|
|
+ // Emscripten's runtime includes all the builtins
|
|
|
+ if target.contains("emscripten") {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // NOTE we are going to assume that llvm-target, what determines our codegen option, matches the
|
|
|
+ // target triple. This is usually correct for our built-in targets but can break in presence of
|
|
|
+ // custom targets, which can have arbitrary names.
|
|
|
+ let llvm_target = target.split('-').collect::<Vec<_>>();
|
|
|
+
|
|
|
+ // Build test files
|
|
|
+ #[cfg(feature = "gen-tests")]
|
|
|
+ tests::generate();
|
|
|
+
|
|
|
+ // Build missing intrinsics from compiler-rt C source code
|
|
|
+ #[cfg(feature = "c")]
|
|
|
+ c::compile(&llvm_target);
|
|
|
+
|
|
|
+ // To compile intrinsics.rs for thumb targets, where there is no libc
|
|
|
+ if llvm_target[0].starts_with("thumb") {
|
|
|
+ println!("cargo:rustc-cfg=thumb")
|
|
|
+ }
|
|
|
+
|
|
|
+ // compiler-rt `cfg`s away some intrinsics for thumbv6m because that target doesn't have full
|
|
|
+ // THUMBv2 support. We have to cfg our code accordingly.
|
|
|
+ if llvm_target[0] == "thumbv6m" {
|
|
|
+ println!("cargo:rustc-cfg=thumbv6m")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[cfg(feature = "gen-tests")]
|
|
|
+mod tests {
|
|
|
+ extern crate cast;
|
|
|
+ extern crate rand;
|
|
|
+
|
|
|
+ use std::collections::HashSet;
|
|
|
+ use std::fmt::Write;
|
|
|
+ use std::fs::File;
|
|
|
+ use std::hash::Hash;
|
|
|
+ use std::path::PathBuf;
|
|
|
+ use std::{env, mem};
|
|
|
+
|
|
|
+ use self::cast::{f32, f64, u32, u64, 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<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f64(rng);
|
|
|
+ let b = gen_f64(rng);
|
|
|
+ let c = a + b;
|
|
|
+ // TODO accept NaNs. We don't do that right now because we can't check
|
|
|
+ // for NaN-ness on the thumb targets (due to missing intrinsics)
|
|
|
+ if a.is_nan() || b.is_nan() || c.is_nan() {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+
|
|
|
+ Some(
|
|
|
+ Adddf3 {
|
|
|
+ a: to_u64(a),
|
|
|
+ b: to_u64(b),
|
|
|
+ c: to_u64(c),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::add::__adddf3;
|
|
|
+
|
|
|
+fn mk_f64(x: u64) -> f64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+fn to_u64(x: f64) -> u64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64, u64), u64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn adddf3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __adddf3(mk_f64(a), mk_f64(b));
|
|
|
+ assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Addsf3 {
|
|
|
+ a: u32, // f32
|
|
|
+ b: u32, // f32
|
|
|
+ c: u32, // f32
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Addsf3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "addsf3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f32(rng);
|
|
|
+ let b = gen_f32(rng);
|
|
|
+ let c = a + b;
|
|
|
+ // TODO accept NaNs. We don't do that right now because we can't check
|
|
|
+ // for NaN-ness on the thumb targets (due to missing intrinsics)
|
|
|
+ if a.is_nan() || b.is_nan() || c.is_nan() {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+
|
|
|
+ Some(
|
|
|
+ Addsf3 {
|
|
|
+ a: to_u32(a),
|
|
|
+ b: to_u32(b),
|
|
|
+ c: to_u32(c),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::add::__addsf3;
|
|
|
+
|
|
|
+fn mk_f32(x: u32) -> f32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+fn to_u32(x: f32) -> u32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32, u32), u32)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn addsf3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __addsf3(mk_f32(a), mk_f32(b));
|
|
|
+ assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Ashldi3 {
|
|
|
+ a: u64,
|
|
|
+ b: u32,
|
|
|
+ c: u64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Ashldi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "ashldi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u64(rng);
|
|
|
+ let b = (rng.gen::<u8>() % 64) as u32;
|
|
|
+ let c = a << b;
|
|
|
+
|
|
|
+ Some(Ashldi3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::shift::__ashldi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64, u32), u64)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn ashldi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __ashldi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Ashlti3 {
|
|
|
+ a: u128,
|
|
|
+ b: u32,
|
|
|
+ c: u128,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Ashlti3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "ashlti3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u128(rng);
|
|
|
+ let b = (rng.gen::<u8>() % 128) as u32;
|
|
|
+ let c = a << b;
|
|
|
+
|
|
|
+ Some(Ashlti3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::shift::__ashlti3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u128, u32), u128)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn ashlti3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __ashlti3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Ashrdi3 {
|
|
|
+ a: i64,
|
|
|
+ b: u32,
|
|
|
+ c: i64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Ashrdi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "ashrdi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i64(rng);
|
|
|
+ let b = (rng.gen::<u8>() % 64) as u32;
|
|
|
+ let c = a >> b;
|
|
|
+
|
|
|
+ Some(Ashrdi3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::shift::__ashrdi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i64, u32), i64)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn ashrdi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __ashrdi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Ashrti3 {
|
|
|
+ a: i128,
|
|
|
+ b: u32,
|
|
|
+ c: i128,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Ashrti3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "ashrti3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i128(rng);
|
|
|
+ let b = (rng.gen::<u8>() % 128) as u32;
|
|
|
+ let c = a >> b;
|
|
|
+
|
|
|
+ Some(Ashrti3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::shift::__ashrti3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i128, u32), i128)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn ashrti3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __ashrti3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Divmoddi4 {
|
|
|
+ a: i64,
|
|
|
+ b: i64,
|
|
|
+ c: i64,
|
|
|
+ rem: i64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Divmoddi4 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "divmoddi4"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i64(rng);
|
|
|
+ let b = gen_i64(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a / b;
|
|
|
+ let rem = a % b;
|
|
|
+
|
|
|
+ Some(Divmoddi4 { a, b, c, rem })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), ({c}, {rem})),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c,
|
|
|
+ rem = self.rem
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::sdiv::__divmoddi4;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i64, i64), (i64, i64))] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn divmoddi4() {
|
|
|
+ for &((a, b), (c, rem)) in TEST_CASES {
|
|
|
+ let mut rem_ = 0;
|
|
|
+ let c_ = __divmoddi4(a, b, &mut rem_);
|
|
|
+ assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Divdi3 {
|
|
|
+ a: i64,
|
|
|
+ b: i64,
|
|
|
+ c: i64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Divdi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "divdi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i64(rng);
|
|
|
+ let b = gen_i64(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a / b;
|
|
|
+
|
|
|
+ Some(Divdi3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::sdiv::__divdi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i64, i64), i64)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn divdi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __divdi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Divmodsi4 {
|
|
|
+ a: i32,
|
|
|
+ b: i32,
|
|
|
+ c: i32,
|
|
|
+ rem: i32,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Divmodsi4 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "divmodsi4"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i32(rng);
|
|
|
+ let b = gen_i32(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a / b;
|
|
|
+ let rem = a % b;
|
|
|
+
|
|
|
+ Some(Divmodsi4 { a, b, c, rem })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), ({c}, {rem})),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c,
|
|
|
+ rem = self.rem
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::sdiv::__divmodsi4;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i32, i32), (i32, i32))] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn divmodsi4() {
|
|
|
+ for &((a, b), (c, rem)) in TEST_CASES {
|
|
|
+ let mut rem_ = 0;
|
|
|
+ let c_ = __divmodsi4(a, b, &mut rem_);
|
|
|
+ assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Divsi3 {
|
|
|
+ a: i32,
|
|
|
+ b: i32,
|
|
|
+ c: i32,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Divsi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "divsi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i32(rng);
|
|
|
+ let b = gen_i32(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a / b;
|
|
|
+
|
|
|
+ Some(Divsi3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::sdiv::__divsi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i32, i32), i32)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn divsi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __divsi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Divti3 {
|
|
|
+ a: i128,
|
|
|
+ b: i128,
|
|
|
+ c: i128,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Divti3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "divti3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i128(rng);
|
|
|
+ let b = gen_i128(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a / b;
|
|
|
+
|
|
|
+ Some(Divti3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::sdiv::__divti3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i128, i128), i128)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn divti3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __divti3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Fixdfdi {
|
|
|
+ a: u64, // f64
|
|
|
+ b: i64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Fixdfdi {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "fixdfdi"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f64(rng);
|
|
|
+ i64(a).ok().map(|b| Fixdfdi { a: to_u64(a), b })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__fixdfdi;
|
|
|
+
|
|
|
+fn mk_f64(x: u64) -> f64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64,), i64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn fixdfdi() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __fixdfdi(mk_f64(a));
|
|
|
+ assert_eq!(((a,), b), ((a,), b_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Fixdfsi {
|
|
|
+ a: u64, // f64
|
|
|
+ b: i32,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Fixdfsi {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "fixdfsi"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f64(rng);
|
|
|
+ i32(a).ok().map(|b| Fixdfsi { a: to_u64(a), b })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__fixdfsi;
|
|
|
+
|
|
|
+fn mk_f64(x: u64) -> f64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64,), i32)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn fixdfdi() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __fixdfsi(mk_f64(a));
|
|
|
+ assert_eq!(((a,), b), ((a,), b_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Fixsfdi {
|
|
|
+ a: u32, // f32
|
|
|
+ b: i64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Fixsfdi {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "fixsfdi"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f32(rng);
|
|
|
+ i64(a).ok().map(|b| Fixsfdi { a: to_u32(a), b })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__fixsfdi;
|
|
|
+
|
|
|
+fn mk_f32(x: u32) -> f32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32,), i64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn fixsfdi() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __fixsfdi(mk_f32(a));
|
|
|
+ assert_eq!(((a,), b), ((a,), b_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Fixsfsi {
|
|
|
+ a: u32, // f32
|
|
|
+ b: i32,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Fixsfsi {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "fixsfsi"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f32(rng);
|
|
|
+ i32(a).ok().map(|b| Fixsfsi { a: to_u32(a), b })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__fixsfsi;
|
|
|
+
|
|
|
+fn mk_f32(x: u32) -> f32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32,), i32)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn 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<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f64(rng);
|
|
|
+ u64(a).ok().map(|b| Fixunsdfdi { a: to_u64(a), b })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__fixunsdfdi;
|
|
|
+
|
|
|
+fn mk_f64(x: u64) -> f64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64,), u64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn fixunsdfdi() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __fixunsdfdi(mk_f64(a));
|
|
|
+ assert_eq!(((a,), b), ((a,), b_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Fixunsdfsi {
|
|
|
+ a: u64, // f64
|
|
|
+ b: u32,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Fixunsdfsi {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "fixunsdfsi"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f64(rng);
|
|
|
+ u32(a).ok().map(|b| Fixunsdfsi { a: to_u64(a), b })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__fixunsdfsi;
|
|
|
+
|
|
|
+fn mk_f64(x: u64) -> f64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64,), u32)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn fixunsdfdi() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __fixunsdfsi(mk_f64(a));
|
|
|
+ assert_eq!(((a,), b), ((a,), b_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Fixunssfdi {
|
|
|
+ a: u32, // f32
|
|
|
+ b: u64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Fixunssfdi {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "fixunssfdi"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f32(rng);
|
|
|
+ u64(a).ok().map(|b| Fixunssfdi { a: to_u32(a), b })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__fixunssfdi;
|
|
|
+
|
|
|
+fn mk_f32(x: u32) -> f32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32,), u64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn fixunssfdi() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __fixunssfdi(mk_f32(a));
|
|
|
+ assert_eq!(((a,), b), ((a,), b_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Fixunssfsi {
|
|
|
+ a: u32, // f32
|
|
|
+ b: u32,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Fixunssfsi {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "fixunssfsi"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f32(rng);
|
|
|
+ u32(a).ok().map(|b| Fixunssfsi { a: to_u32(a), b })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__fixunssfsi;
|
|
|
+
|
|
|
+fn mk_f32(x: u32) -> f32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32,), u32)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn fixunssfsi() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __fixunssfsi(mk_f32(a));
|
|
|
+ assert_eq!(((a,), b), ((a,), b_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Floatdidf {
|
|
|
+ a: i64,
|
|
|
+ b: u64, // f64
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Floatdidf {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "floatdidf"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i64(rng);
|
|
|
+ Some(
|
|
|
+ Floatdidf {
|
|
|
+ a,
|
|
|
+ b: to_u64(f64(a)),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__floatdidf;
|
|
|
+
|
|
|
+fn to_u64(x: f64) -> u64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((i64,), u64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn floatdidf() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __floatdidf(a);
|
|
|
+ assert_eq!(((a,), b), ((a,), to_u64(b_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Floatsidf {
|
|
|
+ a: i32,
|
|
|
+ b: u64, // f64
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Floatsidf {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "floatsidf"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i32(rng);
|
|
|
+ Some(
|
|
|
+ Floatsidf {
|
|
|
+ a,
|
|
|
+ b: to_u64(f64(a)),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__floatsidf;
|
|
|
+
|
|
|
+fn to_u64(x: f64) -> u64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((i32,), u64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn floatsidf() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __floatsidf(a);
|
|
|
+ assert_eq!(((a,), b), ((a,), to_u64(b_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Floatsisf {
|
|
|
+ a: i32,
|
|
|
+ b: u32, // f32
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Floatsisf {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "floatsisf"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i32(rng);
|
|
|
+ Some(
|
|
|
+ Floatsisf {
|
|
|
+ a,
|
|
|
+ b: to_u32(f32(a)),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__floatsisf;
|
|
|
+
|
|
|
+fn to_u32(x: f32) -> u32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((i32,), u32)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn floatsisf() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __floatsisf(a);
|
|
|
+ assert_eq!(((a,), b), ((a,), to_u32(b_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Floatundidf {
|
|
|
+ a: u64,
|
|
|
+ b: u64, // f64
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Floatundidf {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "floatundidf"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u64(rng);
|
|
|
+ Some(
|
|
|
+ Floatundidf {
|
|
|
+ a,
|
|
|
+ b: to_u64(f64(a)),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__floatundidf;
|
|
|
+
|
|
|
+fn to_u64(x: f64) -> u64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64,), u64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn floatundidf() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __floatundidf(a);
|
|
|
+ assert_eq!(((a,), b), ((a,), to_u64(b_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Floatunsidf {
|
|
|
+ a: u32,
|
|
|
+ b: u64, // f64
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Floatunsidf {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "floatunsidf"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u32(rng);
|
|
|
+ Some(
|
|
|
+ Floatunsidf {
|
|
|
+ a,
|
|
|
+ b: to_u64(f64(a)),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__floatunsidf;
|
|
|
+
|
|
|
+fn to_u64(x: f64) -> u64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32,), u64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn floatunsidf() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __floatunsidf(a);
|
|
|
+ assert_eq!(((a,), b), ((a,), to_u64(b_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Floatunsisf {
|
|
|
+ a: u32,
|
|
|
+ b: u32, // f32
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Floatunsisf {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "floatunsisf"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u32(rng);
|
|
|
+ Some(
|
|
|
+ Floatunsisf {
|
|
|
+ a,
|
|
|
+ b: to_u32(f32(a)),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(buffer, "(({a},), {b}),", a = self.a, b = self.b).unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::conv::__floatunsisf;
|
|
|
+
|
|
|
+fn to_u32(x: f32) -> u32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32,), u32)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn floatunsisf() {
|
|
|
+ for &((a,), b) in TEST_CASES {
|
|
|
+ let b_ = __floatunsisf(a);
|
|
|
+ assert_eq!(((a,), b), ((a,), to_u32(b_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Moddi3 {
|
|
|
+ a: i64,
|
|
|
+ b: i64,
|
|
|
+ c: i64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Moddi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "moddi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i64(rng);
|
|
|
+ let b = gen_i64(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a % b;
|
|
|
+
|
|
|
+ Some(Moddi3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::sdiv::__moddi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i64, i64), i64)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn moddi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __moddi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Modsi3 {
|
|
|
+ a: i32,
|
|
|
+ b: i32,
|
|
|
+ c: i32,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Modsi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "modsi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i32(rng);
|
|
|
+ let b = gen_i32(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a % b;
|
|
|
+
|
|
|
+ Some(Modsi3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::sdiv::__modsi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i32, i32), i32)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn modsi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __modsi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Modti3 {
|
|
|
+ a: i128,
|
|
|
+ b: i128,
|
|
|
+ c: i128,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Modti3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "modti3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i128(rng);
|
|
|
+ let b = gen_i128(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a % b;
|
|
|
+
|
|
|
+ Some(Modti3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::sdiv::__modti3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i128, i128), i128)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn modti3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __modti3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ struct Muldi3 {
|
|
|
+ a: u64,
|
|
|
+ b: u64,
|
|
|
+ c: u64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Muldi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "muldi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u64(rng);
|
|
|
+ let b = gen_u64(rng);
|
|
|
+ let c = a.wrapping_mul(b);
|
|
|
+
|
|
|
+ Some(Muldi3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::mul::__muldi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64, u64), u64)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn muldi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __muldi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Mulodi4 {
|
|
|
+ a: i64,
|
|
|
+ b: i64,
|
|
|
+ c: i64,
|
|
|
+ overflow: u32,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Mulodi4 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "mulodi4"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ {
|
|
|
+ let a = gen_i64(rng);
|
|
|
+ let b = gen_i64(rng);
|
|
|
+ let c = a.wrapping_mul(b);
|
|
|
+ let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 };
|
|
|
+
|
|
|
+ Some(Mulodi4 { a, b, c, overflow })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), ({c}, {overflow})),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c,
|
|
|
+ overflow = self.overflow
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::mul::__mulodi4;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i64, i64), (i64, i32))] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn mulodi4() {
|
|
|
+ let mut overflow_ = 2;
|
|
|
+ for &((a, b), (c, overflow)) in TEST_CASES {
|
|
|
+ let c_ = __mulodi4(a, b, &mut overflow_);
|
|
|
+ assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Mulosi4 {
|
|
|
+ a: i32,
|
|
|
+ b: i32,
|
|
|
+ c: i32,
|
|
|
+ overflow: u32,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Mulosi4 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "mulosi4"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ {
|
|
|
+ let a = gen_i32(rng);
|
|
|
+ let b = gen_i32(rng);
|
|
|
+ let c = a.wrapping_mul(b);
|
|
|
+ let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 };
|
|
|
+
|
|
|
+ Some(Mulosi4 { a, b, c, overflow })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::mul::__mulosi4;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i32, i32), (i32, i32))] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn mulosi4() {
|
|
|
+ let mut overflow_ = 2;
|
|
|
+ for &((a, b), (c, overflow)) in TEST_CASES {
|
|
|
+ let c_ = __mulosi4(a, b, &mut overflow_);
|
|
|
+ assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), ({c}, {overflow})),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c,
|
|
|
+ overflow = self.overflow
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Muloti4 {
|
|
|
+ a: i128,
|
|
|
+ b: i128,
|
|
|
+ c: i128,
|
|
|
+ overflow: u32,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Muloti4 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "muloti4"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ {
|
|
|
+ let a = gen_i128(rng);
|
|
|
+ let b = gen_i128(rng);
|
|
|
+ let c = a.wrapping_mul(b);
|
|
|
+ let overflow = if a.checked_mul(b).is_some() { 0 } else { 1 };
|
|
|
+
|
|
|
+ Some(Muloti4 { a, b, c, overflow })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::mul::__muloti4;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i128, i128), (i128, i32))] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn muloti4() {
|
|
|
+ let mut overflow_ = 2;
|
|
|
+ for &((a, b), (c, overflow)) in TEST_CASES {
|
|
|
+ let c_ = __muloti4(a, b, &mut overflow_);
|
|
|
+ assert_eq!(((a, b), (c, overflow)), ((a, b), (c_, overflow_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), ({c}, {overflow})),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c,
|
|
|
+ overflow = self.overflow
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Multi3 {
|
|
|
+ a: i128,
|
|
|
+ b: i128,
|
|
|
+ c: i128,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Multi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "multi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_i128(rng);
|
|
|
+ let b = gen_i128(rng);
|
|
|
+ let c = a.wrapping_mul(b);
|
|
|
+
|
|
|
+ Some(Multi3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::mul::__multi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((i128, i128), i128)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn multi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __multi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Powidf2 {
|
|
|
+ a: u64, // f64
|
|
|
+ b: i32,
|
|
|
+ c: u64, // f64
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Powidf2 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "powidf2"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f64(rng);
|
|
|
+ let b = gen_i32(rng);
|
|
|
+ let c = a.powi(b);
|
|
|
+ // TODO accept NaNs. We don't do that right now because we can't check
|
|
|
+ // for NaN-ness on the thumb targets
|
|
|
+ if a.is_nan() || c.is_nan() {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+
|
|
|
+ Some(
|
|
|
+ Powidf2 {
|
|
|
+ a: to_u64(a),
|
|
|
+ b,
|
|
|
+ c: to_u64(c),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::pow::__powidf2;
|
|
|
+
|
|
|
+fn mk_f64(x: u64) -> f64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+fn to_u64(x: f64) -> u64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64, i32), u64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn powidf2() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __powidf2(mk_f64(a), b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Powisf2 {
|
|
|
+ a: u32, // f32
|
|
|
+ b: i32,
|
|
|
+ c: u32, // f32
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Powisf2 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "powisf2"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f32(rng);
|
|
|
+ let b = gen_i32(rng);
|
|
|
+ let c = a.powi(b);
|
|
|
+ // TODO accept NaNs. We don't do that right now because we can't check
|
|
|
+ // for NaN-ness on the thumb targets
|
|
|
+ if a.is_nan() || c.is_nan() {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+
|
|
|
+ Some(
|
|
|
+ Powisf2 {
|
|
|
+ a: to_u32(a),
|
|
|
+ b,
|
|
|
+ c: to_u32(c),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::pow::__powisf2;
|
|
|
+
|
|
|
+fn mk_f32(x: u32) -> f32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+fn to_u32(x: f32) -> u32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32, i32), u32)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn powisf2() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __powisf2(mk_f32(a), b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Lshrdi3 {
|
|
|
+ a: u64,
|
|
|
+ b: u32,
|
|
|
+ c: u64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Lshrdi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "lshrdi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u64(rng);
|
|
|
+ let b = (rng.gen::<u8>() % 64) as u32;
|
|
|
+ let c = a >> b;
|
|
|
+
|
|
|
+ Some(Lshrdi3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::shift::__lshrdi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64, u32), u64)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn lshrdi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __lshrdi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Lshrti3 {
|
|
|
+ a: u128,
|
|
|
+ b: u32,
|
|
|
+ c: u128,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Lshrti3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "lshrti3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u128(rng);
|
|
|
+ let b = (rng.gen::<u8>() % 128) as u32;
|
|
|
+ let c = a >> b;
|
|
|
+
|
|
|
+ Some(Lshrti3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::shift::__lshrti3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u128, u32), u128)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn lshrti3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __lshrti3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Subdf3 {
|
|
|
+ a: u64, // f64
|
|
|
+ b: u64, // f64
|
|
|
+ c: u64, // f64
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Subdf3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "subdf3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f64(rng);
|
|
|
+ let b = gen_f64(rng);
|
|
|
+ let c = a - b;
|
|
|
+ // TODO accept NaNs. We don't do that right now because we can't check
|
|
|
+ // for NaN-ness on the thumb targets (due to missing intrinsics)
|
|
|
+ if a.is_nan() || b.is_nan() || c.is_nan() {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+
|
|
|
+ Some(
|
|
|
+ Subdf3 {
|
|
|
+ a: to_u64(a),
|
|
|
+ b: to_u64(b),
|
|
|
+ c: to_u64(c),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::sub::__subdf3;
|
|
|
+
|
|
|
+fn mk_f64(x: u64) -> f64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+fn to_u64(x: f64) -> u64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64, u64), u64)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn subdf3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __subdf3(mk_f64(a), mk_f64(b));
|
|
|
+ assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Subsf3 {
|
|
|
+ a: u32, // f32
|
|
|
+ b: u32, // f32
|
|
|
+ c: u32, // f32
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Subsf3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "subsf3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_f32(rng);
|
|
|
+ let b = gen_f32(rng);
|
|
|
+ let c = a - b;
|
|
|
+ // TODO accept NaNs. We don't do that right now because we can't check
|
|
|
+ // for NaN-ness on the thumb targets (due to missing intrinsics)
|
|
|
+ if a.is_nan() || b.is_nan() || c.is_nan() {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+
|
|
|
+ Some(
|
|
|
+ Subsf3 {
|
|
|
+ a: to_u32(a),
|
|
|
+ b: to_u32(b),
|
|
|
+ c: to_u32(c),
|
|
|
+ },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ r#"
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+use core::mem;
|
|
|
+#[cfg(not(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test)))]
|
|
|
+use std::mem;
|
|
|
+use compiler_builtins::float::sub::__subsf3;
|
|
|
+
|
|
|
+fn mk_f32(x: u32) -> f32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+fn to_u32(x: f32) -> u32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+}
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32, u32), u32)] = &[
|
|
|
+"#
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn subsf3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __subsf3(mk_f32(a), mk_f32(b));
|
|
|
+ assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Udivdi3 {
|
|
|
+ a: u64,
|
|
|
+ b: u64,
|
|
|
+ c: u64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Udivdi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "udivdi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u64(rng);
|
|
|
+ let b = gen_u64(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a / b;
|
|
|
+
|
|
|
+ Some(Udivdi3 { a, b, c })
|
|
|
+ }
|
|
|
|
|
|
-#[cfg(feature = "c")]
|
|
|
-use std::collections::BTreeMap;
|
|
|
-use std::io::Write;
|
|
|
-#[cfg(feature = "c")]
|
|
|
-use std::path::Path;
|
|
|
-use std::{env, io, process};
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
|
|
|
-use rustc_cfg::Cfg;
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::udiv::__udivdi3;
|
|
|
|
|
|
-#[cfg(feature = "c")]
|
|
|
-struct Sources {
|
|
|
- // SYMBOL -> PATH TO SOURCE
|
|
|
- map: BTreeMap<&'static str, &'static str>,
|
|
|
+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_));
|
|
|
+ }
|
|
|
}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-#[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);
|
|
|
- }
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Udivmoddi4 {
|
|
|
+ a: u64,
|
|
|
+ b: u64,
|
|
|
+ c: u64,
|
|
|
+ rem: u64,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Udivmoddi4 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "udivmoddi4"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u64(rng);
|
|
|
+ let b = gen_u64(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
}
|
|
|
+ let c = a / b;
|
|
|
+ let rem = a % b;
|
|
|
+
|
|
|
+ Some(Udivmoddi4 { a, b, c, rem })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), ({c}, {rem})),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c,
|
|
|
+ rem = self.rem
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::udiv::__udivmoddi4;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64, u64), (u64, u64))] = &[
|
|
|
+"
|
|
|
}
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn udivmoddi4() {
|
|
|
+ for &((a, b), (c, rem)) in TEST_CASES {
|
|
|
+ let mut rem_ = 0;
|
|
|
+ let c_ = __udivmoddi4(a, b, Some(&mut rem_));
|
|
|
+ assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Udivmodsi4 {
|
|
|
+ a: u32,
|
|
|
+ b: u32,
|
|
|
+ c: u32,
|
|
|
+ rem: u32,
|
|
|
}
|
|
|
|
|
|
- fn remove(&mut self, symbols: &[&str]) {
|
|
|
- for symbol in symbols {
|
|
|
- self.map.remove(*symbol).unwrap();
|
|
|
+ impl TestCase for Udivmodsi4 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "udivmodsi4"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u32(rng);
|
|
|
+ let b = gen_u32(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a / b;
|
|
|
+ let rem = a % b;
|
|
|
+
|
|
|
+ Some(Udivmodsi4 { a, b, c, rem })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), ({c}, {rem})),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c,
|
|
|
+ rem = self.rem
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::udiv::__udivmodsi4;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32, u32), (u32, u32))] = &[
|
|
|
+"
|
|
|
}
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn udivmodsi4() {
|
|
|
+ for &((a, b), (c, rem)) in TEST_CASES {
|
|
|
+ let mut rem_ = 0;
|
|
|
+ let c_ = __udivmodsi4(a, b, Some(&mut rem_));
|
|
|
+ assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
|
|
|
}
|
|
|
}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-fn main() {
|
|
|
- println!("cargo:rerun-if-changed=build.rs");
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Udivmodti4 {
|
|
|
+ a: u128,
|
|
|
+ b: u128,
|
|
|
+ c: u128,
|
|
|
+ rem: u128,
|
|
|
+ }
|
|
|
|
|
|
- let target = env::var("TARGET").unwrap();
|
|
|
+ impl TestCase for Udivmodti4 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "udivmodti4"
|
|
|
+ }
|
|
|
|
|
|
- // Emscripten's runtime includes all the builtins
|
|
|
- if target.contains("emscripten") {
|
|
|
- return;
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u128(rng);
|
|
|
+ let b = gen_u128(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
+ }
|
|
|
+ let c = a / b;
|
|
|
+ let rem = a % b;
|
|
|
+
|
|
|
+ Some(Udivmodti4 { a, b, c, rem })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), ({c}, {rem})),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c,
|
|
|
+ rem = self.rem
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::udiv::__udivmodti4;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u128, u128), (u128, u128))] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn udivmodti4() {
|
|
|
+ for &((a, b), (c, rem)) in TEST_CASES {
|
|
|
+ let mut rem_ = 0;
|
|
|
+ let c_ = __udivmodti4(a, b, Some(&mut rem_));
|
|
|
+ assert_eq!(((a, b), (c, rem)), ((a, b), (c_, rem_)));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- 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::<Vec<_>>();
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Udivsi3 {
|
|
|
+ a: u32,
|
|
|
+ b: u32,
|
|
|
+ c: u32,
|
|
|
+ }
|
|
|
|
|
|
- // 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");
|
|
|
- }
|
|
|
+ impl TestCase for Udivsi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "udivsi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u32(rng);
|
|
|
+ let b = gen_u32(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
}
|
|
|
+ let c = a / b;
|
|
|
|
|
|
- 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"]);
|
|
|
- }
|
|
|
+ Some(Udivsi3 { a, b, 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"]);
|
|
|
- }
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
|
|
|
- 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"]);
|
|
|
- }
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::udiv::__udivsi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u32, u32), u32)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn udivsi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __udivsi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Udivti3 {
|
|
|
+ a: u128,
|
|
|
+ b: u128,
|
|
|
+ c: u128,
|
|
|
+ }
|
|
|
+
|
|
|
+ impl TestCase for Udivti3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "udivti3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u128(rng);
|
|
|
+ let b = gen_u128(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
}
|
|
|
+ let c = a / b;
|
|
|
|
|
|
- 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"]);
|
|
|
- }
|
|
|
+ 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,
|
|
|
+ }
|
|
|
|
|
|
- sources.extend(&["arm/negdf2vfp.S", "arm/negsf2vfp.S"]);
|
|
|
+ impl TestCase for Umoddi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "umoddi3"
|
|
|
+ }
|
|
|
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u64(rng);
|
|
|
+ let b = gen_u64(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
}
|
|
|
+ let c = a % b;
|
|
|
+
|
|
|
+ Some(Umoddi3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::udiv::__umoddi3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u64, u64), u64)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn umoddi3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __umoddi3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #[derive(Eq, Hash, PartialEq)]
|
|
|
+ pub struct Umodsi3 {
|
|
|
+ a: u32,
|
|
|
+ b: u32,
|
|
|
+ c: u32,
|
|
|
+ }
|
|
|
|
|
|
- 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"]);
|
|
|
+ impl TestCase for Umodsi3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "umodsi3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u32(rng);
|
|
|
+ let b = gen_u32(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
}
|
|
|
+ let c = a % b;
|
|
|
+
|
|
|
+ Some(Umodsi3 { a, b, c })
|
|
|
+ }
|
|
|
|
|
|
- // 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"]);
|
|
|
+ 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,
|
|
|
+ }
|
|
|
|
|
|
- // But use some generic implementations where possible
|
|
|
- sources.extend(&["clzdi2.c", "clzsi2.c"])
|
|
|
+ impl TestCase for Umodti3 {
|
|
|
+ fn name() -> &'static str {
|
|
|
+ "umodti3"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized,
|
|
|
+ {
|
|
|
+ let a = gen_u128(rng);
|
|
|
+ let b = gen_u128(rng);
|
|
|
+ if b == 0 {
|
|
|
+ return None;
|
|
|
}
|
|
|
+ let c = a % b;
|
|
|
+
|
|
|
+ Some(Umodti3 { a, b, c })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn to_string(&self, buffer: &mut String) {
|
|
|
+ writeln!(
|
|
|
+ buffer,
|
|
|
+ "(({a}, {b}), {c}),",
|
|
|
+ a = self.a,
|
|
|
+ b = self.b,
|
|
|
+ c = self.c
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prologue() -> &'static str {
|
|
|
+ "
|
|
|
+use compiler_builtins::int::udiv::__umodti3;
|
|
|
+
|
|
|
+static TEST_CASES: &[((u128, u128), u128)] = &[
|
|
|
+"
|
|
|
+ }
|
|
|
+
|
|
|
+ fn epilogue() -> &'static str {
|
|
|
+ "
|
|
|
+];
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn umodti3() {
|
|
|
+ for &((a, b), c) in TEST_CASES {
|
|
|
+ let c_ = __umodti3(a, b);
|
|
|
+ assert_eq!(((a, b), c), ((a, b), c_));
|
|
|
+ }
|
|
|
+}
|
|
|
+"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ trait TestCase {
|
|
|
+ /// Name of the intrinsic to test
|
|
|
+ fn name() -> &'static str;
|
|
|
+ /// Generates a valid test case
|
|
|
+ fn generate<R>(rng: &mut R) -> Option<Self>
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ Self: Sized;
|
|
|
+ /// Stringifies a test case
|
|
|
+ fn to_string(&self, buffer: &mut String);
|
|
|
+ /// Prologue of the test file
|
|
|
+ fn prologue() -> &'static str;
|
|
|
+ /// Epilogue of the test file
|
|
|
+ fn epilogue() -> &'static str;
|
|
|
+ }
|
|
|
+
|
|
|
+ const PROLOGUE: &'static str = r#"
|
|
|
+extern crate compiler_builtins;
|
|
|
+
|
|
|
+// test runner
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+extern crate utest_cortex_m_qemu;
|
|
|
+
|
|
|
+// overrides `panic!`
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+#[macro_use]
|
|
|
+extern crate utest_macros;
|
|
|
|
|
|
- if llvm_target[0] == "thumbv7m" || llvm_target[0] == "thumbv7em" {
|
|
|
- sources.remove(&["aeabi_cdcmp", "aeabi_cfcmp"]);
|
|
|
+#[cfg(all(target_arch = "arm",
|
|
|
+ not(any(target_env = "gnu", target_env = "musl")),
|
|
|
+ target_os = "linux",
|
|
|
+ test))]
|
|
|
+macro_rules! panic {
|
|
|
+ ($($tt:tt)*) => {
|
|
|
+ upanic!($($tt)*);
|
|
|
+ };
|
|
|
+}
|
|
|
+"#;
|
|
|
+
|
|
|
+ macro_rules! gen_int {
|
|
|
+ ($name:ident, $ity:ident, $hty:ident) => {
|
|
|
+ fn $name<R>(rng: &mut R) -> $ity
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ {
|
|
|
+ let mut mk = || if rng.gen_weighted_bool(10) {
|
|
|
+ *rng.choose(&[::std::$hty::MAX, 0, ::std::$hty::MIN]).unwrap()
|
|
|
+ } else {
|
|
|
+ rng.gen::<$hty>()
|
|
|
+ };
|
|
|
+ unsafe { mem::transmute([mk(), mk()]) }
|
|
|
}
|
|
|
|
|
|
- let root = if env::var_os("CARGO_FEATURE_RUSTBUILD").is_some() {
|
|
|
- Path::new("../../libcompiler_builtins")
|
|
|
- } else {
|
|
|
- Path::new(".")
|
|
|
- };
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ gen_int!(gen_i32, i32, i16);
|
|
|
+ gen_int!(gen_i64, i64, i32);
|
|
|
+ gen_int!(gen_i128, i128, i64);
|
|
|
+
|
|
|
+ macro_rules! gen_float {
|
|
|
+ ($name:ident,
|
|
|
+ $fty:ident,
|
|
|
+ $uty:ident,
|
|
|
+ $bits:expr,
|
|
|
+ $significand_bits:expr) => {
|
|
|
+ pub fn $name<R>(rng: &mut R) -> $fty
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ {
|
|
|
+ const BITS: u8 = $bits;
|
|
|
+ const SIGNIFICAND_BITS: u8 = $significand_bits;
|
|
|
+
|
|
|
+ const SIGNIFICAND_MASK: $uty = (1 << SIGNIFICAND_BITS) - 1;
|
|
|
+ const SIGN_MASK: $uty = (1 << (BITS - 1));
|
|
|
+ const EXPONENT_MASK: $uty = !(SIGN_MASK | SIGNIFICAND_MASK);
|
|
|
+
|
|
|
+ fn mk_f32(sign: bool, exponent: $uty, significand: $uty) -> $fty {
|
|
|
+ unsafe {
|
|
|
+ mem::transmute(((sign as $uty) << (BITS - 1)) |
|
|
|
+ ((exponent & EXPONENT_MASK) <<
|
|
|
+ SIGNIFICAND_BITS) |
|
|
|
+ (significand & SIGNIFICAND_MASK))
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- 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());
|
|
|
+ if rng.gen_weighted_bool(10) {
|
|
|
+ // Special values
|
|
|
+ *rng.choose(&[-0.0,
|
|
|
+ 0.0,
|
|
|
+ ::std::$fty::NAN,
|
|
|
+ ::std::$fty::INFINITY,
|
|
|
+ -::std::$fty::INFINITY])
|
|
|
+ .unwrap()
|
|
|
+ } else if rng.gen_weighted_bool(10) {
|
|
|
+ // NaN patterns
|
|
|
+ mk_f32(rng.gen(), rng.gen(), 0)
|
|
|
+ } else if rng.gen() {
|
|
|
+ // Denormalized
|
|
|
+ mk_f32(rng.gen(), 0, rng.gen())
|
|
|
+ } else {
|
|
|
+ // Random anything
|
|
|
+ mk_f32(rng.gen(), rng.gen(), rng.gen())
|
|
|
+ }
|
|
|
}
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ gen_float!(gen_f32, f32, u32, 32, 23);
|
|
|
+ gen_float!(gen_f64, f64, u64, 64, 52);
|
|
|
+
|
|
|
+ pub fn gen_u128<R>(rng: &mut R) -> u128
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ {
|
|
|
+ gen_i128(rng) as u128
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn gen_u32<R>(rng: &mut R) -> u32
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ {
|
|
|
+ gen_i32(rng) as u32
|
|
|
+ }
|
|
|
+
|
|
|
+ fn gen_u64<R>(rng: &mut R) -> u64
|
|
|
+ where
|
|
|
+ R: Rng,
|
|
|
+ {
|
|
|
+ gen_i64(rng) as u64
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn to_u32(x: f32) -> u32 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn to_u64(x: f64) -> u64 {
|
|
|
+ unsafe { mem::transmute(x) }
|
|
|
+ }
|
|
|
|
|
|
- cfg.compile("libcompiler-rt.a");
|
|
|
+ fn mk_tests<T, R>(mut n: usize, rng: &mut R) -> String
|
|
|
+ where
|
|
|
+ T: Eq + Hash + TestCase,
|
|
|
+ R: Rng,
|
|
|
+ {
|
|
|
+ let mut buffer = PROLOGUE.to_owned();
|
|
|
+ buffer.push_str(T::prologue());
|
|
|
+ let mut cases = HashSet::new();
|
|
|
+ while n != 0 {
|
|
|
+ if let Some(case) = T::generate(rng) {
|
|
|
+ if cases.contains(&case) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ case.to_string(&mut buffer);
|
|
|
+ n -= 1;
|
|
|
+ cases.insert(case);
|
|
|
+ }
|
|
|
}
|
|
|
- #[cfg(not(feature = "c"))]
|
|
|
- () => {}
|
|
|
+ buffer.push_str(T::epilogue());
|
|
|
+ buffer
|
|
|
}
|
|
|
|
|
|
- // 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")
|
|
|
+ fn mk_file<T>()
|
|
|
+ where
|
|
|
+ T: Eq + Hash + TestCase,
|
|
|
+ {
|
|
|
+ use std::io::Write;
|
|
|
+
|
|
|
+ let rng = &mut rand::thread_rng();
|
|
|
+ let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
|
|
+ let out_file = out_dir.join(format!("{}.rs", T::name()));
|
|
|
+ let contents = mk_tests::<T, _>(NTESTS, rng);
|
|
|
+
|
|
|
+ File::create(out_file)
|
|
|
+ .unwrap()
|
|
|
+ .write_all(contents.as_bytes())
|
|
|
+ .unwrap();
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- // To compile intrinsics.rs for thumb targets, where there is no libc
|
|
|
- if llvm_target[0].starts_with("thumb") {
|
|
|
- println!("cargo:rustc-cfg=thumb")
|
|
|
+#[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>,
|
|
|
}
|
|
|
|
|
|
- // compiler-rt `cfg`s away some intrinsics for thumbv6m because that target doesn't have full
|
|
|
- // THUMBv2 support. We have to cfg our code accordingly.
|
|
|
- if llvm_target[0] == "thumbv6m" {
|
|
|
- println!("cargo:rustc-cfg=thumbv6m")
|
|
|
+ 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");
|
|
|
}
|
|
|
}
|