aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-09-28 18:55:43 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-09-28 19:19:28 -0700
commit54675824449d16029fdf6a1873e78cb8f2147f60 (patch)
treea3495ecdbbca9a963f514938f20003f1aeb69b64 /src/value.zig
parent71da169c67ad544bd1d4dfc4bfff9fe302e8284d (diff)
downloadzig-54675824449d16029fdf6a1873e78cb8f2147f60.tar.gz
zig-54675824449d16029fdf6a1873e78cb8f2147f60.zip
saturating arithmetic modifications
* Remove the builtins `@addWithSaturation`, `@subWithSaturation`, `@mulWithSaturation`, and `@shlWithSaturation` now that we have first-class syntax for saturating arithmetic. * langref: Clarify the behavior of `@shlExact`. * Ast: rename `bit_shift_left` to `shl` and `bit_shift_right` to `shr` for consistency. * Air: rename to include underscore separator with consistency with the rest of the ops. * Air: add shl_exact instruction * Use non-extended tags for saturating arithmetic, to keep it simple so that all the arithmetic operations can be done the same way. - Sema: unify analyzeArithmetic with analyzeSatArithmetic - implement comptime `+|`, `-|`, and `*|` - allow float operands to saturating arithmetic * `<<|` allows any integer type for the RHS. * C backend: fix rebase conflicts * LLVM backend: reduce the amount of branching for arithmetic ops * zig.h: fix magic number not matching actual size of C integer types
Diffstat (limited to 'src/value.zig')
-rw-r--r--src/value.zig87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/value.zig b/src/value.zig
index 29d8fa8db9..73a2b3a49f 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1589,6 +1589,35 @@ pub const Value = extern union {
}
/// Supports both floats and ints; handles undefined.
+ pub fn numberAddSat(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: *Allocator,
+ target: Target,
+ ) !Value {
+ if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
+
+ if (ty.isAnyFloat()) {
+ // TODO: handle outside float range
+ return floatAdd(lhs, rhs, ty, arena);
+ }
+ const result = try intAdd(lhs, rhs, arena);
+
+ const max = try ty.maxInt(arena, target);
+ if (compare(result, .gt, max, ty)) {
+ return max;
+ }
+
+ const min = try ty.minInt(arena, target);
+ if (compare(result, .lt, min, ty)) {
+ return min;
+ }
+
+ return result;
+ }
+
+ /// Supports both floats and ints; handles undefined.
pub fn numberSubWrap(
lhs: Value,
rhs: Value,
@@ -1617,6 +1646,35 @@ pub const Value = extern union {
}
/// Supports both floats and ints; handles undefined.
+ pub fn numberSubSat(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: *Allocator,
+ target: Target,
+ ) !Value {
+ if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
+
+ if (ty.isAnyFloat()) {
+ // TODO: handle outside float range
+ return floatSub(lhs, rhs, ty, arena);
+ }
+ const result = try intSub(lhs, rhs, arena);
+
+ const max = try ty.maxInt(arena, target);
+ if (compare(result, .gt, max, ty)) {
+ return max;
+ }
+
+ const min = try ty.minInt(arena, target);
+ if (compare(result, .lt, min, ty)) {
+ return min;
+ }
+
+ return result;
+ }
+
+ /// Supports both floats and ints; handles undefined.
pub fn numberMulWrap(
lhs: Value,
rhs: Value,
@@ -1645,6 +1703,35 @@ pub const Value = extern union {
}
/// Supports both floats and ints; handles undefined.
+ pub fn numberMulSat(
+ lhs: Value,
+ rhs: Value,
+ ty: Type,
+ arena: *Allocator,
+ target: Target,
+ ) !Value {
+ if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
+
+ if (ty.isAnyFloat()) {
+ // TODO: handle outside float range
+ return floatMul(lhs, rhs, ty, arena);
+ }
+ const result = try intMul(lhs, rhs, arena);
+
+ const max = try ty.maxInt(arena, target);
+ if (compare(result, .gt, max, ty)) {
+ return max;
+ }
+
+ const min = try ty.minInt(arena, target);
+ if (compare(result, .lt, min, ty)) {
+ return min;
+ }
+
+ return result;
+ }
+
+ /// Supports both floats and ints; handles undefined.
pub fn numberMax(lhs: Value, rhs: Value, arena: *Allocator) !Value {
if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);