aboutsummaryrefslogtreecommitdiff
path: root/src/InternPool.zig
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2024-12-22 21:16:29 +0000
committermlugg <mlugg@mlugg.co.uk>2024-12-24 02:18:41 +0000
commit40aafcd6a85d3c517f445f17149c17523c832420 (patch)
treeb8e1a5361c6a20ce9e3ba568b61b199aff1c8f13 /src/InternPool.zig
parent18362ebe13ece2ea7c4f57303ec4687f55d2dba5 (diff)
downloadzig-40aafcd6a85d3c517f445f17149c17523c832420.tar.gz
zig-40aafcd6a85d3c517f445f17149c17523c832420.zip
compiler: remove Cau
The `Cau` abstraction originated from noting that one of the two primary roles of the legacy `Decl` type was to be the subject of comptime semantic analysis. However, the data stored in `Cau` has always had some level of redundancy. While preparing for #131, I went to remove that redundany, and realised that `Cau` now had exactly one field: `owner`. This led me to conclude that `Cau` is, in fact, an unnecessary level of abstraction over what are in reality *fundamentally different* kinds of analysis unit (`AnalUnit`). Types, `Nav` vals, and `comptime` declarations are all analyzed in different ways, and trying to treat them as the same thing is counterproductive! So, these 3 cases are now different alternatives in `AnalUnit`. To avoid stealing bits from `InternPool`-based IDs, which are already a little starved for bits due to the sharding datastructures, `AnalUnit` is expanded to 64 bits (30 of which are currently unused). This doesn't impact memory usage too much by default, because we don't store `AnalUnit`s all too often; however, we do store them a lot under `-fincremental`, so a non-trivial bump to peak RSS can be observed there. This will be improved in the future when I made `InternPool.DepEntry` less memory-inefficient. `Zcu.PerThread.ensureCauAnalyzed` is split into 3 functions, for each of the 3 new types of `AnalUnit`. The new logic is much easier to understand, because it avoids conflating the logic of these fundamentally different cases.
Diffstat (limited to 'src/InternPool.zig')
-rw-r--r--src/InternPool.zig429
1 files changed, 154 insertions, 275 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig
index 920f0df4ee..41019ea9d9 100644
--- a/src/InternPool.zig
+++ b/src/InternPool.zig
@@ -363,33 +363,53 @@ pub fn rehashTrackedInsts(
}
/// Analysis Unit. Represents a single entity which undergoes semantic analysis.
-/// This is either a `Cau` or a runtime function.
-/// The LSB is used as a tag bit.
/// This is the "source" of an incremental dependency edge.
-pub const AnalUnit = packed struct(u32) {
- kind: enum(u1) { cau, func },
- index: u31,
- pub const Unwrapped = union(enum) {
- cau: Cau.Index,
+pub const AnalUnit = packed struct(u64) {
+ kind: Kind,
+ id: u32,
+
+ pub const Kind = enum(u32) {
+ @"comptime",
+ nav_val,
+ type,
+ func,
+ };
+
+ pub const Unwrapped = union(Kind) {
+ /// This `AnalUnit` analyzes the body of the given `comptime` declaration.
+ @"comptime": ComptimeUnit.Id,
+ /// This `AnalUnit` resolves the value of the given `Nav`.
+ nav_val: Nav.Index,
+ /// This `AnalUnit` resolves the given `struct`/`union`/`enum` type.
+ /// Generated tag enums are never used here (they do not undergo type resolution).
+ type: InternPool.Index,
+ /// This `AnalUnit` analyzes the body of the given runtime function.
func: InternPool.Index,
};
- pub fn unwrap(as: AnalUnit) Unwrapped {
- return switch (as.kind) {
- .cau => .{ .cau = @enumFromInt(as.index) },
- .func => .{ .func = @enumFromInt(as.index) },
+
+ pub fn unwrap(au: AnalUnit) Unwrapped {
+ return switch (au.kind) {
+ inline else => |tag| @unionInit(
+ Unwrapped,
+ @tagName(tag),
+ @enumFromInt(au.id),
+ ),
};
}
pub fn wrap(raw: Unwrapped) AnalUnit {
return switch (raw) {
- .cau => |cau| .{ .kind = .cau, .index = @intCast(@intFromEnum(cau)) },
- .func => |func| .{ .kind = .func, .index = @intCast(@intFromEnum(func)) },
+ inline else => |id, tag| .{
+ .kind = tag,
+ .id = @intFromEnum(id),
+ },
};
}
+
pub fn toOptional(as: AnalUnit) Optional {
- return @enumFromInt(@as(u32, @bitCast(as)));
+ return @enumFromInt(@as(u64, @bitCast(as)));
}
- pub const Optional = enum(u32) {
- none = std.math.maxInt(u32),
+ pub const Optional = enum(u64) {
+ none = std.math.maxInt(u64),
_,
pub fn unwrap(opt: Optional) ?AnalUnit {
return switch (opt) {
@@ -400,97 +420,30 @@ pub const AnalUnit = packed struct(u32) {
};
};
-/// Comptime Analysis Unit. This is the "subject" of semantic analysis where the root context is
-/// comptime; every `Sema` is owned by either a `Cau` or a runtime function (see `AnalUnit`).
-/// The state stored here is immutable.
-///
-/// * Every ZIR `declaration` has a `Cau` (post-instantiation) to analyze the declaration body.
-/// * Every `struct`, `union`, and `enum` has a `Cau` for type resolution.
-///
-/// The analysis status of a `Cau` is known only from state in `Zcu`.
-/// An entry in `Zcu.failed_analysis` indicates an analysis failure with associated error message.
-/// An entry in `Zcu.transitive_failed_analysis` indicates a transitive analysis failure.
-///
-/// 12 bytes.
-pub const Cau = struct {
- /// The `declaration`, `struct_decl`, `enum_decl`, or `union_decl` instruction which this `Cau` analyzes.
+pub const ComptimeUnit = extern struct {
zir_index: TrackedInst.Index,
- /// The namespace which this `Cau` should be analyzed within.
namespace: NamespaceIndex,
- /// This field essentially tells us what to do with the information resulting from
- /// semantic analysis. See `Owner.Unwrapped` for details.
- owner: Owner,
-
- /// See `Owner.Unwrapped` for details. In terms of representation, the `InternPool.Index`
- /// or `Nav.Index` is cast to a `u31` and stored in `index`. As a special case, if
- /// `@as(u32, @bitCast(owner)) == 0xFFFF_FFFF`, then the value is treated as `.none`.
- pub const Owner = packed struct(u32) {
- kind: enum(u1) { type, nav },
- index: u31,
-
- pub const Unwrapped = union(enum) {
- /// This `Cau` exists in isolation. It is a global `comptime` declaration, or (TODO ANYTHING ELSE?).
- /// After semantic analysis completes, the result is discarded.
- none,
- /// This `Cau` is owned by the given type for type resolution.
- /// This is a `struct`, `union`, or `enum` type.
- type: InternPool.Index,
- /// This `Cau` is owned by the given `Nav` to resolve its value.
- /// When analyzing the `Cau`, the resulting value is stored as the value of this `Nav`.
- nav: Nav.Index,
- };
- pub fn unwrap(owner: Owner) Unwrapped {
- if (@as(u32, @bitCast(owner)) == std.math.maxInt(u32)) {
- return .none;
- }
- return switch (owner.kind) {
- .type => .{ .type = @enumFromInt(owner.index) },
- .nav => .{ .nav = @enumFromInt(owner.index) },
- };
- }
-
- fn wrap(raw: Unwrapped) Owner {
- return switch (raw) {
- .none => @bitCast(@as(u32, std.math.maxInt(u32))),
- .type => |ty| .{ .kind = .type, .index = @intCast(@intFromEnum(ty)) },
- .nav => |nav| .{ .kind = .nav, .index = @intCast(@intFromEnum(nav)) },
- };
- }
- };
+ comptime {
+ assert(std.meta.hasUniqueRepresentation(ComptimeUnit));
+ }
- pub const Index = enum(u32) {
+ pub const Id = enum(u32) {
_,
- pub const Optional = enum(u32) {
- none = std.math.maxInt(u32),
- _,
- pub fn unwrap(opt: Optional) ?Cau.Index {
- return switch (opt) {
- .none => null,
- _ => @enumFromInt(@intFromEnum(opt)),
- };
- }
-
- const debug_state = InternPool.debug_state;
- };
- pub fn toOptional(i: Cau.Index) Optional {
- return @enumFromInt(@intFromEnum(i));
- }
const Unwrapped = struct {
tid: Zcu.PerThread.Id,
index: u32,
-
- fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Cau.Index {
+ fn wrap(unwrapped: Unwrapped, ip: *const InternPool) ComptimeUnit.Id {
assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask());
- assert(unwrapped.index <= ip.getIndexMask(u31));
- return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_31 |
+ assert(unwrapped.index <= ip.getIndexMask(u32));
+ return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_32 |
unwrapped.index);
}
};
- fn unwrap(cau_index: Cau.Index, ip: *const InternPool) Unwrapped {
+ fn unwrap(id: Id, ip: *const InternPool) Unwrapped {
return .{
- .tid = @enumFromInt(@intFromEnum(cau_index) >> ip.tid_shift_31 & ip.getTidMask()),
- .index = @intFromEnum(cau_index) & ip.getIndexMask(u31),
+ .tid = @enumFromInt(@intFromEnum(id) >> ip.tid_shift_32 & ip.getTidMask()),
+ .index = @intFromEnum(id) & ip.getIndexMask(u31),
};
}
@@ -507,6 +460,11 @@ pub const Cau = struct {
/// * Generic instances have a `Nav` corresponding to the instantiated function.
/// * `@extern` calls create a `Nav` whose value is a `.@"extern"`.
///
+/// This data structure is optimized for the `analysis_info != null` case, because this is much more
+/// common in practice; the other case is used only for externs and for generic instances. At the time
+/// of writing, in the compiler itself, around 74% of all `Nav`s have `analysis_info != null`.
+/// (Specifically, 104225 / 140923)
+///
/// `Nav.Repr` is the in-memory representation.
pub const Nav = struct {
/// The unqualified name of this `Nav`. Namespace lookups use this name, and error messages may use it.
@@ -514,13 +472,16 @@ pub const Nav = struct {
name: NullTerminatedString,
/// The fully-qualified name of this `Nav`.
fqn: NullTerminatedString,
- /// If the value of this `Nav` is resolved by semantic analysis, it is within this `Cau`.
- /// If this is `.none`, then `status == .resolved` always.
- analysis_owner: Cau.Index.Optional,
+ /// This field is populated iff this `Nav` is resolved by semantic analysis.
+ /// If this is `null`, then `status == .resolved` always.
+ analysis: ?struct {
+ namespace: NamespaceIndex,
+ zir_index: TrackedInst.Index,
+ },
/// TODO: this is a hack! If #20663 isn't accepted, let's figure out something a bit better.
is_usingnamespace: bool,
status: union(enum) {
- /// This `Nav` is pending semantic analysis through `analysis_owner`.
+ /// This `Nav` is pending semantic analysis.
unresolved,
/// The value of this `Nav` is resolved.
resolved: struct {
@@ -544,17 +505,16 @@ pub const Nav = struct {
/// Get the ZIR instruction corresponding to this `Nav`, used to resolve source locations.
/// This is a `declaration`.
pub fn srcInst(nav: Nav, ip: *const InternPool) TrackedInst.Index {
- if (nav.analysis_owner.unwrap()) |cau| {
- return ip.getCau(cau).zir_index;
+ if (nav.analysis) |a| {
+ return a.zir_index;
}
- // A `Nav` with no corresponding `Cau` always has a resolved value.
+ // A `Nav` which does not undergo analysis always has a resolved value.
return switch (ip.indexToKey(nav.status.resolved.val)) {
.func => |func| {
- // Since there was no `analysis_owner`, this must be an instantiation.
- // Go up to the generic owner and consult *its* `analysis_owner`.
+ // Since `analysis` was not populated, this must be an instantiation.
+ // Go up to the generic owner and consult *its* `analysis` field.
const go_nav = ip.getNav(ip.indexToKey(func.generic_owner).func.owner_nav);
- const go_cau = ip.getCau(go_nav.analysis_owner.unwrap().?);
- return go_cau.zir_index;
+ return go_nav.analysis.?.zir_index;
},
.@"extern" => |@"extern"| @"extern".zir_index, // extern / @extern
else => unreachable,
@@ -600,11 +560,13 @@ pub const Nav = struct {
};
/// The compact in-memory representation of a `Nav`.
- /// 18 bytes.
+ /// 26 bytes.
const Repr = struct {
name: NullTerminatedString,
fqn: NullTerminatedString,
- analysis_owner: Cau.Index.Optional,
+ // The following 1 fields are either both populated, or both `.none`.
+ analysis_namespace: OptionalNamespaceIndex,
+ analysis_zir_index: TrackedInst.Index.Optional,
/// Populated only if `bits.status == .resolved`.
val: InternPool.Index,
/// Populated only if `bits.status == .resolved`.
@@ -625,7 +587,13 @@ pub const Nav = struct {
return .{
.name = repr.name,
.fqn = repr.fqn,
- .analysis_owner = repr.analysis_owner,
+ .analysis = if (repr.analysis_namespace.unwrap()) |namespace| .{
+ .namespace = namespace,
+ .zir_index = repr.analysis_zir_index.unwrap().?,
+ } else a: {
+ assert(repr.analysis_zir_index == .none);
+ break :a null;
+ },
.is_usingnamespace = repr.bits.is_usingnamespace,
.status = switch (repr.bits.status) {
.unresolved => .unresolved,
@@ -646,7 +614,8 @@ pub const Nav = struct {
return .{
.name = nav.name,
.fqn = nav.fqn,
- .analysis_owner = nav.analysis_owner,
+ .analysis_namespace = if (nav.analysis) |a| a.namespace.toOptional() else .none,
+ .analysis_zir_index = if (nav.analysis) |a| a.zir_index.toOptional() else .none,
.val = switch (nav.status) {
.unresolved => .none,
.resolved => |r| r.val,
@@ -862,8 +831,8 @@ const Local = struct {
tracked_insts: ListMutate,
files: ListMutate,
maps: ListMutate,
- caus: ListMutate,
navs: ListMutate,
+ comptime_units: ListMutate,
namespaces: BucketListMutate,
} align(std.atomic.cache_line),
@@ -876,8 +845,8 @@ const Local = struct {
tracked_insts: TrackedInsts,
files: List(File),
maps: Maps,
- caus: Caus,
navs: Navs,
+ comptime_units: ComptimeUnits,
namespaces: Namespaces,
@@ -899,8 +868,8 @@ const Local = struct {
const Strings = List(struct { u8 });
const TrackedInsts = List(struct { TrackedInst.MaybeLost });
const Maps = List(struct { FieldMap });
- const Caus = List(struct { Cau });
const Navs = List(Nav.Repr);
+ const ComptimeUnits = List(struct { ComptimeUnit });
const namespaces_bucket_width = 8;
const namespaces_bucket_mask = (1 << namespaces_bucket_width) - 1;
@@ -1275,21 +1244,21 @@ const Local = struct {
};
}
- pub fn getMutableCaus(local: *Local, gpa: Allocator) Caus.Mutable {
+ pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable {
return .{
.gpa = gpa,
.arena = &local.mutate.arena,
- .mutate = &local.mutate.caus,
- .list = &local.shared.caus,
+ .mutate = &local.mutate.navs,
+ .list = &local.shared.navs,
};
}
- pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable {
+ pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator) ComptimeUnits.Mutable {
return .{
.gpa = gpa,
.arena = &local.mutate.arena,
- .mutate = &local.mutate.navs,
- .list = &local.shared.navs,
+ .mutate = &local.mutate.comptime_units,
+ .list = &local.shared.comptime_units,
};
}
@@ -3052,8 +3021,6 @@ pub const LoadedUnionType = struct {
// TODO: the non-fqn will be needed by the new dwarf structure
/// The name of this union type.
name: NullTerminatedString,
- /// The `Cau` within which type resolution occurs.
- cau: Cau.Index,
/// Represents the declarations inside this union.
namespace: NamespaceIndex,
/// The enum tag type.
@@ -3370,7 +3337,6 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
.tid = unwrapped_index.tid,
.extra_index = data,
.name = type_union.data.name,
- .cau = type_union.data.cau,
.namespace = type_union.data.namespace,
.enum_tag_ty = type_union.data.tag_ty,
.field_types = field_types,
@@ -3387,8 +3353,6 @@ pub const LoadedStructType = struct {
// TODO: the non-fqn will be needed by the new dwarf structure
/// The name of this struct type.
name: NullTerminatedString,
- /// The `Cau` within which type resolution occurs.
- cau: Cau.Index,
namespace: NamespaceIndex,
/// Index of the `struct_decl` or `reify` ZIR instruction.
zir_index: TrackedInst.Index,
@@ -3979,7 +3943,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
switch (item.tag) {
.type_struct => {
const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]);
- const cau: Cau.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "cau").?]);
const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]);
const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);
const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "fields_len").?];
@@ -4066,7 +4029,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
.tid = unwrapped_index.tid,
.extra_index = item.data,
.name = name,
- .cau = cau,
.namespace = namespace,
.zir_index = zir_index,
.layout = if (flags.is_extern) .@"extern" else .auto,
@@ -4083,7 +4045,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
},
.type_struct_packed, .type_struct_packed_inits => {
const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]);
- const cau: Cau.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "cau").?]);
const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);
const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?];
const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]);
@@ -4130,7 +4091,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
.tid = unwrapped_index.tid,
.extra_index = item.data,
.name = name,
- .cau = cau,
.namespace = namespace,
.zir_index = zir_index,
.layout = .@"packed",
@@ -4153,9 +4113,6 @@ pub const LoadedEnumType = struct {
// TODO: the non-fqn will be needed by the new dwarf structure
/// The name of this enum type.
name: NullTerminatedString,
- /// The `Cau` within which type resolution occurs.
- /// `null` if this is a generated tag type.
- cau: Cau.Index.Optional,
/// Represents the declarations inside this enum.
namespace: NamespaceIndex,
/// An integer type which is used for the numerical value of the enum.
@@ -4232,21 +4189,15 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
.type_enum_auto => {
const extra = extraDataTrail(extra_list, EnumAuto, item.data);
var extra_index: u32 = @intCast(extra.end);
- const cau: Cau.Index.Optional = if (extra.data.zir_index == .none) cau: {
+ if (extra.data.zir_index == .none) {
extra_index += 1; // owner_union
- break :cau .none;
- } else cau: {
- const cau: Cau.Index = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);
- extra_index += 1; // cau
- break :cau cau.toOptional();
- };
+ }
const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {
extra_index += 2; // type_hash: PackedU64
break :c 0;
} else extra.data.captures_len;
return .{
.name = extra.data.name,
- .cau = cau,
.namespace = extra.data.namespace,
.tag_ty = extra.data.int_tag_type,
.names = .{
@@ -4272,21 +4223,15 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
};
const extra = extraDataTrail(extra_list, EnumExplicit, item.data);
var extra_index: u32 = @intCast(extra.end);
- const cau: Cau.Index.Optional = if (extra.data.zir_index == .none) cau: {
+ if (extra.data.zir_index == .none) {
extra_index += 1; // owner_union
- break :cau .none;
- } else cau: {
- const cau: Cau.Index = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);
- extra_index += 1; // cau
- break :cau cau.toOptional();
- };
+ }
const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {
extra_index += 2; // type_hash: PackedU64
break :c 0;
} else extra.data.captures_len;
return .{
.name = extra.data.name,
- .cau = cau,
.namespace = extra.data.namespace,
.tag_ty = extra.data.int_tag_type,
.names = .{
@@ -5256,7 +5201,6 @@ pub const Tag = enum(u8) {
.payload = EnumExplicit,
.trailing = struct {
owner_union: Index,
- cau: ?Cau.Index,
captures: ?[]CaptureValue,
type_hash: ?u64,
field_names: []NullTerminatedString,
@@ -5302,7 +5246,6 @@ pub const Tag = enum(u8) {
.payload = EnumAuto,
.trailing = struct {
owner_union: ?Index,
- cau: ?Cau.Index,
captures: ?[]CaptureValue,
type_hash: ?u64,
field_names: []NullTerminatedString,
@@ -5679,7 +5622,6 @@ pub const Tag = enum(u8) {
size: u32,
/// Only valid after .have_layout
padding: u32,
- cau: Cau.Index,
namespace: NamespaceIndex,
/// The enum that provides the list of field names and values.
tag_ty: Index,
@@ -5710,7 +5652,6 @@ pub const Tag = enum(u8) {
/// 5. init: Index for each fields_len // if tag is type_struct_packed_inits
pub const TypeStructPacked = struct {
name: NullTerminatedString,
- cau: Cau.Index,
zir_index: TrackedInst.Index,
fields_len: u32,
namespace: NamespaceIndex,
@@ -5758,7 +5699,6 @@ pub const Tag = enum(u8) {
/// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved
pub const TypeStruct = struct {
name: NullTerminatedString,
- cau: Cau.Index,
zir_index: TrackedInst.Index,
namespace: NamespaceIndex,
fields_len: u32,
@@ -6088,11 +6028,10 @@ pub const Array = struct {
/// Trailing:
/// 0. owner_union: Index // if `zir_index == .none`
-/// 1. cau: Cau.Index // if `zir_index != .none`
-/// 2. capture: CaptureValue // for each `captures_len`
-/// 3. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)
-/// 4. field name: NullTerminatedString for each fields_len; declaration order
-/// 5. tag value: Index for each fields_len; declaration order
+/// 1. capture: CaptureValue // for each `captures_len`
+/// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)
+/// 3. field name: NullTerminatedString for each fields_len; declaration order
+/// 4. tag value: Index for each fields_len; declaration order
pub const EnumExplicit = struct {
name: NullTerminatedString,
/// `std.math.maxInt(u32)` indicates this type is reified.
@@ -6115,10 +6054,9 @@ pub const EnumExplicit = struct {
/// Trailing:
/// 0. owner_union: Index // if `zir_index == .none`
-/// 1. cau: Cau.Index // if `zir_index != .none`
-/// 2. capture: CaptureValue // for each `captures_len`
-/// 3. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)
-/// 4. field name: NullTerminatedString for each fields_len; declaration order
+/// 1. capture: CaptureValue // for each `captures_len`
+/// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)
+/// 3. field name: NullTerminatedString for each fields_len; declaration order
pub const EnumAuto = struct {
name: NullTerminatedString,
/// `std.math.maxInt(u32)` indicates this type is reified.
@@ -6408,32 +6346,32 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
ip.locals = try gpa.alloc(Local, used_threads);
@memset(ip.locals, .{
.shared = .{
- .items = Local.List(Item).empty,
- .extra = Local.Extra.empty,
- .limbs = Local.Limbs.empty,
- .strings = Local.Strings.empty,
- .tracked_insts = Local.TrackedInsts.empty,
- .files = Local.List(File).empty,
- .maps = Local.Maps.empty,
- .caus = Local.Caus.empty,
- .navs = Local.Navs.empty,
-
- .namespaces = Local.Namespaces.empty,
+ .items = .empty,
+ .extra = .empty,
+ .limbs = .empty,
+ .strings = .empty,
+ .tracked_insts = .empty,
+ .files = .empty,
+ .maps = .empty,
+ .navs = .empty,
+ .comptime_units = .empty,
+
+ .namespaces = .empty,
},
.mutate = .{
.arena = .{},
- .items = Local.ListMutate.empty,
- .extra = Local.ListMutate.empty,
- .limbs = Local.ListMutate.empty,
- .strings = Local.ListMutate.empty,
- .tracked_insts = Local.ListMutate.empty,
- .files = Local.ListMutate.empty,
- .maps = Local.ListMutate.empty,
- .caus = Local.ListMutate.empty,
- .navs = Local.ListMutate.empty,
+ .items = .empty,
+ .extra = .empty,
+ .limbs = .empty,
+ .strings = .empty,
+ .tracked_insts = .empty,
+ .files = .empty,
+ .maps = .empty,
+ .navs = .empty,
+ .comptime_units = .empty,
- .namespaces = Local.BucketListMutate.empty,
+ .namespaces = .empty,
},
});
@@ -6506,7 +6444,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
namespace.priv_decls.deinit(gpa);
namespace.pub_usingnamespace.deinit(gpa);
namespace.priv_usingnamespace.deinit(gpa);
- namespace.other_decls.deinit(gpa);
+ namespace.comptime_decls.deinit(gpa);
+ namespace.test_decls.deinit(gpa);
}
};
const maps = local.getMutableMaps(gpa);
@@ -6525,8 +6464,6 @@ pub fn activate(ip: *const InternPool) void {
_ = OptionalString.debug_state;
_ = NullTerminatedString.debug_state;
_ = OptionalNullTerminatedString.debug_state;
- _ = Cau.Index.debug_state;
- _ = Cau.Index.Optional.debug_state;
_ = Nav.Index.debug_state;
_ = Nav.Index.Optional.debug_state;
std.debug.assert(debug_state.intern_pool == null);
@@ -6711,14 +6648,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
if (extra.data.captures_len == std.math.maxInt(u32)) {
break :ns .{ .reified = .{
.zir_index = zir_index,
- .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(),
+ .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
} };
}
break :ns .{ .declared = .{
.zir_index = zir_index,
.captures = .{ .owned = .{
.tid = unwrapped_index.tid,
- .start = extra.end + 1,
+ .start = extra.end,
.len = extra.data.captures_len,
} },
} };
@@ -6735,14 +6672,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
if (extra.data.captures_len == std.math.maxInt(u32)) {
break :ns .{ .reified = .{
.zir_index = zir_index,
- .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(),
+ .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
} };
}
break :ns .{ .declared = .{
.zir_index = zir_index,
.captures = .{ .owned = .{
.tid = unwrapped_index.tid,
- .start = extra.end + 1,
+ .start = extra.end,
.len = extra.data.captures_len,
} },
} };
@@ -8323,7 +8260,6 @@ pub fn getUnionType(
.size = std.math.maxInt(u32),
.padding = std.math.maxInt(u32),
.name = undefined, // set by `finish`
- .cau = undefined, // set by `finish`
.namespace = undefined, // set by `finish`
.tag_ty = ini.enum_tag_ty,
.zir_index = switch (ini.key) {
@@ -8375,7 +8311,6 @@ pub fn getUnionType(
.tid = tid,
.index = gop.put(),
.type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?,
- .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "cau").?,
.namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?,
} };
}
@@ -8384,7 +8319,6 @@ pub const WipNamespaceType = struct {
tid: Zcu.PerThread.Id,
index: Index,
type_name_extra_index: u32,
- cau_extra_index: ?u32,
namespace_extra_index: u32,
pub fn setName(
@@ -8400,18 +8334,11 @@ pub const WipNamespaceType = struct {
pub fn finish(
wip: WipNamespaceType,
ip: *InternPool,
- analysis_owner: Cau.Index.Optional,
namespace: NamespaceIndex,
) Index {
const extra = ip.getLocalShared(wip.tid).extra.acquire();
const extra_items = extra.view().items(.@"0");
- if (wip.cau_extra_index) |i| {
- extra_items[i] = @intFromEnum(analysis_owner.unwrap().?);
- } else {
- assert(analysis_owner == .none);
- }
-
extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);
return wip.index;
@@ -8510,7 +8437,6 @@ pub fn getStructType(
ini.fields_len); // inits
const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{
.name = undefined, // set by `finish`
- .cau = undefined, // set by `finish`
.zir_index = zir_index,
.fields_len = ini.fields_len,
.namespace = undefined, // set by `finish`
@@ -8555,7 +8481,6 @@ pub fn getStructType(
.tid = tid,
.index = gop.put(),
.type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?,
- .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "cau").?,
.namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?,
} };
},
@@ -8578,7 +8503,6 @@ pub fn getStructType(
1); // names_map
const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{
.name = undefined, // set by `finish`
- .cau = undefined, // set by `finish`
.zir_index = zir_index,
.namespace = undefined, // set by `finish`
.fields_len = ini.fields_len,
@@ -8647,7 +8571,6 @@ pub fn getStructType(
.tid = tid,
.index = gop.put(),
.type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?,
- .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "cau").?,
.namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?,
} };
}
@@ -9383,7 +9306,7 @@ fn finishFuncInstance(
func_extra_index: u32,
) Allocator.Error!void {
const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav);
- const fn_namespace = ip.getCau(fn_owner_nav.analysis_owner.unwrap().?).namespace;
+ const fn_namespace = fn_owner_nav.analysis.?.namespace;
// TODO: improve this name
const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{}__anon_{d}", .{
@@ -9429,7 +9352,6 @@ pub const WipEnumType = struct {
index: Index,
tag_ty_index: u32,
type_name_extra_index: u32,
- cau_extra_index: u32,
namespace_extra_index: u32,
names_map: MapIndex,
names_start: u32,
@@ -9449,13 +9371,11 @@ pub const WipEnumType = struct {
pub fn prepare(
wip: WipEnumType,
ip: *InternPool,
- analysis_owner: Cau.Index,
namespace: NamespaceIndex,
) void {
const extra = ip.getLocalShared(wip.tid).extra.acquire();
const extra_items = extra.view().items(.@"0");
- extra_items[wip.cau_extra_index] = @intFromEnum(analysis_owner);
extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);
}
@@ -9556,7 +9476,6 @@ pub fn getEnumType(
.reified => 2, // type_hash: PackedU64
} +
// zig fmt: on
- 1 + // cau
ini.fields_len); // field types
const extra_index = addExtraAssumeCapacity(extra, EnumAuto{
@@ -9577,8 +9496,6 @@ pub fn getEnumType(
.tag = .type_enum_auto,
.data = extra_index,
});
- const cau_extra_index = extra.view().len;
- extra.appendAssumeCapacity(undefined); // `cau` will be set by `finish`
switch (ini.key) {
.declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
.declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),
@@ -9591,7 +9508,6 @@ pub fn getEnumType(
.index = gop.put(),
.tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?,
.type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?,
- .cau_extra_index = @intCast(cau_extra_index),
.namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?,
.names_map = names_map,
.names_start = @intCast(names_start),
@@ -9616,7 +9532,6 @@ pub fn getEnumType(
.reified => 2, // type_hash: PackedU64
} +
// zig fmt: on
- 1 + // cau
ini.fields_len + // field types
ini.fields_len * @intFromBool(ini.has_values)); // field values
@@ -9643,8 +9558,6 @@ pub fn getEnumType(
},
.data = extra_index,
});
- const cau_extra_index = extra.view().len;
- extra.appendAssumeCapacity(undefined); // `cau` will be set by `finish`
switch (ini.key) {
.declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
.declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),
@@ -9661,7 +9574,6 @@ pub fn getEnumType(
.index = gop.put(),
.tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?,
.type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?,
- .cau_extra_index = @intCast(cau_extra_index),
.namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?,
.names_map = names_map,
.names_start = @intCast(names_start),
@@ -9858,7 +9770,6 @@ pub fn getOpaqueType(
.tid = tid,
.index = gop.put(),
.type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?,
- .cau_extra_index = null, // opaques do not undergo type resolution
.namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?,
},
};
@@ -9974,7 +9885,6 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 {
inline for (@typeInfo(@TypeOf(item)).@"struct".fields) |field| {
extra.appendAssumeCapacity(.{switch (field.type) {
Index,
- Cau.Index,
Nav.Index,
NamespaceIndex,
OptionalNamespaceIndex,
@@ -10037,7 +9947,6 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat
const extra_item = extra_items[extra_index];
@field(result, field.name) = switch (field.type) {
Index,
- Cau.Index,
Nav.Index,
NamespaceIndex,
OptionalNamespaceIndex,
@@ -11058,12 +10967,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
try bw.flush();
}
-pub fn getCau(ip: *const InternPool, index: Cau.Index) Cau {
- const unwrapped = index.unwrap(ip);
- const caus = ip.getLocalShared(unwrapped.tid).caus.acquire();
- return caus.view().items(.@"0")[unwrapped.index];
-}
-
pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {
const unwrapped = index.unwrap(ip);
const navs = ip.getLocalShared(unwrapped.tid).navs.acquire();
@@ -11077,51 +10980,34 @@ pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Names
return &namespaces_bucket[unwrapped_namespace_index.index];
}
-/// Create a `Cau` associated with the type at the given `InternPool.Index`.
-pub fn createTypeCau(
+/// Create a `ComptimeUnit`, forming an `AnalUnit` for a `comptime` declaration.
+pub fn createComptimeUnit(
ip: *InternPool,
gpa: Allocator,
tid: Zcu.PerThread.Id,
zir_index: TrackedInst.Index,
namespace: NamespaceIndex,
- owner_type: InternPool.Index,
-) Allocator.Error!Cau.Index {
- const caus = ip.getLocal(tid).getMutableCaus(gpa);
- const index_unwrapped: Cau.Index.Unwrapped = .{
+) Allocator.Error!ComptimeUnit.Id {
+ const comptime_units = ip.getLocal(tid).getMutableComptimeUnits(gpa);
+ const id_unwrapped: ComptimeUnit.Id.Unwrapped = .{
.tid = tid,
- .index = caus.mutate.len,
+ .index = comptime_units.mutate.len,
};
- try caus.append(.{.{
+ try comptime_units.append(.{.{
.zir_index = zir_index,
.namespace = namespace,
- .owner = Cau.Owner.wrap(.{ .type = owner_type }),
}});
- return index_unwrapped.wrap(ip);
+ return id_unwrapped.wrap(ip);
}
-/// Create a `Cau` for a `comptime` declaration.
-pub fn createComptimeCau(
- ip: *InternPool,
- gpa: Allocator,
- tid: Zcu.PerThread.Id,
- zir_index: TrackedInst.Index,
- namespace: NamespaceIndex,
-) Allocator.Error!Cau.Index {
- const caus = ip.getLocal(tid).getMutableCaus(gpa);
- const index_unwrapped: Cau.Index.Unwrapped = .{
- .tid = tid,
- .index = caus.mutate.len,
- };
- try caus.append(.{.{
- .zir_index = zir_index,
- .namespace = namespace,
- .owner = Cau.Owner.wrap(.none),
- }});
- return index_unwrapped.wrap(ip);
+pub fn getComptimeUnit(ip: *const InternPool, id: ComptimeUnit.Id) ComptimeUnit {
+ const unwrapped = id.unwrap(ip);
+ const comptime_units = ip.getLocalShared(unwrapped.tid).comptime_units.acquire();
+ return comptime_units.view().items(.@"0")[unwrapped.index];
}
-/// Create a `Nav` not associated with any `Cau`.
-/// Since there is no analysis owner, the `Nav`'s value must be known at creation time.
+/// Create a `Nav` which does not undergo semantic analysis.
+/// Since it is never analyzed, the `Nav`'s value must be known at creation time.
pub fn createNav(
ip: *InternPool,
gpa: Allocator,
@@ -11143,7 +11029,7 @@ pub fn createNav(
try navs.append(Nav.pack(.{
.name = opts.name,
.fqn = opts.fqn,
- .analysis_owner = .none,
+ .analysis = null,
.status = .{ .resolved = .{
.val = opts.val,
.alignment = opts.alignment,
@@ -11155,10 +11041,9 @@ pub fn createNav(
return index_unwrapped.wrap(ip);
}
-/// Create a `Cau` and `Nav` which are paired. The value of the `Nav` is
-/// determined by semantic analysis of the `Cau`. The value of the `Nav`
-/// is initially unresolved.
-pub fn createPairedCauNav(
+/// Create a `Nav` which undergoes semantic analysis because it corresponds to a source declaration.
+/// The value of the `Nav` is initially unresolved.
+pub fn createDeclNav(
ip: *InternPool,
gpa: Allocator,
tid: Zcu.PerThread.Id,
@@ -11168,36 +11053,28 @@ pub fn createPairedCauNav(
namespace: NamespaceIndex,
/// TODO: this is hacky! See `Nav.is_usingnamespace`.
is_usingnamespace: bool,
-) Allocator.Error!struct { Cau.Index, Nav.Index } {
- const caus = ip.getLocal(tid).getMutableCaus(gpa);
+) Allocator.Error!Nav.Index {
const navs = ip.getLocal(tid).getMutableNavs(gpa);
- try caus.ensureUnusedCapacity(1);
try navs.ensureUnusedCapacity(1);
- const cau = Cau.Index.Unwrapped.wrap(.{
- .tid = tid,
- .index = caus.mutate.len,
- }, ip);
const nav = Nav.Index.Unwrapped.wrap(.{
.tid = tid,
.index = navs.mutate.len,
}, ip);
- caus.appendAssumeCapacity(.{.{
- .zir_index = zir_index,
- .namespace = namespace,
- .owner = Cau.Owner.wrap(.{ .nav = nav }),
- }});
navs.appendAssumeCapacity(Nav.pack(.{
.name = name,
.fqn = fqn,
- .analysis_owner = cau.toOptional(),
+ .analysis = .{
+ .namespace = namespace,
+ .zir_index = zir_index,
+ },
.status = .unresolved,
.is_usingnamespace = is_usingnamespace,
}));
- return .{ cau, nav };
+ return nav;
}
/// Resolve the value of a `Nav` with an analysis owner.
@@ -11220,12 +11097,14 @@ pub fn resolveNavValue(
const navs = local.shared.navs.view();
- const nav_analysis_owners = navs.items(.analysis_owner);
+ const nav_analysis_namespace = navs.items(.analysis_namespace);
+ const nav_analysis_zir_index = navs.items(.analysis_zir_index);
const nav_vals = navs.items(.val);
const nav_linksections = navs.items(.@"linksection");
const nav_bits = navs.items(.bits);
- assert(nav_analysis_owners[unwrapped.index] != .none);
+ assert(nav_analysis_namespace[unwrapped.index] != .none);
+ assert(nav_analysis_zir_index[unwrapped.index] != .none);
@atomicStore(InternPool.Index, &nav_vals[unwrapped.index], resolved.val, .release);
@atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release);