Sema: port Value.decl_ptr to InternPool

This commit is contained in:
Jacob Young 2023-05-20 00:05:29 -04:00 committed by Andrew Kelley
parent c473594114
commit be78a12d7d
2 changed files with 50 additions and 34 deletions

View File

@ -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,

View File

@ -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 {