| ... | @@ -13,6 +13,12 @@ extra: std.ArrayListUnmanaged(u32) = .{}, | ... | @@ -13,6 +13,12 @@ extra: std.ArrayListUnmanaged(u32) = .{}, |
| 13 | /// Use the helper methods instead of accessing this directly in order to not | 13 | /// Use the helper methods instead of accessing this directly in order to not |
| 14 | /// violate the above mechanism. | 14 | /// violate the above mechanism. |
| 15 | limbs: std.ArrayListUnmanaged(u64) = .{}, | 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 | /// Struct objects are stored in this data structure because: | 23 | /// Struct objects are stored in this data structure because: |
| 18 | /// * They contain pointers such as the field maps. | 24 | /// * They contain pointers such as the field maps. |
| ... | @@ -28,6 +34,12 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{}, | ... | @@ -28,6 +34,12 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{}, |
| 28 | /// When a Union object is freed from `allocated_unions`, it is pushed into this stack. | 34 | /// When a Union object is freed from `allocated_unions`, it is pushed into this stack. |
| 29 | unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{}, | 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 | const std = @import("std"); | 43 | const std = @import("std"); |
| 32 | const Allocator = std.mem.Allocator; | 44 | const Allocator = std.mem.Allocator; |
| 33 | const assert = std.debug.assert; | 45 | const assert = std.debug.assert; |
| ... | @@ -52,6 +64,46 @@ const KeyAdapter = struct { | ... | @@ -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 | pub const Key = union(enum) { | 107 | pub const Key = union(enum) { |
| 56 | int_type: IntType, | 108 | int_type: IntType, |
| 57 | ptr_type: PtrType, | 109 | ptr_type: PtrType, |
| ... | @@ -68,6 +120,7 @@ pub const Key = union(enum) { | ... | @@ -68,6 +120,7 @@ pub const Key = union(enum) { |
| 68 | struct_type: StructType, | 120 | struct_type: StructType, |
| 69 | union_type: UnionType, | 121 | union_type: UnionType, |
| 70 | opaque_type: OpaqueType, | 122 | opaque_type: OpaqueType, |
| | 123 | enum_type: EnumType, |
| 71 | | 124 | |
| 72 | simple_value: SimpleValue, | 125 | simple_value: SimpleValue, |
| 73 | extern_func: struct { | 126 | extern_func: struct { |
| ... | @@ -174,6 +227,30 @@ pub const Key = union(enum) { | ... | @@ -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 | pub const Int = struct { | 254 | pub const Int = struct { |
| 178 | ty: Index, | 255 | ty: Index, |
| 179 | storage: Storage, | 256 | storage: Storage, |
| ... | @@ -263,6 +340,7 @@ pub const Key = union(enum) { | ... | @@ -263,6 +340,7 @@ pub const Key = union(enum) { |
| 263 | => |info| std.hash.autoHash(hasher, info), | 340 | => |info| std.hash.autoHash(hasher, info), |
| 264 | | 341 | |
| 265 | .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl), | 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 | .int => |int| { | 345 | .int => |int| { |
| 268 | // Canonicalize all integers by converting them to BigIntConst. | 346 | // Canonicalize all integers by converting them to BigIntConst. |
| ... | @@ -410,6 +488,10 @@ pub const Key = union(enum) { | ... | @@ -410,6 +488,10 @@ pub const Key = union(enum) { |
| 410 | const b_info = b.opaque_type; | 488 | const b_info = b.opaque_type; |
| 411 | return a_info.decl == b_info.decl; | 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 | .aggregate => |a_info| { | 495 | .aggregate => |a_info| { |
| 414 | const b_info = b.aggregate; | 496 | const b_info = b.aggregate; |
| 415 | if (a_info.ty != b_info.ty) return false; | 497 | if (a_info.ty != b_info.ty) return false; |
| ... | @@ -430,6 +512,7 @@ pub const Key = union(enum) { | ... | @@ -430,6 +512,7 @@ pub const Key = union(enum) { |
| 430 | .struct_type, | 512 | .struct_type, |
| 431 | .union_type, | 513 | .union_type, |
| 432 | .opaque_type, | 514 | .opaque_type, |
| | 515 | .enum_type, |
| 433 | => return .type_type, | 516 | => return .type_type, |
| 434 | | 517 | |
| 435 | inline .ptr, | 518 | inline .ptr, |
| ... | @@ -592,6 +675,21 @@ pub const Index = enum(u32) { | ... | @@ -592,6 +675,21 @@ pub const Index = enum(u32) { |
| 592 | .legacy = undefined, | 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 | pub const static_keys = [_]Key{ | 695 | pub const static_keys = [_]Key{ |
| ... | @@ -848,10 +946,12 @@ pub const Tag = enum(u8) { | ... | @@ -848,10 +946,12 @@ pub const Tag = enum(u8) { |
| 848 | /// An error union type. | 946 | /// An error union type. |
| 849 | /// data is payload to ErrorUnion. | 947 | /// data is payload to ErrorUnion. |
| 850 | type_error_union, | 948 | type_error_union, |
| 851 | /// Represents the data that an enum declaration provides, when the fields | 949 | /// An enum type with an explicitly provided integer tag type. |
| 852 | /// are auto-numbered, and there are no declarations. | 950 | /// data is payload index to `EnumExplicit`. |
| 853 | /// data is payload index to `EnumSimple`. | 951 | type_enum_explicit, |
| 854 | type_enum_simple, | 952 | /// An enum type with auto-numbered tag values. |
| | 953 | /// data is payload index to `EnumAuto`. |
| | 954 | type_enum_auto, |
| 855 | /// A type that can be represented with only an enum tag. | 955 | /// A type that can be represented with only an enum tag. |
| 856 | /// data is SimpleType enum value. | 956 | /// data is SimpleType enum value. |
| 857 | simple_type, | 957 | simple_type, |
| ... | @@ -1087,17 +1187,35 @@ pub const ErrorUnion = struct { | ... | @@ -1087,17 +1187,35 @@ pub const ErrorUnion = struct { |
| 1087 | }; | 1187 | }; |
| 1088 | | 1188 | |
| 1089 | /// Trailing: | 1189 | /// Trailing: |
| 1090 | /// 0. field name: null-terminated string index for each fields_len; declaration order | 1190 | /// 0. field name: NullTerminatedString for each fields_len; declaration order |
| 1091 | pub const EnumSimple = struct { | 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 | /// The Decl that corresponds to the enum itself. | 1212 | /// The Decl that corresponds to the enum itself. |
| 1093 | decl: Module.Decl.Index, | 1213 | decl: Module.Decl.Index, |
| 1094 | /// An integer type which is used for the numerical value of the enum. This | 1214 | /// This may be `none` if there are no declarations. |
| 1095 | /// is inferred by Zig to be the smallest power of two unsigned int that | 1215 | namespace: Module.Namespace.OptionalIndex, |
| 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, | | |
| 1100 | fields_len: u32, | 1216 | fields_len: u32, |
| | 1217 | /// Maps field names to declaration index. |
| | 1218 | names_map: MapIndex, |
| 1101 | }; | 1219 | }; |
| 1102 | | 1220 | |
| 1103 | pub const PackedU64 = packed struct(u64) { | 1221 | pub const PackedU64 = packed struct(u64) { |
| ... | @@ -1183,6 +1301,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { | ... | @@ -1183,6 +1301,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 1183 | ip.unions_free_list.deinit(gpa); | 1301 | ip.unions_free_list.deinit(gpa); |
| 1184 | ip.allocated_unions.deinit(gpa); | 1302 | ip.allocated_unions.deinit(gpa); |
| 1185 | | 1303 | |
| | 1304 | ip.maps.deinit(gpa); |
| | 1305 | ip.string_bytes.deinit(gpa); |
| | 1306 | |
| 1186 | ip.* = undefined; | 1307 | ip.* = undefined; |
| 1187 | } | 1308 | } |
| 1188 | | 1309 | |
| ... | @@ -1256,7 +1377,6 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { | ... | @@ -1256,7 +1377,6 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1256 | .type_optional => .{ .opt_type = @intToEnum(Index, data) }, | 1377 | .type_optional => .{ .opt_type = @intToEnum(Index, data) }, |
| 1257 | | 1378 | |
| 1258 | .type_error_union => @panic("TODO"), | 1379 | .type_error_union => @panic("TODO"), |
| 1259 | .type_enum_simple => @panic("TODO"), | | |
| 1260 | | 1380 | |
| 1261 | .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) }, | 1381 | .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) }, |
| 1262 | .type_struct => { | 1382 | .type_struct => { |
| ... | @@ -1288,6 +1408,46 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { | ... | @@ -1288,6 +1408,46 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { |
| 1288 | .runtime_tag = .safety, | 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 | .opt_null => .{ .opt = .{ | 1451 | .opt_null => .{ .opt = .{ |
| 1292 | .ty = @intToEnum(Index, data), | 1452 | .ty = @intToEnum(Index, data), |
| 1293 | .val = .none, | 1453 | .val = .none, |
| ... | @@ -1362,6 +1522,14 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { | ... | @@ -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 | fn indexToKeyBigInt(ip: InternPool, limb_index: u32, positive: bool) Key { | 1533 | fn indexToKeyBigInt(ip: InternPool, limb_index: u32, positive: bool) Key { |
| 1366 | const int_info = ip.limbData(Int, limb_index); | 1534 | const int_info = ip.limbData(Int, limb_index); |
| 1367 | return .{ .int = .{ | 1535 | return .{ .int = .{ |
| ... | @@ -1522,6 +1690,54 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -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 | .extern_func => @panic("TODO"), | 1741 | .extern_func => @panic("TODO"), |
| 1526 | | 1742 | |
| 1527 | .ptr => |ptr| switch (ptr.addr) { | 1743 | .ptr => |ptr| switch (ptr.addr) { |
| ... | @@ -1723,6 +1939,40 @@ pub fn getAssumeExists(ip: InternPool, key: Key) Index { | ... | @@ -1723,6 +1939,40 @@ pub fn getAssumeExists(ip: InternPool, key: Key) Index { |
| 1723 | return @intToEnum(Index, index); | 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 | /// This operation only happens under compile error conditions. | 1976 | /// This operation only happens under compile error conditions. |
| 1727 | /// Leak the index until the next garbage collection. | 1977 | /// Leak the index until the next garbage collection. |
| 1728 | pub fn remove(ip: *InternPool, index: Index) void { | 1978 | pub fn remove(ip: *InternPool, index: Index) void { |
| ... | @@ -1758,6 +2008,9 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { | ... | @@ -1758,6 +2008,9 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 1758 | Index => @enumToInt(@field(extra, field.name)), | 2008 | Index => @enumToInt(@field(extra, field.name)), |
| 1759 | Module.Decl.Index => @enumToInt(@field(extra, field.name)), | 2009 | Module.Decl.Index => @enumToInt(@field(extra, field.name)), |
| 1760 | Module.Namespace.Index => @enumToInt(@field(extra, field.name)), | 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 | i32 => @bitCast(u32, @field(extra, field.name)), | 2014 | i32 => @bitCast(u32, @field(extra, field.name)), |
| 1762 | Pointer.Flags => @bitCast(u32, @field(extra, field.name)), | 2015 | Pointer.Flags => @bitCast(u32, @field(extra, field.name)), |
| 1763 | Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)), | 2016 | Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)), |
| ... | @@ -1806,15 +2059,19 @@ fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void { | ... | @@ -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 | var result: T = undefined; | 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 | const int32 = ip.extra.items[i + index]; | 2066 | const int32 = ip.extra.items[i + index]; |
| 1813 | @field(result, field.name) = switch (field.type) { | 2067 | @field(result, field.name) = switch (field.type) { |
| 1814 | u32 => int32, | 2068 | u32 => int32, |
| 1815 | Index => @intToEnum(Index, int32), | 2069 | Index => @intToEnum(Index, int32), |
| 1816 | Module.Decl.Index => @intToEnum(Module.Decl.Index, int32), | 2070 | Module.Decl.Index => @intToEnum(Module.Decl.Index, int32), |
| 1817 | Module.Namespace.Index => @intToEnum(Module.Namespace.Index, int32), | 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 | i32 => @bitCast(i32, int32), | 2075 | i32 => @bitCast(i32, int32), |
| 1819 | Pointer.Flags => @bitCast(Pointer.Flags, int32), | 2076 | Pointer.Flags => @bitCast(Pointer.Flags, int32), |
| 1820 | Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32), | 2077 | Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32), |
| ... | @@ -1822,7 +2079,14 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T { | ... | @@ -1822,7 +2079,14 @@ fn extraData(ip: InternPool, comptime T: type, index: usize) T { |
| 1822 | else => @compileError("bad field type: " ++ @typeName(field.type)), | 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 | /// Asserts the struct has 32-bit fields and the number of fields is evenly divisible by 2. | 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,7 +2335,8 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 2071 | .type_slice => 0, | 2335 | .type_slice => 0, |
| 2072 | .type_optional => 0, | 2336 | .type_optional => 0, |
| 2073 | .type_error_union => @sizeOf(ErrorUnion), | 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 | .type_opaque => @sizeOf(Key.OpaqueType), | 2340 | .type_opaque => @sizeOf(Key.OpaqueType), |
| 2076 | .type_struct => @sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl), | 2341 | .type_struct => @sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl), |
| 2077 | .type_struct_ns => @sizeOf(Module.Namespace), | 2342 | .type_struct_ns => @sizeOf(Module.Namespace), |