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.
This commit is contained in:
mlugg
2024-12-22 21:16:29 +00:00
parent 18362ebe13
commit 40aafcd6a8
7 changed files with 1082 additions and 1285 deletions

View File

@@ -348,12 +348,15 @@ const Job = union(enum) {
/// Corresponds to the task in `link.Task`.
/// Only needed for backends that haven't yet been updated to not race against Sema.
codegen_type: InternPool.Index,
/// The `Cau` must be semantically analyzed (and possibly export itself).
/// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.
/// This may be its first time being analyzed, or it may be outdated.
/// If the unit is a function, a `codegen_func` job will then be queued.
analyze_comptime_unit: InternPool.AnalUnit,
/// This function must be semantically analyzed.
/// This may be its first time being analyzed, or it may be outdated.
analyze_cau: InternPool.Cau.Index,
/// Analyze the body of a runtime function.
/// After analysis, a `codegen_func` job will be queued.
/// These must be separate jobs to ensure any needed type resolution occurs *before* codegen.
/// This job is separate from `analyze_comptime_unit` because it has a different priority.
analyze_func: InternPool.Index,
/// The main source file for the module needs to be analyzed.
analyze_mod: *Package.Module,
@@ -3141,8 +3144,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
}
const file_index = switch (anal_unit.unwrap()) {
.cau => |cau| zcu.namespacePtr(ip.getCau(cau).namespace).file_scope,
.func => |ip_index| (zcu.funcInfo(ip_index).zir_body_inst.resolveFull(ip) orelse continue).file,
.@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index.resolveFile(ip),
.nav_val => |nav| ip.getNav(nav).analysis.?.zir_index.resolveFile(ip),
.type => |ty| Type.fromInterned(ty).typeDeclInst(zcu).?.resolveFile(ip),
.func => |ip_index| zcu.funcInfo(ip_index).zir_body_inst.resolveFile(ip),
};
// Skip errors for AnalUnits within files that had a parse failure.
@@ -3374,11 +3379,9 @@ pub fn addModuleErrorMsg(
const rt_file_path = try src.file_scope.fullPath(gpa);
defer gpa.free(rt_file_path);
const name = switch (ref.referencer.unwrap()) {
.cau => |cau| switch (ip.getCau(cau).owner.unwrap()) {
.nav => |nav| ip.getNav(nav).name.toSlice(ip),
.type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
.none => "comptime",
},
.@"comptime" => "comptime",
.nav_val => |nav| ip.getNav(nav).name.toSlice(ip),
.type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
.func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
};
try ref_traces.append(gpa, .{
@@ -3641,10 +3644,13 @@ fn performAllTheWorkInner(
// If there's no work queued, check if there's anything outdated
// which we need to work on, and queue it if so.
if (try zcu.findOutdatedToAnalyze()) |outdated| {
switch (outdated.unwrap()) {
.cau => |cau| try comp.queueJob(.{ .analyze_cau = cau }),
.func => |func| try comp.queueJob(.{ .analyze_func = func }),
}
try comp.queueJob(switch (outdated.unwrap()) {
.func => |f| .{ .analyze_func = f },
.@"comptime",
.nav_val,
.type,
=> .{ .analyze_comptime_unit = outdated },
});
continue;
}
}
@@ -3667,8 +3673,8 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
.codegen_nav => |nav_index| {
const zcu = comp.zcu.?;
const nav = zcu.intern_pool.getNav(nav_index);
if (nav.analysis_owner.unwrap()) |cau| {
const unit = InternPool.AnalUnit.wrap(.{ .cau = cau });
if (nav.analysis != null) {
const unit: InternPool.AnalUnit = .wrap(.{ .nav_val = nav_index });
if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) {
return;
}
@@ -3688,36 +3694,47 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
defer pt.deactivate();
pt.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
pt.ensureFuncBodyUpToDate(func) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
error.AnalysisFail => return,
};
},
.analyze_cau => |cau_index| {
.analyze_comptime_unit => |unit| {
const named_frame = tracy.namedFrame("analyze_comptime_unit");
defer named_frame.end();
const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
defer pt.deactivate();
pt.ensureCauAnalyzed(cau_index) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) {
.@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu),
.nav_val => |nav| pt.ensureNavValUpToDate(nav),
.type => |ty| if (pt.ensureTypeUpToDate(ty)) |_| {} else |err| err,
.func => unreachable,
};
maybe_err catch |err| switch (err) {
error.OutOfMemory => |e| return e,
error.AnalysisFail => return,
};
queue_test_analysis: {
if (!comp.config.is_test) break :queue_test_analysis;
const nav = switch (unit.unwrap()) {
.nav_val => |nav| nav,
else => break :queue_test_analysis,
};
// Check if this is a test function.
const ip = &pt.zcu.intern_pool;
const cau = ip.getCau(cau_index);
const nav_index = switch (cau.owner.unwrap()) {
.none, .type => break :queue_test_analysis,
.nav => |nav| nav,
};
if (!pt.zcu.test_functions.contains(nav_index)) {
if (!pt.zcu.test_functions.contains(nav)) {
break :queue_test_analysis;
}
// Tests are always emitted in test binaries. The decl_refs are created by
// Zcu.populateTestFunctions, but this will not queue body analysis, so do
// that now.
try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav_index).status.resolved.val);
try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav).status.resolved.val);
}
},
.resolve_type_fully => |ty| {

View File

@@ -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,
comptime {
assert(std.meta.hasUniqueRepresentation(ComptimeUnit));
}
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)) },
};
}
};
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,15 +1244,6 @@ const Local = struct {
};
}
pub fn getMutableCaus(local: *Local, gpa: Allocator) Caus.Mutable {
return .{
.gpa = gpa,
.arena = &local.mutate.arena,
.mutate = &local.mutate.caus,
.list = &local.shared.caus,
};
}
pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable {
return .{
.gpa = gpa,
@@ -1293,6 +1253,15 @@ const Local = struct {
};
}
pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator) ComptimeUnits.Mutable {
return .{
.gpa = gpa,
.arena = &local.mutate.arena,
.mutate = &local.mutate.comptime_units,
.list = &local.shared.comptime_units,
};
}
/// Rather than allocating Namespace objects with an Allocator, we instead allocate
/// them with this BucketList. This provides four advantages:
/// * Stable memory so that one thread can access a Namespace object while another
@@ -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,
.items = .empty,
.extra = .empty,
.limbs = .empty,
.strings = .empty,
.tracked_insts = .empty,
.files = .empty,
.maps = .empty,
.navs = .empty,
.comptime_units = .empty,
.namespaces = Local.Namespaces.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);

View File

@@ -2870,7 +2870,7 @@ fn zirStructDecl(
};
const wip_ty = switch (try ip.getStructType(gpa, pt.tid, struct_init, false)) {
.existing => |ty| {
const new_ty = try pt.ensureTypeUpToDate(ty, false);
const new_ty = try pt.ensureTypeUpToDate(ty);
// Make sure we update the namespace if the declaration is re-analyzed, to pick
// up on e.g. changed comptime decls.
@@ -2900,12 +2900,10 @@ fn zirStructDecl(
});
errdefer pt.destroyNamespace(new_namespace_index);
const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
if (pt.zcu.comp.incremental) {
try ip.addDependency(
sema.gpa,
AnalUnit.wrap(.{ .cau = new_cau_index }),
AnalUnit.wrap(.{ .type = wip_ty.index }),
.{ .src_hash = tracked_inst },
);
}
@@ -2922,7 +2920,7 @@ fn zirStructDecl(
}
try sema.declareDependency(.{ .interned = wip_ty.index });
try sema.addTypeReferenceEntry(src, wip_ty.index);
return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));
return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
}
fn createTypeName(
@@ -3100,7 +3098,7 @@ fn zirEnumDecl(
};
const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, enum_init, false)) {
.existing => |ty| {
const new_ty = try pt.ensureTypeUpToDate(ty, false);
const new_ty = try pt.ensureTypeUpToDate(ty);
// Make sure we update the namespace if the declaration is re-analyzed, to pick
// up on e.g. changed comptime decls.
@@ -3136,16 +3134,14 @@ fn zirEnumDecl(
});
errdefer if (!done) pt.destroyNamespace(new_namespace_index);
const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
try pt.scanNamespace(new_namespace_index, decls);
try sema.declareDependency(.{ .interned = wip_ty.index });
try sema.addTypeReferenceEntry(src, wip_ty.index);
// We've finished the initial construction of this type, and are about to perform analysis.
// Set the Cau and namespace appropriately, and don't destroy anything on failure.
wip_ty.prepare(ip, new_cau_index, new_namespace_index);
// Set the namespace appropriately, and don't destroy anything on failure.
wip_ty.prepare(ip, new_namespace_index);
done = true;
try Sema.resolveDeclaredEnum(
@@ -3155,7 +3151,6 @@ fn zirEnumDecl(
tracked_inst,
new_namespace_index,
type_name,
new_cau_index,
small,
body,
tag_type_ref,
@@ -3245,7 +3240,7 @@ fn zirUnionDecl(
};
const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, union_init, false)) {
.existing => |ty| {
const new_ty = try pt.ensureTypeUpToDate(ty, false);
const new_ty = try pt.ensureTypeUpToDate(ty);
// Make sure we update the namespace if the declaration is re-analyzed, to pick
// up on e.g. changed comptime decls.
@@ -3275,12 +3270,10 @@ fn zirUnionDecl(
});
errdefer pt.destroyNamespace(new_namespace_index);
const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
if (pt.zcu.comp.incremental) {
try zcu.intern_pool.addDependency(
gpa,
AnalUnit.wrap(.{ .cau = new_cau_index }),
AnalUnit.wrap(.{ .type = wip_ty.index }),
.{ .src_hash = tracked_inst },
);
}
@@ -3297,7 +3290,7 @@ fn zirUnionDecl(
}
try sema.declareDependency(.{ .interned = wip_ty.index });
try sema.addTypeReferenceEntry(src, wip_ty.index);
return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));
return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
}
fn zirOpaqueDecl(
@@ -3382,7 +3375,7 @@ fn zirOpaqueDecl(
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
}
try sema.addTypeReferenceEntry(src, wip_ty.index);
return Air.internedToRef(wip_ty.finish(ip, .none, new_namespace_index));
return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
}
fn zirErrorSetDecl(
@@ -6547,7 +6540,10 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
const ip = &zcu.intern_pool;
const func = switch (sema.owner.unwrap()) {
.func => |func| func,
.cau => return, // does nothing outside a function
.@"comptime",
.nav_val,
.type,
=> return, // does nothing outside a function
};
ip.funcSetDisableInstrumentation(func);
sema.allow_memoize = false;
@@ -6868,11 +6864,8 @@ fn lookupInNamespace(
ignore_self: {
const skip_nav = switch (sema.owner.unwrap()) {
.func => break :ignore_self,
.cau => |cau| switch (ip.getCau(cau).owner.unwrap()) {
.none, .type => break :ignore_self,
.nav => |nav| nav,
},
.@"comptime", .type, .func => break :ignore_self,
.nav_val => |nav| nav,
};
var i: usize = 0;
while (i < candidates.items.len) {
@@ -7132,7 +7125,7 @@ fn zirCall(
const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);
switch (sema.owner.unwrap()) {
.cau => input_is_error = false,
.@"comptime", .type, .nav_val => input_is_error = false,
.func => |owner_func| if (!zcu.intern_pool.funcAnalysisUnordered(owner_func).calls_or_awaits_errorable_fn) {
// No errorable fn actually called; we have no error return trace
input_is_error = false;
@@ -7747,11 +7740,9 @@ fn analyzeCall(
// The call site definitely depends on the function's signature.
try sema.declareDependency(.{ .src_hash = module_fn.zir_body_inst });
// This is not a function instance, so the function's `Nav` has a
// `Cau` -- we don't need to check `generic_owner`.
// This is not a function instance, so the function's `Nav` has analysis
// state -- we don't need to check `generic_owner`.
const fn_nav = ip.getNav(module_fn.owner_nav);
const fn_cau_index = fn_nav.analysis_owner.unwrap().?;
const fn_cau = ip.getCau(fn_cau_index);
// We effectively want a child Sema here, but can't literally do that, because we need AIR
// to be shared. InlineCallSema is a wrapper which handles this for us. While `ics` is in
@@ -7759,7 +7750,7 @@ fn analyzeCall(
// whenever performing an operation where the difference matters.
var ics = InlineCallSema.init(
sema,
zcu.cauFileScope(fn_cau_index).zir,
zcu.navFileScope(module_fn.owner_nav).zir,
module_fn_index,
block.error_return_trace_index,
);
@@ -7769,7 +7760,7 @@ fn analyzeCall(
.parent = null,
.sema = sema,
// The function body exists in the same namespace as the corresponding function declaration.
.namespace = fn_cau.namespace,
.namespace = fn_nav.analysis.?.namespace,
.instructions = .{},
.label = null,
.inlining = &inlining,
@@ -7780,7 +7771,7 @@ fn analyzeCall(
.runtime_cond = block.runtime_cond,
.runtime_loop = block.runtime_loop,
.runtime_index = block.runtime_index,
.src_base_inst = fn_cau.zir_index,
.src_base_inst = fn_nav.analysis.?.zir_index,
.type_name_ctx = fn_nav.fqn,
};
@@ -7795,7 +7786,7 @@ fn analyzeCall(
// mutate comptime state.
// TODO: comptime call memoization is currently not supported under incremental compilation
// since dependencies are not marked on callers. If we want to keep this around (we should
// check that it's worthwhile first!), each memoized call needs a `Cau`.
// check that it's worthwhile first!), each memoized call needs an `AnalUnit`.
var should_memoize = !zcu.comp.incremental;
// If it's a comptime function call, we need to memoize it as long as no external
@@ -7904,7 +7895,7 @@ fn analyzeCall(
// Since we're doing an inline call, we depend on the source code of the whole
// function declaration.
try sema.declareDependency(.{ .src_hash = fn_cau.zir_index });
try sema.declareDependency(.{ .src_hash = fn_nav.analysis.?.zir_index });
new_fn_info.return_type = sema.fn_ret_ty.toIntern();
if (!is_comptime_call and !block.is_typeof) {
@@ -8016,7 +8007,7 @@ fn analyzeCall(
if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
switch (sema.owner.unwrap()) {
.cau => {},
.@"comptime", .nav_val, .type => {},
.func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {
ip.funcSetCallsOrAwaitsErrorableFn(owner_func);
},
@@ -8268,10 +8259,9 @@ fn instantiateGenericCall(
// The actual monomorphization happens via adding `func_instance` to
// `InternPool`.
// Since we are looking at the generic owner here, it has a `Cau`.
// Since we are looking at the generic owner here, it has analysis state.
const fn_nav = ip.getNav(generic_owner_func.owner_nav);
const fn_cau = ip.getCau(fn_nav.analysis_owner.unwrap().?);
const fn_zir = zcu.namespacePtr(fn_cau.namespace).fileScope(zcu).zir;
const fn_zir = zcu.navFileScope(generic_owner_func.owner_nav).zir;
const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst.resolve(ip) orelse return error.AnalysisFail);
const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());
@@ -8312,11 +8302,11 @@ fn instantiateGenericCall(
var child_block: Block = .{
.parent = null,
.sema = &child_sema,
.namespace = fn_cau.namespace,
.namespace = fn_nav.analysis.?.namespace,
.instructions = .{},
.inlining = null,
.is_comptime = true,
.src_base_inst = fn_cau.zir_index,
.src_base_inst = fn_nav.analysis.?.zir_index,
.type_name_ctx = fn_nav.fqn,
};
defer child_block.instructions.deinit(gpa);
@@ -8481,7 +8471,7 @@ fn instantiateGenericCall(
if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
switch (sema.owner.unwrap()) {
.cau => {},
.@"comptime", .nav_val, .type => {},
.func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {
ip.funcSetCallsOrAwaitsErrorableFn(owner_func);
},
@@ -9510,14 +9500,11 @@ fn zirFunc(
// the callconv based on whether it is exported. Otherwise, the callconv defaults
// to `.auto`.
const cc: std.builtin.CallingConvention = if (has_body) cc: {
const func_decl_cau = if (sema.generic_owner != .none) cau: {
const generic_owner_fn = zcu.funcInfo(sema.generic_owner);
// The generic owner definitely has a `Cau` for the corresponding function declaration.
const generic_owner_nav = ip.getNav(generic_owner_fn.owner_nav);
break :cau generic_owner_nav.analysis_owner.unwrap().?;
} else sema.owner.unwrap().cau;
const func_decl_nav = if (sema.generic_owner != .none) nav: {
break :nav zcu.funcInfo(sema.generic_owner).owner_nav;
} else sema.owner.unwrap().nav_val;
const fn_is_exported = exported: {
const decl_inst = ip.getCau(func_decl_cau).zir_index.resolve(ip) orelse return error.AnalysisFail;
const decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(ip) orelse return error.AnalysisFail;
const zir_decl = sema.code.getDeclaration(decl_inst);
break :exported zir_decl.linkage == .@"export";
};
@@ -9991,7 +9978,7 @@ fn funcCommon(
if (!ret_poison)
try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
const func_index = try ip.getFuncDeclIes(gpa, pt.tid, .{
.owner_nav = sema.getOwnerCauNav(),
.owner_nav = sema.owner.unwrap().nav_val,
.param_types = param_types,
.noalias_bits = noalias_bits,
@@ -10040,7 +10027,7 @@ fn funcCommon(
if (has_body) {
const func_index = try ip.getFuncDecl(gpa, pt.tid, .{
.owner_nav = sema.getOwnerCauNav(),
.owner_nav = sema.owner.unwrap().nav_val,
.ty = func_ty,
.cc = cc,
.is_noinline = is_noinline,
@@ -17664,7 +17651,7 @@ fn zirAsm(
if (is_volatile) {
return sema.fail(block, src, "volatile keyword is redundant on module-level assembly", .{});
}
try zcu.addGlobalAssembly(sema.owner.unwrap().cau, asm_source);
try zcu.addGlobalAssembly(sema.owner, asm_source);
return .void_value;
}
@@ -18155,7 +18142,7 @@ fn zirThis(
_ = extended;
const pt = sema.pt;
const namespace = pt.zcu.namespacePtr(block.namespace);
const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type, false);
const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type);
switch (pt.zcu.intern_pool.indexToKey(new_ty)) {
.struct_type, .union_type, .enum_type => try sema.declareDependency(.{ .interned = new_ty }),
.opaque_type => {},
@@ -19321,10 +19308,8 @@ fn typeInfoNamespaceDecls(
}
for (namespace.pub_usingnamespace.items) |nav| {
if (ip.getNav(nav).analysis_owner.unwrap()) |cau| {
if (zcu.analysis_in_progress.contains(AnalUnit.wrap(.{ .cau = cau }))) {
continue;
}
if (zcu.analysis_in_progress.contains(.wrap(.{ .nav_val = nav }))) {
continue;
}
try sema.ensureNavResolved(src, nav);
const namespace_ty = Type.fromInterned(ip.getNav(nav).status.resolved.val);
@@ -21187,14 +21172,13 @@ fn structInitAnon(
.file_scope = block.getFileScopeIndex(zcu),
.generation = zcu.generation,
});
const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip.index);
try zcu.comp.queueJob(.{ .resolve_type_fully = wip.index });
codegen_type: {
if (zcu.comp.config.use_llvm) break :codegen_type;
if (block.ownerModule().strip) break :codegen_type;
try zcu.comp.queueJob(.{ .codegen_type = wip.index });
}
break :ty wip.finish(ip, new_cau_index.toOptional(), new_namespace_index);
break :ty wip.finish(ip, new_namespace_index);
},
.existing => |ty| ty,
};
@@ -21618,7 +21602,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
.func => |func| if (ip.funcAnalysisUnordered(func).calls_or_awaits_errorable_fn and block.ownerModule().error_tracing) {
return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
},
.cau => {},
.@"comptime", .nav_val, .type => {},
}
return Air.internedToRef(try pt.intern(.{ .opt = .{
.ty = opt_ptr_stack_trace_ty.toIntern(),
@@ -22296,7 +22280,7 @@ fn zirReify(
});
try sema.addTypeReferenceEntry(src, wip_ty.index);
return Air.internedToRef(wip_ty.finish(ip, .none, new_namespace_index));
return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
},
.@"union" => {
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
@@ -22505,11 +22489,9 @@ fn reifyEnum(
.generation = zcu.generation,
});
const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
try sema.declareDependency(.{ .interned = wip_ty.index });
try sema.addTypeReferenceEntry(src, wip_ty.index);
wip_ty.prepare(ip, new_cau_index, new_namespace_index);
wip_ty.prepare(ip, new_namespace_index);
wip_ty.setTagTy(ip, tag_ty.toIntern());
done = true;
@@ -22811,8 +22793,6 @@ fn reifyUnion(
.generation = zcu.generation,
});
const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
codegen_type: {
if (zcu.comp.config.use_llvm) break :codegen_type;
@@ -22822,7 +22802,7 @@ fn reifyUnion(
}
try sema.declareDependency(.{ .interned = wip_ty.index });
try sema.addTypeReferenceEntry(src, wip_ty.index);
return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));
return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
}
fn reifyTuple(
@@ -23170,8 +23150,6 @@ fn reifyStruct(
.generation = zcu.generation,
});
const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
codegen_type: {
if (zcu.comp.config.use_llvm) break :codegen_type;
@@ -23181,7 +23159,7 @@ fn reifyStruct(
}
try sema.declareDependency(.{ .interned = wip_ty.index });
try sema.addTypeReferenceEntry(src, wip_ty.index);
return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));
return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
}
fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {
@@ -26713,15 +26691,13 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val);
} else cc: {
if (has_body) {
const decl_inst = if (sema.generic_owner != .none) decl_inst: {
const func_decl_nav = if (sema.generic_owner != .none) nav: {
// Generic instance -- use the original function declaration to
// look for the `export` syntax.
const nav = zcu.intern_pool.getNav(zcu.funcInfo(sema.generic_owner).owner_nav);
const cau = zcu.intern_pool.getCau(nav.analysis_owner.unwrap().?);
break :decl_inst cau.zir_index;
} else sema.getOwnerCauDeclInst(); // not an instantiation so we're analyzing a function declaration Cau
const zir_decl = sema.code.getDeclaration(decl_inst.resolve(&zcu.intern_pool) orelse return error.AnalysisFail);
break :nav zcu.funcInfo(sema.generic_owner).owner_nav;
} else sema.owner.unwrap().nav_val;
const func_decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(&zcu.intern_pool) orelse return error.AnalysisFail;
const zir_decl = sema.code.getDeclaration(func_decl_inst);
if (zir_decl.linkage == .@"export") {
break :cc target.cCallingConvention() orelse {
// This target has no default C calling convention. We sometimes trigger a similar
@@ -27108,8 +27084,16 @@ fn zirBuiltinExtern(
// `builtin_extern` doesn't provide enough information, and isn't currently tracked.
// So, for now, just use our containing `declaration`.
.zir_index = switch (sema.owner.unwrap()) {
.cau => sema.getOwnerCauDeclInst(),
.func => sema.getOwnerFuncDeclInst(),
.@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index,
.type => |owner_ty| Type.fromInterned(owner_ty).typeDeclInst(zcu).?,
.nav_val => |nav| ip.getNav(nav).analysis.?.zir_index,
.func => |func| zir_index: {
const func_info = zcu.funcInfo(func);
const owner_func_info = if (func_info.generic_owner != .none) owner: {
break :owner zcu.funcInfo(func_info.generic_owner);
} else func_info;
break :zir_index ip.getNav(owner_func_info.owner_nav).analysis.?.zir_index;
},
},
.owner_nav = undefined, // ignored by `getExtern`
});
@@ -32670,28 +32654,25 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
const cau_index = nav.analysis_owner.unwrap() orelse {
if (nav.analysis == null) {
assert(nav.status == .resolved);
return;
};
}
// Note that even if `nav.status == .resolved`, we must still trigger `ensureCauAnalyzed`
// Note that even if `nav.status == .resolved`, we must still trigger `ensureNavValUpToDate`
// to make sure the value is up-to-date on incremental updates.
assert(ip.getCau(cau_index).owner.unwrap().nav == nav_index);
const anal_unit = AnalUnit.wrap(.{ .cau = cau_index });
const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_index });
try sema.addReferenceEntry(src, anal_unit);
if (zcu.analysis_in_progress.contains(anal_unit)) {
return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{
.base_node_inst = ip.getCau(cau_index).zir_index,
.base_node_inst = nav.analysis.?.zir_index,
.offset = LazySrcLoc.Offset.nodeOffset(0),
}, "dependency loop detected", .{}));
}
return pt.ensureCauAnalyzed(cau_index);
return pt.ensureNavValUpToDate(nav_index);
}
fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
@@ -35641,7 +35622,7 @@ pub fn resolveStructAlignment(
const ip = &zcu.intern_pool;
const target = zcu.getTarget();
assert(sema.owner.unwrap().cau == struct_type.cau);
assert(sema.owner.unwrap().type == ty);
assert(struct_type.layout != .@"packed");
assert(struct_type.flagsUnordered(ip).alignment == .none);
@@ -35684,7 +35665,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
const ip = &zcu.intern_pool;
const struct_type = zcu.typeToStruct(ty) orelse return;
assert(sema.owner.unwrap().cau == struct_type.cau);
assert(sema.owner.unwrap().type == ty.toIntern());
if (struct_type.haveLayout(ip))
return;
@@ -35831,15 +35812,13 @@ fn backingIntType(
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const cau_index = struct_type.cau;
var analysis_arena = std.heap.ArenaAllocator.init(gpa);
defer analysis_arena.deinit();
var block: Block = .{
.parent = null,
.sema = sema,
.namespace = ip.getCau(cau_index).namespace,
.namespace = struct_type.namespace,
.instructions = .{},
.inlining = null,
.is_comptime = true,
@@ -35971,7 +35950,7 @@ pub fn resolveUnionAlignment(
const ip = &zcu.intern_pool;
const target = zcu.getTarget();
assert(sema.owner.unwrap().cau == union_type.cau);
assert(sema.owner.unwrap().type == ty.toIntern());
assert(!union_type.haveLayout(ip));
@@ -36011,7 +35990,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
// Load again, since the tag type might have changed due to resolution.
const union_type = ip.loadUnionType(ty.ip_index);
assert(sema.owner.unwrap().cau == union_type.cau);
assert(sema.owner.unwrap().type == ty.toIntern());
const old_flags = union_type.flagsUnordered(ip);
switch (old_flags.status) {
@@ -36126,7 +36105,7 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {
const ip = &zcu.intern_pool;
const struct_type = zcu.typeToStruct(ty).?;
assert(sema.owner.unwrap().cau == struct_type.cau);
assert(sema.owner.unwrap().type == ty.toIntern());
if (struct_type.setFullyResolved(ip)) return;
errdefer struct_type.clearFullyResolved(ip);
@@ -36149,7 +36128,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {
const ip = &zcu.intern_pool;
const union_obj = zcu.typeToUnion(ty).?;
assert(sema.owner.unwrap().cau == union_obj.cau);
assert(sema.owner.unwrap().type == ty.toIntern());
switch (union_obj.flagsUnordered(ip).status) {
.none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
@@ -36184,7 +36163,7 @@ pub fn resolveStructFieldTypes(
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
assert(sema.owner.unwrap().cau == struct_type.cau);
assert(sema.owner.unwrap().type == ty);
if (struct_type.haveFieldTypes(ip)) return;
@@ -36210,7 +36189,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
const ip = &zcu.intern_pool;
const struct_type = zcu.typeToStruct(ty) orelse return;
assert(sema.owner.unwrap().cau == struct_type.cau);
assert(sema.owner.unwrap().type == ty.toIntern());
// Inits can start as resolved
if (struct_type.haveFieldInits(ip)) return;
@@ -36239,7 +36218,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
assert(sema.owner.unwrap().cau == union_type.cau);
assert(sema.owner.unwrap().type == ty.toIntern());
switch (union_type.flagsUnordered(ip).status) {
.none => {},
@@ -36315,7 +36294,7 @@ fn resolveInferredErrorSet(
// In this case we are dealing with the actual InferredErrorSet object that
// corresponds to the function, not one created to track an inline/comptime call.
try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = func_index }));
try pt.ensureFuncBodyAnalyzed(func_index);
try pt.ensureFuncBodyUpToDate(func_index);
}
// This will now have been resolved by the logic at the end of `Zcu.analyzeFnBody`
@@ -36472,8 +36451,7 @@ fn structFields(
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const cau_index = struct_type.cau;
const namespace_index = ip.getCau(cau_index).namespace;
const namespace_index = struct_type.namespace;
const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;
const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
@@ -36671,8 +36649,7 @@ fn structFieldInits(
assert(!struct_type.haveFieldInits(ip));
const cau_index = struct_type.cau;
const namespace_index = ip.getCau(cau_index).namespace;
const namespace_index = struct_type.namespace;
const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;
const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
const fields_len, _, var extra_index = structZirInfo(zir, zir_index);
@@ -38474,13 +38451,11 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {
// just result in over-analysis since `Zcu.findOutdatedToAnalyze` would never be able to resolve
// the loop.
switch (sema.owner.unwrap()) {
.cau => |cau| switch (dependee) {
.nav_val => |nav| if (zcu.intern_pool.getNav(nav).analysis_owner == cau.toOptional()) {
return;
},
.nav_val => |this_nav| switch (dependee) {
.nav_val => |other_nav| if (this_nav == other_nav) return,
else => {},
},
.func => {},
else => {},
}
try zcu.intern_pool.addDependency(sema.gpa, sema.owner, dependee);
@@ -38659,38 +38634,6 @@ pub fn flushExports(sema: *Sema) !void {
}
}
/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches
/// the corresponding `Nav`.
fn getOwnerCauNav(sema: *Sema) InternPool.Nav.Index {
const cau = sema.owner.unwrap().cau;
return sema.pt.zcu.intern_pool.getCau(cau).owner.unwrap().nav;
}
/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches
/// the `TrackedInst` corresponding to this `declaration` instruction.
fn getOwnerCauDeclInst(sema: *Sema) InternPool.TrackedInst.Index {
const ip = &sema.pt.zcu.intern_pool;
const cau = ip.getCau(sema.owner.unwrap().cau);
assert(cau.owner.unwrap() == .nav);
return cau.zir_index;
}
/// Given that this `Sema` is owned by a runtime function, fetches the
/// `TrackedInst` corresponding to its `declaration` instruction.
fn getOwnerFuncDeclInst(sema: *Sema) InternPool.TrackedInst.Index {
const zcu = sema.pt.zcu;
const ip = &zcu.intern_pool;
const func = sema.owner.unwrap().func;
const func_info = zcu.funcInfo(func);
const cau = if (func_info.generic_owner == .none) cau: {
break :cau ip.getNav(func_info.owner_nav).analysis_owner.unwrap().?;
} else cau: {
const generic_owner = zcu.funcInfo(func_info.generic_owner);
break :cau ip.getNav(generic_owner.owner_nav).analysis_owner.unwrap().?;
};
return ip.getCau(cau).zir_index;
}
/// Called as soon as a `declared` enum type is created.
/// Resolves the tag type and field inits.
/// Marks the `src_inst` dependency on the enum's declaration, so call sites need not do this.
@@ -38701,7 +38644,6 @@ pub fn resolveDeclaredEnum(
tracked_inst: InternPool.TrackedInst.Index,
namespace: InternPool.NamespaceIndex,
type_name: InternPool.NullTerminatedString,
enum_cau: InternPool.Cau.Index,
small: Zir.Inst.EnumDecl.Small,
body: []const Zir.Inst.Index,
tag_type_ref: Zir.Inst.Ref,
@@ -38719,7 +38661,7 @@ pub fn resolveDeclaredEnum(
const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };
const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };
const anal_unit = AnalUnit.wrap(.{ .cau = enum_cau });
const anal_unit = AnalUnit.wrap(.{ .type = wip_ty.index });
var arena = std.heap.ArenaAllocator.init(gpa);
defer arena.deinit();
@@ -38943,6 +38885,6 @@ fn getBuiltin(sema: *Sema, name: []const u8) SemaError!Air.Inst.Ref {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const nav = try pt.getBuiltinNav(name);
try pt.ensureCauAnalyzed(ip.getNav(nav).analysis_owner.unwrap().?);
try pt.ensureNavValUpToDate(nav);
return Air.internedToRef(ip.getNav(nav).status.resolved.val);
}

View File

@@ -3851,7 +3851,7 @@ fn resolveStructInner(
const gpa = zcu.gpa;
const struct_obj = zcu.typeToStruct(ty).?;
const owner = InternPool.AnalUnit.wrap(.{ .cau = struct_obj.cau });
const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() });
if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {
return error.AnalysisFail;
@@ -3905,7 +3905,7 @@ fn resolveUnionInner(
const gpa = zcu.gpa;
const union_obj = zcu.typeToUnion(ty).?;
const owner = InternPool.AnalUnit.wrap(.{ .cau = union_obj.cau });
const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() });
if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {
return error.AnalysisFail;

View File

@@ -192,7 +192,7 @@ compile_log_text: std.ArrayListUnmanaged(u8) = .empty,
test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
global_assembly: std.AutoArrayHashMapUnmanaged(InternPool.Cau.Index, []u8) = .empty,
global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty,
/// Key is the `AnalUnit` *performing* the reference. This representation allows
/// incremental updates to quickly delete references caused by a specific `AnalUnit`.
@@ -344,9 +344,12 @@ pub const Namespace = struct {
pub_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
/// All `usingnamespace` declarations in this namespace which are *not* marked `pub`.
priv_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
/// All `comptime` and `test` declarations in this namespace. We store these purely so that
/// incremental compilation can re-use the existing `Cau`s when a namespace changes.
other_decls: std.ArrayListUnmanaged(InternPool.Cau.Index) = .empty,
/// All `comptime` declarations in this namespace. We store these purely so that incremental
/// compilation can re-use the existing `ComptimeUnit`s when a namespace changes.
comptime_decls: std.ArrayListUnmanaged(InternPool.ComptimeUnit.Id) = .empty,
/// All `test` declarations in this namespace. We store these purely so that incremental
/// compilation can re-use the existing `Nav`s when a namespace changes.
test_decls: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
pub const Index = InternPool.NamespaceIndex;
pub const OptionalIndex = InternPool.OptionalNamespaceIndex;
@@ -2436,11 +2439,9 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
// If this is a Decl, we must recursively mark dependencies on its tyval
// as no longer PO.
switch (depender.unwrap()) {
.cau => |cau| switch (zcu.intern_pool.getCau(cau).owner.unwrap()) {
.nav => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }),
.type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }),
.none => {},
},
.@"comptime" => {},
.nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }),
.type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }),
.func => |func| try zcu.markPoDependeeUpToDate(.{ .interned = func }),
}
}
@@ -2451,11 +2452,9 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void {
const ip = &zcu.intern_pool;
const dependee: InternPool.Dependee = switch (maybe_outdated.unwrap()) {
.cau => |cau| switch (ip.getCau(cau).owner.unwrap()) {
.nav => |nav| .{ .nav_val = nav }, // TODO: also `nav_ref` deps when introduced
.type => |ty| .{ .interned = ty },
.none => return, // analysis of this `Cau` can't outdate any dependencies
},
.@"comptime" => return, // analysis of a comptime decl can't outdate any dependencies
.nav_val => |nav| .{ .nav_val = nav }, // TODO: also `nav_ref` deps when introduced
.type => |ty| .{ .interned = ty },
.func => |func_index| .{ .interned = func_index }, // IES
};
log.debug("potentially outdated dependee: {}", .{zcu.fmtDependee(dependee)});
@@ -2512,14 +2511,14 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
}
// There is no single AnalUnit which is ready for re-analysis. Instead, we must assume that some
// Cau with PO dependencies is outdated -- e.g. in the above example we arbitrarily pick one of
// A or B. We should select a Cau, since a Cau is definitely responsible for the loop in the
// dependency graph (since IES dependencies can't have loops). We should also, of course, not
// select a Cau owned by a `comptime` declaration, since you can't depend on those!
// AnalUnit with PO dependencies is outdated -- e.g. in the above example we arbitrarily pick one of
// A or B. We should definitely not select a function, since a function can't be responsible for the
// loop (IES dependencies can't have loops). We should also, of course, not select a `comptime`
// declaration, since you can't depend on those!
// The choice of this Cau could have a big impact on how much total analysis we perform, since
// The choice of this unit could have a big impact on how much total analysis we perform, since
// if analysis concludes any dependencies on its result are up-to-date, then other PO AnalUnit
// may be resolved as up-to-date. To hopefully avoid doing too much work, let's find a Decl
// may be resolved as up-to-date. To hopefully avoid doing too much work, let's find a unit
// which the most things depend on - the idea is that this will resolve a lot of loops (but this
// is only a heuristic).
@@ -2530,33 +2529,28 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
const ip = &zcu.intern_pool;
var chosen_cau: ?InternPool.Cau.Index = null;
var chosen_cau_dependers: u32 = undefined;
var chosen_unit: ?AnalUnit = null;
var chosen_unit_dependers: u32 = undefined;
inline for (.{ zcu.outdated.keys(), zcu.potentially_outdated.keys() }) |outdated_units| {
for (outdated_units) |unit| {
const cau = switch (unit.unwrap()) {
.cau => |cau| cau,
.func => continue, // a `func` definitely can't be causing the loop so it is a bad choice
};
const cau_owner = ip.getCau(cau).owner;
var n: u32 = 0;
var it = ip.dependencyIterator(switch (cau_owner.unwrap()) {
.none => continue, // there can be no dependencies on this `Cau` so it is a terrible choice
var it = ip.dependencyIterator(switch (unit.unwrap()) {
.func => continue, // a `func` definitely can't be causing the loop so it is a bad choice
.@"comptime" => continue, // a `comptime` block can't even be depended on so it is a terrible choice
.type => |ty| .{ .interned = ty },
.nav => |nav| .{ .nav_val = nav },
.nav_val => |nav| .{ .nav_val = nav },
});
while (it.next()) |_| n += 1;
if (chosen_cau == null or n > chosen_cau_dependers) {
chosen_cau = cau;
chosen_cau_dependers = n;
if (chosen_unit == null or n > chosen_unit_dependers) {
chosen_unit = unit;
chosen_unit_dependers = n;
}
}
}
if (chosen_cau == null) {
if (chosen_unit == null) {
for (zcu.outdated.keys(), zcu.outdated.values()) |o, opod| {
const func = o.unwrap().func;
const nav = zcu.funcInfo(func).owner_nav;
@@ -2570,11 +2564,11 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
}
log.debug("findOutdatedToAnalyze: heuristic returned '{}' ({d} dependers)", .{
zcu.fmtAnalUnit(AnalUnit.wrap(.{ .cau = chosen_cau.? })),
chosen_cau_dependers,
zcu.fmtAnalUnit(chosen_unit.?),
chosen_unit_dependers,
});
return AnalUnit.wrap(.{ .cau = chosen_cau.? });
return chosen_unit.?;
}
/// During an incremental update, before semantic analysis, call this to flush all values from
@@ -3019,9 +3013,9 @@ pub fn handleUpdateExports(
};
}
pub fn addGlobalAssembly(zcu: *Zcu, cau: InternPool.Cau.Index, source: []const u8) !void {
pub fn addGlobalAssembly(zcu: *Zcu, unit: AnalUnit, source: []const u8) !void {
const gpa = zcu.gpa;
const gop = try zcu.global_assembly.getOrPut(gpa, cau);
const gop = try zcu.global_assembly.getOrPut(gpa, unit);
if (gop.found_existing) {
const new_value = try std.fmt.allocPrint(gpa, "{s}\n{s}", .{ gop.value_ptr.*, source });
gpa.free(gop.value_ptr.*);
@@ -3304,23 +3298,22 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
log.debug("handle type '{}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});
// If this type has a `Cau` for resolution, it's automatically referenced.
const resolution_cau: InternPool.Cau.Index.Optional = switch (ip.indexToKey(ty)) {
.struct_type => ip.loadStructType(ty).cau.toOptional(),
.union_type => ip.loadUnionType(ty).cau.toOptional(),
.enum_type => ip.loadEnumType(ty).cau,
.opaque_type => .none,
// If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced.
const has_resolution: bool = switch (ip.indexToKey(ty)) {
.struct_type, .union_type => true,
.enum_type => |k| k != .generated_tag,
.opaque_type => false,
else => unreachable,
};
if (resolution_cau.unwrap()) |cau| {
if (has_resolution) {
// this should only be referenced by the type
const unit = AnalUnit.wrap(.{ .cau = cau });
const unit: AnalUnit = .wrap(.{ .type = ty });
assert(!result.contains(unit));
try unit_queue.putNoClobber(gpa, unit, referencer);
}
// If this is a union with a generated tag, its tag type is automatically referenced.
// We don't add this reference for non-generated tags, as those will already be referenced via the union's `Cau`, with a better source location.
// We don't add this reference for non-generated tags, as those will already be referenced via the union's type resolution, with a better source location.
if (zcu.typeToUnion(Type.fromInterned(ty))) |union_obj| {
const tag_ty = union_obj.enum_tag_ty;
if (tag_ty != .none) {
@@ -3335,24 +3328,35 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
// Queue any decls within this type which would be automatically analyzed.
// Keep in sync with analysis queueing logic in `Zcu.PerThread.ScanDeclIter.scanDecl`.
const ns = Type.fromInterned(ty).getNamespace(zcu).unwrap().?;
for (zcu.namespacePtr(ns).other_decls.items) |cau| {
// These are `comptime` and `test` declarations.
// `comptime` decls are always analyzed; `test` declarations are analyzed depending on the test filter.
const inst_info = ip.getCau(cau).zir_index.resolveFull(ip) orelse continue;
for (zcu.namespacePtr(ns).comptime_decls.items) |cu| {
// `comptime` decls are always analyzed.
const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });
if (!result.contains(unit)) {
log.debug("type '{}': ref comptime %{}", .{
Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
@intFromEnum(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue),
});
try unit_queue.put(gpa, unit, referencer);
}
}
for (zcu.namespacePtr(ns).test_decls.items) |nav_id| {
const nav = ip.getNav(nav_id);
// `test` declarations are analyzed depending on the test filter.
const inst_info = nav.analysis.?.zir_index.resolveFull(ip) orelse continue;
const file = zcu.fileByIndex(inst_info.file);
// If the file failed AstGen, the TrackedInst refers to the old ZIR.
const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
const decl = zir.getDeclaration(inst_info.inst);
if (!comp.config.is_test or file.mod != zcu.main_mod) continue;
const want_analysis = switch (decl.kind) {
.@"usingnamespace" => unreachable,
.@"const", .@"var" => unreachable,
.@"comptime" => true,
.unnamed_test => comp.config.is_test and file.mod == zcu.main_mod,
.@"comptime" => unreachable,
.unnamed_test => true,
.@"test", .decltest => a: {
if (!comp.config.is_test) break :a false;
if (file.mod != zcu.main_mod) break :a false;
const nav = ip.getCau(cau).owner.unwrap().nav;
const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);
const fqn_slice = nav.fqn.toSlice(ip);
for (comp.test_filters) |test_filter| {
if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
} else break :a false;
@@ -3360,28 +3364,25 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
},
};
if (want_analysis) {
const unit = AnalUnit.wrap(.{ .cau = cau });
if (!result.contains(unit)) {
log.debug("type '{}': ref cau %{}", .{
Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
@intFromEnum(inst_info.inst),
});
try unit_queue.put(gpa, unit, referencer);
}
log.debug("type '{}': ref test %{}", .{
Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
@intFromEnum(inst_info.inst),
});
const unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
try unit_queue.put(gpa, unit, referencer);
}
}
for (zcu.namespacePtr(ns).pub_decls.keys()) |nav| {
// These are named declarations. They are analyzed only if marked `export`.
const cau = ip.getNav(nav).analysis_owner.unwrap().?;
const inst_info = ip.getCau(cau).zir_index.resolveFull(ip) orelse continue;
const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue;
const file = zcu.fileByIndex(inst_info.file);
// If the file failed AstGen, the TrackedInst refers to the old ZIR.
const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
const decl = zir.getDeclaration(inst_info.inst);
if (decl.linkage == .@"export") {
const unit = AnalUnit.wrap(.{ .cau = cau });
const unit: AnalUnit = .wrap(.{ .nav_val = nav });
if (!result.contains(unit)) {
log.debug("type '{}': ref cau %{}", .{
log.debug("type '{}': ref named %{}", .{
Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
@intFromEnum(inst_info.inst),
});
@@ -3391,16 +3392,15 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
}
for (zcu.namespacePtr(ns).priv_decls.keys()) |nav| {
// These are named declarations. They are analyzed only if marked `export`.
const cau = ip.getNav(nav).analysis_owner.unwrap().?;
const inst_info = ip.getCau(cau).zir_index.resolveFull(ip) orelse continue;
const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue;
const file = zcu.fileByIndex(inst_info.file);
// If the file failed AstGen, the TrackedInst refers to the old ZIR.
const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
const decl = zir.getDeclaration(inst_info.inst);
if (decl.linkage == .@"export") {
const unit = AnalUnit.wrap(.{ .cau = cau });
const unit: AnalUnit = .wrap(.{ .nav_val = nav });
if (!result.contains(unit)) {
log.debug("type '{}': ref cau %{}", .{
log.debug("type '{}': ref named %{}", .{
Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
@intFromEnum(inst_info.inst),
});
@@ -3411,13 +3411,11 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
// Incremental compilation does not support `usingnamespace`.
// These are only included to keep good reference traces in non-incremental updates.
for (zcu.namespacePtr(ns).pub_usingnamespace.items) |nav| {
const cau = ip.getNav(nav).analysis_owner.unwrap().?;
const unit = AnalUnit.wrap(.{ .cau = cau });
const unit: AnalUnit = .wrap(.{ .nav_val = nav });
if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);
}
for (zcu.namespacePtr(ns).priv_usingnamespace.items) |nav| {
const cau = ip.getNav(nav).analysis_owner.unwrap().?;
const unit = AnalUnit.wrap(.{ .cau = cau });
const unit: AnalUnit = .wrap(.{ .nav_val = nav });
if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);
}
continue;
@@ -3527,12 +3525,6 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File {
return zcu.fileByIndex(zcu.navFileScopeIndex(nav));
}
pub fn cauFileScope(zcu: *Zcu, cau: InternPool.Cau.Index) *File {
const ip = &zcu.intern_pool;
const file_index = ip.getCau(cau).zir_index.resolveFile(ip);
return zcu.fileByIndex(file_index);
}
pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Formatter(formatAnalUnit) {
return .{ .data = .{ .unit = unit, .zcu = zcu } };
}
@@ -3545,19 +3537,17 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co
const zcu = data.zcu;
const ip = &zcu.intern_pool;
switch (data.unit.unwrap()) {
.cau => |cau_index| {
const cau = ip.getCau(cau_index);
switch (cau.owner.unwrap()) {
.nav => |nav| return writer.print("cau(decl='{}')", .{ip.getNav(nav).fqn.fmt(ip)}),
.type => |ty| return writer.print("cau(ty='{}')", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}),
.none => if (cau.zir_index.resolveFull(ip)) |resolved| {
const file_path = zcu.fileByIndex(resolved.file).sub_file_path;
return writer.print("cau(inst=('{s}', %{}))", .{ file_path, @intFromEnum(resolved.inst) });
} else {
return writer.writeAll("cau(inst=<lost>)");
},
.@"comptime" => |cu_id| {
const cu = ip.getComptimeUnit(cu_id);
if (cu.zir_index.resolveFull(ip)) |resolved| {
const file_path = zcu.fileByIndex(resolved.file).sub_file_path;
return writer.print("comptime(inst=('{s}', %{}))", .{ file_path, @intFromEnum(resolved.inst) });
} else {
return writer.writeAll("comptime(inst=<list>)");
}
},
.nav_val => |nav| return writer.print("nav_val('{}')", .{ip.getNav(nav).fqn.fmt(ip)}),
.type => |ty| return writer.print("ty('{}')", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}),
.func => |func| {
const nav = zcu.funcInfo(func).owner_nav;
return writer.print("func('{}')", .{ip.getNav(nav).fqn.fmt(ip)});

File diff suppressed because it is too large Load Diff

View File

@@ -2261,8 +2261,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
assert(file.zir_loaded);
const decl = file.zir.getDeclaration(inst_info.inst);
const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {
const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);
const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
const parent_namespace_ptr = ip.namespacePtr(a.namespace);
break :parent .{
parent_namespace_ptr.owner_type,
if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,
@@ -2292,8 +2292,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
assert(file.zir_loaded);
const decl = file.zir.getDeclaration(inst_info.inst);
const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {
const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);
const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
const parent_namespace_ptr = ip.namespacePtr(a.namespace);
break :parent .{
parent_namespace_ptr.owner_type,
if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,
@@ -2321,8 +2321,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
assert(file.zir_loaded);
const decl = file.zir.getDeclaration(inst_info.inst);
const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {
const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);
const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
const parent_namespace_ptr = ip.namespacePtr(a.namespace);
break :parent .{
parent_namespace_ptr.owner_type,
if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,
@@ -2563,8 +2563,8 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
return;
}
const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {
const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);
const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
const parent_namespace_ptr = ip.namespacePtr(a.namespace);
break :parent .{
parent_namespace_ptr.owner_type,
if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,