| ... | ... | @@ -506,7 +506,12 @@ pub const Key = union(enum) { |
| 506 | 506 | |
| 507 | 507 | pub const Aggregate = struct { |
| 508 | 508 | ty: Index, |
| 509 | | fields: []const Index, |
| 509 | storage: Storage, |
| 510 | |
| 511 | pub const Storage = union(enum) { |
| 512 | elems: []const Index, |
| 513 | repeated_elem: Index, |
| 514 | }; |
| 510 | 515 | }; |
| 511 | 516 | |
| 512 | 517 | pub fn hash32(key: Key) u32 { |
| ... | ... | @@ -578,7 +583,14 @@ pub const Key = union(enum) { |
| 578 | 583 | |
| 579 | 584 | .aggregate => |aggregate| { |
| 580 | 585 | std.hash.autoHash(hasher, aggregate.ty); |
| 581 | | for (aggregate.fields) |field| std.hash.autoHash(hasher, field); |
| 586 | std.hash.autoHash(hasher, @as( |
| 587 | @typeInfo(Key.Aggregate.Storage).Union.tag_type.?, |
| 588 | aggregate.storage, |
| 589 | )); |
| 590 | switch (aggregate.storage) { |
| 591 | .elems => |elems| for (elems) |elem| std.hash.autoHash(hasher, elem), |
| 592 | .repeated_elem => |elem| std.hash.autoHash(hasher, elem), |
| 593 | } |
| 582 | 594 | }, |
| 583 | 595 | |
| 584 | 596 | .error_set_type => |error_set_type| { |
| ... | ... | @@ -756,7 +768,14 @@ pub const Key = union(enum) { |
| 756 | 768 | .aggregate => |a_info| { |
| 757 | 769 | const b_info = b.aggregate; |
| 758 | 770 | if (a_info.ty != b_info.ty) return false; |
| 759 | | return std.mem.eql(Index, a_info.fields, b_info.fields); |
| 771 | |
| 772 | const StorageTag = @typeInfo(Key.Aggregate.Storage).Union.tag_type.?; |
| 773 | if (@as(StorageTag, a_info.storage) != @as(StorageTag, b_info.storage)) return false; |
| 774 | |
| 775 | return switch (a_info.storage) { |
| 776 | .elems => |a_elems| std.mem.eql(Index, a_elems, b_info.storage.elems), |
| 777 | .repeated_elem => |a_elem| a_elem == b_info.storage.repeated_elem, |
| 778 | }; |
| 760 | 779 | }, |
| 761 | 780 | .anon_struct_type => |a_info| { |
| 762 | 781 | const b_info = b.anon_struct_type; |
| ... | ... | @@ -1407,6 +1426,9 @@ pub const Tag = enum(u8) { |
| 1407 | 1426 | /// An instance of a struct, array, or vector. |
| 1408 | 1427 | /// data is extra index to `Aggregate`. |
| 1409 | 1428 | aggregate, |
| 1429 | /// An instance of an array or vector with every element being the same value. |
| 1430 | /// data is extra index to `Repeated`. |
| 1431 | repeated, |
| 1410 | 1432 | }; |
| 1411 | 1433 | |
| 1412 | 1434 | /// Trailing: |
| ... | ... | @@ -1446,6 +1468,13 @@ pub const Aggregate = struct { |
| 1446 | 1468 | ty: Index, |
| 1447 | 1469 | }; |
| 1448 | 1470 | |
| 1471 | pub const Repeated = struct { |
| 1472 | /// The type of the aggregate. |
| 1473 | ty: Index, |
| 1474 | /// The value of every element. |
| 1475 | elem_val: Index, |
| 1476 | }; |
| 1477 | |
| 1449 | 1478 | /// Trailing: |
| 1450 | 1479 | /// 0. type: Index for each fields_len |
| 1451 | 1480 | /// 1. value: Index for each fields_len |
| ... | ... | @@ -2049,13 +2078,13 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 2049 | 2078 | // as the tuple case below). |
| 2050 | 2079 | .struct_type => .{ .aggregate = .{ |
| 2051 | 2080 | .ty = ty, |
| 2052 | | .fields = &.{}, |
| 2081 | .storage = .{ .elems = &.{} }, |
| 2053 | 2082 | } }, |
| 2054 | 2083 | // There is only one possible value precisely due to the |
| 2055 | 2084 | // fact that this values slice is fully populated! |
| 2056 | 2085 | .anon_struct_type => |anon_struct_type| .{ .aggregate = .{ |
| 2057 | 2086 | .ty = ty, |
| 2058 | | .fields = anon_struct_type.values, |
| 2087 | .storage = .{ .elems = anon_struct_type.values }, |
| 2059 | 2088 | } }, |
| 2060 | 2089 | else => unreachable, |
| 2061 | 2090 | }; |
| ... | ... | @@ -2066,7 +2095,14 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 2066 | 2095 | const fields = @ptrCast([]const Index, ip.extra.items[extra.end..][0..len]); |
| 2067 | 2096 | return .{ .aggregate = .{ |
| 2068 | 2097 | .ty = extra.data.ty, |
| 2069 | | .fields = fields, |
| 2098 | .storage = .{ .elems = fields }, |
| 2099 | } }; |
| 2100 | }, |
| 2101 | .repeated => { |
| 2102 | const extra = ip.extraData(Repeated, data); |
| 2103 | return .{ .aggregate = .{ |
| 2104 | .ty = extra.ty, |
| 2105 | .storage = .{ .repeated_elem = extra.elem_val }, |
| 2070 | 2106 | } }; |
| 2071 | 2107 | }, |
| 2072 | 2108 | .union_value => .{ .un = ip.extraData(Key.Union, data) }, |
| ... | ... | @@ -2663,10 +2699,18 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 2663 | 2699 | |
| 2664 | 2700 | .aggregate => |aggregate| { |
| 2665 | 2701 | assert(aggregate.ty != .none); |
| 2666 | | for (aggregate.fields) |elem| assert(elem != .none); |
| 2667 | | assert(aggregate.fields.len == ip.aggregateTypeLen(aggregate.ty)); |
| 2702 | const aggregate_len = ip.aggregateTypeLen(aggregate.ty); |
| 2703 | switch (aggregate.storage) { |
| 2704 | .elems => |elems| { |
| 2705 | assert(elems.len == aggregate_len); |
| 2706 | for (elems) |elem| assert(elem != .none); |
| 2707 | }, |
| 2708 | .repeated_elem => |elem| { |
| 2709 | assert(elem != .none); |
| 2710 | }, |
| 2711 | } |
| 2668 | 2712 | |
| 2669 | | if (aggregate.fields.len == 0) { |
| 2713 | if (aggregate_len == 0) { |
| 2670 | 2714 | ip.items.appendAssumeCapacity(.{ |
| 2671 | 2715 | .tag = .only_possible_value, |
| 2672 | 2716 | .data = @enumToInt(aggregate.ty), |
| ... | ... | @@ -2676,7 +2720,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 2676 | 2720 | |
| 2677 | 2721 | switch (ip.indexToKey(aggregate.ty)) { |
| 2678 | 2722 | .anon_struct_type => |anon_struct_type| { |
| 2679 | | if (std.mem.eql(Index, anon_struct_type.values, aggregate.fields)) { |
| 2723 | if (switch (aggregate.storage) { |
| 2724 | .elems => |elems| std.mem.eql(Index, anon_struct_type.values, elems), |
| 2725 | .repeated_elem => |elem| for (anon_struct_type.values) |value| { |
| 2726 | if (value != elem) break false; |
| 2727 | } else true, |
| 2728 | }) { |
| 2680 | 2729 | // This encoding works thanks to the fact that, as we just verified, |
| 2681 | 2730 | // the type itself contains a slice of values that can be provided |
| 2682 | 2731 | // in the aggregate fields. |
| ... | ... | @@ -2690,9 +2739,33 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 2690 | 2739 | else => {}, |
| 2691 | 2740 | } |
| 2692 | 2741 | |
| 2742 | if (switch (aggregate.storage) { |
| 2743 | .elems => |elems| for (elems[1..]) |elem| { |
| 2744 | if (elem != elems[0]) break false; |
| 2745 | } else true, |
| 2746 | .repeated_elem => true, |
| 2747 | }) { |
| 2748 | try ip.extra.ensureUnusedCapacity( |
| 2749 | gpa, |
| 2750 | @typeInfo(Repeated).Struct.fields.len, |
| 2751 | ); |
| 2752 | |
| 2753 | ip.items.appendAssumeCapacity(.{ |
| 2754 | .tag = .repeated, |
| 2755 | .data = ip.addExtraAssumeCapacity(Repeated{ |
| 2756 | .ty = aggregate.ty, |
| 2757 | .elem_val = switch (aggregate.storage) { |
| 2758 | .elems => |elems| elems[0], |
| 2759 | .repeated_elem => |elem| elem, |
| 2760 | }, |
| 2761 | }), |
| 2762 | }); |
| 2763 | return @intToEnum(Index, ip.items.len - 1); |
| 2764 | } |
| 2765 | |
| 2693 | 2766 | try ip.extra.ensureUnusedCapacity( |
| 2694 | 2767 | gpa, |
| 2695 | | @typeInfo(Aggregate).Struct.fields.len + aggregate.fields.len, |
| 2768 | @typeInfo(Aggregate).Struct.fields.len + aggregate_len, |
| 2696 | 2769 | ); |
| 2697 | 2770 | |
| 2698 | 2771 | ip.items.appendAssumeCapacity(.{ |
| ... | ... | @@ -2701,7 +2774,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 2701 | 2774 | .ty = aggregate.ty, |
| 2702 | 2775 | }), |
| 2703 | 2776 | }); |
| 2704 | | ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.fields)); |
| 2777 | ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.storage.elems)); |
| 2705 | 2778 | }, |
| 2706 | 2779 | |
| 2707 | 2780 | .un => |un| { |
| ... | ... | @@ -3417,6 +3490,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 3417 | 3490 | const fields_len = @intCast(u32, ip.aggregateTypeLen(info.ty)); |
| 3418 | 3491 | break :b @sizeOf(Aggregate) + (@sizeOf(u32) * fields_len); |
| 3419 | 3492 | }, |
| 3493 | .repeated => @sizeOf(Repeated), |
| 3420 | 3494 | |
| 3421 | 3495 | .float_f16 => 0, |
| 3422 | 3496 | .float_f32 => 0, |