| ... | ... | @@ -13,6 +13,12 @@ extra: std.ArrayListUnmanaged(u32) = .{}, |
| 13 | 13 | /// Use the helper methods instead of accessing this directly in order to not |
| 14 | 14 | /// violate the above mechanism. |
| 15 | 15 | limbs: std.ArrayListUnmanaged(u64) = .{}, |
| 16 | /// In order to store references to strings in fewer bytes, we copy all |
| 17 | /// string bytes into here. String bytes can be null. It is up to whomever |
| 18 | /// is referencing the data here whether they want to store both index and length, |
| 19 | /// thus allowing null bytes, or store only index, and use null-termination. The |
| 20 | /// `string_bytes` array is agnostic to either usage. |
| 21 | string_bytes: std.ArrayListUnmanaged(u8) = .{}, |
| 16 | 22 | |
| 17 | 23 | /// Struct objects are stored in this data structure because: |
| 18 | 24 | /// * They contain pointers such as the field maps. |
| ... | ... | @@ -28,6 +34,12 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{}, |
| 28 | 34 | /// When a Union object is freed from `allocated_unions`, it is pushed into this stack. |
| 29 | 35 | unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{}, |
| 30 | 36 | |
| 37 | /// Some types such as enums, structs, and unions need to store mappings from field names |
| 38 | /// to field index, or value to field index. In such cases, they will store the underlying |
| 39 | /// field names and values directly, relying on one of these maps, stored separately, |
| 40 | /// to provide lookup. |
| 41 | maps: std.ArrayListUnmanaged(std.AutoArrayHashMapUnmanaged(void, void)) = .{}, |
| 42 | |
| 31 | 43 | const std = @import("std"); |
| 32 | 44 | const Allocator = std.mem.Allocator; |
| 33 | 45 | const assert = std.debug.assert; |
| ... | ... | @@ -52,6 +64,46 @@ const KeyAdapter = struct { |
| 52 | 64 | } |
| 53 | 65 | }; |
| 54 | 66 | |
| 67 | /// An index into `maps` which might be `none`. |
| 68 | pub const OptionalMapIndex = enum(u32) { |
| 69 | none = std.math.maxInt(u32), |
| 70 | _, |
| 71 | }; |
| 72 | |
| 73 | /// An index into `maps`. |
| 74 | pub const MapIndex = enum(u32) { |
| 75 | _, |
| 76 | |
| 77 | pub fn toOptional(i: MapIndex) OptionalMapIndex { |
| 78 | return @intToEnum(OptionalMapIndex, @enumToInt(i)); |
| 79 | } |
| 80 | }; |
| 81 | |
| 82 | /// An index into `string_bytes`. |
| 83 | pub const NullTerminatedString = enum(u32) { |
| 84 | _, |
| 85 | |
| 86 | const Adapter = struct { |
| 87 | strings: []const NullTerminatedString, |
| 88 | |
| 89 | pub fn eql(ctx: @This(), a: NullTerminatedString, b_void: void, b_map_index: usize) bool { |
| 90 | _ = b_void; |
| 91 | return a == ctx.strings[b_map_index]; |
| 92 | } |
| 93 | |
| 94 | pub fn hash(ctx: @This(), a: NullTerminatedString) u32 { |
| 95 | _ = ctx; |
| 96 | return std.hash.uint32(@enumToInt(a)); |
| 97 | } |
| 98 | }; |
| 99 | }; |
| 100 | |
| 101 | /// An index into `string_bytes` which might be `none`. |
| 102 | pub const OptionalNullTerminatedString = enum(u32) { |
| 103 | none = std.math.maxInt(u32), |
| 104 | _, |
| 105 | }; |
| 106 | |
| 55 | 107 | pub const Key = union(enum) { |
| 56 | 108 | int_type: IntType, |
| 57 | 109 | ptr_type: PtrType, |
| ... | ... | @@ -68,6 +120,7 @@ pub const Key = union(enum) { |
| 68 | 120 | struct_type: StructType, |
| 69 | 121 | union_type: UnionType, |
| 70 | 122 | opaque_type: OpaqueType, |
| 123 | enum_type: EnumType, |
| 71 | 124 | |
| 72 | 125 | simple_value: SimpleValue, |
| 73 | 126 | extern_func: struct { |
| ... | ... | @@ -174,6 +227,30 @@ pub const Key = union(enum) { |
| 174 | 227 | } |
| 175 | 228 | }; |
| 176 | 229 | |
| 230 | pub const EnumType = struct { |
| 231 | /// The Decl that corresponds to the enum itself. |
| 232 | decl: Module.Decl.Index, |
| 233 | /// Represents the declarations inside this enum. |
| 234 | namespace: Module.Namespace.OptionalIndex, |
| 235 | /// An integer type which is used for the numerical value of the enum. |
| 236 | /// This field is present regardless of whether the enum has an |
| 237 | /// explicitly provided tag type or auto-numbered. |
| 238 | tag_ty: Index, |
| 239 | /// Set of field names in declaration order. |
| 240 | names: []const NullTerminatedString, |
| 241 | /// Maps integer tag value to field index. |
| 242 | /// Entries are in declaration order, same as `fields`. |
| 243 | /// If this is empty, it means the enum tags are auto-numbered. |
| 244 | values: []const Index, |
| 245 | /// true if zig inferred this tag type, false if user specified it |
| 246 | tag_ty_inferred: bool, |
| 247 | /// This is ignored by `get` but will always be provided by `indexToKey`. |
| 248 | names_map: OptionalMapIndex = .none, |
| 249 | /// This is ignored by `get` but will be provided by `indexToKey` when |
| 250 | /// a value map exists. |
| 251 | values_map: OptionalMapIndex = .none, |
| 252 | }; |
| 253 | |
| 177 | 254 | pub const Int = struct { |
| 178 | 255 | ty: Index, |
| 179 | 256 | storage: Storage, |
| ... | ... | @@ -263,6 +340,7 @@ pub const Key = union(enum) { |
| 263 | 340 | => |info| std.hash.autoHash(hasher, info), |
| 264 | 341 | |
| 265 | 342 | .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl), |
| 343 | .enum_type => |enum_type| std.hash.autoHash(hasher, enum_type.decl), |
| 266 | 344 | |
| 267 | 345 | .int => |int| { |
| 268 | 346 | // Canonicalize all integers by converting them to BigIntConst. |
| ... | ... | @@ -410,6 +488,10 @@ pub const Key = union(enum) { |
| 410 | 488 | const b_info = b.opaque_type; |
| 411 | 489 | return a_info.decl == b_info.decl; |
| 412 | 490 | }, |
| 491 | .enum_type => |a_info| { |
| 492 | const b_info = b.enum_type; |
| 493 | return a_info.decl == b_info.decl; |
| 494 | }, |
| 413 | 495 | .aggregate => |a_info| { |
| 414 | 496 | const b_info = b.aggregate; |
| 415 | 497 | if (a_info.ty != b_info.ty) return false; |
| ... | ... | @@ -430,6 +512,7 @@ pub const Key = union(enum) { |
| 430 | 512 | .struct_type, |
| 431 | 513 | .union_type, |
| 432 | 514 | .opaque_type, |
| 515 | .enum_type, |
| 433 | 516 | => return .type_type, |
| 434 | 517 | |
| 435 | 518 | inline .ptr, |
| ... | ... | @@ -592,6 +675,21 @@ pub const Index = enum(u32) { |
| 592 | 675 | .legacy = undefined, |
| 593 | 676 | }; |
| 594 | 677 | } |
| 678 | |
| 679 | /// Used for a map of `Index` values to the index within a list of `Index` values. |
| 680 | const Adapter = struct { |
| 681 | indexes: []const Index, |
| 682 | |
| 683 | pub fn eql(ctx: @This(), a: Index, b_void: void, b_map_index: usize) bool { |
| 684 | _ = b_void; |
| 685 | return a == ctx.indexes[b_map_index]; |
| 686 | } |
| 687 | |
| 688 | pub fn hash(ctx: @This(), a: Index) u32 { |
| 689 | _ = ctx; |
| 690 | return std.hash.uint32(@enumToInt(a)); |
| 691 | } |
| 692 | }; |
| 595 | 693 | }; |
| 596 | 694 | |
| 597 | 695 | pub const static_keys = [_]Key{ |
| ... | ... | @@ -848,10 +946,12 @@ pub const Tag = enum(u8) { |
| 848 | 946 | /// An error union type. |
| 849 | 947 | /// data is payload to ErrorUnion. |
| 850 | 948 | type_error_union, |
| 851 | | /// Represents the data that an enum declaration provides, when the fields |
| 852 | | /// are auto-numbered, and there are no declarations. |
| 853 | | /// data is payload index to `EnumSimple`. |
| 854 | | type_enum_simple, |
| 949 | /// An enum type with an explicitly provided integer tag type. |
| 950 | /// data is payload index to `EnumExplicit`. |
| 951 | type_enum_explicit, |
| 952 | /// An enum type with auto-numbered tag values. |
| 953 | /// data is payload index to `EnumAuto`. |
| 954 | type_enum_auto, |
| 855 | 955 | /// A type that can be represented with only an enum tag. |
| 856 | 956 | /// data is SimpleType enum value. |
| 857 | 957 | simple_type, |
| ... | ... | @@ -1087,17 +1187,35 @@ pub const ErrorUnion = struct { |
| 1087 | 1187 | }; |
| 1088 | 1188 | |
| 1089 | 1189 | /// Trailing: |
| 1090 | | /// 0. field name: null-terminated string index for each fields_len; declaration order |
| 1091 | | pub const EnumSimple = struct { |
| 1190 | /// 0. field name: NullTerminatedString for each fields_len; declaration order |
| 1191 | /// 1. tag value: Index for each fields_len; declaration order |
| 1192 | pub const EnumExplicit = struct { |
| 1193 | /// The Decl that corresponds to the enum itself. |
| 1194 | decl: Module.Decl.Index, |
| 1195 | /// This may be `none` if there are no declarations. |
| 1196 | namespace: Module.Namespace.OptionalIndex, |
| 1197 | /// An integer type which is used for the numerical value of the enum, which |
| 1198 | /// has been explicitly provided by the enum declaration. |
| 1199 | int_tag_type: Index, |
| 1200 | fields_len: u32, |
| 1201 | /// Maps field names to declaration index. |
| 1202 | names_map: MapIndex, |
| 1203 | /// Maps field values to declaration index. |
| 1204 | /// If this is `none`, it means the trailing tag values are absent because |
| 1205 | /// they are auto-numbered. |
| 1206 | values_map: OptionalMapIndex, |
| 1207 | }; |
| 1208 | |
| 1209 | /// Trailing: |
| 1210 | /// 0. field name: NullTerminatedString for each fields_len; declaration order |
| 1211 | pub const EnumAuto = struct { |
| 1092 | 1212 | /// The Decl that corresponds to the enum itself. |
| 1093 | 1213 | decl: Module.Decl.Index, |
| 1094 | | /// An integer type which is used for the numerical value of the enum. This |
| 1095 | | /// is inferred by Zig to be the smallest power of two unsigned int that |
| 1096 | | /// fits the number of fields. It is stored here to avoid unnecessary |
| 1097 | | /// calculations and possibly allocation failure when querying the tag type |
| 1098 | | /// of enums. |
| 1099 | | int_tag_ty: Index, |
| 1214 | /// This may be `none` if there are no declarations. |
| 1215 | namespace: Module.Namespace.OptionalIndex, |
| 1100 | 1216 | fields_len: u32, |
| 1217 | /// Maps field names to declaration index. |
| 1218 | names_map: MapIndex, |
| 1101 | 1219 | }; |
| 1102 | 1220 | |
| 1103 | 1221 | pub const PackedU64 = packed struct(u64) { |
| ... | ... | @@ -1183,6 +1301,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 1183 | 1301 | ip.unions_free_list.deinit(gpa); |
| 1184 | 1302 | ip.allocated_unions.deinit(gpa); |
| 1185 | 1303 | |
| 1304 | ip.maps.deinit(gpa); |
| 1305 | ip.string_bytes.deinit(gpa); |
| 1306 | |
| 1186 | 1307 | ip.* = undefined; |
| 1187 | 1308 | } |
| 1188 | 1309 | |
| ... | ... | @@ -1256,7 +1377,6 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1256 | 1377 | .type_optional => .{ .opt_type = @intToEnum(Index, data) }, |
| 1257 | 1378 | |
| 1258 | 1379 | .type_error_union => @panic("TODO"), |
| 1259 | | .type_enum_simple => @panic("TODO"), |
| 1260 | 1380 | |
| 1261 | 1381 | .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) }, |
| 1262 | 1382 | .type_struct => { |
| ... | ... | @@ -1288,6 +1408,46 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1288 | 1408 | .runtime_tag = .safety, |
| 1289 | 1409 | } }, |
| 1290 | 1410 | |
| 1411 | .type_enum_auto => { |
| 1412 | const enum_auto = ip.extraDataTrail(EnumAuto, data); |
| 1413 | const names = @ptrCast( |
| 1414 | []const NullTerminatedString, |
| 1415 | ip.extra.items[enum_auto.end..][0..enum_auto.data.fields_len], |
| 1416 | ); |
| 1417 | return .{ .enum_type = .{ |
| 1418 | .decl = enum_auto.data.decl, |
| 1419 | .namespace = enum_auto.data.namespace, |
| 1420 | .tag_ty = ip.getEnumIntTagType(enum_auto.data.fields_len), |
| 1421 | .names = names, |
| 1422 | .values = &.{}, |
| 1423 | .tag_ty_inferred = true, |
| 1424 | .names_map = enum_auto.data.names_map.toOptional(), |
| 1425 | .values_map = .none, |
| 1426 | } }; |
| 1427 | }, |
| 1428 | .type_enum_explicit => { |
| 1429 | const enum_explicit = ip.extraDataTrail(EnumExplicit, data); |
| 1430 | const names = @ptrCast( |
| 1431 | []const NullTerminatedString, |
| 1432 | ip.extra.items[enum_explicit.end..][0..enum_explicit.data.fields_len], |
| 1433 | ); |
| 1434 | const values = if (enum_explicit.data.values_map != .none) @ptrCast( |
| 1435 | []const Index, |
| 1436 | ip.extra.items[enum_explicit.end + names.len ..][0..enum_explicit.data.fields_len], |
| 1437 | ) else &[0]Index{}; |
| 1438 | |
| 1439 | return .{ .enum_type = .{ |
| 1440 | .decl = enum_explicit.data.decl, |
| 1441 | .namespace = enum_explicit.data.namespace, |
| 1442 | .tag_ty = enum_explicit.data.int_tag_type, |
| 1443 | .names = names, |
| 1444 | .values = values, |
| 1445 | .tag_ty_inferred = false, |
| 1446 | .names_map = enum_explicit.data.names_map.toOptional(), |
| 1447 | .values_map = enum_explicit.data.values_map, |
| 1448 | } }; |
| 1449 | }, |
| 1450 | |
| 1291 | 1451 | .opt_null => .{ .opt = .{ |
| 1292 | 1452 | .ty = @intToEnum(Index, data), |
| 1293 | 1453 | .val = .none, |
| ... | ... | @@ -1362,6 +1522,14 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1362 | 1522 | }; |
| 1363 | 1523 | } |
| 1364 | 1524 | |
| 1525 | /// Asserts the integer tag type is already present in the InternPool. |
| 1526 | fn getEnumIntTagType(ip: InternPool, fields_len: u32) Index { |
| 1527 | return ip.getAssumeExists(.{ .int_type = .{ |
| 1528 | .bits = if (fields_len == 0) 0 else std.math.log2_int_ceil(u32, fields_len), |
| 1529 | .signedness = .unsigned, |
| 1530 | } }); |
| 1531 | } |
| 1532 | |
| 1365 | 1533 | fn indexToKeyBigInt(ip: InternPool, limb_index: u32, positive: bool) Key { |
| 1366 | 1534 | const int_info = ip.limbData(Int, limb_index); |
| 1367 | 1535 | return .{ .int = .{ |
| ... | ... | @@ -1522,6 +1690,54 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 1522 | 1690 | }); |
| 1523 | 1691 | }, |
| 1524 | 1692 | |
| 1693 | .enum_type => |enum_type| { |
| 1694 | assert(enum_type.tag_ty != .none); |
| 1695 | assert(enum_type.names_map == .none); |
| 1696 | assert(enum_type.values_map == .none); |
| 1697 | |
| 1698 | const names_map = try ip.addMap(gpa); |
| 1699 | try addStringsToMap(ip, gpa, names_map, enum_type.names); |
| 1700 | |
| 1701 | const fields_len = @intCast(u32, enum_type.names.len); |
| 1702 | |
| 1703 | if (enum_type.tag_ty_inferred) { |
| 1704 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len + |
| 1705 | fields_len); |
| 1706 | ip.items.appendAssumeCapacity(.{ |
| 1707 | .tag = .type_enum_auto, |
| 1708 | .data = ip.addExtraAssumeCapacity(EnumAuto{ |
| 1709 | .decl = enum_type.decl, |
| 1710 | .namespace = enum_type.namespace, |
| 1711 | .names_map = names_map, |
| 1712 | .fields_len = fields_len, |
| 1713 | }), |
| 1714 | }); |
| 1715 | ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, enum_type.names)); |
| 1716 | return @intToEnum(Index, ip.items.len - 1); |
| 1717 | } |
| 1718 | |
| 1719 | const values_map: OptionalMapIndex = if (enum_type.values.len == 0) .none else m: { |
| 1720 | const values_map = try ip.addMap(gpa); |
| 1721 | try addIndexesToMap(ip, gpa, values_map, enum_type.values); |
| 1722 | break :m values_map.toOptional(); |
| 1723 | }; |
| 1724 | try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len + |
| 1725 | fields_len); |
| 1726 | ip.items.appendAssumeCapacity(.{ |
| 1727 | .tag = .type_enum_auto, |
| 1728 | .data = ip.addExtraAssumeCapacity(EnumExplicit{ |
| 1729 | .decl = enum_type.decl, |
| 1730 | .namespace = enum_type.namespace, |
| 1731 | .int_tag_type = enum_type.tag_ty, |
| 1732 | .fields_len = fields_len, |
| 1733 | .names_map = names_map, |
| 1734 | .values_map = values_map, |
| 1735 | }), |
| 1736 | }); |
| 1737 | ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, enum_type.names)); |
| 1738 | ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, enum_type.values)); |
| 1739 | }, |
| 1740 | |
| 1525 | 1741 | .extern_func => @panic("TODO"), |
| 1526 | 1742 | |
| 1527 | 1743 | .ptr => |ptr| switch (ptr.addr) { |
| ... | ... | @@ -1723,6 +1939,40 @@ pub fn getAssumeExists(ip: InternPool, key: Key) Index { |
| 1723 | 1939 | return @intToEnum(Index, index); |
| 1724 | 1940 | } |
| 1725 | 1941 | |
| 1942 | fn addStringsToMap( |
| 1943 | ip: *InternPool, |
| 1944 | gpa: Allocator, |
| 1945 | map_index: MapIndex, |
| 1946 | strings: []const NullTerminatedString, |
| 1947 | ) Allocator.Error!void { |
| 1948 | const map = &ip.maps.items[@enumToInt(map_index)]; |
| 1949 | const adapter: NullTerminatedString.Adapter = .{ .strings = strings }; |
| 1950 | for (strings) |string| { |
| 1951 | const gop = try map.getOrPutAdapted(gpa, string, adapter); |
| 1952 | assert(!gop.found_existing); |
| 1953 | } |
| 1954 | } |
| 1955 | |
| 1956 | fn addIndexesToMap( |
| 1957 | ip: *InternPool, |
| 1958 | gpa: Allocator, |
| 1959 | map_index: MapIndex, |
| 1960 | indexes: []const Index, |
| 1961 | ) Allocator.Error!void { |
| 1962 | const map = &ip.maps.items[@enumToInt(map_index)]; |
| 1963 | const adapter: Index.Adapter = .{ .indexes = indexes }; |
| 1964 | for (indexes) |index| { |
| 1965 | const gop = try map.getOrPutAdapted(gpa, index, adapter); |
| 1966 | assert(!gop.found_existing); |
| 1967 | } |
| 1968 | } |
| 1969 | |
| 1970 | fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex { |
| 1971 | const ptr = try ip.maps.addOne(gpa); |
| 1972 | ptr.* = .{}; |
| 1973 | return @intToEnum(MapIndex, ip.maps.items.len - 1); |
| 1974 | } |
| 1975 | |
| 1726 | 1976 | /// This operation only happens under compile error conditions. |
| 1727 | 1977 | /// Leak the index until the next garbage collection. |
| 1728 | 1978 | pub fn remove(ip: *InternPool, index: Index) void { |
| ... | ... | @@ -1758,6 +2008,9 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 1758 | 2008 | Index => @enumToInt(@field(extra, field.name)), |
| 1759 | 2009 | Module.Decl.Index => @enumToInt(@field(extra, field.name)), |
| 1760 | 2010 | Module.Namespace.Index => @enumToInt(@field(extra, field.name)), |
| 2011 | Module.Namespace.OptionalIndex => @enumToInt(@field(extra, field.name)), |
| 2012 | MapIndex => @enumToInt(@field(extra, field.name)), |
| 2013 | OptionalMapIndex => @enumToInt(@field(extra, field.name)), |
| 1761 | 2014 | i32 => @bitCast(u32, @field(extra, field.name)), |
| 1762 | 2015 | Pointer.Flags => @bitCast(u32, @field(extra, field.name)), |
| 1763 | 2016 | Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)), |
| ... | ... | @@ -1806,15 +2059,19 @@ fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void { |
| 1806 | 2059 | } |
| 1807 | 2060 | } |
| 1808 | 2061 | |
| 1809 | | fn extraData(ip: InternPool, comptime T: type, index: usize) T { |
| 2062 | fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data: T, end: usize } { |
| 1810 | 2063 | var result: T = undefined; |
| 1811 | | inline for (@typeInfo(T).Struct.fields, 0..) |field, i| { |
| 2064 | const fields = @typeInfo(T).Struct.fields; |
| 2065 | inline for (fields, 0..) |field, i| { |
| 1812 | 2066 | const int32 = ip.extra.items[i + index]; |
| 1813 | 2067 | @field(result, field.name) = switch (field.type) { |
| 1814 | 2068 | u32 => int32, |
| 1815 | 2069 | Index => @intToEnum(Index, int32), |
| 1816 | 2070 | Module.Decl.Index => @intToEnum(Module.Decl.Index, int32), |
| 1817 | 2071 | Module.Namespace.Index => @intToEnum(Module.Namespace.Index, int32), |
| 2072 | Module.Namespace.OptionalIndex => @intToEnum(Module.Namespace.OptionalIndex, int32), |
| 2073 | MapIndex => @intToEnum(MapIndex, int32), |
| 2074 | OptionalMapIndex => @intToEnum(OptionalMapIndex, int32), |
| 1818 | 2075 | i32 => @bitCast(i32, int32), |
| 1819 | 2076 | Pointer.Flags => @bitCast(Pointer.Flags, int32), |
| 1820 | 2077 | Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32), |
| ... | ... | @@ -1822,7 +2079,14 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T { |
| 1822 | 2079 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| 1823 | 2080 | }; |
| 1824 | 2081 | } |
| 1825 | | return result; |
| 2082 | return .{ |
| 2083 | .data = result, |
| 2084 | .end = index + fields.len, |
| 2085 | }; |
| 2086 | } |
| 2087 | |
| 2088 | fn extraData(ip: InternPool, comptime T: type, index: usize) T { |
| 2089 | return extraDataTrail(ip, T, index).data; |
| 1826 | 2090 | } |
| 1827 | 2091 | |
| 1828 | 2092 | /// Asserts the struct has 32-bit fields and the number of fields is evenly divisible by 2. |
| ... | ... | @@ -2071,7 +2335,8 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 2071 | 2335 | .type_slice => 0, |
| 2072 | 2336 | .type_optional => 0, |
| 2073 | 2337 | .type_error_union => @sizeOf(ErrorUnion), |
| 2074 | | .type_enum_simple => @sizeOf(EnumSimple), |
| 2338 | .type_enum_explicit => @sizeOf(EnumExplicit), |
| 2339 | .type_enum_auto => @sizeOf(EnumAuto), |
| 2075 | 2340 | .type_opaque => @sizeOf(Key.OpaqueType), |
| 2076 | 2341 | .type_struct => @sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl), |
| 2077 | 2342 | .type_struct_ns => @sizeOf(Module.Namespace), |