InternPool: create specialized functions for loading namespace types
Namespace types (`struct`, `enum`, `union`, `opaque`) do not use structural equality - equivalence is based on their Decl index (and soon will change to AST node + captures). However, we previously stored all other information in the corresponding `InternPool.Key` anyway. For logical consistency, it makes sense to have the key only be the true key (that is, the Decl index) and to load all other data through another function. This introduces those functions, by the name of `loadStructType` etc. It's a big diff, but most of it is no-brainer changes. In future, it might be nice to eliminate a bunch of the loaded state in favour of accessor functions on the `LoadedXyzType` types (like how we have `LoadedUnionType.size()`), but that can be explored at a later date.
This commit is contained in:
@@ -527,7 +527,7 @@ pub const Decl = struct {
|
||||
|
||||
/// If the Decl owns its value and it is a union, return it,
|
||||
/// otherwise null.
|
||||
pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.UnionType {
|
||||
pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.LoadedUnionType {
|
||||
if (!decl.owns_tv) return null;
|
||||
if (decl.val.ip_index == .none) return null;
|
||||
return zcu.typeToUnion(decl.val.toType());
|
||||
@@ -563,14 +563,15 @@ pub const Decl = struct {
|
||||
/// enum, or opaque.
|
||||
pub fn getInnerNamespaceIndex(decl: Decl, zcu: *Zcu) Namespace.OptionalIndex {
|
||||
if (!decl.has_tv) return .none;
|
||||
const ip = &zcu.intern_pool;
|
||||
return switch (decl.val.ip_index) {
|
||||
.empty_struct_type => .none,
|
||||
.none => .none,
|
||||
else => switch (zcu.intern_pool.indexToKey(decl.val.toIntern())) {
|
||||
.opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
|
||||
.struct_type => |struct_type| struct_type.namespace,
|
||||
.union_type => |union_type| union_type.namespace.toOptional(),
|
||||
.enum_type => |enum_type| enum_type.namespace,
|
||||
else => switch (ip.indexToKey(decl.val.toIntern())) {
|
||||
.opaque_type => ip.loadOpaqueType(decl.val.toIntern()).namespace.toOptional(),
|
||||
.struct_type => ip.loadStructType(decl.val.toIntern()).namespace,
|
||||
.union_type => ip.loadUnionType(decl.val.toIntern()).namespace.toOptional(),
|
||||
.enum_type => ip.loadEnumType(decl.val.toIntern()).namespace,
|
||||
else => .none,
|
||||
},
|
||||
};
|
||||
@@ -5682,7 +5683,7 @@ pub fn enumValue(mod: *Module, ty: Type, tag_int: InternPool.Index) Allocator.Er
|
||||
pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.Error!Value {
|
||||
const ip = &mod.intern_pool;
|
||||
const gpa = mod.gpa;
|
||||
const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
|
||||
const enum_type = ip.loadEnumType(ty.toIntern());
|
||||
|
||||
if (enum_type.values.len == 0) {
|
||||
// Auto-numbered fields.
|
||||
@@ -5988,28 +5989,26 @@ pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File {
|
||||
/// * `@TypeOf(.{})`
|
||||
/// * A struct which has no fields (`struct {}`).
|
||||
/// * Not a struct.
|
||||
pub fn typeToStruct(mod: *Module, ty: Type) ?InternPool.Key.StructType {
|
||||
if (ty.ip_index == .none) return null;
|
||||
return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
|
||||
.struct_type => |t| t,
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn typeToPackedStruct(mod: *Module, ty: Type) ?InternPool.Key.StructType {
|
||||
if (ty.ip_index == .none) return null;
|
||||
return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
|
||||
.struct_type => |t| if (t.layout == .Packed) t else null,
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// This asserts that the union's enum tag type has been resolved.
|
||||
pub fn typeToUnion(mod: *Module, ty: Type) ?InternPool.UnionType {
|
||||
pub fn typeToStruct(mod: *Module, ty: Type) ?InternPool.LoadedStructType {
|
||||
if (ty.ip_index == .none) return null;
|
||||
const ip = &mod.intern_pool;
|
||||
return switch (ip.indexToKey(ty.ip_index)) {
|
||||
.union_type => |k| ip.loadUnionType(k),
|
||||
.struct_type => ip.loadStructType(ty.ip_index),
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn typeToPackedStruct(mod: *Module, ty: Type) ?InternPool.LoadedStructType {
|
||||
const s = mod.typeToStruct(ty) orelse return null;
|
||||
if (s.layout != .Packed) return null;
|
||||
return s;
|
||||
}
|
||||
|
||||
pub fn typeToUnion(mod: *Module, ty: Type) ?InternPool.LoadedUnionType {
|
||||
if (ty.ip_index == .none) return null;
|
||||
const ip = &mod.intern_pool;
|
||||
return switch (ip.indexToKey(ty.ip_index)) {
|
||||
.union_type => ip.loadUnionType(ty.ip_index),
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
@@ -6111,7 +6110,7 @@ pub const UnionLayout = struct {
|
||||
padding: u32,
|
||||
};
|
||||
|
||||
pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {
|
||||
pub fn getUnionLayout(mod: *Module, u: InternPool.LoadedUnionType) UnionLayout {
|
||||
const ip = &mod.intern_pool;
|
||||
assert(u.haveLayout(ip));
|
||||
var most_aligned_field: u32 = undefined;
|
||||
@@ -6157,7 +6156,7 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {
|
||||
const tag_size = Type.fromInterned(u.enum_tag_ty).abiSize(mod);
|
||||
const tag_align = Type.fromInterned(u.enum_tag_ty).abiAlignment(mod).max(.@"1");
|
||||
return .{
|
||||
.abi_size = u.size,
|
||||
.abi_size = u.size(ip).*,
|
||||
.abi_align = tag_align.max(payload_align),
|
||||
.most_aligned_field = most_aligned_field,
|
||||
.most_aligned_field_size = most_aligned_field_size,
|
||||
@@ -6166,16 +6165,16 @@ pub fn getUnionLayout(mod: *Module, u: InternPool.UnionType) UnionLayout {
|
||||
.payload_align = payload_align,
|
||||
.tag_align = tag_align,
|
||||
.tag_size = tag_size,
|
||||
.padding = u.padding,
|
||||
.padding = u.padding(ip).*,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn unionAbiSize(mod: *Module, u: InternPool.UnionType) u64 {
|
||||
pub fn unionAbiSize(mod: *Module, u: InternPool.LoadedUnionType) u64 {
|
||||
return mod.getUnionLayout(u).abi_size;
|
||||
}
|
||||
|
||||
/// Returns 0 if the union is represented with 0 bits at runtime.
|
||||
pub fn unionAbiAlignment(mod: *Module, u: InternPool.UnionType) Alignment {
|
||||
pub fn unionAbiAlignment(mod: *Module, u: InternPool.LoadedUnionType) Alignment {
|
||||
const ip = &mod.intern_pool;
|
||||
const have_tag = u.flagsPtr(ip).runtime_tag.hasTag();
|
||||
var max_align: Alignment = .none;
|
||||
@@ -6192,7 +6191,7 @@ pub fn unionAbiAlignment(mod: *Module, u: InternPool.UnionType) Alignment {
|
||||
/// Returns the field alignment, assuming the union is not packed.
|
||||
/// Keep implementation in sync with `Sema.unionFieldAlignment`.
|
||||
/// Prefer to call that function instead of this one during Sema.
|
||||
pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.UnionType, field_index: u32) Alignment {
|
||||
pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.LoadedUnionType, field_index: u32) Alignment {
|
||||
const ip = &mod.intern_pool;
|
||||
const field_align = u.fieldAlign(ip, field_index);
|
||||
if (field_align != .none) return field_align;
|
||||
@@ -6201,12 +6200,11 @@ pub fn unionFieldNormalAlignment(mod: *Module, u: InternPool.UnionType, field_in
|
||||
}
|
||||
|
||||
/// Returns the index of the active field, given the current tag value
|
||||
pub fn unionTagFieldIndex(mod: *Module, u: InternPool.UnionType, enum_tag: Value) ?u32 {
|
||||
pub fn unionTagFieldIndex(mod: *Module, u: InternPool.LoadedUnionType, enum_tag: Value) ?u32 {
|
||||
const ip = &mod.intern_pool;
|
||||
if (enum_tag.toIntern() == .none) return null;
|
||||
assert(ip.typeOf(enum_tag.toIntern()) == u.enum_tag_ty);
|
||||
const enum_type = ip.indexToKey(u.enum_tag_ty).enum_type;
|
||||
return enum_type.tagValueIndex(ip, enum_tag.toIntern());
|
||||
return u.loadTagType(ip).tagValueIndex(ip, enum_tag.toIntern());
|
||||
}
|
||||
|
||||
/// Returns the field alignment of a non-packed struct in byte units.
|
||||
@@ -6253,7 +6251,7 @@ pub fn structFieldAlignmentExtern(mod: *Module, field_ty: Type) Alignment {
|
||||
/// projects.
|
||||
pub fn structPackedFieldBitOffset(
|
||||
mod: *Module,
|
||||
struct_type: InternPool.Key.StructType,
|
||||
struct_type: InternPool.LoadedStructType,
|
||||
field_index: u32,
|
||||
) u16 {
|
||||
const ip = &mod.intern_pool;
|
||||
|
||||
Reference in New Issue
Block a user