authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-19 21:35:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:53-07:00
logd28fc5bacb2b27ba3f2a5ed17475b9b790be3ed5
tree84560d77289cec63fa1711414ce53d575069a85e
parent9ff514b6a35b7201f45f8bff31c61b4f8cfa7a7a

InternPool: add repeated aggregate storage


4 files changed, 104 insertions(+), 24 deletions(-)

src/InternPool.zig+86-12
......@@ -506,7 +506,12 @@ pub const Key = union(enum) {
506506
507507 pub const Aggregate = struct {
508508 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 };
510515 };
511516
512517 pub fn hash32(key: Key) u32 {
......@@ -578,7 +583,14 @@ pub const Key = union(enum) {
578583
579584 .aggregate => |aggregate| {
580585 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 }
582594 },
583595
584596 .error_set_type => |error_set_type| {
......@@ -756,7 +768,14 @@ pub const Key = union(enum) {
756768 .aggregate => |a_info| {
757769 const b_info = b.aggregate;
758770 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 };
760779 },
761780 .anon_struct_type => |a_info| {
762781 const b_info = b.anon_struct_type;
......@@ -1407,6 +1426,9 @@ pub const Tag = enum(u8) {
14071426 /// An instance of a struct, array, or vector.
14081427 /// data is extra index to `Aggregate`.
14091428 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,
14101432};
14111433
14121434/// Trailing:
......@@ -1446,6 +1468,13 @@ pub const Aggregate = struct {
14461468 ty: Index,
14471469};
14481470
1471pub const Repeated = struct {
1472 /// The type of the aggregate.
1473 ty: Index,
1474 /// The value of every element.
1475 elem_val: Index,
1476};
1477
14491478/// Trailing:
14501479/// 0. type: Index for each fields_len
14511480/// 1. value: Index for each fields_len
......@@ -2049,13 +2078,13 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
20492078 // as the tuple case below).
20502079 .struct_type => .{ .aggregate = .{
20512080 .ty = ty,
2052 .fields = &.{},
2081 .storage = .{ .elems = &.{} },
20532082 } },
20542083 // There is only one possible value precisely due to the
20552084 // fact that this values slice is fully populated!
20562085 .anon_struct_type => |anon_struct_type| .{ .aggregate = .{
20572086 .ty = ty,
2058 .fields = anon_struct_type.values,
2087 .storage = .{ .elems = anon_struct_type.values },
20592088 } },
20602089 else => unreachable,
20612090 };
......@@ -2066,7 +2095,14 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
20662095 const fields = @ptrCast([]const Index, ip.extra.items[extra.end..][0..len]);
20672096 return .{ .aggregate = .{
20682097 .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 },
20702106 } };
20712107 },
20722108 .union_value => .{ .un = ip.extraData(Key.Union, data) },
......@@ -2663,10 +2699,18 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
26632699
26642700 .aggregate => |aggregate| {
26652701 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 }
26682712
2669 if (aggregate.fields.len == 0) {
2713 if (aggregate_len == 0) {
26702714 ip.items.appendAssumeCapacity(.{
26712715 .tag = .only_possible_value,
26722716 .data = @enumToInt(aggregate.ty),
......@@ -2676,7 +2720,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
26762720
26772721 switch (ip.indexToKey(aggregate.ty)) {
26782722 .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 }) {
26802729 // This encoding works thanks to the fact that, as we just verified,
26812730 // the type itself contains a slice of values that can be provided
26822731 // in the aggregate fields.
......@@ -2690,9 +2739,33 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
26902739 else => {},
26912740 }
26922741
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
26932766 try ip.extra.ensureUnusedCapacity(
26942767 gpa,
2695 @typeInfo(Aggregate).Struct.fields.len + aggregate.fields.len,
2768 @typeInfo(Aggregate).Struct.fields.len + aggregate_len,
26962769 );
26972770
26982771 ip.items.appendAssumeCapacity(.{
......@@ -2701,7 +2774,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
27012774 .ty = aggregate.ty,
27022775 }),
27032776 });
2704 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.fields));
2777 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.storage.elems));
27052778 },
27062779
27072780 .un => |un| {
......@@ -3417,6 +3490,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
34173490 const fields_len = @intCast(u32, ip.aggregateTypeLen(info.ty));
34183491 break :b @sizeOf(Aggregate) + (@sizeOf(u32) * fields_len);
34193492 },
3493 .repeated => @sizeOf(Repeated),
34203494
34213495 .float_f16 => 0,
34223496 .float_f32 => 0,
src/Sema.zig+7-7
......@@ -12671,7 +12671,7 @@ fn analyzeTupleCat(
1267112671 const runtime_src = opt_runtime_src orelse {
1267212672 const tuple_val = try mod.intern(.{ .aggregate = .{
1267312673 .ty = tuple_ty,
12674 .fields = values,
12674 .storage = .{ .elems = values },
1267512675 } });
1267612676 return sema.addConstant(tuple_ty.toType(), tuple_val.toValue());
1267712677 };
......@@ -12989,7 +12989,7 @@ fn analyzeTupleMul(
1298912989 const runtime_src = opt_runtime_src orelse {
1299012990 const tuple_val = try mod.intern(.{ .aggregate = .{
1299112991 .ty = tuple_ty,
12992 .fields = values,
12992 .storage = .{ .elems = values },
1299312993 } });
1299412994 return sema.addConstant(tuple_ty.toType(), tuple_val.toValue());
1299512995 };
......@@ -18227,7 +18227,7 @@ fn zirStructInitAnon(
1822718227 const runtime_index = opt_runtime_index orelse {
1822818228 const tuple_val = try mod.intern(.{ .aggregate = .{
1822918229 .ty = tuple_ty,
18230 .fields = values,
18230 .storage = .{ .elems = values },
1823118231 } });
1823218232 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
1823318233 };
......@@ -18442,7 +18442,7 @@ fn zirArrayInitAnon(
1844218442 const runtime_src = opt_runtime_src orelse {
1844318443 const tuple_val = try mod.intern(.{ .aggregate = .{
1844418444 .ty = tuple_ty,
18445 .fields = values,
18445 .storage = .{ .elems = values },
1844618446 } });
1844718447 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
1844818448 };
......@@ -29176,7 +29176,7 @@ fn coerceTupleToTuple(
2917629176 tuple_ty,
2917729177 (try mod.intern(.{ .aggregate = .{
2917829178 .ty = tuple_ty.ip_index,
29179 .fields = field_vals,
29179 .storage = .{ .elems = field_vals },
2918029180 } })).toValue(),
2918129181 );
2918229182}
......@@ -33085,7 +33085,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3308533085 // one-possible-value in type.zig.
3308633086 const empty = try mod.intern(.{ .aggregate = .{
3308733087 .ty = ty.ip_index,
33088 .fields = &.{},
33088 .storage = .{ .elems = &.{} },
3308933089 } });
3309033090 return empty.toValue();
3309133091 },
......@@ -33098,7 +33098,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3309833098 // therefore has one possible value.
3309933099 return (try mod.intern(.{ .aggregate = .{
3310033100 .ty = ty.ip_index,
33101 .fields = tuple.values,
33101 .storage = .{ .elems = tuple.values },
3310233102 } })).toValue();
3310333103 },
3310433104
src/type.zig+2-2
......@@ -2738,7 +2738,7 @@ pub const Type = struct {
27382738 // one-possible-value logic in Sema.zig.
27392739 const empty = try mod.intern(.{ .aggregate = .{
27402740 .ty = ty.ip_index,
2741 .fields = &.{},
2741 .storage = .{ .elems = &.{} },
27422742 } });
27432743 return empty.toValue();
27442744 },
......@@ -2751,7 +2751,7 @@ pub const Type = struct {
27512751 // therefore has one possible value.
27522752 return (try mod.intern(.{ .aggregate = .{
27532753 .ty = ty.ip_index,
2754 .fields = tuple.values,
2754 .storage = .{ .elems = tuple.values },
27552755 } })).toValue();
27562756 },
27572757
src/value.zig+9-3
......@@ -2665,7 +2665,10 @@ pub const Value = struct {
26652665 else => unreachable,
26662666 },
26672667 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2668 .aggregate => |aggregate| aggregate.fields[index].toValue(),
2668 .aggregate => |aggregate| switch (aggregate.storage) {
2669 .elems => |elems| elems[index],
2670 .repeated_elem => |elem| elem,
2671 }.toValue(),
26692672 else => unreachable,
26702673 },
26712674 }
......@@ -2753,8 +2756,11 @@ pub const Value = struct {
27532756 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
27542757 .undef => return true,
27552758 .simple_value => |v| if (v == .undefined) return true,
2756 .aggregate => |aggregate| for (aggregate.fields) |field| {
2757 if (try anyUndef(field.toValue(), mod)) return true;
2759 .aggregate => |aggregate| switch (aggregate.storage) {
2760 .elems => |elems| for (elems) |elem| {
2761 if (try anyUndef(elem.toValue(), mod)) return true;
2762 },
2763 .repeated_elem => |elem| if (try anyUndef(elem.toValue(), mod)) return true,
27582764 },
27592765 else => {},
27602766 },