est31 преди 8 години
родител
ревизия
b78e956f08
променени са 7 файла, в които са добавени 171 реда и са изтрити 0 реда
  1. 11 0
      compiler-rt/compiler-rt-cdylib/build.rs
  2. 27 0
      compiler-rt/compiler-rt-cdylib/src/lib.rs
  3. 24 0
      src/int/mul.rs
  4. 26 0
      src/int/sdiv.rs
  5. 36 0
      src/int/shift.rs
  6. 45 0
      src/int/udiv.rs
  7. 2 0
      src/qc.rs

+ 11 - 0
compiler-rt/compiler-rt-cdylib/build.rs

@@ -60,6 +60,17 @@ fn main() {
         "addsf3.c",
         "powidf2.c",
         "powisf2.c",
+        // 128 bit integers
+        "lshrti3.c",
+        "modti3.c",
+        "muloti4.c",
+        "multi3.c",
+        "udivmodti4.c",
+        "udivti3.c",
+        "umodti3.c",
+        "ashlti3.c",
+        "ashrti3.c",
+        "divti3.c",
     ]);
 
     for src in sources.files.iter() {

+ 27 - 0
compiler-rt/compiler-rt-cdylib/src/lib.rs

@@ -58,6 +58,33 @@ declare!(___adddf3, __adddf3);
 declare!(___powisf2, __powisf2);
 declare!(___powidf2, __powidf2);
 
+#[cfg(all(not(windows), target_pointer_width="64"))]
+pub mod int_128 {
+    extern {
+        fn __lshrti3();
+        fn __modti3();
+        fn __muloti4();
+        fn __multi3();
+        fn __udivmodti4();
+        fn __udivti3();
+        fn __umodti3();
+        fn __ashlti3();
+        fn __ashrti3();
+        fn __divti3();
+    }
+
+    declare!(___lshrti3, __lshrti3);
+    declare!(___modti3, __modti3);
+    declare!(___muloti4, __muloti4);
+    declare!(___multi3, __multi3);
+    declare!(___udivmodti4, __udivmodti4);
+    declare!(___udivti3, __udivti3);
+    declare!(___umodti3, __umodti3);
+    declare!(___ashlti3, __ashlti3);
+    declare!(___ashrti3, __ashrti3);
+    declare!(___divti3, __divti3);
+}
+
 #[lang = "eh_personality"]
 fn eh_personality() {}
 #[lang = "panic_fmt"]

+ 24 - 0
src/int/mul.rs

@@ -120,3 +120,27 @@ mod tests {
         }
     }
 }
+
+#[cfg(test)]
+#[cfg(all(not(windows), target_pointer_width="64"))]
+mod tests_i128 {
+    use qc::I128;
+
+    check! {
+        fn __multi3(f: extern fn(i128, i128) -> i128, a: I128, b: I128)
+                    -> Option<i128> {
+            Some(f(a.0, b.0))
+        }
+        fn __muloti4(f: extern fn(i128, i128, &mut i32) -> i128,
+                     a: I128,
+                     b: I128) -> Option<(i128, i32)> {
+            let (a, b) = (a.0, b.0);
+            let mut overflow = 2;
+            let r = f(a, b, &mut overflow);
+            if overflow != 0 && overflow != 1 {
+                return None
+            }
+            Some((r, overflow))
+        }
+    }
+}

+ 26 - 0
src/int/sdiv.rs

@@ -162,3 +162,29 @@ mod tests {
         }
     }
 }
+
+#[cfg(test)]
+#[cfg(all(not(windows), target_pointer_width="64"))]
+mod tests_i128 {
+    use qc::U128;
+
+    check! {
+        fn __divti3(f: extern fn(i128, i128) -> i128, n: U128, d: U128) -> Option<i128> {
+            let (n, d) = (n.0 as i128, d.0 as i128);
+            if d == 0 {
+                None
+            } else {
+                Some(f(n, d))
+            }
+        }
+
+        fn __modti3(f: extern fn(i128, i128) -> i128, n: U128, d: U128) -> Option<i128> {
+            let (n, d) = (n.0 as i128, d.0 as i128);
+            if d == 0 {
+                None
+            } else {
+                Some(f(n, d))
+            }
+        }
+    }
+}

+ 36 - 0
src/int/shift.rs

@@ -103,3 +103,39 @@ mod tests {
         }
     }
 }
+
+#[cfg(test)]
+#[cfg(all(not(windows), target_pointer_width="64"))]
+mod tests_i128 {
+    use qc::{I128, U128};
+
+    // NOTE We purposefully stick to `u32` for `b` here because we want "small" values (b < 64)
+    check! {
+        fn __ashlti3(f: extern fn(u128, u32) -> u128, a: U128, b: u32) -> Option<u128> {
+            let a = a.0;
+            if b >= 64 {
+                None
+            } else {
+                Some(f(a, b))
+            }
+        }
+
+        fn __ashrti3(f: extern fn(i128, u32) -> i128, a: I128, b: u32) -> Option<i128> {
+            let a = a.0;
+            if b >= 64 {
+                None
+            } else {
+                Some(f(a, b))
+            }
+        }
+
+        fn __lshrti3(f: extern fn(u128, u32) -> u128, a: U128, b: u32) -> Option<u128> {
+            let a = a.0;
+            if b >= 128 {
+                None
+            } else {
+                Some(f(a, b))
+            }
+        }
+    }
+}

+ 45 - 0
src/int/udiv.rs

@@ -380,3 +380,48 @@ mod tests {
         }
     }
 }
+
+#[cfg(test)]
+#[cfg(all(not(windows), target_pointer_width="64"))]
+mod tests_i128 {
+    use qc::U128;
+
+    check! {
+        fn __udivti3(f: extern fn(u128, u128) -> u128,
+                     n: U128,
+                     d: U128) -> Option<u128> {
+            let (n, d) = (n.0, d.0);
+            if d == 0 {
+                None
+            } else {
+                Some(f(n, d))
+            }
+        }
+
+        fn __umodti3(f: extern fn(u128, u128) -> u128,
+                     n: U128,
+                     d: U128) -> Option<u128> {
+            let (n, d) = (n.0, d.0);
+            if d == 0 {
+                None
+            } else {
+                Some(f(n, d))
+            }
+        }
+
+        fn __udivmodti4(f: extern fn(u128, u128, Option<&mut u128>) -> u128,
+                        n: U128,
+                        d: U128) -> Option<u128> {
+            let (n, d) = (n.0, d.0);
+            if d == 0 {
+                None
+            } else {
+                // FIXME fix the segfault when the remainder is requested
+                /*let mut r = 0;
+                let q = f(n, d, Some(&mut r));
+                Some((q, r))*/
+                Some(f(n, d, None))
+            }
+        }
+    }
+}

+ 2 - 0
src/qc.rs

@@ -144,6 +144,8 @@ macro_rules! arbitrary_large {
 
 arbitrary_large!(I64: i64);
 arbitrary_large!(U64: u64);
+arbitrary_large!(I128: i128);
+arbitrary_large!(U128: u128);
 
 macro_rules! arbitrary_float {
     ($TY:ident : $ty:ident) => {