diff --git a/src/InternPool.zig b/src/InternPool.zig index a16ebe6487..04ec10fe72 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -575,9 +575,10 @@ pub const Key = union(enum) { std.hash.autoHash(hasher, ptr.ty); // Int-to-ptr pointers are hashed separately than decl-referencing pointers. // This is sound due to pointer provenance rules. + std.hash.autoHash(hasher, @as(@typeInfo(Key.Ptr.Addr).Union.tag_type.?, ptr.addr)); switch (ptr.addr) { + .decl => |decl| std.hash.autoHash(hasher, decl), .int => |int| std.hash.autoHash(hasher, int), - .decl => @panic("TODO"), } }, @@ -690,19 +691,14 @@ pub const Key = union(enum) { .ptr => |a_info| { const b_info = b.ptr; + if (a_info.ty != b_info.ty) return false; - 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) { - .int => |a_int| switch (b_info.addr) { - .int => |b_int| a_int == b_int, - .decl => false, - }, - .decl => |a_decl| switch (b_info.addr) { - .int => false, - .decl => |b_decl| a_decl == b_decl, - }, + .decl => |a_decl| a_decl == b_info.addr.decl, + .int => |a_int| a_int == b_info.addr.int, }; }, @@ -1334,7 +1330,10 @@ pub const Tag = enum(u8) { /// A value that can be represented with only an enum tag. /// data is SimpleValue enum value. simple_value, - /// A pointer to an integer value. + /// A pointer to a decl. + /// data is extra index of PtrDecl, which contains the type and address. + ptr_decl, + /// A pointer with an integer value. /// data is extra index of PtrInt, which contains the type and address. /// Only pointer types are allowed to have this encoding. Optional types must use /// `opt_payload` or `opt_null`. @@ -1673,6 +1672,11 @@ pub const PackedU64 = packed struct(u64) { } }; +pub const PtrDecl = struct { + ty: Index, + decl: Module.Decl.Index, +}; + pub const PtrInt = struct { ty: Index, addr: Index, @@ -1990,6 +1994,13 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { .val = payload_val, } }; }, + .ptr_decl => { + const info = ip.extraData(PtrDecl, data); + return .{ .ptr = .{ + .ty = info.ty, + .addr = .{ .decl = info.decl }, + } }; + }, .ptr_int => { const info = ip.extraData(PtrInt, data); return .{ .ptr = .{ @@ -2462,7 +2473,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { .extern_func => @panic("TODO"), .ptr => |ptr| switch (ptr.addr) { - .decl => @panic("TODO"), + .decl => |decl| { + assert(ptr.ty != .none); + ip.items.appendAssumeCapacity(.{ + .tag = .ptr_decl, + .data = try ip.addExtra(gpa, PtrDecl{ + .ty = ptr.ty, + .decl = decl, + }), + }); + }, .int => |int| { assert(ptr.ty != .none); ip.items.appendAssumeCapacity(.{ @@ -3465,6 +3485,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { .undef => 0, .simple_type => 0, .simple_value => 0, + .ptr_decl => @sizeOf(PtrDecl), .ptr_int => @sizeOf(PtrInt), .opt_null => 0, .opt_payload => 0, diff --git a/src/Sema.zig b/src/Sema.zig index ebef3e929b..145f514ebc 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -29294,33 +29294,28 @@ fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref /// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeDeclRef` wraps /// this function with `analyze_fn_body` set to true. fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: bool) CompileError!Air.Inst.Ref { - try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index); + const mod = sema.mod; + try mod.declareDeclDependency(sema.owner_decl_index, decl_index); try sema.ensureDeclAnalyzed(decl_index); - const decl = sema.mod.declPtr(decl_index); + const decl = mod.declPtr(decl_index); const decl_tv = try decl.typedValue(); - if (decl_tv.val.castTag(.variable)) |payload| { - const variable = payload.data; - const ty = try Type.ptr(sema.arena, sema.mod, .{ - .pointee_type = decl_tv.ty, - .mutable = variable.is_mutable, - .@"addrspace" = decl.@"addrspace", - .@"align" = decl.@"align", - }); - return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl_index)); - } + const ptr_ty = try mod.ptrType(.{ + .elem_type = decl_tv.ty.ip_index, + .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"), + .is_const = if (decl_tv.val.castTag(.variable)) |payload| + !payload.data.is_mutable + else + false, + .address_space = decl.@"addrspace", + }); if (analyze_fn_body) { try sema.maybeQueueFuncBodyAnalysis(decl_index); } - return sema.addConstant( - try Type.ptr(sema.arena, sema.mod, .{ - .pointee_type = decl_tv.ty, - .mutable = false, - .@"addrspace" = decl.@"addrspace", - .@"align" = decl.@"align", - }), - try Value.Tag.decl_ref.create(sema.arena, decl_index), - ); + return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{ + .ty = ptr_ty.ip_index, + .addr = .{ .decl = decl_index }, + } })).toValue()); } fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {