diff options
Diffstat (limited to 'src/InternPool.zig')
| -rw-r--r-- | src/InternPool.zig | 452 |
1 files changed, 312 insertions, 140 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig index 15dba62e07..e62bdc8499 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -565,7 +565,7 @@ pub const OptionalNullTerminatedString = enum(u32) { /// * decl val (so that we can analyze the value lazily) /// * decl ref (so that we can analyze the reference lazily) pub const CaptureValue = packed struct(u32) { - tag: enum { @"comptime", runtime, decl_val, decl_ref }, + tag: enum(u2) { @"comptime", runtime, decl_val, decl_ref }, idx: u30, pub fn wrap(val: Unwrapped) CaptureValue { @@ -1026,22 +1026,76 @@ pub const Key = union(enum) { pub const Ptr = struct { /// This is the pointer type, not the element type. ty: Index, - /// The value of the address that the pointer points to. - addr: Addr, + /// The base address which this pointer is offset from. + base_addr: BaseAddr, + /// The offset of this pointer from `base_addr` in bytes. + byte_offset: u64, - pub const Addr = union(enum) { - const Tag = @typeInfo(Addr).Union.tag_type.?; + pub const BaseAddr = union(enum) { + const Tag = @typeInfo(BaseAddr).Union.tag_type.?; + /// Points to the value of a single `Decl`, which may be constant or a `variable`. decl: DeclIndex, + + /// Points to the value of a single comptime alloc stored in `Sema`. comptime_alloc: ComptimeAllocIndex, + + /// Points to a single unnamed constant value. anon_decl: AnonDecl, + + /// Points to a comptime field of a struct. Index is the field's value. + /// + /// TODO: this exists because these fields are semantically mutable. We + /// should probably change the language so that this isn't the case. comptime_field: Index, - int: Index, + + /// A pointer with a fixed integer address, usually from `@ptrFromInt`. + /// + /// The address is stored entirely by `byte_offset`, which will be positive + /// and in-range of a `usize`. The base address is, for all intents and purposes, 0. + int, + + /// A pointer to the payload of an error union. Index is the error union pointer. + /// To ensure a canonical representation, the type of the base pointer must: + /// * be a one-pointer + /// * be `const`, `volatile` and `allowzero` + /// * have alignment 1 + /// * have the same address space as this pointer + /// * have a host size, bit offset, and vector index of 0 + /// See `Value.canonicalizeBasePtr` which enforces these properties. eu_payload: Index, + + /// A pointer to the payload of a non-pointer-like optional. Index is the + /// optional pointer. To ensure a canonical representation, the base + /// pointer is subject to the same restrictions as in `eu_payload`. opt_payload: Index, - elem: BaseIndex, + + /// A pointer to a field of a slice, or of an auto-layout struct or union. Slice fields + /// are referenced according to `Value.slice_ptr_index` and `Value.slice_len_index`. + /// Base is the aggregate pointer, which is subject to the same restrictions as + /// in `eu_payload`. field: BaseIndex, + /// A pointer to an element of a comptime-only array. Base is the + /// many-pointer we are indexing into. It is subject to the same restrictions + /// as in `eu_payload`, except it must be a many-pointer rather than a one-pointer. + /// + /// The element type of the base pointer must NOT be an array. Additionally, the + /// base pointer is guaranteed to not be an `arr_elem` into a pointer with the + /// same child type. Thus, since there are no two comptime-only types which are + /// IMC to one another, the only case where the base pointer may also be an + /// `arr_elem` is when this pointer is semantically invalid (e.g. it reinterprets + /// a `type` as a `comptime_int`). These restrictions are in place to ensure + /// a canonical representation. + /// + /// This kind of base address differs from others in that it may refer to any + /// sequence of values; for instance, an `arr_elem` at index 2 may refer to + /// any number of elements starting from index 2. + /// + /// Index must not be 0. To refer to the element at index 0, simply reinterpret + /// the aggregate pointer. + arr_elem: BaseIndex, + pub const MutDecl = struct { decl: DeclIndex, runtime_index: RuntimeIndex, @@ -1222,10 +1276,11 @@ pub const Key = union(enum) { .ptr => |ptr| { // Int-to-ptr pointers are hashed separately than decl-referencing pointers. // This is sound due to pointer provenance rules. - const addr: @typeInfo(Key.Ptr.Addr).Union.tag_type.? = ptr.addr; - const seed2 = seed + @intFromEnum(addr); - const common = asBytes(&ptr.ty); - return switch (ptr.addr) { + const addr_tag: Key.Ptr.BaseAddr.Tag = ptr.base_addr; + const seed2 = seed + @intFromEnum(addr_tag); + const big_offset: i128 = ptr.byte_offset; + const common = asBytes(&ptr.ty) ++ asBytes(&big_offset); + return switch (ptr.base_addr) { inline .decl, .comptime_alloc, .anon_decl, @@ -1235,7 +1290,7 @@ pub const Key = union(enum) { .comptime_field, => |x| Hash.hash(seed2, common ++ asBytes(&x)), - .elem, .field => |x| Hash.hash( + .arr_elem, .field => |x| Hash.hash( seed2, common ++ asBytes(&x.base) ++ asBytes(&x.index), ), @@ -1494,21 +1549,21 @@ pub const Key = union(enum) { .ptr => |a_info| { const b_info = b.ptr; if (a_info.ty != b_info.ty) return false; - - const AddrTag = @typeInfo(Key.Ptr.Addr).Union.tag_type.?; - if (@as(AddrTag, a_info.addr) != @as(AddrTag, b_info.addr)) return false; - - return switch (a_info.addr) { - .decl => |a_decl| a_decl == b_info.addr.decl, - .comptime_alloc => |a_alloc| a_alloc == b_info.addr.comptime_alloc, - .anon_decl => |ad| ad.val == b_info.addr.anon_decl.val and - ad.orig_ty == b_info.addr.anon_decl.orig_ty, - .int => |a_int| a_int == b_info.addr.int, - .eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload, - .opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload, - .comptime_field => |a_comptime_field| a_comptime_field == b_info.addr.comptime_field, - .elem => |a_elem| std.meta.eql(a_elem, b_info.addr.elem), - .field => |a_field| std.meta.eql(a_field, b_info.addr.field), + if (a_info.byte_offset != b_info.byte_offset) return false; + + if (@as(Key.Ptr.BaseAddr.Tag, a_info.base_addr) != @as(Key.Ptr.BaseAddr.Tag, b_info.base_addr)) return false; + + return switch (a_info.base_addr) { + .decl => |a_decl| a_decl == b_info.base_addr.decl, + .comptime_alloc => |a_alloc| a_alloc == b_info.base_addr.comptime_alloc, + .anon_decl => |ad| ad.val == b_info.base_addr.anon_decl.val and + ad.orig_ty == b_info.base_addr.anon_decl.orig_ty, + .int => true, + .eu_payload => |a_eu_payload| a_eu_payload == b_info.base_addr.eu_payload, + .opt_payload => |a_opt_payload| a_opt_payload == b_info.base_addr.opt_payload, + .comptime_field => |a_comptime_field| a_comptime_field == b_info.base_addr.comptime_field, + .arr_elem => |a_elem| std.meta.eql(a_elem, b_info.base_addr.arr_elem), + .field => |a_field| std.meta.eql(a_field, b_info.base_addr.field), }; }, @@ -2271,6 +2326,46 @@ pub const LoadedStructType = struct { .struct_type = s, }; } + + pub const ReverseRuntimeOrderIterator = struct { + ip: *InternPool, + last_index: u32, + struct_type: InternPool.LoadedStructType, + + pub fn next(it: *@This()) ?u32 { + if (it.last_index == 0) + return null; + + if (it.struct_type.hasReorderedFields()) { + it.last_index -= 1; + const order = it.struct_type.runtime_order.get(it.ip); + while (order[it.last_index] == .omitted) { + it.last_index -= 1; + if (it.last_index == 0) + return null; + } + return order[it.last_index].toInt(); + } + + it.last_index -= 1; + while (it.struct_type.fieldIsComptime(it.ip, it.last_index)) { + it.last_index -= 1; + if (it.last_index == 0) + return null; + } + + return it.last_index; + } + }; + + pub fn iterateRuntimeOrderReverse(s: @This(), ip: *InternPool) ReverseRuntimeOrderIterator { + assert(s.layout != .@"packed"); + return .{ + .ip = ip, + .last_index = s.field_types.len, + .struct_type = s, + }; + } }; pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { @@ -2836,7 +2931,7 @@ pub const Index = enum(u32) { ptr_anon_decl: struct { data: *PtrAnonDecl }, ptr_anon_decl_aligned: struct { data: *PtrAnonDeclAligned }, ptr_comptime_field: struct { data: *PtrComptimeField }, - ptr_int: struct { data: *PtrBase }, + ptr_int: struct { data: *PtrInt }, ptr_eu_payload: struct { data: *PtrBase }, ptr_opt_payload: struct { data: *PtrBase }, ptr_elem: struct { data: *PtrBaseIndex }, @@ -3304,7 +3399,7 @@ pub const Tag = enum(u8) { /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value. ptr_comptime_field, /// A pointer with an integer value. - /// data is extra index of `PtrBase`, which contains the type and address. + /// data is extra index of `PtrInt`, which contains the type and address (byte offset from 0). /// Only pointer types are allowed to have this encoding. Optional types must use /// `opt_payload` or `opt_null`. ptr_int, @@ -3497,7 +3592,7 @@ pub const Tag = enum(u8) { .ptr_anon_decl => PtrAnonDecl, .ptr_anon_decl_aligned => PtrAnonDeclAligned, .ptr_comptime_field => PtrComptimeField, - .ptr_int => PtrBase, + .ptr_int => PtrInt, .ptr_eu_payload => PtrBase, .ptr_opt_payload => PtrBase, .ptr_elem => PtrBaseIndex, @@ -4153,11 +4248,37 @@ pub const PackedU64 = packed struct(u64) { pub const PtrDecl = struct { ty: Index, decl: DeclIndex, + byte_offset_a: u32, + byte_offset_b: u32, + fn init(ty: Index, decl: DeclIndex, byte_offset: u64) @This() { + return .{ + .ty = ty, + .decl = decl, + .byte_offset_a = @intCast(byte_offset >> 32), + .byte_offset_b = @truncate(byte_offset), + }; + } + fn byteOffset(data: @This()) u64 { + return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + } }; pub const PtrAnonDecl = struct { ty: Index, val: Index, + byte_offset_a: u32, + byte_offset_b: u32, + fn init(ty: Index, val: Index, byte_offset: u64) @This() { + return .{ + .ty = ty, + .val = val, + .byte_offset_a = @intCast(byte_offset >> 32), + .byte_offset_b = @truncate(byte_offset), + }; + } + fn byteOffset(data: @This()) u64 { + return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + } }; pub const PtrAnonDeclAligned = struct { @@ -4165,27 +4286,110 @@ pub const PtrAnonDeclAligned = struct { val: Index, /// Must be nonequal to `ty`. Only the alignment from this value is important. orig_ty: Index, + byte_offset_a: u32, + byte_offset_b: u32, + fn init(ty: Index, val: Index, orig_ty: Index, byte_offset: u64) @This() { + return .{ + .ty = ty, + .val = val, + .orig_ty = orig_ty, + .byte_offset_a = @intCast(byte_offset >> 32), + .byte_offset_b = @truncate(byte_offset), + }; + } + fn byteOffset(data: @This()) u64 { + return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + } }; pub const PtrComptimeAlloc = struct { ty: Index, index: ComptimeAllocIndex, + byte_offset_a: u32, + byte_offset_b: u32, + fn init(ty: Index, index: ComptimeAllocIndex, byte_offset: u64) @This() { + return .{ + .ty = ty, + .index = index, + .byte_offset_a = @intCast(byte_offset >> 32), + .byte_offset_b = @truncate(byte_offset), + }; + } + fn byteOffset(data: @This()) u64 { + return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + } }; pub const PtrComptimeField = struct { ty: Index, field_val: Index, + byte_offset_a: u32, + byte_offset_b: u32, + fn init(ty: Index, field_val: Index, byte_offset: u64) @This() { + return .{ + .ty = ty, + .field_val = field_val, + .byte_offset_a = @intCast(byte_offset >> 32), + .byte_offset_b = @truncate(byte_offset), + }; + } + fn byteOffset(data: @This()) u64 { + return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + } }; pub const PtrBase = struct { ty: Index, base: Index, + byte_offset_a: u32, + byte_offset_b: u32, + fn init(ty: Index, base: Index, byte_offset: u64) @This() { + return .{ + .ty = ty, + .base = base, + .byte_offset_a = @intCast(byte_offset >> 32), + .byte_offset_b = @truncate(byte_offset), + }; + } + fn byteOffset(data: @This()) u64 { + return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + } }; pub const PtrBaseIndex = struct { ty: Index, base: Index, index: Index, + byte_offset_a: u32, + byte_offset_b: u32, + fn init(ty: Index, base: Index, index: Index, byte_offset: u64) @This() { + return .{ + .ty = ty, + .base = base, + .index = index, + .byte_offset_a = @intCast(byte_offset >> 32), + .byte_offset_b = @truncate(byte_offset), + }; + } + fn byteOffset(data: @This()) u64 { + return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + } +}; + +pub const PtrInt = struct { + ty: Index, + byte_offset_a: u32, + byte_offset_b: u32, + fn init(ty: Index, byte_offset: u64) @This() { + return .{ + .ty = ty, + .byte_offset_a = @intCast(byte_offset >> 32), + .byte_offset_b = @truncate(byte_offset), + }; + } + fn byteOffset(data: @This()) u64 { + return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; + } }; pub const PtrSlice = struct { @@ -4569,78 +4773,55 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { }, .ptr_decl => { const info = ip.extraData(PtrDecl, data); - return .{ .ptr = .{ - .ty = info.ty, - .addr = .{ .decl = info.decl }, - } }; + return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .decl = info.decl }, .byte_offset = info.byteOffset() } }; }, .ptr_comptime_alloc => { const info = ip.extraData(PtrComptimeAlloc, data); - return .{ .ptr = .{ - .ty = info.ty, - .addr = .{ .comptime_alloc = info.index }, - } }; + return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .comptime_alloc = info.index }, .byte_offset = info.byteOffset() } }; }, .ptr_anon_decl => { const info = ip.extraData(PtrAnonDecl, data); - return .{ .ptr = .{ - .ty = info.ty, - .addr = .{ .anon_decl = .{ - .val = info.val, - .orig_ty = info.ty, - } }, - } }; + return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .anon_decl = .{ + .val = info.val, + .orig_ty = info.ty, + } }, .byte_offset = info.byteOffset() } }; }, .ptr_anon_decl_aligned => { const info = ip.extraData(PtrAnonDeclAligned, data); - return .{ .ptr = .{ - .ty = info.ty, - .addr = .{ .anon_decl = .{ - .val = info.val, - .orig_ty = info.orig_ty, - } }, - } }; + return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .anon_decl = .{ + .val = info.val, + .orig_ty = info.orig_ty, + } }, .byte_offset = info.byteOffset() } }; }, .ptr_comptime_field => { const info = ip.extraData(PtrComptimeField, data); - return .{ .ptr = .{ - .ty = info.ty, - .addr = .{ .comptime_field = info.field_val }, - } }; + return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .comptime_field = info.field_val }, .byte_offset = info.byteOffset() } }; }, .ptr_int => { - const info = ip.extraData(PtrBase, data); + const info = ip.extraData(PtrInt, data); return .{ .ptr = .{ .ty = info.ty, - .addr = .{ .int = info.base }, + .base_addr = .int, + .byte_offset = info.byteOffset(), } }; }, .ptr_eu_payload => { const info = ip.extraData(PtrBase, data); - return .{ .ptr = .{ - .ty = info.ty, - .addr = .{ .eu_payload = info.base }, - } }; + return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .eu_payload = info.base }, .byte_offset = info.byteOffset() } }; }, .ptr_opt_payload => { const info = ip.extraData(PtrBase, data); - return .{ .ptr = .{ - .ty = info.ty, - .addr = .{ .opt_payload = info.base }, - } }; + return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .opt_payload = info.base }, .byte_offset = info.byteOffset() } }; }, .ptr_elem => { // Avoid `indexToKey` recursion by asserting the tag encoding. const info = ip.extraData(PtrBaseIndex, data); const index_item = ip.items.get(@intFromEnum(info.index)); return switch (index_item.tag) { - .int_usize => .{ .ptr = .{ - .ty = info.ty, - .addr = .{ .elem = .{ - .base = info.base, - .index = index_item.data, - } }, - } }, + .int_usize => .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .arr_elem = .{ + .base = info.base, + .index = index_item.data, + } }, .byte_offset = info.byteOffset() } }, .int_positive => @panic("TODO"), // implement along with behavior test coverage else => unreachable, }; @@ -4650,13 +4831,10 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { const info = ip.extraData(PtrBaseIndex, data); const index_item = ip.items.get(@intFromEnum(info.index)); return switch (index_item.tag) { - .int_usize => .{ .ptr = .{ - .ty = info.ty, - .addr = .{ .field = .{ - .base = info.base, - .index = index_item.data, - } }, - } }, + .int_usize => .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .field = .{ + .base = info.base, + .index = index_item.data, + } }, .byte_offset = info.byteOffset() } }, .int_positive => @panic("TODO"), // implement along with behavior test coverage else => unreachable, }; @@ -5211,57 +5389,40 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { .ptr => |ptr| { const ptr_type = ip.indexToKey(ptr.ty).ptr_type; assert(ptr_type.flags.size != .Slice); - ip.items.appendAssumeCapacity(switch (ptr.addr) { + ip.items.appendAssumeCapacity(switch (ptr.base_addr) { .decl => |decl| .{ .tag = .ptr_decl, - .data = try ip.addExtra(gpa, PtrDecl{ - .ty = ptr.ty, - .decl = decl, - }), + .data = try ip.addExtra(gpa, PtrDecl.init(ptr.ty, decl, ptr.byte_offset)), }, .comptime_alloc => |alloc_index| .{ .tag = .ptr_comptime_alloc, - .data = try ip.addExtra(gpa, PtrComptimeAlloc{ - .ty = ptr.ty, - .index = alloc_index, - }), + .data = try ip.addExtra(gpa, PtrComptimeAlloc.init(ptr.ty, alloc_index, ptr.byte_offset)), }, .anon_decl => |anon_decl| if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) item: { if (ptr.ty != anon_decl.orig_ty) { _ = ip.map.pop(); var new_key = key; - new_key.ptr.addr.anon_decl.orig_ty = ptr.ty; + new_key.ptr.base_addr.anon_decl.orig_ty = ptr.ty; const new_gop = try ip.map.getOrPutAdapted(gpa, new_key, adapter); if (new_gop.found_existing) return @enumFromInt(new_gop.index); } break :item .{ .tag = .ptr_anon_decl, - .data = try ip.addExtra(gpa, PtrAnonDecl{ - .ty = ptr.ty, - .val = anon_decl.val, - }), + .data = try ip.addExtra(gpa, PtrAnonDecl.init(ptr.ty, anon_decl.val, ptr.byte_offset)), }; } else .{ .tag = .ptr_anon_decl_aligned, - .data = try ip.addExtra(gpa, PtrAnonDeclAligned{ - .ty = ptr.ty, - .val = anon_decl.val, - .orig_ty = anon_decl.orig_ty, - }), + .data = try ip.addExtra(gpa, PtrAnonDeclAligned.init(ptr.ty, anon_decl.val, anon_decl.orig_ty, ptr.byte_offset)), }, .comptime_field => |field_val| item: { assert(field_val != .none); break :item .{ .tag = .ptr_comptime_field, - .data = try ip.addExtra(gpa, PtrComptimeField{ - .ty = ptr.ty, - .field_val = field_val, - }), + .data = try ip.addExtra(gpa, PtrComptimeField.init(ptr.ty, field_val, ptr.byte_offset)), }; }, - .int, .eu_payload, .opt_payload => |base| item: { - switch (ptr.addr) { - .int => assert(ip.typeOf(base) == .usize_type), + .eu_payload, .opt_payload => |base| item: { + switch (ptr.base_addr) { .eu_payload => assert(ip.indexToKey( ip.indexToKey(ip.typeOf(base)).ptr_type.child, ) == .error_union_type), @@ -5271,40 +5432,40 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { else => unreachable, } break :item .{ - .tag = switch (ptr.addr) { - .int => .ptr_int, + .tag = switch (ptr.base_addr) { .eu_payload => .ptr_eu_payload, .opt_payload => .ptr_opt_payload, else => unreachable, }, - .data = try ip.addExtra(gpa, PtrBase{ - .ty = ptr.ty, - .base = base, - }), + .data = try ip.addExtra(gpa, PtrBase.init(ptr.ty, base, ptr.byte_offset)), }; }, - .elem, .field => |base_index| item: { + .int => .{ + .tag = .ptr_int, + .data = try ip.addExtra(gpa, PtrInt.init(ptr.ty, ptr.byte_offset)), + }, + .arr_elem, .field => |base_index| item: { const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type; - switch (ptr.addr) { - .elem => assert(base_ptr_type.flags.size == .Many), + switch (ptr.base_addr) { + .arr_elem => assert(base_ptr_type.flags.size == .Many), .field => { assert(base_ptr_type.flags.size == .One); switch (ip.indexToKey(base_ptr_type.child)) { .anon_struct_type => |anon_struct_type| { - assert(ptr.addr == .field); + assert(ptr.base_addr == .field); assert(base_index.index < anon_struct_type.types.len); }, .struct_type => { - assert(ptr.addr == .field); + assert(ptr.base_addr == .field); assert(base_index.index < ip.loadStructType(base_ptr_type.child).field_types.len); }, .union_type => { const union_type = ip.loadUnionType(base_ptr_type.child); - assert(ptr.addr == .field); + assert(ptr.base_addr == .field); assert(base_index.index < union_type.field_types.len); }, .ptr_type => |slice_type| { - assert(ptr.addr == .field); + assert(ptr.base_addr == .field); assert(slice_type.flags.size == .Slice); assert(base_index.index < 2); }, @@ -5321,16 +5482,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing); try ip.items.ensureUnusedCapacity(gpa, 1); break :item .{ - .tag = switch (ptr.addr) { - .elem => .ptr_elem, + .tag = switch (ptr.base_addr) { + .arr_elem => .ptr_elem, .field => .ptr_field, else => unreachable, }, - .data = try ip.addExtra(gpa, PtrBaseIndex{ - .ty = ptr.ty, - .base = base_index.base, - .index = index_index, - }), + .data = try ip.addExtra(gpa, PtrBaseIndex.init(ptr.ty, base_index.base, index_index, ptr.byte_offset)), }; }, }); @@ -7584,13 +7741,15 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al if (ip.isPointerType(new_ty)) switch (ip.indexToKey(new_ty).ptr_type.flags.size) { .One, .Many, .C => return ip.get(gpa, .{ .ptr = .{ .ty = new_ty, - .addr = .{ .int = .zero_usize }, + .base_addr = .int, + .byte_offset = 0, } }), .Slice => return ip.get(gpa, .{ .slice = .{ .ty = new_ty, .ptr = try ip.get(gpa, .{ .ptr = .{ .ty = ip.slicePtrType(new_ty), - .addr = .{ .int = .zero_usize }, + .base_addr = .int, + .byte_offset = 0, } }), .len = try ip.get(gpa, .{ .undef = .usize_type }), } }), @@ -7630,10 +7789,15 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al .ty = new_ty, .int = try ip.getCoerced(gpa, val, ip.loadEnumType(new_ty).tag_ty), } }), - .ptr_type => return ip.get(gpa, .{ .ptr = .{ - .ty = new_ty, - .addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) }, - } }), + .ptr_type => switch (int.storage) { + inline .u64, .i64 => |int_val| return ip.get(gpa, .{ .ptr = .{ + .ty = new_ty, + .base_addr = .int, + .byte_offset = @intCast(int_val), + } }), + .big_int => unreachable, // must be a usize + .lazy_align, .lazy_size => {}, + }, else => if (ip.isIntegerType(new_ty)) return getCoercedInts(ip, gpa, int, new_ty), }, @@ -7684,11 +7848,15 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al .ptr => |ptr| if (ip.isPointerType(new_ty) and ip.indexToKey(new_ty).ptr_type.flags.size != .Slice) return ip.get(gpa, .{ .ptr = .{ .ty = new_ty, - .addr = ptr.addr, + .base_addr = ptr.base_addr, + .byte_offset = ptr.byte_offset, } }) else if (ip.isIntegerType(new_ty)) - switch (ptr.addr) { - .int => |int| return ip.getCoerced(gpa, int, new_ty), + switch (ptr.base_addr) { + .int => return ip.get(gpa, .{ .int = .{ + .ty = .usize_type, + .storage = .{ .u64 = @intCast(ptr.byte_offset) }, + } }), else => {}, }, .opt => |opt| switch (ip.indexToKey(new_ty)) { @@ -7696,13 +7864,15 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al .none => switch (ptr_type.flags.size) { .One, .Many, .C => try ip.get(gpa, .{ .ptr = .{ .ty = new_ty, - .addr = .{ .int = .zero_usize }, + .base_addr = .int, + .byte_offset = 0, } }), .Slice => try ip.get(gpa, .{ .slice = .{ .ty = new_ty, .ptr = try ip.get(gpa, .{ .ptr = .{ .ty = ip.slicePtrType(new_ty), - .addr = .{ .int = .zero_usize }, + .base_addr = .int, + .byte_offset = 0, } }), .len = try ip.get(gpa, .{ .undef = .usize_type }), } }), @@ -8181,7 +8351,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { .ptr_anon_decl => @sizeOf(PtrAnonDecl), .ptr_anon_decl_aligned => @sizeOf(PtrAnonDeclAligned), .ptr_comptime_field => @sizeOf(PtrComptimeField), - .ptr_int => @sizeOf(PtrBase), + .ptr_int => @sizeOf(PtrInt), .ptr_eu_payload => @sizeOf(PtrBase), .ptr_opt_payload => @sizeOf(PtrBase), .ptr_elem => @sizeOf(PtrBaseIndex), @@ -8854,13 +9024,15 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) OptionalDeclIndex { } } -pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag { +pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.BaseAddr.Tag { var base = @intFromEnum(val); while (true) { switch (ip.items.items(.tag)[base]) { .ptr_decl => return .decl, .ptr_comptime_alloc => return .comptime_alloc, - .ptr_anon_decl, .ptr_anon_decl_aligned => return .anon_decl, + .ptr_anon_decl, + .ptr_anon_decl_aligned, + => return .anon_decl, .ptr_comptime_field => return .comptime_field, .ptr_int => return .int, inline .ptr_eu_payload, |
