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 {
565565 .int_u64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_u64).?.int).toConst(),
566566 .int_i64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_i64).?.int).toConst(),
567567 .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(),
569569 }
570570 }
571571
......@@ -1255,7 +1255,6 @@ pub const Value = extern union {
12551255
12561256 pub fn hash(self: Value) u64 {
12571257 var hasher = std.hash.Wyhash.init(0);
1258 std.hash.autoHash(&hasher, self.tag());
12591258
12601259 switch (self.tag()) {
12611260 .u8_type,
......@@ -1321,18 +1320,19 @@ pub const Value = extern union {
13211320 }
13221321 },
13231322
1324 .undef,
1325 .zero,
1326 .one,
1327 .void_value,
1328 .unreachable_value,
13291323 .empty_struct_value,
13301324 .empty_array,
1331 .null_value,
1332 .bool_true,
1333 .bool_false,
13341325 => {},
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
13361336 .float_16, .float_32, .float_64, .float_128 => {},
13371337 .enum_literal, .bytes => {
13381338 const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise);
......@@ -1357,9 +1357,18 @@ pub const Value = extern union {
13571357 .int_big_positive, .int_big_negative => {
13581358 var space: BigIntSpace = undefined;
13591359 const big = self.toBigInt(&space);
1360 std.hash.autoHash(&hasher, big.positive);
1361 for (big.limbs) |limb| {
1362 std.hash.autoHash(&hasher, limb);
1360 if (big.limbs.len == 1) {
1361 // handle like {u,i}64 to ensure same hash as with Int{i,u}64
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 }
13631372 }
13641373 },
13651374 .elem_ptr => {
......@@ -1741,7 +1750,7 @@ pub const Value = extern union {
17411750 .@"error",
17421751 .empty_struct_value,
17431752 .null_value,
1744 => false,
1753 => false,
17451754
17461755 .undef => unreachable,
17471756 .unreachable_value => unreachable,
......@@ -1882,3 +1891,18 @@ pub const Value = extern union {
18821891 limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb,
18831892 };
18841893};
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
12531253 return mod.constNoReturn(scope, inst.base.src);
12541254 }
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
12561262 const parent_block = try mod.requireRuntimeBlock(scope, inst.base.src);
12571263 const cases = try parent_block.arena.alloc(Inst.SwitchBr.Case, inst.positionals.cases.len);
12581264