diff options
| author | gingerBill <bill@gingerbill.org> | 2021-12-09 15:36:12 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-12-09 15:36:12 +0000 |
| commit | 94bad4d7861c78b9e7191ec0c3114861a1536d5c (patch) | |
| tree | 797ad4024663f57c85df7975af91e4fe5e9dcd75 /core | |
| parent | 1d7c9cf87223971620e1812ca3c84c9581a1c43a (diff) | |
| parent | 3d85013abafff94df11079da949fbf6c03749e35 (diff) | |
Merge branch 'master' of https://github.com/odin-lang/Odin
Diffstat (limited to 'core')
| -rw-r--r-- | core/math/big/common.odin | 15 | ||||
| -rw-r--r-- | core/math/big/internal.odin | 60 | ||||
| -rw-r--r-- | core/runtime/internal.odin | 14 | ||||
| -rw-r--r-- | core/runtime/procs_wasm32.odin | 41 |
4 files changed, 89 insertions, 41 deletions
diff --git a/core/math/big/common.odin b/core/math/big/common.odin index d534cc90e..31ad54b14 100644 --- a/core/math/big/common.odin +++ b/core/math/big/common.odin @@ -158,13 +158,14 @@ Error :: enum int { Invalid_Pointer = 2, Invalid_Argument = 3, - Assignment_To_Immutable = 4, - Max_Iterations_Reached = 5, - Buffer_Overflow = 6, - Integer_Overflow = 7, - - Division_by_Zero = 8, - Math_Domain_Error = 9, + Assignment_To_Immutable = 10, + Max_Iterations_Reached = 11, + Buffer_Overflow = 12, + Integer_Overflow = 13, + Integer_Underflow = 14, + + Division_by_Zero = 30, + Math_Domain_Error = 31, Cannot_Open_File = 50, Cannot_Read_File = 51, diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index a5e1e7ba3..2d412d84e 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -34,6 +34,7 @@ package math_big import "core:mem" import "core:intrinsics" import rnd "core:math/rand" +import "core:builtin" /* Low-level addition, unsigned. Handbook of Applied Cryptography, algorithm 14.7. @@ -1880,8 +1881,6 @@ internal_int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, al where intrinsics.type_is_integer(T) { context.allocator = allocator - src := src - internal_error_if_immutable(dest) or_return /* Most internal procs asssume an Int to have already been initialize, @@ -1892,13 +1891,27 @@ internal_int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, al dest.flags = {} // We're not -Inf, Inf, NaN or Immutable. dest.used = 0 - dest.sign = .Zero_or_Positive if src >= 0 else .Negative - src = internal_abs(src) + dest.sign = .Negative if src < 0 else .Zero_or_Positive + + temp := src + + is_maximally_negative := src == min(T) + if is_maximally_negative { + /* + Prevent overflow on abs() + */ + temp += 1 + } + temp = -temp if temp < 0 else temp - #no_bounds_check for src != 0 { - dest.digit[dest.used] = DIGIT(src) & _MASK + #no_bounds_check for temp != 0 { + dest.digit[dest.used] = DIGIT(temp) & _MASK dest.used += 1 - src >>= _DIGIT_BITS + temp >>= _DIGIT_BITS + } + + if is_maximally_negative { + return internal_sub(dest, dest, 1) } internal_zero_unused(dest) return nil @@ -2341,24 +2354,31 @@ internal_get_low_u64 :: proc(a: ^Int) -> u64 #no_bounds_check { and maybe return max(T), .Integer_Overflow if not? */ internal_int_get :: proc(a: ^Int, $T: typeid) -> (res: T, err: Error) where intrinsics.type_is_integer(T) { - size_in_bits := int(size_of(T) * 8) - i := int((size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS) - i = min(int(a.used), i) - - #no_bounds_check for ; i >= 0; i -= 1 { - res <<= uint(0) if size_in_bits <= _DIGIT_BITS else _DIGIT_BITS - res |= T(a.digit[i]) - if size_in_bits <= _DIGIT_BITS { - break + /* + Calculate target bit size. + */ + target_bit_size := int(size_of(T) * 8) + when !intrinsics.type_is_unsigned(T) { + if a.sign == .Zero_or_Positive { + target_bit_size -= 1 + } + } + bits_used := internal_count_bits(a) + + if bits_used > target_bit_size { + if a.sign == .Negative { + return min(T), .Integer_Underflow } + return max(T), .Integer_Overflow + } + + for i := a.used; i > 0; i -= 1 { + res <<= _DIGIT_BITS + res |= T(a.digit[i - 1]) } when !intrinsics.type_is_unsigned(T) { /* - Mask off sign bit. - */ - res ~= 1 << uint(size_in_bits - 1) - /* Set the sign. */ if a.sign == .Negative { res = -res } diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index ed58f4318..6498c4db7 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -2,13 +2,15 @@ package runtime import "core:intrinsics" +@(private="file") +IS_WASM :: ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" + @(private) RUNTIME_LINKAGE :: "strong" when ( (ODIN_USE_SEPARATE_MODULES || ODIN_BUILD_MODE == "dynamic" || !ODIN_NO_CRT) && - !(ODIN_ARCH == "wasm32" || - ODIN_ARCH == "wasm64")) else "internal" + !IS_WASM) else "internal" RUNTIME_REQUIRE :: true @@ -752,6 +754,9 @@ extendhfsf2 :: proc "c" (value: u16) -> f32 { @(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) floattidf :: proc "c" (a: i128) -> f64 { +when IS_WASM { + return 0 +} else { DBL_MANT_DIG :: 53 if a == 0 { return 0.0 @@ -791,10 +796,14 @@ floattidf :: proc "c" (a: i128) -> f64 { fb[0] = u32(a) // mantissa-low return transmute(f64)fb } +} @(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE) floattidf_unsigned :: proc "c" (a: u128) -> f64 { +when IS_WASM { + return 0 +} else { DBL_MANT_DIG :: 53 if a == 0 { return 0.0 @@ -832,6 +841,7 @@ floattidf_unsigned :: proc "c" (a: u128) -> f64 { fb[0] = u32(a) // mantissa-low return transmute(f64)fb } +} diff --git a/core/runtime/procs_wasm32.odin b/core/runtime/procs_wasm32.odin index 5caf6d2f8..2a4210c1e 100644 --- a/core/runtime/procs_wasm32.odin +++ b/core/runtime/procs_wasm32.odin @@ -1,23 +1,40 @@ //+build wasm32 package runtime +@(private="file") +ti_int :: struct #raw_union { + using s: struct { lo, hi: u64 }, + all: i128, +} + @(link_name="__ashlti3", linkage="strong") -__ashlti3 :: proc "c" (a: i64, b_: i32) -> i64 { - /* +__ashlti3 :: proc "c" (a: i128, b_: u32) -> i128 { + bits_in_dword :: size_of(u32)*8 b := u32(b_) - input := transmute([2]i32)a - result: [2]i32 - if b & 32 != 0 { - result[0] = 0 - result[1] = input[0] << (b - 32) + + input, result: ti_int + input.all = a + if b & bits_in_dword != 0 { + result.lo = 0 + result.hi = input.lo << (b-bits_in_dword) } else { if b == 0 { return a } - result[0] = input[0]<<b - result[1] = (input[1]<<b) | (input[0]>>(32-b)) + result.lo = input.lo<<b + result.hi = (input.hi<<b) | (input.lo>>(bits_in_dword-b)) } - return transmute(i64)result - */ - return 0 + return result.all +} + + +@(link_name="__multi3", linkage="strong") +__multi3 :: proc "c" (a, b: i128) -> i128 { + x, y, r: ti_int + + x.all = a + y.all = b + r.all = i128(x.lo * y.lo) // TODO this is incorrect + r.hi += x.hi*y.lo + x.lo*y.hi + return r.all }
\ No newline at end of file |