authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-19 18:44:09+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-22 00:12:37+02:00
log5f5ab491684f0f5dd235189416f9c3d85e8e9be0
tree51d450c61c1ece9b6208d0904ab306f660502251
parenta492a607d5410b1136db3a63fabd01c10827144c

Value: implement `compareAllWithZero` for `bytes` and `str_lit`

Closes #10692

4 files changed, 47 insertions(+), 12 deletions(-)

src/Sema.zig+4-4
...@@ -11842,7 +11842,7 @@ fn zirShl(...@@ -11842,7 +11842,7 @@ fn zirShl(
11842 if (scalar_ty.zigTypeTag() == .ComptimeInt) {11842 if (scalar_ty.zigTypeTag() == .ComptimeInt) {
11843 break :val shifted.wrapped_result;11843 break :val shifted.wrapped_result;
11844 }11844 }
11845 if (shifted.overflow_bit.compareAllWithZero(.eq)) {11845 if (shifted.overflow_bit.compareAllWithZero(.eq, sema.mod)) {
11846 break :val shifted.wrapped_result;11846 break :val shifted.wrapped_result;
11847 }11847 }
11848 return sema.fail(block, src, "operation caused overflow", .{});11848 return sema.fail(block, src, "operation caused overflow", .{});
...@@ -12831,7 +12831,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -12831,7 +12831,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
12831 const lhs_val = maybe_lhs_val orelse unreachable;12831 const lhs_val = maybe_lhs_val orelse unreachable;
12832 const rhs_val = maybe_rhs_val orelse unreachable;12832 const rhs_val = maybe_rhs_val orelse unreachable;
12833 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod) catch unreachable;12833 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod) catch unreachable;
12834 if (!rem.compareAllWithZero(.eq)) {12834 if (!rem.compareAllWithZero(.eq, mod)) {
12835 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{12835 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{
12836 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),12836 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),
12837 });12837 });
...@@ -13024,7 +13024,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13024,7 +13024,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13024 if (maybe_rhs_val) |rhs_val| {13024 if (maybe_rhs_val) |rhs_val| {
13025 if (is_int) {13025 if (is_int) {
13026 const modulus_val = try lhs_val.intMod(rhs_val, resolved_type, sema.arena, mod);13026 const modulus_val = try lhs_val.intMod(rhs_val, resolved_type, sema.arena, mod);
13027 if (!(modulus_val.compareAllWithZero(.eq))) {13027 if (!(modulus_val.compareAllWithZero(.eq, mod))) {
13028 return sema.fail(block, src, "exact division produced remainder", .{});13028 return sema.fail(block, src, "exact division produced remainder", .{});
13029 }13029 }
13030 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod);13030 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod);
...@@ -13035,7 +13035,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13035,7 +13035,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13035 return sema.addConstant(resolved_type, res);13035 return sema.addConstant(resolved_type, res);
13036 } else {13036 } else {
13037 const modulus_val = try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, mod);13037 const modulus_val = try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, mod);
13038 if (!(modulus_val.compareAllWithZero(.eq))) {13038 if (!(modulus_val.compareAllWithZero(.eq, mod))) {
13039 return sema.fail(block, src, "exact division produced remainder", .{});13039 return sema.fail(block, src, "exact division produced remainder", .{});
13040 }13040 }
13041 return sema.addConstant(13041 return sema.addConstant(
src/type.zig+3-3
...@@ -5533,7 +5533,7 @@ pub const Type = extern union {...@@ -5533,7 +5533,7 @@ pub const Type = extern union {
5533 }5533 }
5534 const S = struct {5534 const S = struct {
5535 fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize {5535 fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize {
5536 if (int_val.compareAllWithZero(.lt)) return null;5536 if (int_val.compareAllWithZero(.lt, m)) return null;
5537 var end_payload: Value.Payload.U64 = .{5537 var end_payload: Value.Payload.U64 = .{
5538 .base = .{ .tag = .int_u64 },5538 .base = .{ .tag = .int_u64 },
5539 .data = end,5539 .data = end,
...@@ -6556,12 +6556,12 @@ pub const Type = extern union {...@@ -6556,12 +6556,12 @@ pub const Type = extern union {
6556 if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {6556 if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {
6557 switch (d.size) {6557 switch (d.size) {
6558 .Slice => {6558 .Slice => {
6559 if (sent.compareAllWithZero(.eq)) {6559 if (sent.compareAllWithZero(.eq, mod)) {
6560 return Type.initTag(.const_slice_u8_sentinel_0);6560 return Type.initTag(.const_slice_u8_sentinel_0);
6561 }6561 }
6562 },6562 },
6563 .Many => {6563 .Many => {
6564 if (sent.compareAllWithZero(.eq)) {6564 if (sent.compareAllWithZero(.eq, mod)) {
6565 return Type.initTag(.manyptr_const_u8_sentinel_0);6565 return Type.initTag(.manyptr_const_u8_sentinel_0);
6566 }6566 }
6567 },6567 },
src/value.zig+29-5
...@@ -2076,13 +2076,22 @@ pub const Value = extern union {...@@ -2076,13 +2076,22 @@ pub const Value = extern union {
2076 /// For vectors, returns true if comparison is true for ALL elements.2076 /// For vectors, returns true if comparison is true for ALL elements.
2077 ///2077 ///
2078 /// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)`2078 /// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)`
2079 pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator) bool {2079 pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator, mod: *Module) bool {
2080 return compareAllWithZeroAdvanced(lhs, op, null) catch unreachable;2080 return compareAllWithZeroAdvancedExtra(lhs, op, mod, null) catch unreachable;
2081 }2081 }
20822082
2083 pub fn compareAllWithZeroAdvanced(2083 pub fn compareAllWithZeroAdvanced(
2084 lhs: Value,2084 lhs: Value,
2085 op: std.math.CompareOperator,2085 op: std.math.CompareOperator,
2086 sema: *Sema,
2087 ) Module.CompileError!bool {
2088 return compareAllWithZeroAdvancedExtra(lhs, op, sema.mod, sema);
2089 }
2090
2091 pub fn compareAllWithZeroAdvancedExtra(
2092 lhs: Value,
2093 op: std.math.CompareOperator,
2094 mod: *Module,
2086 opt_sema: ?*Sema,2095 opt_sema: ?*Sema,
2087 ) Module.CompileError!bool {2096 ) Module.CompileError!bool {
2088 if (lhs.isInf()) {2097 if (lhs.isInf()) {
...@@ -2095,10 +2104,25 @@ pub const Value = extern union {...@@ -2095,10 +2104,25 @@ pub const Value = extern union {
2095 }2104 }
20962105
2097 switch (lhs.tag()) {2106 switch (lhs.tag()) {
2098 .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvanced(op, opt_sema),2107 .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvancedExtra(op, mod, opt_sema),
2099 .aggregate => {2108 .aggregate => {
2100 for (lhs.castTag(.aggregate).?.data) |elem_val| {2109 for (lhs.castTag(.aggregate).?.data) |elem_val| {
2101 if (!(try elem_val.compareAllWithZeroAdvanced(op, opt_sema))) return false;2110 if (!(try elem_val.compareAllWithZeroAdvancedExtra(op, mod, opt_sema))) return false;
2111 }
2112 return true;
2113 },
2114 .str_lit => {
2115 const str_lit = lhs.castTag(.str_lit).?.data;
2116 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
2117 for (bytes) |byte| {
2118 if (!std.math.compare(byte, op, 0)) return false;
2119 }
2120 return true;
2121 },
2122 .bytes => {
2123 const bytes = lhs.castTag(.bytes).?.data;
2124 for (bytes) |byte| {
2125 if (!std.math.compare(byte, op, 0)) return false;
2102 }2126 }
2103 return true;2127 return true;
2104 },2128 },
...@@ -3103,7 +3127,7 @@ pub const Value = extern union {...@@ -3103,7 +3127,7 @@ pub const Value = extern union {
3103 .int_i64,3127 .int_i64,
3104 .int_big_positive,3128 .int_big_positive,
3105 .int_big_negative,3129 .int_big_negative,
3106 => compareAllWithZero(self, .eq),3130 => self.orderAgainstZero().compare(.eq),
31073131
3108 .undef => unreachable,3132 .undef => unreachable,
3109 .unreachable_value => unreachable,3133 .unreachable_value => unreachable,
test/behavior/vector.zig+11
...@@ -1286,3 +1286,14 @@ test "store to vector in slice" {...@@ -1286,3 +1286,14 @@ test "store to vector in slice" {
1286 s[i] = s[0];1286 s[i] = s[0];
1287 try expectEqual(v[1], v[0]);1287 try expectEqual(v[1], v[0]);
1288}1288}
1289
1290test "addition of vectors represented as strings" {
1291 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1292 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1293 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1294
1295 const V = @Vector(3, u8);
1296 const foo: V = "foo".*;
1297 const bar: V = @typeName(u32).*;
1298 try expectEqual(V{ 219, 162, 161 }, foo + bar);
1299}