diff options
Diffstat (limited to 'src/InternPool.zig')
| -rw-r--r-- | src/InternPool.zig | 691 |
1 files changed, 355 insertions, 336 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig index f923332f88..64cf95c7b2 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -34,6 +34,9 @@ src_hash_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index), /// Dependencies on the value of a Nav. /// Value is index into `dep_entries` of the first dependency on this Nav value. nav_val_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index), +/// Dependencies on the type of a Nav. +/// Value is index into `dep_entries` of the first dependency on this Nav value. +nav_ty_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index), /// Dependencies on an interned value, either: /// * a runtime function (invalidated when its IES changes) /// * a container type requiring resolution (invalidated when the type must be recreated at a new index) @@ -80,6 +83,7 @@ pub const empty: InternPool = .{ .file_deps = .empty, .src_hash_deps = .empty, .nav_val_deps = .empty, + .nav_ty_deps = .empty, .interned_deps = .empty, .namespace_deps = .empty, .namespace_name_deps = .empty, @@ -363,33 +367,56 @@ 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, + nav_ty, + 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 type of the given `Nav`. + nav_ty: 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 +427,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 +467,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,16 +479,31 @@ 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 type of this `Nav` is resolved; the value is queued for resolution. + type_resolved: struct { + type: InternPool.Index, + alignment: Alignment, + @"linksection": OptionalNullTerminatedString, + @"addrspace": std.builtin.AddressSpace, + is_const: bool, + is_threadlocal: bool, + /// This field is whether this `Nav` is a literal `extern` definition. + /// It does *not* tell you whether this might alias an extern fn (see #21027). + is_extern_decl: bool, + }, /// The value of this `Nav` is resolved. - resolved: struct { + fully_resolved: struct { val: InternPool.Index, alignment: Alignment, @"linksection": OptionalNullTerminatedString, @@ -531,30 +511,96 @@ pub const Nav = struct { }, }, - /// Asserts that `status == .resolved`. + /// Asserts that `status != .unresolved`. pub fn typeOf(nav: Nav, ip: *const InternPool) InternPool.Index { - return ip.typeOf(nav.status.resolved.val); + return switch (nav.status) { + .unresolved => unreachable, + .type_resolved => |r| r.type, + .fully_resolved => |r| ip.typeOf(r.val), + }; + } + + /// Always returns `null` for `status == .type_resolved`. This function is inteded + /// to be used by code generation, since semantic analysis will ensure that any `Nav` + /// which is potentially `extern` is fully resolved. + /// Asserts that `status != .unresolved`. + pub fn getExtern(nav: Nav, ip: *const InternPool) ?Key.Extern { + return switch (nav.status) { + .unresolved => unreachable, + .type_resolved => null, + .fully_resolved => |r| switch (ip.indexToKey(r.val)) { + .@"extern" => |e| e, + else => null, + }, + }; } - /// Asserts that `status == .resolved`. - pub fn isExtern(nav: Nav, ip: *const InternPool) bool { - return ip.indexToKey(nav.status.resolved.val) == .@"extern"; + /// Asserts that `status != .unresolved`. + pub fn getAddrspace(nav: Nav) std.builtin.AddressSpace { + return switch (nav.status) { + .unresolved => unreachable, + .type_resolved => |r| r.@"addrspace", + .fully_resolved => |r| r.@"addrspace", + }; + } + + /// Asserts that `status != .unresolved`. + pub fn getAlignment(nav: Nav) Alignment { + return switch (nav.status) { + .unresolved => unreachable, + .type_resolved => |r| r.alignment, + .fully_resolved => |r| r.alignment, + }; + } + + /// Asserts that `status != .unresolved`. + pub fn isThreadlocal(nav: Nav, ip: *const InternPool) bool { + return switch (nav.status) { + .unresolved => unreachable, + .type_resolved => |r| r.is_threadlocal, + .fully_resolved => |r| switch (ip.indexToKey(r.val)) { + .@"extern" => |e| e.is_threadlocal, + .variable => |v| v.is_threadlocal, + else => false, + }, + }; + } + + /// If this returns `true`, then a pointer to this `Nav` might actually be encoded as a pointer + /// to some other `Nav` due to an extern definition or extern alias (see #21027). + /// This query is valid on `Nav`s for whom only the type is resolved. + /// Asserts that `status != .unresolved`. + pub fn isExternOrFn(nav: Nav, ip: *const InternPool) bool { + return switch (nav.status) { + .unresolved => unreachable, + .type_resolved => |r| { + if (r.is_extern_decl) return true; + const tag = ip.zigTypeTagOrPoison(r.type) catch unreachable; + if (tag == .@"fn") return true; + return false; + }, + .fully_resolved => |r| { + if (ip.indexToKey(r.val) == .@"extern") return true; + const tag = ip.zigTypeTagOrPoison(ip.typeOf(r.val)) catch unreachable; + if (tag == .@"fn") return true; + return false; + }, + }; } /// 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. - return switch (ip.indexToKey(nav.status.resolved.val)) { + // A `Nav` which does not undergo analysis always has a resolved value. + return switch (ip.indexToKey(nav.status.fully_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,24 +646,29 @@ 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, - /// Populated only if `bits.status == .resolved`. - val: InternPool.Index, - /// Populated only if `bits.status == .resolved`. + // 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 != .unresolved`. + type_or_val: InternPool.Index, + /// Populated only if `bits.status != .unresolved`. @"linksection": OptionalNullTerminatedString, bits: Bits, const Bits = packed struct(u16) { - status: enum(u1) { unresolved, resolved }, - /// Populated only if `bits.status == .resolved`. + status: enum(u2) { unresolved, type_resolved, fully_resolved, type_resolved_extern_decl }, + /// Populated only if `bits.status != .unresolved`. alignment: Alignment, - /// Populated only if `bits.status == .resolved`. + /// Populated only if `bits.status != .unresolved`. @"addrspace": std.builtin.AddressSpace, - _: u3 = 0, + /// Populated only if `bits.status == .type_resolved`. + is_const: bool, + /// Populated only if `bits.status == .type_resolved`. + is_threadlocal: bool, is_usingnamespace: bool, }; @@ -625,12 +676,27 @@ 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, - .resolved => .{ .resolved = .{ - .val = repr.val, + .type_resolved, .type_resolved_extern_decl => .{ .type_resolved = .{ + .type = repr.type_or_val, + .alignment = repr.bits.alignment, + .@"linksection" = repr.@"linksection", + .@"addrspace" = repr.bits.@"addrspace", + .is_const = repr.bits.is_const, + .is_threadlocal = repr.bits.is_threadlocal, + .is_extern_decl = repr.bits.status == .type_resolved_extern_decl, + } }, + .fully_resolved => .{ .fully_resolved = .{ + .val = repr.type_or_val, .alignment = repr.bits.alignment, .@"linksection" = repr.@"linksection", .@"addrspace" = repr.bits.@"addrspace", @@ -646,14 +712,17 @@ pub const Nav = struct { return .{ .name = nav.name, .fqn = nav.fqn, - .analysis_owner = nav.analysis_owner, - .val = switch (nav.status) { + .analysis_namespace = if (nav.analysis) |a| a.namespace.toOptional() else .none, + .analysis_zir_index = if (nav.analysis) |a| a.zir_index.toOptional() else .none, + .type_or_val = switch (nav.status) { .unresolved => .none, - .resolved => |r| r.val, + .type_resolved => |r| r.type, + .fully_resolved => |r| r.val, }, .@"linksection" = switch (nav.status) { .unresolved => .none, - .resolved => |r| r.@"linksection", + .type_resolved => |r| r.@"linksection", + .fully_resolved => |r| r.@"linksection", }, .bits = switch (nav.status) { .unresolved => .{ @@ -661,12 +730,24 @@ pub const Nav = struct { .alignment = .none, .@"addrspace" = .generic, .is_usingnamespace = nav.is_usingnamespace, + .is_const = false, + .is_threadlocal = false, + }, + .type_resolved => |r| .{ + .status = if (r.is_extern_decl) .type_resolved_extern_decl else .type_resolved, + .alignment = r.alignment, + .@"addrspace" = r.@"addrspace", + .is_usingnamespace = nav.is_usingnamespace, + .is_const = r.is_const, + .is_threadlocal = r.is_threadlocal, }, - .resolved => |r| .{ - .status = .resolved, + .fully_resolved => |r| .{ + .status = .fully_resolved, .alignment = r.alignment, .@"addrspace" = r.@"addrspace", .is_usingnamespace = nav.is_usingnamespace, + .is_const = false, + .is_threadlocal = false, }, }, }; @@ -677,6 +758,7 @@ pub const Dependee = union(enum) { file: FileIndex, src_hash: TrackedInst.Index, nav_val: Nav.Index, + nav_ty: Nav.Index, interned: Index, namespace: TrackedInst.Index, namespace_name: NamespaceNameKey, @@ -726,6 +808,7 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI .file => |x| ip.file_deps.get(x), .src_hash => |x| ip.src_hash_deps.get(x), .nav_val => |x| ip.nav_val_deps.get(x), + .nav_ty => |x| ip.nav_ty_deps.get(x), .interned => |x| ip.interned_deps.get(x), .namespace => |x| ip.namespace_deps.get(x), .namespace_name => |x| ip.namespace_name_deps.get(x), @@ -763,6 +846,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend .file => ip.file_deps, .src_hash => ip.src_hash_deps, .nav_val => ip.nav_val_deps, + .nav_ty => ip.nav_ty_deps, .interned => ip.interned_deps, .namespace => ip.namespace_deps, .namespace_name => ip.namespace_name_deps, @@ -862,8 +946,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 +960,8 @@ const Local = struct { tracked_insts: TrackedInsts, files: List(File), maps: Maps, - caus: Caus, navs: Navs, + comptime_units: ComptimeUnits, namespaces: Namespaces, @@ -899,8 +983,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 +1359,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, }; } @@ -2018,7 +2102,6 @@ pub const Key = union(enum) { ty: Index, init: Index, owner_nav: Nav.Index, - lib_name: OptionalNullTerminatedString, is_threadlocal: bool, is_weak_linkage: bool, }; @@ -2111,36 +2194,36 @@ pub const Key = union(enum) { return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered); } - pub fn setAnalysisState(func: Func, ip: *InternPool, state: FuncAnalysis.State) void { + pub fn setCallsOrAwaitsErrorableFn(func: Func, ip: *InternPool, value: bool) void { const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; extra_mutex.lock(); defer extra_mutex.unlock(); const analysis_ptr = func.analysisPtr(ip); var analysis = analysis_ptr.*; - analysis.state = state; + analysis.calls_or_awaits_errorable_fn = value; @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); } - pub fn setCallsOrAwaitsErrorableFn(func: Func, ip: *InternPool, value: bool) void { + pub fn setBranchHint(func: Func, ip: *InternPool, hint: std.builtin.BranchHint) void { const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; extra_mutex.lock(); defer extra_mutex.unlock(); const analysis_ptr = func.analysisPtr(ip); var analysis = analysis_ptr.*; - analysis.calls_or_awaits_errorable_fn = value; + analysis.branch_hint = hint; @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); } - pub fn setBranchHint(func: Func, ip: *InternPool, hint: std.builtin.BranchHint) void { + pub fn setAnalyzed(func: Func, ip: *InternPool) void { const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; extra_mutex.lock(); defer extra_mutex.unlock(); const analysis_ptr = func.analysisPtr(ip); var analysis = analysis_ptr.*; - analysis.branch_hint = hint; + analysis.is_analyzed = true; @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); } @@ -2741,7 +2824,6 @@ pub const Key = union(enum) { return a_info.owner_nav == b_info.owner_nav and a_info.ty == b_info.ty and a_info.init == b_info.init and - a_info.lib_name == b_info.lib_name and a_info.is_threadlocal == b_info.is_threadlocal and a_info.is_weak_linkage == b_info.is_weak_linkage; }, @@ -3054,8 +3136,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. @@ -3372,7 +3452,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, @@ -3389,8 +3468,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, @@ -3981,7 +4058,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").?]; @@ -4068,7 +4144,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, @@ -4085,7 +4160,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").?]); @@ -4132,7 +4206,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", @@ -4155,9 +4228,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. @@ -4234,21 +4304,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 = .{ @@ -4274,21 +4338,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 = .{ @@ -5258,7 +5316,6 @@ pub const Tag = enum(u8) { .payload = EnumExplicit, .trailing = struct { owner_union: Index, - cau: ?Cau.Index, captures: ?[]CaptureValue, type_hash: ?u64, field_names: []NullTerminatedString, @@ -5304,7 +5361,6 @@ pub const Tag = enum(u8) { .payload = EnumAuto, .trailing = struct { owner_union: ?Index, - cau: ?Cau.Index, captures: ?[]CaptureValue, type_hash: ?u64, field_names: []NullTerminatedString, @@ -5573,9 +5629,6 @@ pub const Tag = enum(u8) { /// May be `none`. init: Index, owner_nav: Nav.Index, - /// Library name if specified. - /// For example `extern "c" var stderrp = ...` would have 'c' as library name. - lib_name: OptionalNullTerminatedString, flags: Flags, pub const Flags = packed struct(u32) { @@ -5684,7 +5737,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, @@ -5715,7 +5767,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, @@ -5763,7 +5814,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, @@ -5820,7 +5870,7 @@ pub const Tag = enum(u8) { /// equality or hashing, except for `inferred_error_set` which is considered /// to be part of the type of the function. pub const FuncAnalysis = packed struct(u32) { - state: State, + is_analyzed: bool, branch_hint: std.builtin.BranchHint, is_noinline: bool, calls_or_awaits_errorable_fn: bool, @@ -5828,20 +5878,7 @@ pub const FuncAnalysis = packed struct(u32) { inferred_error_set: bool, disable_instrumentation: bool, - _: u23 = 0, - - pub const State = enum(u2) { - /// The runtime function has never been referenced. - /// As such, it has never been analyzed, nor is it queued for analysis. - unreferenced, - /// The runtime function has been referenced, but has not yet been analyzed. - /// Its semantic analysis is queued. - queued, - /// The runtime function has been (or is currently being) semantically analyzed. - /// To know if analysis succeeded, consult `zcu.[transitive_]failed_analysis`. - /// To know if analysis is up-to-date, consult `zcu.[potentially_]outdated`. - analyzed, - }; + _: u24 = 0, }; pub const Bytes = struct { @@ -6093,11 +6130,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. @@ -6120,10 +6156,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. @@ -6413,32 +6448,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, }, }); @@ -6486,6 +6521,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { ip.file_deps.deinit(gpa); ip.src_hash_deps.deinit(gpa); ip.nav_val_deps.deinit(gpa); + ip.nav_ty_deps.deinit(gpa); ip.interned_deps.deinit(gpa); ip.namespace_deps.deinit(gpa); ip.namespace_name_deps.deinit(gpa); @@ -6511,7 +6547,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); @@ -6530,8 +6567,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); @@ -6716,14 +6751,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, } }, } }; @@ -6740,14 +6775,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, } }, } }; @@ -6928,7 +6963,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .ty = extra.ty, .init = extra.init, .owner_nav = extra.owner_nav, - .lib_name = extra.lib_name, .is_threadlocal = extra.flags.is_threadlocal, .is_weak_linkage = extra.flags.is_weak_linkage, } }; @@ -6944,8 +6978,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .is_threadlocal = extra.flags.is_threadlocal, .is_weak_linkage = extra.flags.is_weak_linkage, .is_dll_import = extra.flags.is_dll_import, - .alignment = nav.status.resolved.alignment, - .@"addrspace" = nav.status.resolved.@"addrspace", + .alignment = nav.status.fully_resolved.alignment, + .@"addrspace" = nav.status.fully_resolved.@"addrspace", .zir_index = extra.zir_index, .owner_nav = extra.owner_nav, } }; @@ -7575,7 +7609,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All .ty = variable.ty, .init = variable.init, .owner_nav = variable.owner_nav, - .lib_name = variable.lib_name, .flags = .{ .is_const = false, .is_threadlocal = variable.is_threadlocal, @@ -8330,7 +8363,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) { @@ -8382,7 +8414,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").?, } }; } @@ -8391,7 +8422,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( @@ -8407,18 +8437,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; @@ -8517,7 +8540,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` @@ -8562,7 +8584,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").?, } }; }, @@ -8585,7 +8606,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, @@ -8654,7 +8674,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").?, } }; } @@ -8878,7 +8897,7 @@ pub fn getFuncDecl( const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{ .analysis = .{ - .state = .unreferenced, + .is_analyzed = false, .branch_hint = .none, .is_noinline = key.is_noinline, .calls_or_awaits_errorable_fn = false, @@ -8987,7 +9006,7 @@ pub fn getFuncDeclIes( const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{ .analysis = .{ - .state = .unreferenced, + .is_analyzed = false, .branch_hint = .none, .is_noinline = key.is_noinline, .calls_or_awaits_errorable_fn = false, @@ -9183,7 +9202,7 @@ pub fn getFuncInstance( const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{ .analysis = .{ - .state = .unreferenced, + .is_analyzed = false, .branch_hint = .none, .is_noinline = arg.is_noinline, .calls_or_awaits_errorable_fn = false, @@ -9281,7 +9300,7 @@ pub fn getFuncInstanceIes( const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{ .analysis = .{ - .state = .unreferenced, + .is_analyzed = false, .branch_hint = .none, .is_noinline = arg.is_noinline, .calls_or_awaits_errorable_fn = false, @@ -9390,7 +9409,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}", .{ @@ -9400,9 +9419,9 @@ fn finishFuncInstance( .name = nav_name, .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, tid, nav_name), .val = func_index, - .alignment = fn_owner_nav.status.resolved.alignment, - .@"linksection" = fn_owner_nav.status.resolved.@"linksection", - .@"addrspace" = fn_owner_nav.status.resolved.@"addrspace", + .alignment = fn_owner_nav.status.fully_resolved.alignment, + .@"linksection" = fn_owner_nav.status.fully_resolved.@"linksection", + .@"addrspace" = fn_owner_nav.status.fully_resolved.@"addrspace", }); // Populate the owner_nav field which was left undefined until now. @@ -9436,7 +9455,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, @@ -9456,13 +9474,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); } @@ -9563,7 +9579,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{ @@ -9584,8 +9599,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))}), @@ -9598,7 +9611,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), @@ -9623,7 +9635,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 @@ -9650,8 +9661,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))}), @@ -9668,7 +9677,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), @@ -9865,7 +9873,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").?, }, }; @@ -9981,7 +9988,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, @@ -10044,7 +10050,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, @@ -11065,12 +11070,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(); @@ -11084,51 +11083,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, @@ -11150,8 +11132,8 @@ pub fn createNav( try navs.append(Nav.pack(.{ .name = opts.name, .fqn = opts.fqn, - .analysis_owner = .none, - .status = .{ .resolved = .{ + .analysis = null, + .status = .{ .fully_resolved = .{ .val = opts.val, .alignment = opts.alignment, .@"linksection" = opts.@"linksection", @@ -11162,10 +11144,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, @@ -11175,36 +11156,72 @@ 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 type of a `Nav` with an analysis owner. +/// If its status is already `resolved`, the old value is discarded. +pub fn resolveNavType( + ip: *InternPool, + nav: Nav.Index, + resolved: struct { + type: InternPool.Index, + alignment: Alignment, + @"linksection": OptionalNullTerminatedString, + @"addrspace": std.builtin.AddressSpace, + is_const: bool, + is_threadlocal: bool, + is_extern_decl: bool, + }, +) void { + const unwrapped = nav.unwrap(ip); + + const local = ip.getLocal(unwrapped.tid); + local.mutate.extra.mutex.lock(); + defer local.mutate.extra.mutex.unlock(); + + const navs = local.shared.navs.view(); + + const nav_analysis_namespace = navs.items(.analysis_namespace); + const nav_analysis_zir_index = navs.items(.analysis_zir_index); + const nav_types = navs.items(.type_or_val); + const nav_linksections = navs.items(.@"linksection"); + const nav_bits = navs.items(.bits); + + assert(nav_analysis_namespace[unwrapped.index] != .none); + assert(nav_analysis_zir_index[unwrapped.index] != .none); + + @atomicStore(InternPool.Index, &nav_types[unwrapped.index], resolved.type, .release); + @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release); + + var bits = nav_bits[unwrapped.index]; + bits.status = if (resolved.is_extern_decl) .type_resolved_extern_decl else .type_resolved; + bits.alignment = resolved.alignment; + bits.@"addrspace" = resolved.@"addrspace"; + bits.is_const = resolved.is_const; + bits.is_threadlocal = resolved.is_threadlocal; + @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release); } /// Resolve the value of a `Nav` with an analysis owner. @@ -11227,18 +11244,20 @@ pub fn resolveNavValue( const navs = local.shared.navs.view(); - const nav_analysis_owners = navs.items(.analysis_owner); - const nav_vals = navs.items(.val); + const nav_analysis_namespace = navs.items(.analysis_namespace); + const nav_analysis_zir_index = navs.items(.analysis_zir_index); + const nav_vals = navs.items(.type_or_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); var bits = nav_bits[unwrapped.index]; - bits.status = .resolved; + bits.status = .fully_resolved; bits.alignment = resolved.alignment; bits.@"addrspace" = resolved.@"addrspace"; @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release); |
