authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-10-30 13:24:47+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-10-30 15:58:13+02:00
loge2e0b6272b98ef2ec810fbabcdc91a21e54a71a3
tree08265c5b1e8f7010cd38ca8d77f2830ba89c853f
parent3cc68bd9138b5fda6d6066d9c49f7e1b5e04a5ee
signaturelock-open Commit is signed but in an unrecognized format.

stage2: return same hash for different representations of same value


2 files changed, 44 insertions(+), 14 deletions(-)

src/value.zig+38-14
...@@ -565,7 +565,7 @@ pub const Value = extern union {...@@ -565,7 +565,7 @@ pub const Value = extern union {
565 .int_u64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_u64).?.int).toConst(),565 .int_u64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_u64).?.int).toConst(),
566 .int_i64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_i64).?.int).toConst(),566 .int_i64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_i64).?.int).toConst(),
567 .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt(),567 .int_big_positive => return self.cast(Payload.IntBigPositive).?.asBigInt(),
568 .int_big_negative => return self.cast(Payload.IntBigPositive).?.asBigInt(),568 .int_big_negative => return self.cast(Payload.IntBigNegative).?.asBigInt(),
569 }569 }
570 }570 }
571571
...@@ -1255,7 +1255,6 @@ pub const Value = extern union {...@@ -1255,7 +1255,6 @@ pub const Value = extern union {
12551255
1256 pub fn hash(self: Value) u64 {1256 pub fn hash(self: Value) u64 {
1257 var hasher = std.hash.Wyhash.init(0);1257 var hasher = std.hash.Wyhash.init(0);
1258 std.hash.autoHash(&hasher, self.tag());
12591258
1260 switch (self.tag()) {1259 switch (self.tag()) {
1261 .u8_type,1260 .u8_type,
...@@ -1321,18 +1320,19 @@ pub const Value = extern union {...@@ -1321,18 +1320,19 @@ pub const Value = extern union {
1321 }1320 }
1322 },1321 },
13231322
1324 .undef,
1325 .zero,
1326 .one,
1327 .void_value,
1328 .unreachable_value,
1329 .empty_struct_value,1323 .empty_struct_value,
1330 .empty_array,1324 .empty_array,
1331 .null_value,
1332 .bool_true,
1333 .bool_false,
1334 => {},1325 => {},
13351326
1327 .undef,
1328 .null_value,
1329 .void_value,
1330 .unreachable_value,
1331 => std.hash.autoHash(&hasher, self.tag()),
1332
1333 .zero, .bool_false => std.hash.autoHash(&hasher, @as(u64, 0)),
1334 .one, .bool_true => std.hash.autoHash(&hasher, @as(u64, 1)),
1335
1336 .float_16, .float_32, .float_64, .float_128 => {},1336 .float_16, .float_32, .float_64, .float_128 => {},
1337 .enum_literal, .bytes => {1337 .enum_literal, .bytes => {
1338 const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise);1338 const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise);
...@@ -1357,9 +1357,18 @@ pub const Value = extern union {...@@ -1357,9 +1357,18 @@ pub const Value = extern union {
1357 .int_big_positive, .int_big_negative => {1357 .int_big_positive, .int_big_negative => {
1358 var space: BigIntSpace = undefined;1358 var space: BigIntSpace = undefined;
1359 const big = self.toBigInt(&space);1359 const big = self.toBigInt(&space);
1360 std.hash.autoHash(&hasher, big.positive);1360 if (big.limbs.len == 1) {
1361 for (big.limbs) |limb| {1361 // handle like {u,i}64 to ensure same hash as with Int{i,u}64
1362 std.hash.autoHash(&hasher, limb);1362 if (big.positive) {
1363 std.hash.autoHash(&hasher, @as(u64, big.limbs[0]));
1364 } else {
1365 std.hash.autoHash(&hasher, @as(u64, @bitCast(usize, -@bitCast(isize, big.limbs[0]))));
1366 }
1367 } else {
1368 std.hash.autoHash(&hasher, big.positive);
1369 for (big.limbs) |limb| {
1370 std.hash.autoHash(&hasher, limb);
1371 }
1363 }1372 }
1364 },1373 },
1365 .elem_ptr => {1374 .elem_ptr => {
...@@ -1741,7 +1750,7 @@ pub const Value = extern union {...@@ -1741,7 +1750,7 @@ pub const Value = extern union {
1741 .@"error",1750 .@"error",
1742 .empty_struct_value,1751 .empty_struct_value,
1743 .null_value,1752 .null_value,
1744 => false,1753 => false,
17451754
1746 .undef => unreachable,1755 .undef => unreachable,
1747 .unreachable_value => unreachable,1756 .unreachable_value => unreachable,
...@@ -1882,3 +1891,18 @@ pub const Value = extern union {...@@ -1882,3 +1891,18 @@ pub const Value = extern union {
1882 limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb,1891 limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb,
1883 };1892 };
1884};1893};
1894
1895test "hash same value different representation" {
1896 const zero_1 = Value.initTag(.zero);
1897 var payload_1 = Value.Payload.Int_u64{ .int = 0 };
1898 const zero_2 = Value.initPayload(&payload_1.base);
1899 std.testing.expectEqual(zero_1.hash(), zero_2.hash());
1900
1901 var payload_2 = Value.Payload.Int_i64{ .int = 0 };
1902 const zero_3 = Value.initPayload(&payload_2.base);
1903 std.testing.expectEqual(zero_2.hash(), zero_3.hash());
1904
1905 var payload_3 = Value.Payload.IntBigNegative{ .limbs = &[_]std.math.big.Limb{0} };
1906 const zero_4 = Value.initPayload(&payload_3.base);
1907 std.testing.expectEqual(zero_3.hash(), zero_4.hash());
1908}
src/zir_sema.zig+6
...@@ -1253,6 +1253,12 @@ fn analyzeInstSwitchBr(mod: *Module, scope: *Scope, inst: *zir.Inst.SwitchBr) In...@@ -1253,6 +1253,12 @@ fn analyzeInstSwitchBr(mod: *Module, scope: *Scope, inst: *zir.Inst.SwitchBr) In
1253 return mod.constNoReturn(scope, inst.base.src);1253 return mod.constNoReturn(scope, inst.base.src);
1254 }1254 }
12551255
1256 if (inst.positionals.cases.len == 0) {
1257 // no cases just analyze else_branch
1258 try analyzeBody(mod, scope, inst.positionals.else_body);
1259 return mod.constNoReturn(scope, inst.base.src);
1260 }
1261
1256 const parent_block = try mod.requireRuntimeBlock(scope, inst.base.src);1262 const parent_block = try mod.requireRuntimeBlock(scope, inst.base.src);
1257 const cases = try parent_block.arena.alloc(Inst.SwitchBr.Case, inst.positionals.cases.len);1263 const cases = try parent_block.arena.alloc(Inst.SwitchBr.Case, inst.positionals.cases.len);
12581264