authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-12-22 21:16:29+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-12-24 02:18:41+00:00
log40aafcd6a85d3c517f445f17149c17523c832420
treeb8e1a5361c6a20ce9e3ba568b61b199aff1c8f13
parent18362ebe13ece2ea7c4f57303ec4687f55d2dba5
signaturelock-open Commit is signed but in an unrecognized format.

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.

7 files changed, 1321 insertions(+), 1524 deletions(-)

src/Compilation.zig+45-28
...@@ -348,12 +348,15 @@ const Job = union(enum) {...@@ -348,12 +348,15 @@ const Job = union(enum) {
348 /// Corresponds to the task in `link.Task`.348 /// Corresponds to the task in `link.Task`.
349 /// Only needed for backends that haven't yet been updated to not race against Sema.349 /// Only needed for backends that haven't yet been updated to not race against Sema.
350 codegen_type: InternPool.Index,350 codegen_type: InternPool.Index,
351 /// The `Cau` must be semantically analyzed (and possibly export itself).351 /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.
352 /// This may be its first time being analyzed, or it may be outdated.
353 /// If the unit is a function, a `codegen_func` job will then be queued.
354 analyze_comptime_unit: InternPool.AnalUnit,
355 /// This function must be semantically analyzed.
352 /// This may be its first time being analyzed, or it may be outdated.356 /// This may be its first time being analyzed, or it may be outdated.
353 analyze_cau: InternPool.Cau.Index,
354 /// Analyze the body of a runtime function.
355 /// After analysis, a `codegen_func` job will be queued.357 /// After analysis, a `codegen_func` job will be queued.
356 /// These must be separate jobs to ensure any needed type resolution occurs *before* codegen.358 /// These must be separate jobs to ensure any needed type resolution occurs *before* codegen.
359 /// This job is separate from `analyze_comptime_unit` because it has a different priority.
357 analyze_func: InternPool.Index,360 analyze_func: InternPool.Index,
358 /// The main source file for the module needs to be analyzed.361 /// The main source file for the module needs to be analyzed.
359 analyze_mod: *Package.Module,362 analyze_mod: *Package.Module,
...@@ -3141,8 +3144,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3141,8 +3144,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3141 }3144 }
31423145
3143 const file_index = switch (anal_unit.unwrap()) {3146 const file_index = switch (anal_unit.unwrap()) {
3144 .cau => |cau| zcu.namespacePtr(ip.getCau(cau).namespace).file_scope,3147 .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index.resolveFile(ip),
3145 .func => |ip_index| (zcu.funcInfo(ip_index).zir_body_inst.resolveFull(ip) orelse continue).file,3148 .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index.resolveFile(ip),
3149 .type => |ty| Type.fromInterned(ty).typeDeclInst(zcu).?.resolveFile(ip),
3150 .func => |ip_index| zcu.funcInfo(ip_index).zir_body_inst.resolveFile(ip),
3146 };3151 };
31473152
3148 // Skip errors for AnalUnits within files that had a parse failure.3153 // Skip errors for AnalUnits within files that had a parse failure.
...@@ -3374,11 +3379,9 @@ pub fn addModuleErrorMsg(...@@ -3374,11 +3379,9 @@ pub fn addModuleErrorMsg(
3374 const rt_file_path = try src.file_scope.fullPath(gpa);3379 const rt_file_path = try src.file_scope.fullPath(gpa);
3375 defer gpa.free(rt_file_path);3380 defer gpa.free(rt_file_path);
3376 const name = switch (ref.referencer.unwrap()) {3381 const name = switch (ref.referencer.unwrap()) {
3377 .cau => |cau| switch (ip.getCau(cau).owner.unwrap()) {3382 .@"comptime" => "comptime",
3378 .nav => |nav| ip.getNav(nav).name.toSlice(ip),3383 .nav_val => |nav| ip.getNav(nav).name.toSlice(ip),
3379 .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),3384 .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
3380 .none => "comptime",
3381 },
3382 .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),3385 .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
3383 };3386 };
3384 try ref_traces.append(gpa, .{3387 try ref_traces.append(gpa, .{
...@@ -3641,10 +3644,13 @@ fn performAllTheWorkInner(...@@ -3641,10 +3644,13 @@ fn performAllTheWorkInner(
3641 // If there's no work queued, check if there's anything outdated3644 // If there's no work queued, check if there's anything outdated
3642 // which we need to work on, and queue it if so.3645 // which we need to work on, and queue it if so.
3643 if (try zcu.findOutdatedToAnalyze()) |outdated| {3646 if (try zcu.findOutdatedToAnalyze()) |outdated| {
3644 switch (outdated.unwrap()) {3647 try comp.queueJob(switch (outdated.unwrap()) {
3645 .cau => |cau| try comp.queueJob(.{ .analyze_cau = cau }),3648 .func => |f| .{ .analyze_func = f },
3646 .func => |func| try comp.queueJob(.{ .analyze_func = func }),3649 .@"comptime",
3647 }3650 .nav_val,
3651 .type,
3652 => .{ .analyze_comptime_unit = outdated },
3653 });
3648 continue;3654 continue;
3649 }3655 }
3650 }3656 }
...@@ -3667,8 +3673,8 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre...@@ -3667,8 +3673,8 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
3667 .codegen_nav => |nav_index| {3673 .codegen_nav => |nav_index| {
3668 const zcu = comp.zcu.?;3674 const zcu = comp.zcu.?;
3669 const nav = zcu.intern_pool.getNav(nav_index);3675 const nav = zcu.intern_pool.getNav(nav_index);
3670 if (nav.analysis_owner.unwrap()) |cau| {3676 if (nav.analysis != null) {
3671 const unit = InternPool.AnalUnit.wrap(.{ .cau = cau });3677 const unit: InternPool.AnalUnit = .wrap(.{ .nav_val = nav_index });
3672 if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) {3678 if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) {
3673 return;3679 return;
3674 }3680 }
...@@ -3688,36 +3694,47 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre...@@ -3688,36 +3694,47 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
36883694
3689 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));3695 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
3690 defer pt.deactivate();3696 defer pt.deactivate();
3691 pt.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {3697
3692 error.OutOfMemory => return error.OutOfMemory,3698 pt.ensureFuncBodyUpToDate(func) catch |err| switch (err) {
3699 error.OutOfMemory => |e| return e,
3693 error.AnalysisFail => return,3700 error.AnalysisFail => return,
3694 };3701 };
3695 },3702 },
3696 .analyze_cau => |cau_index| {3703 .analyze_comptime_unit => |unit| {
3704 const named_frame = tracy.namedFrame("analyze_comptime_unit");
3705 defer named_frame.end();
3706
3697 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));3707 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
3698 defer pt.deactivate();3708 defer pt.deactivate();
3699 pt.ensureCauAnalyzed(cau_index) catch |err| switch (err) {3709
3700 error.OutOfMemory => return error.OutOfMemory,3710 const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) {
3711 .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu),
3712 .nav_val => |nav| pt.ensureNavValUpToDate(nav),
3713 .type => |ty| if (pt.ensureTypeUpToDate(ty)) |_| {} else |err| err,
3714 .func => unreachable,
3715 };
3716 maybe_err catch |err| switch (err) {
3717 error.OutOfMemory => |e| return e,
3701 error.AnalysisFail => return,3718 error.AnalysisFail => return,
3702 };3719 };
3720
3703 queue_test_analysis: {3721 queue_test_analysis: {
3704 if (!comp.config.is_test) break :queue_test_analysis;3722 if (!comp.config.is_test) break :queue_test_analysis;
3723 const nav = switch (unit.unwrap()) {
3724 .nav_val => |nav| nav,
3725 else => break :queue_test_analysis,
3726 };
37053727
3706 // Check if this is a test function.3728 // Check if this is a test function.
3707 const ip = &pt.zcu.intern_pool;3729 const ip = &pt.zcu.intern_pool;
3708 const cau = ip.getCau(cau_index);3730 if (!pt.zcu.test_functions.contains(nav)) {
3709 const nav_index = switch (cau.owner.unwrap()) {
3710 .none, .type => break :queue_test_analysis,
3711 .nav => |nav| nav,
3712 };
3713 if (!pt.zcu.test_functions.contains(nav_index)) {
3714 break :queue_test_analysis;3731 break :queue_test_analysis;
3715 }3732 }
37163733
3717 // Tests are always emitted in test binaries. The decl_refs are created by3734 // Tests are always emitted in test binaries. The decl_refs are created by
3718 // Zcu.populateTestFunctions, but this will not queue body analysis, so do3735 // Zcu.populateTestFunctions, but this will not queue body analysis, so do
3719 // that now.3736 // that now.
3720 try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav_index).status.resolved.val);3737 try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav).status.resolved.val);
3721 }3738 }
3722 },3739 },
3723 .resolve_type_fully => |ty| {3740 .resolve_type_fully => |ty| {
src/InternPool.zig+154-275
...@@ -363,33 +363,53 @@ pub fn rehashTrackedInsts(...@@ -363,33 +363,53 @@ pub fn rehashTrackedInsts(
363}363}
364364
365/// Analysis Unit. Represents a single entity which undergoes semantic analysis.365/// Analysis Unit. Represents a single entity which undergoes semantic analysis.
366/// This is either a `Cau` or a runtime function.
367/// The LSB is used as a tag bit.
368/// This is the "source" of an incremental dependency edge.366/// This is the "source" of an incremental dependency edge.
369pub const AnalUnit = packed struct(u32) {367pub const AnalUnit = packed struct(u64) {
370 kind: enum(u1) { cau, func },368 kind: Kind,
371 index: u31,369 id: u32,
372 pub const Unwrapped = union(enum) {370
373 cau: Cau.Index,371 pub const Kind = enum(u32) {
372 @"comptime",
373 nav_val,
374 type,
375 func,
376 };
377
378 pub const Unwrapped = union(Kind) {
379 /// This `AnalUnit` analyzes the body of the given `comptime` declaration.
380 @"comptime": ComptimeUnit.Id,
381 /// This `AnalUnit` resolves the value of the given `Nav`.
382 nav_val: Nav.Index,
383 /// This `AnalUnit` resolves the given `struct`/`union`/`enum` type.
384 /// Generated tag enums are never used here (they do not undergo type resolution).
385 type: InternPool.Index,
386 /// This `AnalUnit` analyzes the body of the given runtime function.
374 func: InternPool.Index,387 func: InternPool.Index,
375 };388 };
376 pub fn unwrap(as: AnalUnit) Unwrapped {389
377 return switch (as.kind) {390 pub fn unwrap(au: AnalUnit) Unwrapped {
378 .cau => .{ .cau = @enumFromInt(as.index) },391 return switch (au.kind) {
379 .func => .{ .func = @enumFromInt(as.index) },392 inline else => |tag| @unionInit(
393 Unwrapped,
394 @tagName(tag),
395 @enumFromInt(au.id),
396 ),
380 };397 };
381 }398 }
382 pub fn wrap(raw: Unwrapped) AnalUnit {399 pub fn wrap(raw: Unwrapped) AnalUnit {
383 return switch (raw) {400 return switch (raw) {
384 .cau => |cau| .{ .kind = .cau, .index = @intCast(@intFromEnum(cau)) },401 inline else => |id, tag| .{
385 .func => |func| .{ .kind = .func, .index = @intCast(@intFromEnum(func)) },402 .kind = tag,
403 .id = @intFromEnum(id),
404 },
386 };405 };
387 }406 }
407
388 pub fn toOptional(as: AnalUnit) Optional {408 pub fn toOptional(as: AnalUnit) Optional {
389 return @enumFromInt(@as(u32, @bitCast(as)));409 return @enumFromInt(@as(u64, @bitCast(as)));
390 }410 }
391 pub const Optional = enum(u32) {411 pub const Optional = enum(u64) {
392 none = std.math.maxInt(u32),412 none = std.math.maxInt(u64),
393 _,413 _,
394 pub fn unwrap(opt: Optional) ?AnalUnit {414 pub fn unwrap(opt: Optional) ?AnalUnit {
395 return switch (opt) {415 return switch (opt) {
...@@ -400,97 +420,30 @@ pub const AnalUnit = packed struct(u32) {...@@ -400,97 +420,30 @@ pub const AnalUnit = packed struct(u32) {
400 };420 };
401};421};
402422
403/// Comptime Analysis Unit. This is the "subject" of semantic analysis where the root context is423pub const ComptimeUnit = extern struct {
404/// comptime; every `Sema` is owned by either a `Cau` or a runtime function (see `AnalUnit`).
405/// The state stored here is immutable.
406///
407/// * Every ZIR `declaration` has a `Cau` (post-instantiation) to analyze the declaration body.
408/// * Every `struct`, `union`, and `enum` has a `Cau` for type resolution.
409///
410/// The analysis status of a `Cau` is known only from state in `Zcu`.
411/// An entry in `Zcu.failed_analysis` indicates an analysis failure with associated error message.
412/// An entry in `Zcu.transitive_failed_analysis` indicates a transitive analysis failure.
413///
414/// 12 bytes.
415pub const Cau = struct {
416 /// The `declaration`, `struct_decl`, `enum_decl`, or `union_decl` instruction which this `Cau` analyzes.
417 zir_index: TrackedInst.Index,424 zir_index: TrackedInst.Index,
418 /// The namespace which this `Cau` should be analyzed within.
419 namespace: NamespaceIndex,425 namespace: NamespaceIndex,
420 /// This field essentially tells us what to do with the information resulting from
421 /// semantic analysis. See `Owner.Unwrapped` for details.
422 owner: Owner,
423
424 /// See `Owner.Unwrapped` for details. In terms of representation, the `InternPool.Index`
425 /// or `Nav.Index` is cast to a `u31` and stored in `index`. As a special case, if
426 /// `@as(u32, @bitCast(owner)) == 0xFFFF_FFFF`, then the value is treated as `.none`.
427 pub const Owner = packed struct(u32) {
428 kind: enum(u1) { type, nav },
429 index: u31,
430
431 pub const Unwrapped = union(enum) {
432 /// This `Cau` exists in isolation. It is a global `comptime` declaration, or (TODO ANYTHING ELSE?).
433 /// After semantic analysis completes, the result is discarded.
434 none,
435 /// This `Cau` is owned by the given type for type resolution.
436 /// This is a `struct`, `union`, or `enum` type.
437 type: InternPool.Index,
438 /// This `Cau` is owned by the given `Nav` to resolve its value.
439 /// When analyzing the `Cau`, the resulting value is stored as the value of this `Nav`.
440 nav: Nav.Index,
441 };
442426
443 pub fn unwrap(owner: Owner) Unwrapped {427 comptime {
444 if (@as(u32, @bitCast(owner)) == std.math.maxInt(u32)) {428 assert(std.meta.hasUniqueRepresentation(ComptimeUnit));
445 return .none;429 }
446 }
447 return switch (owner.kind) {
448 .type => .{ .type = @enumFromInt(owner.index) },
449 .nav => .{ .nav = @enumFromInt(owner.index) },
450 };
451 }
452
453 fn wrap(raw: Unwrapped) Owner {
454 return switch (raw) {
455 .none => @bitCast(@as(u32, std.math.maxInt(u32))),
456 .type => |ty| .{ .kind = .type, .index = @intCast(@intFromEnum(ty)) },
457 .nav => |nav| .{ .kind = .nav, .index = @intCast(@intFromEnum(nav)) },
458 };
459 }
460 };
461430
462 pub const Index = enum(u32) {431 pub const Id = enum(u32) {
463 _,432 _,
464 pub const Optional = enum(u32) {
465 none = std.math.maxInt(u32),
466 _,
467 pub fn unwrap(opt: Optional) ?Cau.Index {
468 return switch (opt) {
469 .none => null,
470 _ => @enumFromInt(@intFromEnum(opt)),
471 };
472 }
473
474 const debug_state = InternPool.debug_state;
475 };
476 pub fn toOptional(i: Cau.Index) Optional {
477 return @enumFromInt(@intFromEnum(i));
478 }
479 const Unwrapped = struct {433 const Unwrapped = struct {
480 tid: Zcu.PerThread.Id,434 tid: Zcu.PerThread.Id,
481 index: u32,435 index: u32,
482436 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) ComptimeUnit.Id {
483 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Cau.Index {
484 assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask());437 assert(@intFromEnum(unwrapped.tid) <= ip.getTidMask());
485 assert(unwrapped.index <= ip.getIndexMask(u31));438 assert(unwrapped.index <= ip.getIndexMask(u32));
486 return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_31 |439 return @enumFromInt(@as(u32, @intFromEnum(unwrapped.tid)) << ip.tid_shift_32 |
487 unwrapped.index);440 unwrapped.index);
488 }441 }
489 };442 };
490 fn unwrap(cau_index: Cau.Index, ip: *const InternPool) Unwrapped {443 fn unwrap(id: Id, ip: *const InternPool) Unwrapped {
491 return .{444 return .{
492 .tid = @enumFromInt(@intFromEnum(cau_index) >> ip.tid_shift_31 & ip.getTidMask()),445 .tid = @enumFromInt(@intFromEnum(id) >> ip.tid_shift_32 & ip.getTidMask()),
493 .index = @intFromEnum(cau_index) & ip.getIndexMask(u31),446 .index = @intFromEnum(id) & ip.getIndexMask(u31),
494 };447 };
495 }448 }
496449
...@@ -507,6 +460,11 @@ pub const Cau = struct {...@@ -507,6 +460,11 @@ pub const Cau = struct {
507/// * Generic instances have a `Nav` corresponding to the instantiated function.460/// * Generic instances have a `Nav` corresponding to the instantiated function.
508/// * `@extern` calls create a `Nav` whose value is a `.@"extern"`.461/// * `@extern` calls create a `Nav` whose value is a `.@"extern"`.
509///462///
463/// This data structure is optimized for the `analysis_info != null` case, because this is much more
464/// common in practice; the other case is used only for externs and for generic instances. At the time
465/// of writing, in the compiler itself, around 74% of all `Nav`s have `analysis_info != null`.
466/// (Specifically, 104225 / 140923)
467///
510/// `Nav.Repr` is the in-memory representation.468/// `Nav.Repr` is the in-memory representation.
511pub const Nav = struct {469pub const Nav = struct {
512 /// The unqualified name of this `Nav`. Namespace lookups use this name, and error messages may use it.470 /// 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 {...@@ -514,13 +472,16 @@ pub const Nav = struct {
514 name: NullTerminatedString,472 name: NullTerminatedString,
515 /// The fully-qualified name of this `Nav`.473 /// The fully-qualified name of this `Nav`.
516 fqn: NullTerminatedString,474 fqn: NullTerminatedString,
517 /// If the value of this `Nav` is resolved by semantic analysis, it is within this `Cau`.475 /// This field is populated iff this `Nav` is resolved by semantic analysis.
518 /// If this is `.none`, then `status == .resolved` always.476 /// If this is `null`, then `status == .resolved` always.
519 analysis_owner: Cau.Index.Optional,477 analysis: ?struct {
478 namespace: NamespaceIndex,
479 zir_index: TrackedInst.Index,
480 },
520 /// TODO: this is a hack! If #20663 isn't accepted, let's figure out something a bit better.481 /// TODO: this is a hack! If #20663 isn't accepted, let's figure out something a bit better.
521 is_usingnamespace: bool,482 is_usingnamespace: bool,
522 status: union(enum) {483 status: union(enum) {
523 /// This `Nav` is pending semantic analysis through `analysis_owner`.484 /// This `Nav` is pending semantic analysis.
524 unresolved,485 unresolved,
525 /// The value of this `Nav` is resolved.486 /// The value of this `Nav` is resolved.
526 resolved: struct {487 resolved: struct {
...@@ -544,17 +505,16 @@ pub const Nav = struct {...@@ -544,17 +505,16 @@ pub const Nav = struct {
544 /// Get the ZIR instruction corresponding to this `Nav`, used to resolve source locations.505 /// Get the ZIR instruction corresponding to this `Nav`, used to resolve source locations.
545 /// This is a `declaration`.506 /// This is a `declaration`.
546 pub fn srcInst(nav: Nav, ip: *const InternPool) TrackedInst.Index {507 pub fn srcInst(nav: Nav, ip: *const InternPool) TrackedInst.Index {
547 if (nav.analysis_owner.unwrap()) |cau| {508 if (nav.analysis) |a| {
548 return ip.getCau(cau).zir_index;509 return a.zir_index;
549 }510 }
550 // A `Nav` with no corresponding `Cau` always has a resolved value.511 // A `Nav` which does not undergo analysis always has a resolved value.
551 return switch (ip.indexToKey(nav.status.resolved.val)) {512 return switch (ip.indexToKey(nav.status.resolved.val)) {
552 .func => |func| {513 .func => |func| {
553 // Since there was no `analysis_owner`, this must be an instantiation.514 // Since `analysis` was not populated, this must be an instantiation.
554 // Go up to the generic owner and consult *its* `analysis_owner`.515 // Go up to the generic owner and consult *its* `analysis` field.
555 const go_nav = ip.getNav(ip.indexToKey(func.generic_owner).func.owner_nav);516 const go_nav = ip.getNav(ip.indexToKey(func.generic_owner).func.owner_nav);
556 const go_cau = ip.getCau(go_nav.analysis_owner.unwrap().?);517 return go_nav.analysis.?.zir_index;
557 return go_cau.zir_index;
558 },518 },
559 .@"extern" => |@"extern"| @"extern".zir_index, // extern / @extern519 .@"extern" => |@"extern"| @"extern".zir_index, // extern / @extern
560 else => unreachable,520 else => unreachable,
...@@ -600,11 +560,13 @@ pub const Nav = struct {...@@ -600,11 +560,13 @@ pub const Nav = struct {
600 };560 };
601561
602 /// The compact in-memory representation of a `Nav`.562 /// The compact in-memory representation of a `Nav`.
603 /// 18 bytes.563 /// 26 bytes.
604 const Repr = struct {564 const Repr = struct {
605 name: NullTerminatedString,565 name: NullTerminatedString,
606 fqn: NullTerminatedString,566 fqn: NullTerminatedString,
607 analysis_owner: Cau.Index.Optional,567 // The following 1 fields are either both populated, or both `.none`.
568 analysis_namespace: OptionalNamespaceIndex,
569 analysis_zir_index: TrackedInst.Index.Optional,
608 /// Populated only if `bits.status == .resolved`.570 /// Populated only if `bits.status == .resolved`.
609 val: InternPool.Index,571 val: InternPool.Index,
610 /// Populated only if `bits.status == .resolved`.572 /// Populated only if `bits.status == .resolved`.
...@@ -625,7 +587,13 @@ pub const Nav = struct {...@@ -625,7 +587,13 @@ pub const Nav = struct {
625 return .{587 return .{
626 .name = repr.name,588 .name = repr.name,
627 .fqn = repr.fqn,589 .fqn = repr.fqn,
628 .analysis_owner = repr.analysis_owner,590 .analysis = if (repr.analysis_namespace.unwrap()) |namespace| .{
591 .namespace = namespace,
592 .zir_index = repr.analysis_zir_index.unwrap().?,
593 } else a: {
594 assert(repr.analysis_zir_index == .none);
595 break :a null;
596 },
629 .is_usingnamespace = repr.bits.is_usingnamespace,597 .is_usingnamespace = repr.bits.is_usingnamespace,
630 .status = switch (repr.bits.status) {598 .status = switch (repr.bits.status) {
631 .unresolved => .unresolved,599 .unresolved => .unresolved,
...@@ -646,7 +614,8 @@ pub const Nav = struct {...@@ -646,7 +614,8 @@ pub const Nav = struct {
646 return .{614 return .{
647 .name = nav.name,615 .name = nav.name,
648 .fqn = nav.fqn,616 .fqn = nav.fqn,
649 .analysis_owner = nav.analysis_owner,617 .analysis_namespace = if (nav.analysis) |a| a.namespace.toOptional() else .none,
618 .analysis_zir_index = if (nav.analysis) |a| a.zir_index.toOptional() else .none,
650 .val = switch (nav.status) {619 .val = switch (nav.status) {
651 .unresolved => .none,620 .unresolved => .none,
652 .resolved => |r| r.val,621 .resolved => |r| r.val,
...@@ -862,8 +831,8 @@ const Local = struct {...@@ -862,8 +831,8 @@ const Local = struct {
862 tracked_insts: ListMutate,831 tracked_insts: ListMutate,
863 files: ListMutate,832 files: ListMutate,
864 maps: ListMutate,833 maps: ListMutate,
865 caus: ListMutate,
866 navs: ListMutate,834 navs: ListMutate,
835 comptime_units: ListMutate,
867836
868 namespaces: BucketListMutate,837 namespaces: BucketListMutate,
869 } align(std.atomic.cache_line),838 } align(std.atomic.cache_line),
...@@ -876,8 +845,8 @@ const Local = struct {...@@ -876,8 +845,8 @@ const Local = struct {
876 tracked_insts: TrackedInsts,845 tracked_insts: TrackedInsts,
877 files: List(File),846 files: List(File),
878 maps: Maps,847 maps: Maps,
879 caus: Caus,
880 navs: Navs,848 navs: Navs,
849 comptime_units: ComptimeUnits,
881850
882 namespaces: Namespaces,851 namespaces: Namespaces,
883852
...@@ -899,8 +868,8 @@ const Local = struct {...@@ -899,8 +868,8 @@ const Local = struct {
899 const Strings = List(struct { u8 });868 const Strings = List(struct { u8 });
900 const TrackedInsts = List(struct { TrackedInst.MaybeLost });869 const TrackedInsts = List(struct { TrackedInst.MaybeLost });
901 const Maps = List(struct { FieldMap });870 const Maps = List(struct { FieldMap });
902 const Caus = List(struct { Cau });
903 const Navs = List(Nav.Repr);871 const Navs = List(Nav.Repr);
872 const ComptimeUnits = List(struct { ComptimeUnit });
904873
905 const namespaces_bucket_width = 8;874 const namespaces_bucket_width = 8;
906 const namespaces_bucket_mask = (1 << namespaces_bucket_width) - 1;875 const namespaces_bucket_mask = (1 << namespaces_bucket_width) - 1;
...@@ -1275,21 +1244,21 @@ const Local = struct {...@@ -1275,21 +1244,21 @@ const Local = struct {
1275 };1244 };
1276 }1245 }
12771246
1278 pub fn getMutableCaus(local: *Local, gpa: Allocator) Caus.Mutable {1247 pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable {
1279 return .{1248 return .{
1280 .gpa = gpa,1249 .gpa = gpa,
1281 .arena = &local.mutate.arena,1250 .arena = &local.mutate.arena,
1282 .mutate = &local.mutate.caus,1251 .mutate = &local.mutate.navs,
1283 .list = &local.shared.caus,1252 .list = &local.shared.navs,
1284 };1253 };
1285 }1254 }
12861255
1287 pub fn getMutableNavs(local: *Local, gpa: Allocator) Navs.Mutable {1256 pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator) ComptimeUnits.Mutable {
1288 return .{1257 return .{
1289 .gpa = gpa,1258 .gpa = gpa,
1290 .arena = &local.mutate.arena,1259 .arena = &local.mutate.arena,
1291 .mutate = &local.mutate.navs,1260 .mutate = &local.mutate.comptime_units,
1292 .list = &local.shared.navs,1261 .list = &local.shared.comptime_units,
1293 };1262 };
1294 }1263 }
12951264
...@@ -3052,8 +3021,6 @@ pub const LoadedUnionType = struct {...@@ -3052,8 +3021,6 @@ pub const LoadedUnionType = struct {
3052 // TODO: the non-fqn will be needed by the new dwarf structure3021 // TODO: the non-fqn will be needed by the new dwarf structure
3053 /// The name of this union type.3022 /// The name of this union type.
3054 name: NullTerminatedString,3023 name: NullTerminatedString,
3055 /// The `Cau` within which type resolution occurs.
3056 cau: Cau.Index,
3057 /// Represents the declarations inside this union.3024 /// Represents the declarations inside this union.
3058 namespace: NamespaceIndex,3025 namespace: NamespaceIndex,
3059 /// The enum tag type.3026 /// The enum tag type.
...@@ -3370,7 +3337,6 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {...@@ -3370,7 +3337,6 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
3370 .tid = unwrapped_index.tid,3337 .tid = unwrapped_index.tid,
3371 .extra_index = data,3338 .extra_index = data,
3372 .name = type_union.data.name,3339 .name = type_union.data.name,
3373 .cau = type_union.data.cau,
3374 .namespace = type_union.data.namespace,3340 .namespace = type_union.data.namespace,
3375 .enum_tag_ty = type_union.data.tag_ty,3341 .enum_tag_ty = type_union.data.tag_ty,
3376 .field_types = field_types,3342 .field_types = field_types,
...@@ -3387,8 +3353,6 @@ pub const LoadedStructType = struct {...@@ -3387,8 +3353,6 @@ pub const LoadedStructType = struct {
3387 // TODO: the non-fqn will be needed by the new dwarf structure3353 // TODO: the non-fqn will be needed by the new dwarf structure
3388 /// The name of this struct type.3354 /// The name of this struct type.
3389 name: NullTerminatedString,3355 name: NullTerminatedString,
3390 /// The `Cau` within which type resolution occurs.
3391 cau: Cau.Index,
3392 namespace: NamespaceIndex,3356 namespace: NamespaceIndex,
3393 /// Index of the `struct_decl` or `reify` ZIR instruction.3357 /// Index of the `struct_decl` or `reify` ZIR instruction.
3394 zir_index: TrackedInst.Index,3358 zir_index: TrackedInst.Index,
...@@ -3979,7 +3943,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -3979,7 +3943,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
3979 switch (item.tag) {3943 switch (item.tag) {
3980 .type_struct => {3944 .type_struct => {
3981 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]);3945 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]);
3982 const cau: Cau.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "cau").?]);
3983 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]);3946 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]);
3984 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);3947 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);
3985 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "fields_len").?];3948 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 {...@@ -4066,7 +4029,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4066 .tid = unwrapped_index.tid,4029 .tid = unwrapped_index.tid,
4067 .extra_index = item.data,4030 .extra_index = item.data,
4068 .name = name,4031 .name = name,
4069 .cau = cau,
4070 .namespace = namespace,4032 .namespace = namespace,
4071 .zir_index = zir_index,4033 .zir_index = zir_index,
4072 .layout = if (flags.is_extern) .@"extern" else .auto,4034 .layout = if (flags.is_extern) .@"extern" else .auto,
...@@ -4083,7 +4045,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {...@@ -4083,7 +4045,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4083 },4045 },
4084 .type_struct_packed, .type_struct_packed_inits => {4046 .type_struct_packed, .type_struct_packed_inits => {
4085 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]);4047 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]);
4086 const cau: Cau.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "cau").?]);
4087 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);4048 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);
4088 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?];4049 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?];
4089 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]);4050 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 {...@@ -4130,7 +4091,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
4130 .tid = unwrapped_index.tid,4091 .tid = unwrapped_index.tid,
4131 .extra_index = item.data,4092 .extra_index = item.data,
4132 .name = name,4093 .name = name,
4133 .cau = cau,
4134 .namespace = namespace,4094 .namespace = namespace,
4135 .zir_index = zir_index,4095 .zir_index = zir_index,
4136 .layout = .@"packed",4096 .layout = .@"packed",
...@@ -4153,9 +4113,6 @@ pub const LoadedEnumType = struct {...@@ -4153,9 +4113,6 @@ pub const LoadedEnumType = struct {
4153 // TODO: the non-fqn will be needed by the new dwarf structure4113 // TODO: the non-fqn will be needed by the new dwarf structure
4154 /// The name of this enum type.4114 /// The name of this enum type.
4155 name: NullTerminatedString,4115 name: NullTerminatedString,
4156 /// The `Cau` within which type resolution occurs.
4157 /// `null` if this is a generated tag type.
4158 cau: Cau.Index.Optional,
4159 /// Represents the declarations inside this enum.4116 /// Represents the declarations inside this enum.
4160 namespace: NamespaceIndex,4117 namespace: NamespaceIndex,
4161 /// An integer type which is used for the numerical value of the enum.4118 /// 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 {...@@ -4232,21 +4189,15 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
4232 .type_enum_auto => {4189 .type_enum_auto => {
4233 const extra = extraDataTrail(extra_list, EnumAuto, item.data);4190 const extra = extraDataTrail(extra_list, EnumAuto, item.data);
4234 var extra_index: u32 = @intCast(extra.end);4191 var extra_index: u32 = @intCast(extra.end);
4235 const cau: Cau.Index.Optional = if (extra.data.zir_index == .none) cau: {4192 if (extra.data.zir_index == .none) {
4236 extra_index += 1; // owner_union4193 extra_index += 1; // owner_union
4237 break :cau .none;4194 }
4238 } else cau: {
4239 const cau: Cau.Index = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);
4240 extra_index += 1; // cau
4241 break :cau cau.toOptional();
4242 };
4243 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {4195 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {
4244 extra_index += 2; // type_hash: PackedU644196 extra_index += 2; // type_hash: PackedU64
4245 break :c 0;4197 break :c 0;
4246 } else extra.data.captures_len;4198 } else extra.data.captures_len;
4247 return .{4199 return .{
4248 .name = extra.data.name,4200 .name = extra.data.name,
4249 .cau = cau,
4250 .namespace = extra.data.namespace,4201 .namespace = extra.data.namespace,
4251 .tag_ty = extra.data.int_tag_type,4202 .tag_ty = extra.data.int_tag_type,
4252 .names = .{4203 .names = .{
...@@ -4272,21 +4223,15 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {...@@ -4272,21 +4223,15 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
4272 };4223 };
4273 const extra = extraDataTrail(extra_list, EnumExplicit, item.data);4224 const extra = extraDataTrail(extra_list, EnumExplicit, item.data);
4274 var extra_index: u32 = @intCast(extra.end);4225 var extra_index: u32 = @intCast(extra.end);
4275 const cau: Cau.Index.Optional = if (extra.data.zir_index == .none) cau: {4226 if (extra.data.zir_index == .none) {
4276 extra_index += 1; // owner_union4227 extra_index += 1; // owner_union
4277 break :cau .none;4228 }
4278 } else cau: {
4279 const cau: Cau.Index = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);
4280 extra_index += 1; // cau
4281 break :cau cau.toOptional();
4282 };
4283 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {4229 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {
4284 extra_index += 2; // type_hash: PackedU644230 extra_index += 2; // type_hash: PackedU64
4285 break :c 0;4231 break :c 0;
4286 } else extra.data.captures_len;4232 } else extra.data.captures_len;
4287 return .{4233 return .{
4288 .name = extra.data.name,4234 .name = extra.data.name,
4289 .cau = cau,
4290 .namespace = extra.data.namespace,4235 .namespace = extra.data.namespace,
4291 .tag_ty = extra.data.int_tag_type,4236 .tag_ty = extra.data.int_tag_type,
4292 .names = .{4237 .names = .{
...@@ -5256,7 +5201,6 @@ pub const Tag = enum(u8) {...@@ -5256,7 +5201,6 @@ pub const Tag = enum(u8) {
5256 .payload = EnumExplicit,5201 .payload = EnumExplicit,
5257 .trailing = struct {5202 .trailing = struct {
5258 owner_union: Index,5203 owner_union: Index,
5259 cau: ?Cau.Index,
5260 captures: ?[]CaptureValue,5204 captures: ?[]CaptureValue,
5261 type_hash: ?u64,5205 type_hash: ?u64,
5262 field_names: []NullTerminatedString,5206 field_names: []NullTerminatedString,
...@@ -5302,7 +5246,6 @@ pub const Tag = enum(u8) {...@@ -5302,7 +5246,6 @@ pub const Tag = enum(u8) {
5302 .payload = EnumAuto,5246 .payload = EnumAuto,
5303 .trailing = struct {5247 .trailing = struct {
5304 owner_union: ?Index,5248 owner_union: ?Index,
5305 cau: ?Cau.Index,
5306 captures: ?[]CaptureValue,5249 captures: ?[]CaptureValue,
5307 type_hash: ?u64,5250 type_hash: ?u64,
5308 field_names: []NullTerminatedString,5251 field_names: []NullTerminatedString,
...@@ -5679,7 +5622,6 @@ pub const Tag = enum(u8) {...@@ -5679,7 +5622,6 @@ pub const Tag = enum(u8) {
5679 size: u32,5622 size: u32,
5680 /// Only valid after .have_layout5623 /// Only valid after .have_layout
5681 padding: u32,5624 padding: u32,
5682 cau: Cau.Index,
5683 namespace: NamespaceIndex,5625 namespace: NamespaceIndex,
5684 /// The enum that provides the list of field names and values.5626 /// The enum that provides the list of field names and values.
5685 tag_ty: Index,5627 tag_ty: Index,
...@@ -5710,7 +5652,6 @@ pub const Tag = enum(u8) {...@@ -5710,7 +5652,6 @@ pub const Tag = enum(u8) {
5710 /// 5. init: Index for each fields_len // if tag is type_struct_packed_inits5652 /// 5. init: Index for each fields_len // if tag is type_struct_packed_inits
5711 pub const TypeStructPacked = struct {5653 pub const TypeStructPacked = struct {
5712 name: NullTerminatedString,5654 name: NullTerminatedString,
5713 cau: Cau.Index,
5714 zir_index: TrackedInst.Index,5655 zir_index: TrackedInst.Index,
5715 fields_len: u32,5656 fields_len: u32,
5716 namespace: NamespaceIndex,5657 namespace: NamespaceIndex,
...@@ -5758,7 +5699,6 @@ pub const Tag = enum(u8) {...@@ -5758,7 +5699,6 @@ pub const Tag = enum(u8) {
5758 /// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved5699 /// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved
5759 pub const TypeStruct = struct {5700 pub const TypeStruct = struct {
5760 name: NullTerminatedString,5701 name: NullTerminatedString,
5761 cau: Cau.Index,
5762 zir_index: TrackedInst.Index,5702 zir_index: TrackedInst.Index,
5763 namespace: NamespaceIndex,5703 namespace: NamespaceIndex,
5764 fields_len: u32,5704 fields_len: u32,
...@@ -6088,11 +6028,10 @@ pub const Array = struct {...@@ -6088,11 +6028,10 @@ pub const Array = struct {
60886028
6089/// Trailing:6029/// Trailing:
6090/// 0. owner_union: Index // if `zir_index == .none`6030/// 0. owner_union: Index // if `zir_index == .none`
6091/// 1. cau: Cau.Index // if `zir_index != .none`6031/// 1. capture: CaptureValue // for each `captures_len`
6092/// 2. capture: CaptureValue // for each `captures_len`6032/// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)
6093/// 3. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)6033/// 3. field name: NullTerminatedString for each fields_len; declaration order
6094/// 4. field name: NullTerminatedString for each fields_len; declaration order6034/// 4. tag value: Index for each fields_len; declaration order
6095/// 5. tag value: Index for each fields_len; declaration order
6096pub const EnumExplicit = struct {6035pub const EnumExplicit = struct {
6097 name: NullTerminatedString,6036 name: NullTerminatedString,
6098 /// `std.math.maxInt(u32)` indicates this type is reified.6037 /// `std.math.maxInt(u32)` indicates this type is reified.
...@@ -6115,10 +6054,9 @@ pub const EnumExplicit = struct {...@@ -6115,10 +6054,9 @@ pub const EnumExplicit = struct {
61156054
6116/// Trailing:6055/// Trailing:
6117/// 0. owner_union: Index // if `zir_index == .none`6056/// 0. owner_union: Index // if `zir_index == .none`
6118/// 1. cau: Cau.Index // if `zir_index != .none`6057/// 1. capture: CaptureValue // for each `captures_len`
6119/// 2. capture: CaptureValue // for each `captures_len`6058/// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)
6120/// 3. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)6059/// 3. field name: NullTerminatedString for each fields_len; declaration order
6121/// 4. field name: NullTerminatedString for each fields_len; declaration order
6122pub const EnumAuto = struct {6060pub const EnumAuto = struct {
6123 name: NullTerminatedString,6061 name: NullTerminatedString,
6124 /// `std.math.maxInt(u32)` indicates this type is reified.6062 /// `std.math.maxInt(u32)` indicates this type is reified.
...@@ -6408,32 +6346,32 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {...@@ -6408,32 +6346,32 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
6408 ip.locals = try gpa.alloc(Local, used_threads);6346 ip.locals = try gpa.alloc(Local, used_threads);
6409 @memset(ip.locals, .{6347 @memset(ip.locals, .{
6410 .shared = .{6348 .shared = .{
6411 .items = Local.List(Item).empty,6349 .items = .empty,
6412 .extra = Local.Extra.empty,6350 .extra = .empty,
6413 .limbs = Local.Limbs.empty,6351 .limbs = .empty,
6414 .strings = Local.Strings.empty,6352 .strings = .empty,
6415 .tracked_insts = Local.TrackedInsts.empty,6353 .tracked_insts = .empty,
6416 .files = Local.List(File).empty,6354 .files = .empty,
6417 .maps = Local.Maps.empty,6355 .maps = .empty,
6418 .caus = Local.Caus.empty,6356 .navs = .empty,
6419 .navs = Local.Navs.empty,6357 .comptime_units = .empty,
64206358
6421 .namespaces = Local.Namespaces.empty,6359 .namespaces = .empty,
6422 },6360 },
6423 .mutate = .{6361 .mutate = .{
6424 .arena = .{},6362 .arena = .{},
64256363
6426 .items = Local.ListMutate.empty,6364 .items = .empty,
6427 .extra = Local.ListMutate.empty,6365 .extra = .empty,
6428 .limbs = Local.ListMutate.empty,6366 .limbs = .empty,
6429 .strings = Local.ListMutate.empty,6367 .strings = .empty,
6430 .tracked_insts = Local.ListMutate.empty,6368 .tracked_insts = .empty,
6431 .files = Local.ListMutate.empty,6369 .files = .empty,
6432 .maps = Local.ListMutate.empty,6370 .maps = .empty,
6433 .caus = Local.ListMutate.empty,6371 .navs = .empty,
6434 .navs = Local.ListMutate.empty,6372 .comptime_units = .empty,
64356373
6436 .namespaces = Local.BucketListMutate.empty,6374 .namespaces = .empty,
6437 },6375 },
6438 });6376 });
64396377
...@@ -6506,7 +6444,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -6506,7 +6444,8 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
6506 namespace.priv_decls.deinit(gpa);6444 namespace.priv_decls.deinit(gpa);
6507 namespace.pub_usingnamespace.deinit(gpa);6445 namespace.pub_usingnamespace.deinit(gpa);
6508 namespace.priv_usingnamespace.deinit(gpa);6446 namespace.priv_usingnamespace.deinit(gpa);
6509 namespace.other_decls.deinit(gpa);6447 namespace.comptime_decls.deinit(gpa);
6448 namespace.test_decls.deinit(gpa);
6510 }6449 }
6511 };6450 };
6512 const maps = local.getMutableMaps(gpa);6451 const maps = local.getMutableMaps(gpa);
...@@ -6525,8 +6464,6 @@ pub fn activate(ip: *const InternPool) void {...@@ -6525,8 +6464,6 @@ pub fn activate(ip: *const InternPool) void {
6525 _ = OptionalString.debug_state;6464 _ = OptionalString.debug_state;
6526 _ = NullTerminatedString.debug_state;6465 _ = NullTerminatedString.debug_state;
6527 _ = OptionalNullTerminatedString.debug_state;6466 _ = OptionalNullTerminatedString.debug_state;
6528 _ = Cau.Index.debug_state;
6529 _ = Cau.Index.Optional.debug_state;
6530 _ = Nav.Index.debug_state;6467 _ = Nav.Index.debug_state;
6531 _ = Nav.Index.Optional.debug_state;6468 _ = Nav.Index.Optional.debug_state;
6532 std.debug.assert(debug_state.intern_pool == null);6469 std.debug.assert(debug_state.intern_pool == null);
...@@ -6711,14 +6648,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6711,14 +6648,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6711 if (extra.data.captures_len == std.math.maxInt(u32)) {6648 if (extra.data.captures_len == std.math.maxInt(u32)) {
6712 break :ns .{ .reified = .{6649 break :ns .{ .reified = .{
6713 .zir_index = zir_index,6650 .zir_index = zir_index,
6714 .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(),6651 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
6715 } };6652 } };
6716 }6653 }
6717 break :ns .{ .declared = .{6654 break :ns .{ .declared = .{
6718 .zir_index = zir_index,6655 .zir_index = zir_index,
6719 .captures = .{ .owned = .{6656 .captures = .{ .owned = .{
6720 .tid = unwrapped_index.tid,6657 .tid = unwrapped_index.tid,
6721 .start = extra.end + 1,6658 .start = extra.end,
6722 .len = extra.data.captures_len,6659 .len = extra.data.captures_len,
6723 } },6660 } },
6724 } };6661 } };
...@@ -6735,14 +6672,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6735,14 +6672,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6735 if (extra.data.captures_len == std.math.maxInt(u32)) {6672 if (extra.data.captures_len == std.math.maxInt(u32)) {
6736 break :ns .{ .reified = .{6673 break :ns .{ .reified = .{
6737 .zir_index = zir_index,6674 .zir_index = zir_index,
6738 .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(),6675 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
6739 } };6676 } };
6740 }6677 }
6741 break :ns .{ .declared = .{6678 break :ns .{ .declared = .{
6742 .zir_index = zir_index,6679 .zir_index = zir_index,
6743 .captures = .{ .owned = .{6680 .captures = .{ .owned = .{
6744 .tid = unwrapped_index.tid,6681 .tid = unwrapped_index.tid,
6745 .start = extra.end + 1,6682 .start = extra.end,
6746 .len = extra.data.captures_len,6683 .len = extra.data.captures_len,
6747 } },6684 } },
6748 } };6685 } };
...@@ -8323,7 +8260,6 @@ pub fn getUnionType(...@@ -8323,7 +8260,6 @@ pub fn getUnionType(
8323 .size = std.math.maxInt(u32),8260 .size = std.math.maxInt(u32),
8324 .padding = std.math.maxInt(u32),8261 .padding = std.math.maxInt(u32),
8325 .name = undefined, // set by `finish`8262 .name = undefined, // set by `finish`
8326 .cau = undefined, // set by `finish`
8327 .namespace = undefined, // set by `finish`8263 .namespace = undefined, // set by `finish`
8328 .tag_ty = ini.enum_tag_ty,8264 .tag_ty = ini.enum_tag_ty,
8329 .zir_index = switch (ini.key) {8265 .zir_index = switch (ini.key) {
...@@ -8375,7 +8311,6 @@ pub fn getUnionType(...@@ -8375,7 +8311,6 @@ pub fn getUnionType(
8375 .tid = tid,8311 .tid = tid,
8376 .index = gop.put(),8312 .index = gop.put(),
8377 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?,8313 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?,
8378 .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "cau").?,
8379 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?,8314 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?,
8380 } };8315 } };
8381}8316}
...@@ -8384,7 +8319,6 @@ pub const WipNamespaceType = struct {...@@ -8384,7 +8319,6 @@ pub const WipNamespaceType = struct {
8384 tid: Zcu.PerThread.Id,8319 tid: Zcu.PerThread.Id,
8385 index: Index,8320 index: Index,
8386 type_name_extra_index: u32,8321 type_name_extra_index: u32,
8387 cau_extra_index: ?u32,
8388 namespace_extra_index: u32,8322 namespace_extra_index: u32,
83898323
8390 pub fn setName(8324 pub fn setName(
...@@ -8400,18 +8334,11 @@ pub const WipNamespaceType = struct {...@@ -8400,18 +8334,11 @@ pub const WipNamespaceType = struct {
8400 pub fn finish(8334 pub fn finish(
8401 wip: WipNamespaceType,8335 wip: WipNamespaceType,
8402 ip: *InternPool,8336 ip: *InternPool,
8403 analysis_owner: Cau.Index.Optional,
8404 namespace: NamespaceIndex,8337 namespace: NamespaceIndex,
8405 ) Index {8338 ) Index {
8406 const extra = ip.getLocalShared(wip.tid).extra.acquire();8339 const extra = ip.getLocalShared(wip.tid).extra.acquire();
8407 const extra_items = extra.view().items(.@"0");8340 const extra_items = extra.view().items(.@"0");
84088341
8409 if (wip.cau_extra_index) |i| {
8410 extra_items[i] = @intFromEnum(analysis_owner.unwrap().?);
8411 } else {
8412 assert(analysis_owner == .none);
8413 }
8414
8415 extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);8342 extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);
84168343
8417 return wip.index;8344 return wip.index;
...@@ -8510,7 +8437,6 @@ pub fn getStructType(...@@ -8510,7 +8437,6 @@ pub fn getStructType(
8510 ini.fields_len); // inits8437 ini.fields_len); // inits
8511 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{8438 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{
8512 .name = undefined, // set by `finish`8439 .name = undefined, // set by `finish`
8513 .cau = undefined, // set by `finish`
8514 .zir_index = zir_index,8440 .zir_index = zir_index,
8515 .fields_len = ini.fields_len,8441 .fields_len = ini.fields_len,
8516 .namespace = undefined, // set by `finish`8442 .namespace = undefined, // set by `finish`
...@@ -8555,7 +8481,6 @@ pub fn getStructType(...@@ -8555,7 +8481,6 @@ pub fn getStructType(
8555 .tid = tid,8481 .tid = tid,
8556 .index = gop.put(),8482 .index = gop.put(),
8557 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?,8483 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?,
8558 .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "cau").?,
8559 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?,8484 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?,
8560 } };8485 } };
8561 },8486 },
...@@ -8578,7 +8503,6 @@ pub fn getStructType(...@@ -8578,7 +8503,6 @@ pub fn getStructType(
8578 1); // names_map8503 1); // names_map
8579 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{8504 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{
8580 .name = undefined, // set by `finish`8505 .name = undefined, // set by `finish`
8581 .cau = undefined, // set by `finish`
8582 .zir_index = zir_index,8506 .zir_index = zir_index,
8583 .namespace = undefined, // set by `finish`8507 .namespace = undefined, // set by `finish`
8584 .fields_len = ini.fields_len,8508 .fields_len = ini.fields_len,
...@@ -8647,7 +8571,6 @@ pub fn getStructType(...@@ -8647,7 +8571,6 @@ pub fn getStructType(
8647 .tid = tid,8571 .tid = tid,
8648 .index = gop.put(),8572 .index = gop.put(),
8649 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?,8573 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?,
8650 .cau_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "cau").?,
8651 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?,8574 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?,
8652 } };8575 } };
8653}8576}
...@@ -9383,7 +9306,7 @@ fn finishFuncInstance(...@@ -9383,7 +9306,7 @@ fn finishFuncInstance(
9383 func_extra_index: u32,9306 func_extra_index: u32,
9384) Allocator.Error!void {9307) Allocator.Error!void {
9385 const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav);9308 const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav);
9386 const fn_namespace = ip.getCau(fn_owner_nav.analysis_owner.unwrap().?).namespace;9309 const fn_namespace = fn_owner_nav.analysis.?.namespace;
93879310
9388 // TODO: improve this name9311 // TODO: improve this name
9389 const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{}__anon_{d}", .{9312 const nav_name = try ip.getOrPutStringFmt(gpa, tid, "{}__anon_{d}", .{
...@@ -9429,7 +9352,6 @@ pub const WipEnumType = struct {...@@ -9429,7 +9352,6 @@ pub const WipEnumType = struct {
9429 index: Index,9352 index: Index,
9430 tag_ty_index: u32,9353 tag_ty_index: u32,
9431 type_name_extra_index: u32,9354 type_name_extra_index: u32,
9432 cau_extra_index: u32,
9433 namespace_extra_index: u32,9355 namespace_extra_index: u32,
9434 names_map: MapIndex,9356 names_map: MapIndex,
9435 names_start: u32,9357 names_start: u32,
...@@ -9449,13 +9371,11 @@ pub const WipEnumType = struct {...@@ -9449,13 +9371,11 @@ pub const WipEnumType = struct {
9449 pub fn prepare(9371 pub fn prepare(
9450 wip: WipEnumType,9372 wip: WipEnumType,
9451 ip: *InternPool,9373 ip: *InternPool,
9452 analysis_owner: Cau.Index,
9453 namespace: NamespaceIndex,9374 namespace: NamespaceIndex,
9454 ) void {9375 ) void {
9455 const extra = ip.getLocalShared(wip.tid).extra.acquire();9376 const extra = ip.getLocalShared(wip.tid).extra.acquire();
9456 const extra_items = extra.view().items(.@"0");9377 const extra_items = extra.view().items(.@"0");
94579378
9458 extra_items[wip.cau_extra_index] = @intFromEnum(analysis_owner);
9459 extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);9379 extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);
9460 }9380 }
94619381
...@@ -9556,7 +9476,6 @@ pub fn getEnumType(...@@ -9556,7 +9476,6 @@ pub fn getEnumType(
9556 .reified => 2, // type_hash: PackedU649476 .reified => 2, // type_hash: PackedU64
9557 } +9477 } +
9558 // zig fmt: on9478 // zig fmt: on
9559 1 + // cau
9560 ini.fields_len); // field types9479 ini.fields_len); // field types
95619480
9562 const extra_index = addExtraAssumeCapacity(extra, EnumAuto{9481 const extra_index = addExtraAssumeCapacity(extra, EnumAuto{
...@@ -9577,8 +9496,6 @@ pub fn getEnumType(...@@ -9577,8 +9496,6 @@ pub fn getEnumType(
9577 .tag = .type_enum_auto,9496 .tag = .type_enum_auto,
9578 .data = extra_index,9497 .data = extra_index,
9579 });9498 });
9580 const cau_extra_index = extra.view().len;
9581 extra.appendAssumeCapacity(undefined); // `cau` will be set by `finish`
9582 switch (ini.key) {9499 switch (ini.key) {
9583 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),9500 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
9584 .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),9501 .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),
...@@ -9591,7 +9508,6 @@ pub fn getEnumType(...@@ -9591,7 +9508,6 @@ pub fn getEnumType(
9591 .index = gop.put(),9508 .index = gop.put(),
9592 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?,9509 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?,
9593 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?,9510 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?,
9594 .cau_extra_index = @intCast(cau_extra_index),
9595 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?,9511 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?,
9596 .names_map = names_map,9512 .names_map = names_map,
9597 .names_start = @intCast(names_start),9513 .names_start = @intCast(names_start),
...@@ -9616,7 +9532,6 @@ pub fn getEnumType(...@@ -9616,7 +9532,6 @@ pub fn getEnumType(
9616 .reified => 2, // type_hash: PackedU649532 .reified => 2, // type_hash: PackedU64
9617 } +9533 } +
9618 // zig fmt: on9534 // zig fmt: on
9619 1 + // cau
9620 ini.fields_len + // field types9535 ini.fields_len + // field types
9621 ini.fields_len * @intFromBool(ini.has_values)); // field values9536 ini.fields_len * @intFromBool(ini.has_values)); // field values
96229537
...@@ -9643,8 +9558,6 @@ pub fn getEnumType(...@@ -9643,8 +9558,6 @@ pub fn getEnumType(
9643 },9558 },
9644 .data = extra_index,9559 .data = extra_index,
9645 });9560 });
9646 const cau_extra_index = extra.view().len;
9647 extra.appendAssumeCapacity(undefined); // `cau` will be set by `finish`
9648 switch (ini.key) {9561 switch (ini.key) {
9649 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),9562 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
9650 .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),9563 .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),
...@@ -9661,7 +9574,6 @@ pub fn getEnumType(...@@ -9661,7 +9574,6 @@ pub fn getEnumType(
9661 .index = gop.put(),9574 .index = gop.put(),
9662 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?,9575 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?,
9663 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?,9576 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?,
9664 .cau_extra_index = @intCast(cau_extra_index),
9665 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?,9577 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?,
9666 .names_map = names_map,9578 .names_map = names_map,
9667 .names_start = @intCast(names_start),9579 .names_start = @intCast(names_start),
...@@ -9858,7 +9770,6 @@ pub fn getOpaqueType(...@@ -9858,7 +9770,6 @@ pub fn getOpaqueType(
9858 .tid = tid,9770 .tid = tid,
9859 .index = gop.put(),9771 .index = gop.put(),
9860 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?,9772 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?,
9861 .cau_extra_index = null, // opaques do not undergo type resolution
9862 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?,9773 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?,
9863 },9774 },
9864 };9775 };
...@@ -9974,7 +9885,6 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 {...@@ -9974,7 +9885,6 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 {
9974 inline for (@typeInfo(@TypeOf(item)).@"struct".fields) |field| {9885 inline for (@typeInfo(@TypeOf(item)).@"struct".fields) |field| {
9975 extra.appendAssumeCapacity(.{switch (field.type) {9886 extra.appendAssumeCapacity(.{switch (field.type) {
9976 Index,9887 Index,
9977 Cau.Index,
9978 Nav.Index,9888 Nav.Index,
9979 NamespaceIndex,9889 NamespaceIndex,
9980 OptionalNamespaceIndex,9890 OptionalNamespaceIndex,
...@@ -10037,7 +9947,6 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat...@@ -10037,7 +9947,6 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat
10037 const extra_item = extra_items[extra_index];9947 const extra_item = extra_items[extra_index];
10038 @field(result, field.name) = switch (field.type) {9948 @field(result, field.name) = switch (field.type) {
10039 Index,9949 Index,
10040 Cau.Index,
10041 Nav.Index,9950 Nav.Index,
10042 NamespaceIndex,9951 NamespaceIndex,
10043 OptionalNamespaceIndex,9952 OptionalNamespaceIndex,
...@@ -11058,12 +10967,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)...@@ -11058,12 +10967,6 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator)
11058 try bw.flush();10967 try bw.flush();
11059}10968}
1106010969
11061pub fn getCau(ip: *const InternPool, index: Cau.Index) Cau {
11062 const unwrapped = index.unwrap(ip);
11063 const caus = ip.getLocalShared(unwrapped.tid).caus.acquire();
11064 return caus.view().items(.@"0")[unwrapped.index];
11065}
11066
11067pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {10970pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {
11068 const unwrapped = index.unwrap(ip);10971 const unwrapped = index.unwrap(ip);
11069 const navs = ip.getLocalShared(unwrapped.tid).navs.acquire();10972 const navs = ip.getLocalShared(unwrapped.tid).navs.acquire();
...@@ -11077,51 +10980,34 @@ pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Names...@@ -11077,51 +10980,34 @@ pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Names
11077 return &namespaces_bucket[unwrapped_namespace_index.index];10980 return &namespaces_bucket[unwrapped_namespace_index.index];
11078}10981}
1107910982
11080/// Create a `Cau` associated with the type at the given `InternPool.Index`.10983/// Create a `ComptimeUnit`, forming an `AnalUnit` for a `comptime` declaration.
11081pub fn createTypeCau(10984pub fn createComptimeUnit(
11082 ip: *InternPool,10985 ip: *InternPool,
11083 gpa: Allocator,10986 gpa: Allocator,
11084 tid: Zcu.PerThread.Id,10987 tid: Zcu.PerThread.Id,
11085 zir_index: TrackedInst.Index,10988 zir_index: TrackedInst.Index,
11086 namespace: NamespaceIndex,10989 namespace: NamespaceIndex,
11087 owner_type: InternPool.Index,10990) Allocator.Error!ComptimeUnit.Id {
11088) Allocator.Error!Cau.Index {10991 const comptime_units = ip.getLocal(tid).getMutableComptimeUnits(gpa);
11089 const caus = ip.getLocal(tid).getMutableCaus(gpa);10992 const id_unwrapped: ComptimeUnit.Id.Unwrapped = .{
11090 const index_unwrapped: Cau.Index.Unwrapped = .{
11091 .tid = tid,10993 .tid = tid,
11092 .index = caus.mutate.len,10994 .index = comptime_units.mutate.len,
11093 };10995 };
11094 try caus.append(.{.{10996 try comptime_units.append(.{.{
11095 .zir_index = zir_index,10997 .zir_index = zir_index,
11096 .namespace = namespace,10998 .namespace = namespace,
11097 .owner = Cau.Owner.wrap(.{ .type = owner_type }),
11098 }});10999 }});
11099 return index_unwrapped.wrap(ip);11000 return id_unwrapped.wrap(ip);
11100}11001}
1110111002
11102/// Create a `Cau` for a `comptime` declaration.11003pub fn getComptimeUnit(ip: *const InternPool, id: ComptimeUnit.Id) ComptimeUnit {
11103pub fn createComptimeCau(11004 const unwrapped = id.unwrap(ip);
11104 ip: *InternPool,11005 const comptime_units = ip.getLocalShared(unwrapped.tid).comptime_units.acquire();
11105 gpa: Allocator,11006 return comptime_units.view().items(.@"0")[unwrapped.index];
11106 tid: Zcu.PerThread.Id,
11107 zir_index: TrackedInst.Index,
11108 namespace: NamespaceIndex,
11109) Allocator.Error!Cau.Index {
11110 const caus = ip.getLocal(tid).getMutableCaus(gpa);
11111 const index_unwrapped: Cau.Index.Unwrapped = .{
11112 .tid = tid,
11113 .index = caus.mutate.len,
11114 };
11115 try caus.append(.{.{
11116 .zir_index = zir_index,
11117 .namespace = namespace,
11118 .owner = Cau.Owner.wrap(.none),
11119 }});
11120 return index_unwrapped.wrap(ip);
11121}11007}
1112211008
11123/// Create a `Nav` not associated with any `Cau`.11009/// Create a `Nav` which does not undergo semantic analysis.
11124/// Since there is no analysis owner, the `Nav`'s value must be known at creation time.11010/// Since it is never analyzed, the `Nav`'s value must be known at creation time.
11125pub fn createNav(11011pub fn createNav(
11126 ip: *InternPool,11012 ip: *InternPool,
11127 gpa: Allocator,11013 gpa: Allocator,
...@@ -11143,7 +11029,7 @@ pub fn createNav(...@@ -11143,7 +11029,7 @@ pub fn createNav(
11143 try navs.append(Nav.pack(.{11029 try navs.append(Nav.pack(.{
11144 .name = opts.name,11030 .name = opts.name,
11145 .fqn = opts.fqn,11031 .fqn = opts.fqn,
11146 .analysis_owner = .none,11032 .analysis = null,
11147 .status = .{ .resolved = .{11033 .status = .{ .resolved = .{
11148 .val = opts.val,11034 .val = opts.val,
11149 .alignment = opts.alignment,11035 .alignment = opts.alignment,
...@@ -11155,10 +11041,9 @@ pub fn createNav(...@@ -11155,10 +11041,9 @@ pub fn createNav(
11155 return index_unwrapped.wrap(ip);11041 return index_unwrapped.wrap(ip);
11156}11042}
1115711043
11158/// Create a `Cau` and `Nav` which are paired. The value of the `Nav` is11044/// Create a `Nav` which undergoes semantic analysis because it corresponds to a source declaration.
11159/// determined by semantic analysis of the `Cau`. The value of the `Nav`11045/// The value of the `Nav` is initially unresolved.
11160/// is initially unresolved.11046pub fn createDeclNav(
11161pub fn createPairedCauNav(
11162 ip: *InternPool,11047 ip: *InternPool,
11163 gpa: Allocator,11048 gpa: Allocator,
11164 tid: Zcu.PerThread.Id,11049 tid: Zcu.PerThread.Id,
...@@ -11168,36 +11053,28 @@ pub fn createPairedCauNav(...@@ -11168,36 +11053,28 @@ pub fn createPairedCauNav(
11168 namespace: NamespaceIndex,11053 namespace: NamespaceIndex,
11169 /// TODO: this is hacky! See `Nav.is_usingnamespace`.11054 /// TODO: this is hacky! See `Nav.is_usingnamespace`.
11170 is_usingnamespace: bool,11055 is_usingnamespace: bool,
11171) Allocator.Error!struct { Cau.Index, Nav.Index } {11056) Allocator.Error!Nav.Index {
11172 const caus = ip.getLocal(tid).getMutableCaus(gpa);
11173 const navs = ip.getLocal(tid).getMutableNavs(gpa);11057 const navs = ip.getLocal(tid).getMutableNavs(gpa);
1117411058
11175 try caus.ensureUnusedCapacity(1);
11176 try navs.ensureUnusedCapacity(1);11059 try navs.ensureUnusedCapacity(1);
1117711060
11178 const cau = Cau.Index.Unwrapped.wrap(.{
11179 .tid = tid,
11180 .index = caus.mutate.len,
11181 }, ip);
11182 const nav = Nav.Index.Unwrapped.wrap(.{11061 const nav = Nav.Index.Unwrapped.wrap(.{
11183 .tid = tid,11062 .tid = tid,
11184 .index = navs.mutate.len,11063 .index = navs.mutate.len,
11185 }, ip);11064 }, ip);
1118611065
11187 caus.appendAssumeCapacity(.{.{
11188 .zir_index = zir_index,
11189 .namespace = namespace,
11190 .owner = Cau.Owner.wrap(.{ .nav = nav }),
11191 }});
11192 navs.appendAssumeCapacity(Nav.pack(.{11066 navs.appendAssumeCapacity(Nav.pack(.{
11193 .name = name,11067 .name = name,
11194 .fqn = fqn,11068 .fqn = fqn,
11195 .analysis_owner = cau.toOptional(),11069 .analysis = .{
11070 .namespace = namespace,
11071 .zir_index = zir_index,
11072 },
11196 .status = .unresolved,11073 .status = .unresolved,
11197 .is_usingnamespace = is_usingnamespace,11074 .is_usingnamespace = is_usingnamespace,
11198 }));11075 }));
1119911076
11200 return .{ cau, nav };11077 return nav;
11201}11078}
1120211079
11203/// Resolve the value of a `Nav` with an analysis owner.11080/// Resolve the value of a `Nav` with an analysis owner.
...@@ -11220,12 +11097,14 @@ pub fn resolveNavValue(...@@ -11220,12 +11097,14 @@ pub fn resolveNavValue(
1122011097
11221 const navs = local.shared.navs.view();11098 const navs = local.shared.navs.view();
1122211099
11223 const nav_analysis_owners = navs.items(.analysis_owner);11100 const nav_analysis_namespace = navs.items(.analysis_namespace);
11101 const nav_analysis_zir_index = navs.items(.analysis_zir_index);
11224 const nav_vals = navs.items(.val);11102 const nav_vals = navs.items(.val);
11225 const nav_linksections = navs.items(.@"linksection");11103 const nav_linksections = navs.items(.@"linksection");
11226 const nav_bits = navs.items(.bits);11104 const nav_bits = navs.items(.bits);
1122711105
11228 assert(nav_analysis_owners[unwrapped.index] != .none);11106 assert(nav_analysis_namespace[unwrapped.index] != .none);
11107 assert(nav_analysis_zir_index[unwrapped.index] != .none);
1122911108
11230 @atomicStore(InternPool.Index, &nav_vals[unwrapped.index], resolved.val, .release);11109 @atomicStore(InternPool.Index, &nav_vals[unwrapped.index], resolved.val, .release);
11231 @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release);11110 @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release);
src/Sema.zig+85-143
...@@ -2870,7 +2870,7 @@ fn zirStructDecl(...@@ -2870,7 +2870,7 @@ fn zirStructDecl(
2870 };2870 };
2871 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, struct_init, false)) {2871 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, struct_init, false)) {
2872 .existing => |ty| {2872 .existing => |ty| {
2873 const new_ty = try pt.ensureTypeUpToDate(ty, false);2873 const new_ty = try pt.ensureTypeUpToDate(ty);
28742874
2875 // Make sure we update the namespace if the declaration is re-analyzed, to pick2875 // Make sure we update the namespace if the declaration is re-analyzed, to pick
2876 // up on e.g. changed comptime decls.2876 // up on e.g. changed comptime decls.
...@@ -2900,12 +2900,10 @@ fn zirStructDecl(...@@ -2900,12 +2900,10 @@ fn zirStructDecl(
2900 });2900 });
2901 errdefer pt.destroyNamespace(new_namespace_index);2901 errdefer pt.destroyNamespace(new_namespace_index);
29022902
2903 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
2904
2905 if (pt.zcu.comp.incremental) {2903 if (pt.zcu.comp.incremental) {
2906 try ip.addDependency(2904 try ip.addDependency(
2907 sema.gpa,2905 sema.gpa,
2908 AnalUnit.wrap(.{ .cau = new_cau_index }),2906 AnalUnit.wrap(.{ .type = wip_ty.index }),
2909 .{ .src_hash = tracked_inst },2907 .{ .src_hash = tracked_inst },
2910 );2908 );
2911 }2909 }
...@@ -2922,7 +2920,7 @@ fn zirStructDecl(...@@ -2922,7 +2920,7 @@ fn zirStructDecl(
2922 }2920 }
2923 try sema.declareDependency(.{ .interned = wip_ty.index });2921 try sema.declareDependency(.{ .interned = wip_ty.index });
2924 try sema.addTypeReferenceEntry(src, wip_ty.index);2922 try sema.addTypeReferenceEntry(src, wip_ty.index);
2925 return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));2923 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
2926}2924}
29272925
2928fn createTypeName(2926fn createTypeName(
...@@ -3100,7 +3098,7 @@ fn zirEnumDecl(...@@ -3100,7 +3098,7 @@ fn zirEnumDecl(
3100 };3098 };
3101 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, enum_init, false)) {3099 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, enum_init, false)) {
3102 .existing => |ty| {3100 .existing => |ty| {
3103 const new_ty = try pt.ensureTypeUpToDate(ty, false);3101 const new_ty = try pt.ensureTypeUpToDate(ty);
31043102
3105 // Make sure we update the namespace if the declaration is re-analyzed, to pick3103 // Make sure we update the namespace if the declaration is re-analyzed, to pick
3106 // up on e.g. changed comptime decls.3104 // up on e.g. changed comptime decls.
...@@ -3136,16 +3134,14 @@ fn zirEnumDecl(...@@ -3136,16 +3134,14 @@ fn zirEnumDecl(
3136 });3134 });
3137 errdefer if (!done) pt.destroyNamespace(new_namespace_index);3135 errdefer if (!done) pt.destroyNamespace(new_namespace_index);
31383136
3139 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
3140
3141 try pt.scanNamespace(new_namespace_index, decls);3137 try pt.scanNamespace(new_namespace_index, decls);
31423138
3143 try sema.declareDependency(.{ .interned = wip_ty.index });3139 try sema.declareDependency(.{ .interned = wip_ty.index });
3144 try sema.addTypeReferenceEntry(src, wip_ty.index);3140 try sema.addTypeReferenceEntry(src, wip_ty.index);
31453141
3146 // We've finished the initial construction of this type, and are about to perform analysis.3142 // We've finished the initial construction of this type, and are about to perform analysis.
3147 // Set the Cau and namespace appropriately, and don't destroy anything on failure.3143 // Set the namespace appropriately, and don't destroy anything on failure.
3148 wip_ty.prepare(ip, new_cau_index, new_namespace_index);3144 wip_ty.prepare(ip, new_namespace_index);
3149 done = true;3145 done = true;
31503146
3151 try Sema.resolveDeclaredEnum(3147 try Sema.resolveDeclaredEnum(
...@@ -3155,7 +3151,6 @@ fn zirEnumDecl(...@@ -3155,7 +3151,6 @@ fn zirEnumDecl(
3155 tracked_inst,3151 tracked_inst,
3156 new_namespace_index,3152 new_namespace_index,
3157 type_name,3153 type_name,
3158 new_cau_index,
3159 small,3154 small,
3160 body,3155 body,
3161 tag_type_ref,3156 tag_type_ref,
...@@ -3245,7 +3240,7 @@ fn zirUnionDecl(...@@ -3245,7 +3240,7 @@ fn zirUnionDecl(
3245 };3240 };
3246 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, union_init, false)) {3241 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, union_init, false)) {
3247 .existing => |ty| {3242 .existing => |ty| {
3248 const new_ty = try pt.ensureTypeUpToDate(ty, false);3243 const new_ty = try pt.ensureTypeUpToDate(ty);
32493244
3250 // Make sure we update the namespace if the declaration is re-analyzed, to pick3245 // Make sure we update the namespace if the declaration is re-analyzed, to pick
3251 // up on e.g. changed comptime decls.3246 // up on e.g. changed comptime decls.
...@@ -3275,12 +3270,10 @@ fn zirUnionDecl(...@@ -3275,12 +3270,10 @@ fn zirUnionDecl(
3275 });3270 });
3276 errdefer pt.destroyNamespace(new_namespace_index);3271 errdefer pt.destroyNamespace(new_namespace_index);
32773272
3278 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
3279
3280 if (pt.zcu.comp.incremental) {3273 if (pt.zcu.comp.incremental) {
3281 try zcu.intern_pool.addDependency(3274 try zcu.intern_pool.addDependency(
3282 gpa,3275 gpa,
3283 AnalUnit.wrap(.{ .cau = new_cau_index }),3276 AnalUnit.wrap(.{ .type = wip_ty.index }),
3284 .{ .src_hash = tracked_inst },3277 .{ .src_hash = tracked_inst },
3285 );3278 );
3286 }3279 }
...@@ -3297,7 +3290,7 @@ fn zirUnionDecl(...@@ -3297,7 +3290,7 @@ fn zirUnionDecl(
3297 }3290 }
3298 try sema.declareDependency(.{ .interned = wip_ty.index });3291 try sema.declareDependency(.{ .interned = wip_ty.index });
3299 try sema.addTypeReferenceEntry(src, wip_ty.index);3292 try sema.addTypeReferenceEntry(src, wip_ty.index);
3300 return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));3293 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
3301}3294}
33023295
3303fn zirOpaqueDecl(3296fn zirOpaqueDecl(
...@@ -3382,7 +3375,7 @@ fn zirOpaqueDecl(...@@ -3382,7 +3375,7 @@ fn zirOpaqueDecl(
3382 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });3375 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
3383 }3376 }
3384 try sema.addTypeReferenceEntry(src, wip_ty.index);3377 try sema.addTypeReferenceEntry(src, wip_ty.index);
3385 return Air.internedToRef(wip_ty.finish(ip, .none, new_namespace_index));3378 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
3386}3379}
33873380
3388fn zirErrorSetDecl(3381fn zirErrorSetDecl(
...@@ -6547,7 +6540,10 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {...@@ -6547,7 +6540,10 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
6547 const ip = &zcu.intern_pool;6540 const ip = &zcu.intern_pool;
6548 const func = switch (sema.owner.unwrap()) {6541 const func = switch (sema.owner.unwrap()) {
6549 .func => |func| func,6542 .func => |func| func,
6550 .cau => return, // does nothing outside a function6543 .@"comptime",
6544 .nav_val,
6545 .type,
6546 => return, // does nothing outside a function
6551 };6547 };
6552 ip.funcSetDisableInstrumentation(func);6548 ip.funcSetDisableInstrumentation(func);
6553 sema.allow_memoize = false;6549 sema.allow_memoize = false;
...@@ -6868,11 +6864,8 @@ fn lookupInNamespace(...@@ -6868,11 +6864,8 @@ fn lookupInNamespace(
68686864
6869 ignore_self: {6865 ignore_self: {
6870 const skip_nav = switch (sema.owner.unwrap()) {6866 const skip_nav = switch (sema.owner.unwrap()) {
6871 .func => break :ignore_self,6867 .@"comptime", .type, .func => break :ignore_self,
6872 .cau => |cau| switch (ip.getCau(cau).owner.unwrap()) {6868 .nav_val => |nav| nav,
6873 .none, .type => break :ignore_self,
6874 .nav => |nav| nav,
6875 },
6876 };6869 };
6877 var i: usize = 0;6870 var i: usize = 0;
6878 while (i < candidates.items.len) {6871 while (i < candidates.items.len) {
...@@ -7132,7 +7125,7 @@ fn zirCall(...@@ -7132,7 +7125,7 @@ fn zirCall(
7132 const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);7125 const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);
71337126
7134 switch (sema.owner.unwrap()) {7127 switch (sema.owner.unwrap()) {
7135 .cau => input_is_error = false,7128 .@"comptime", .type, .nav_val => input_is_error = false,
7136 .func => |owner_func| if (!zcu.intern_pool.funcAnalysisUnordered(owner_func).calls_or_awaits_errorable_fn) {7129 .func => |owner_func| if (!zcu.intern_pool.funcAnalysisUnordered(owner_func).calls_or_awaits_errorable_fn) {
7137 // No errorable fn actually called; we have no error return trace7130 // No errorable fn actually called; we have no error return trace
7138 input_is_error = false;7131 input_is_error = false;
...@@ -7747,11 +7740,9 @@ fn analyzeCall(...@@ -7747,11 +7740,9 @@ fn analyzeCall(
7747 // The call site definitely depends on the function's signature.7740 // The call site definitely depends on the function's signature.
7748 try sema.declareDependency(.{ .src_hash = module_fn.zir_body_inst });7741 try sema.declareDependency(.{ .src_hash = module_fn.zir_body_inst });
77497742
7750 // This is not a function instance, so the function's `Nav` has a7743 // This is not a function instance, so the function's `Nav` has analysis
7751 // `Cau` -- we don't need to check `generic_owner`.7744 // state -- we don't need to check `generic_owner`.
7752 const fn_nav = ip.getNav(module_fn.owner_nav);7745 const fn_nav = ip.getNav(module_fn.owner_nav);
7753 const fn_cau_index = fn_nav.analysis_owner.unwrap().?;
7754 const fn_cau = ip.getCau(fn_cau_index);
77557746
7756 // We effectively want a child Sema here, but can't literally do that, because we need AIR7747 // We effectively want a child Sema here, but can't literally do that, because we need AIR
7757 // to be shared. InlineCallSema is a wrapper which handles this for us. While `ics` is in7748 // to be shared. InlineCallSema is a wrapper which handles this for us. While `ics` is in
...@@ -7759,7 +7750,7 @@ fn analyzeCall(...@@ -7759,7 +7750,7 @@ fn analyzeCall(
7759 // whenever performing an operation where the difference matters.7750 // whenever performing an operation where the difference matters.
7760 var ics = InlineCallSema.init(7751 var ics = InlineCallSema.init(
7761 sema,7752 sema,
7762 zcu.cauFileScope(fn_cau_index).zir,7753 zcu.navFileScope(module_fn.owner_nav).zir,
7763 module_fn_index,7754 module_fn_index,
7764 block.error_return_trace_index,7755 block.error_return_trace_index,
7765 );7756 );
...@@ -7769,7 +7760,7 @@ fn analyzeCall(...@@ -7769,7 +7760,7 @@ fn analyzeCall(
7769 .parent = null,7760 .parent = null,
7770 .sema = sema,7761 .sema = sema,
7771 // The function body exists in the same namespace as the corresponding function declaration.7762 // The function body exists in the same namespace as the corresponding function declaration.
7772 .namespace = fn_cau.namespace,7763 .namespace = fn_nav.analysis.?.namespace,
7773 .instructions = .{},7764 .instructions = .{},
7774 .label = null,7765 .label = null,
7775 .inlining = &inlining,7766 .inlining = &inlining,
...@@ -7780,7 +7771,7 @@ fn analyzeCall(...@@ -7780,7 +7771,7 @@ fn analyzeCall(
7780 .runtime_cond = block.runtime_cond,7771 .runtime_cond = block.runtime_cond,
7781 .runtime_loop = block.runtime_loop,7772 .runtime_loop = block.runtime_loop,
7782 .runtime_index = block.runtime_index,7773 .runtime_index = block.runtime_index,
7783 .src_base_inst = fn_cau.zir_index,7774 .src_base_inst = fn_nav.analysis.?.zir_index,
7784 .type_name_ctx = fn_nav.fqn,7775 .type_name_ctx = fn_nav.fqn,
7785 };7776 };
77867777
...@@ -7795,7 +7786,7 @@ fn analyzeCall(...@@ -7795,7 +7786,7 @@ fn analyzeCall(
7795 // mutate comptime state.7786 // mutate comptime state.
7796 // TODO: comptime call memoization is currently not supported under incremental compilation7787 // TODO: comptime call memoization is currently not supported under incremental compilation
7797 // since dependencies are not marked on callers. If we want to keep this around (we should7788 // since dependencies are not marked on callers. If we want to keep this around (we should
7798 // check that it's worthwhile first!), each memoized call needs a `Cau`.7789 // check that it's worthwhile first!), each memoized call needs an `AnalUnit`.
7799 var should_memoize = !zcu.comp.incremental;7790 var should_memoize = !zcu.comp.incremental;
78007791
7801 // If it's a comptime function call, we need to memoize it as long as no external7792 // If it's a comptime function call, we need to memoize it as long as no external
...@@ -7904,7 +7895,7 @@ fn analyzeCall(...@@ -7904,7 +7895,7 @@ fn analyzeCall(
79047895
7905 // Since we're doing an inline call, we depend on the source code of the whole7896 // Since we're doing an inline call, we depend on the source code of the whole
7906 // function declaration.7897 // function declaration.
7907 try sema.declareDependency(.{ .src_hash = fn_cau.zir_index });7898 try sema.declareDependency(.{ .src_hash = fn_nav.analysis.?.zir_index });
79087899
7909 new_fn_info.return_type = sema.fn_ret_ty.toIntern();7900 new_fn_info.return_type = sema.fn_ret_ty.toIntern();
7910 if (!is_comptime_call and !block.is_typeof) {7901 if (!is_comptime_call and !block.is_typeof) {
...@@ -8016,7 +8007,7 @@ fn analyzeCall(...@@ -8016,7 +8007,7 @@ fn analyzeCall(
8016 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);8007 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
80178008
8018 switch (sema.owner.unwrap()) {8009 switch (sema.owner.unwrap()) {
8019 .cau => {},8010 .@"comptime", .nav_val, .type => {},
8020 .func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {8011 .func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {
8021 ip.funcSetCallsOrAwaitsErrorableFn(owner_func);8012 ip.funcSetCallsOrAwaitsErrorableFn(owner_func);
8022 },8013 },
...@@ -8268,10 +8259,9 @@ fn instantiateGenericCall(...@@ -8268,10 +8259,9 @@ fn instantiateGenericCall(
8268 // The actual monomorphization happens via adding `func_instance` to8259 // The actual monomorphization happens via adding `func_instance` to
8269 // `InternPool`.8260 // `InternPool`.
82708261
8271 // Since we are looking at the generic owner here, it has a `Cau`.8262 // Since we are looking at the generic owner here, it has analysis state.
8272 const fn_nav = ip.getNav(generic_owner_func.owner_nav);8263 const fn_nav = ip.getNav(generic_owner_func.owner_nav);
8273 const fn_cau = ip.getCau(fn_nav.analysis_owner.unwrap().?);8264 const fn_zir = zcu.navFileScope(generic_owner_func.owner_nav).zir;
8274 const fn_zir = zcu.namespacePtr(fn_cau.namespace).fileScope(zcu).zir;
8275 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst.resolve(ip) orelse return error.AnalysisFail);8265 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst.resolve(ip) orelse return error.AnalysisFail);
82768266
8277 const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());8267 const comptime_args = try sema.arena.alloc(InternPool.Index, args_info.count());
...@@ -8312,11 +8302,11 @@ fn instantiateGenericCall(...@@ -8312,11 +8302,11 @@ fn instantiateGenericCall(
8312 var child_block: Block = .{8302 var child_block: Block = .{
8313 .parent = null,8303 .parent = null,
8314 .sema = &child_sema,8304 .sema = &child_sema,
8315 .namespace = fn_cau.namespace,8305 .namespace = fn_nav.analysis.?.namespace,
8316 .instructions = .{},8306 .instructions = .{},
8317 .inlining = null,8307 .inlining = null,
8318 .is_comptime = true,8308 .is_comptime = true,
8319 .src_base_inst = fn_cau.zir_index,8309 .src_base_inst = fn_nav.analysis.?.zir_index,
8320 .type_name_ctx = fn_nav.fqn,8310 .type_name_ctx = fn_nav.fqn,
8321 };8311 };
8322 defer child_block.instructions.deinit(gpa);8312 defer child_block.instructions.deinit(gpa);
...@@ -8481,7 +8471,7 @@ fn instantiateGenericCall(...@@ -8481,7 +8471,7 @@ fn instantiateGenericCall(
8481 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);8471 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
84828472
8483 switch (sema.owner.unwrap()) {8473 switch (sema.owner.unwrap()) {
8484 .cau => {},8474 .@"comptime", .nav_val, .type => {},
8485 .func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {8475 .func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {
8486 ip.funcSetCallsOrAwaitsErrorableFn(owner_func);8476 ip.funcSetCallsOrAwaitsErrorableFn(owner_func);
8487 },8477 },
...@@ -9510,14 +9500,11 @@ fn zirFunc(...@@ -9510,14 +9500,11 @@ fn zirFunc(
9510 // the callconv based on whether it is exported. Otherwise, the callconv defaults9500 // the callconv based on whether it is exported. Otherwise, the callconv defaults
9511 // to `.auto`.9501 // to `.auto`.
9512 const cc: std.builtin.CallingConvention = if (has_body) cc: {9502 const cc: std.builtin.CallingConvention = if (has_body) cc: {
9513 const func_decl_cau = if (sema.generic_owner != .none) cau: {9503 const func_decl_nav = if (sema.generic_owner != .none) nav: {
9514 const generic_owner_fn = zcu.funcInfo(sema.generic_owner);9504 break :nav zcu.funcInfo(sema.generic_owner).owner_nav;
9515 // The generic owner definitely has a `Cau` for the corresponding function declaration.9505 } else sema.owner.unwrap().nav_val;
9516 const generic_owner_nav = ip.getNav(generic_owner_fn.owner_nav);
9517 break :cau generic_owner_nav.analysis_owner.unwrap().?;
9518 } else sema.owner.unwrap().cau;
9519 const fn_is_exported = exported: {9506 const fn_is_exported = exported: {
9520 const decl_inst = ip.getCau(func_decl_cau).zir_index.resolve(ip) orelse return error.AnalysisFail;9507 const decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(ip) orelse return error.AnalysisFail;
9521 const zir_decl = sema.code.getDeclaration(decl_inst);9508 const zir_decl = sema.code.getDeclaration(decl_inst);
9522 break :exported zir_decl.linkage == .@"export";9509 break :exported zir_decl.linkage == .@"export";
9523 };9510 };
...@@ -9991,7 +9978,7 @@ fn funcCommon(...@@ -9991,7 +9978,7 @@ fn funcCommon(
9991 if (!ret_poison)9978 if (!ret_poison)
9992 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);9979 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
9993 const func_index = try ip.getFuncDeclIes(gpa, pt.tid, .{9980 const func_index = try ip.getFuncDeclIes(gpa, pt.tid, .{
9994 .owner_nav = sema.getOwnerCauNav(),9981 .owner_nav = sema.owner.unwrap().nav_val,
99959982
9996 .param_types = param_types,9983 .param_types = param_types,
9997 .noalias_bits = noalias_bits,9984 .noalias_bits = noalias_bits,
...@@ -10040,7 +10027,7 @@ fn funcCommon(...@@ -10040,7 +10027,7 @@ fn funcCommon(
1004010027
10041 if (has_body) {10028 if (has_body) {
10042 const func_index = try ip.getFuncDecl(gpa, pt.tid, .{10029 const func_index = try ip.getFuncDecl(gpa, pt.tid, .{
10043 .owner_nav = sema.getOwnerCauNav(),10030 .owner_nav = sema.owner.unwrap().nav_val,
10044 .ty = func_ty,10031 .ty = func_ty,
10045 .cc = cc,10032 .cc = cc,
10046 .is_noinline = is_noinline,10033 .is_noinline = is_noinline,
...@@ -17664,7 +17651,7 @@ fn zirAsm(...@@ -17664,7 +17651,7 @@ fn zirAsm(
17664 if (is_volatile) {17651 if (is_volatile) {
17665 return sema.fail(block, src, "volatile keyword is redundant on module-level assembly", .{});17652 return sema.fail(block, src, "volatile keyword is redundant on module-level assembly", .{});
17666 }17653 }
17667 try zcu.addGlobalAssembly(sema.owner.unwrap().cau, asm_source);17654 try zcu.addGlobalAssembly(sema.owner, asm_source);
17668 return .void_value;17655 return .void_value;
17669 }17656 }
1767017657
...@@ -18155,7 +18142,7 @@ fn zirThis(...@@ -18155,7 +18142,7 @@ fn zirThis(
18155 _ = extended;18142 _ = extended;
18156 const pt = sema.pt;18143 const pt = sema.pt;
18157 const namespace = pt.zcu.namespacePtr(block.namespace);18144 const namespace = pt.zcu.namespacePtr(block.namespace);
18158 const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type, false);18145 const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type);
18159 switch (pt.zcu.intern_pool.indexToKey(new_ty)) {18146 switch (pt.zcu.intern_pool.indexToKey(new_ty)) {
18160 .struct_type, .union_type, .enum_type => try sema.declareDependency(.{ .interned = new_ty }),18147 .struct_type, .union_type, .enum_type => try sema.declareDependency(.{ .interned = new_ty }),
18161 .opaque_type => {},18148 .opaque_type => {},
...@@ -19321,10 +19308,8 @@ fn typeInfoNamespaceDecls(...@@ -19321,10 +19308,8 @@ fn typeInfoNamespaceDecls(
19321 }19308 }
1932219309
19323 for (namespace.pub_usingnamespace.items) |nav| {19310 for (namespace.pub_usingnamespace.items) |nav| {
19324 if (ip.getNav(nav).analysis_owner.unwrap()) |cau| {19311 if (zcu.analysis_in_progress.contains(.wrap(.{ .nav_val = nav }))) {
19325 if (zcu.analysis_in_progress.contains(AnalUnit.wrap(.{ .cau = cau }))) {19312 continue;
19326 continue;
19327 }
19328 }19313 }
19329 try sema.ensureNavResolved(src, nav);19314 try sema.ensureNavResolved(src, nav);
19330 const namespace_ty = Type.fromInterned(ip.getNav(nav).status.resolved.val);19315 const namespace_ty = Type.fromInterned(ip.getNav(nav).status.resolved.val);
...@@ -21187,14 +21172,13 @@ fn structInitAnon(...@@ -21187,14 +21172,13 @@ fn structInitAnon(
21187 .file_scope = block.getFileScopeIndex(zcu),21172 .file_scope = block.getFileScopeIndex(zcu),
21188 .generation = zcu.generation,21173 .generation = zcu.generation,
21189 });21174 });
21190 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip.index);
21191 try zcu.comp.queueJob(.{ .resolve_type_fully = wip.index });21175 try zcu.comp.queueJob(.{ .resolve_type_fully = wip.index });
21192 codegen_type: {21176 codegen_type: {
21193 if (zcu.comp.config.use_llvm) break :codegen_type;21177 if (zcu.comp.config.use_llvm) break :codegen_type;
21194 if (block.ownerModule().strip) break :codegen_type;21178 if (block.ownerModule().strip) break :codegen_type;
21195 try zcu.comp.queueJob(.{ .codegen_type = wip.index });21179 try zcu.comp.queueJob(.{ .codegen_type = wip.index });
21196 }21180 }
21197 break :ty wip.finish(ip, new_cau_index.toOptional(), new_namespace_index);21181 break :ty wip.finish(ip, new_namespace_index);
21198 },21182 },
21199 .existing => |ty| ty,21183 .existing => |ty| ty,
21200 };21184 };
...@@ -21618,7 +21602,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {...@@ -21618,7 +21602,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
21618 .func => |func| if (ip.funcAnalysisUnordered(func).calls_or_awaits_errorable_fn and block.ownerModule().error_tracing) {21602 .func => |func| if (ip.funcAnalysisUnordered(func).calls_or_awaits_errorable_fn and block.ownerModule().error_tracing) {
21619 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);21603 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
21620 },21604 },
21621 .cau => {},21605 .@"comptime", .nav_val, .type => {},
21622 }21606 }
21623 return Air.internedToRef(try pt.intern(.{ .opt = .{21607 return Air.internedToRef(try pt.intern(.{ .opt = .{
21624 .ty = opt_ptr_stack_trace_ty.toIntern(),21608 .ty = opt_ptr_stack_trace_ty.toIntern(),
...@@ -22296,7 +22280,7 @@ fn zirReify(...@@ -22296,7 +22280,7 @@ fn zirReify(
22296 });22280 });
2229722281
22298 try sema.addTypeReferenceEntry(src, wip_ty.index);22282 try sema.addTypeReferenceEntry(src, wip_ty.index);
22299 return Air.internedToRef(wip_ty.finish(ip, .none, new_namespace_index));22283 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
22300 },22284 },
22301 .@"union" => {22285 .@"union" => {
22302 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));22286 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
...@@ -22505,11 +22489,9 @@ fn reifyEnum(...@@ -22505,11 +22489,9 @@ fn reifyEnum(
22505 .generation = zcu.generation,22489 .generation = zcu.generation,
22506 });22490 });
2250722491
22508 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
22509
22510 try sema.declareDependency(.{ .interned = wip_ty.index });22492 try sema.declareDependency(.{ .interned = wip_ty.index });
22511 try sema.addTypeReferenceEntry(src, wip_ty.index);22493 try sema.addTypeReferenceEntry(src, wip_ty.index);
22512 wip_ty.prepare(ip, new_cau_index, new_namespace_index);22494 wip_ty.prepare(ip, new_namespace_index);
22513 wip_ty.setTagTy(ip, tag_ty.toIntern());22495 wip_ty.setTagTy(ip, tag_ty.toIntern());
22514 done = true;22496 done = true;
2251522497
...@@ -22811,8 +22793,6 @@ fn reifyUnion(...@@ -22811,8 +22793,6 @@ fn reifyUnion(
22811 .generation = zcu.generation,22793 .generation = zcu.generation,
22812 });22794 });
2281322795
22814 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
22815
22816 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });22796 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
22817 codegen_type: {22797 codegen_type: {
22818 if (zcu.comp.config.use_llvm) break :codegen_type;22798 if (zcu.comp.config.use_llvm) break :codegen_type;
...@@ -22822,7 +22802,7 @@ fn reifyUnion(...@@ -22822,7 +22802,7 @@ fn reifyUnion(
22822 }22802 }
22823 try sema.declareDependency(.{ .interned = wip_ty.index });22803 try sema.declareDependency(.{ .interned = wip_ty.index });
22824 try sema.addTypeReferenceEntry(src, wip_ty.index);22804 try sema.addTypeReferenceEntry(src, wip_ty.index);
22825 return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));22805 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
22826}22806}
2282722807
22828fn reifyTuple(22808fn reifyTuple(
...@@ -23170,8 +23150,6 @@ fn reifyStruct(...@@ -23170,8 +23150,6 @@ fn reifyStruct(
23170 .generation = zcu.generation,23150 .generation = zcu.generation,
23171 });23151 });
2317223152
23173 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, new_namespace_index, wip_ty.index);
23174
23175 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });23153 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
23176 codegen_type: {23154 codegen_type: {
23177 if (zcu.comp.config.use_llvm) break :codegen_type;23155 if (zcu.comp.config.use_llvm) break :codegen_type;
...@@ -23181,7 +23159,7 @@ fn reifyStruct(...@@ -23181,7 +23159,7 @@ fn reifyStruct(
23181 }23159 }
23182 try sema.declareDependency(.{ .interned = wip_ty.index });23160 try sema.declareDependency(.{ .interned = wip_ty.index });
23183 try sema.addTypeReferenceEntry(src, wip_ty.index);23161 try sema.addTypeReferenceEntry(src, wip_ty.index);
23184 return Air.internedToRef(wip_ty.finish(ip, new_cau_index.toOptional(), new_namespace_index));23162 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
23185}23163}
2318623164
23187fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {23165fn 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...@@ -26713,15 +26691,13 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
26713 break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val);26691 break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val);
26714 } else cc: {26692 } else cc: {
26715 if (has_body) {26693 if (has_body) {
26716 const decl_inst = if (sema.generic_owner != .none) decl_inst: {26694 const func_decl_nav = if (sema.generic_owner != .none) nav: {
26717 // Generic instance -- use the original function declaration to26695 // Generic instance -- use the original function declaration to
26718 // look for the `export` syntax.26696 // look for the `export` syntax.
26719 const nav = zcu.intern_pool.getNav(zcu.funcInfo(sema.generic_owner).owner_nav);26697 break :nav zcu.funcInfo(sema.generic_owner).owner_nav;
26720 const cau = zcu.intern_pool.getCau(nav.analysis_owner.unwrap().?);26698 } else sema.owner.unwrap().nav_val;
26721 break :decl_inst cau.zir_index;26699 const func_decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(&zcu.intern_pool) orelse return error.AnalysisFail;
26722 } else sema.getOwnerCauDeclInst(); // not an instantiation so we're analyzing a function declaration Cau26700 const zir_decl = sema.code.getDeclaration(func_decl_inst);
26723
26724 const zir_decl = sema.code.getDeclaration(decl_inst.resolve(&zcu.intern_pool) orelse return error.AnalysisFail);
26725 if (zir_decl.linkage == .@"export") {26701 if (zir_decl.linkage == .@"export") {
26726 break :cc target.cCallingConvention() orelse {26702 break :cc target.cCallingConvention() orelse {
26727 // This target has no default C calling convention. We sometimes trigger a similar26703 // This target has no default C calling convention. We sometimes trigger a similar
...@@ -27108,8 +27084,16 @@ fn zirBuiltinExtern(...@@ -27108,8 +27084,16 @@ fn zirBuiltinExtern(
27108 // `builtin_extern` doesn't provide enough information, and isn't currently tracked.27084 // `builtin_extern` doesn't provide enough information, and isn't currently tracked.
27109 // So, for now, just use our containing `declaration`.27085 // So, for now, just use our containing `declaration`.
27110 .zir_index = switch (sema.owner.unwrap()) {27086 .zir_index = switch (sema.owner.unwrap()) {
27111 .cau => sema.getOwnerCauDeclInst(),27087 .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index,
27112 .func => sema.getOwnerFuncDeclInst(),27088 .type => |owner_ty| Type.fromInterned(owner_ty).typeDeclInst(zcu).?,
27089 .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index,
27090 .func => |func| zir_index: {
27091 const func_info = zcu.funcInfo(func);
27092 const owner_func_info = if (func_info.generic_owner != .none) owner: {
27093 break :owner zcu.funcInfo(func_info.generic_owner);
27094 } else func_info;
27095 break :zir_index ip.getNav(owner_func_info.owner_nav).analysis.?.zir_index;
27096 },
27113 },27097 },
27114 .owner_nav = undefined, // ignored by `getExtern`27098 .owner_nav = undefined, // ignored by `getExtern`
27115 });27099 });
...@@ -32670,28 +32654,25 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav...@@ -32670,28 +32654,25 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav
32670 const ip = &zcu.intern_pool;32654 const ip = &zcu.intern_pool;
3267132655
32672 const nav = ip.getNav(nav_index);32656 const nav = ip.getNav(nav_index);
3267332657 if (nav.analysis == null) {
32674 const cau_index = nav.analysis_owner.unwrap() orelse {
32675 assert(nav.status == .resolved);32658 assert(nav.status == .resolved);
32676 return;32659 return;
32677 };32660 }
3267832661
32679 // Note that even if `nav.status == .resolved`, we must still trigger `ensureCauAnalyzed`32662 // Note that even if `nav.status == .resolved`, we must still trigger `ensureNavValUpToDate`
32680 // to make sure the value is up-to-date on incremental updates.32663 // to make sure the value is up-to-date on incremental updates.
3268132664
32682 assert(ip.getCau(cau_index).owner.unwrap().nav == nav_index);32665 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_index });
32683
32684 const anal_unit = AnalUnit.wrap(.{ .cau = cau_index });
32685 try sema.addReferenceEntry(src, anal_unit);32666 try sema.addReferenceEntry(src, anal_unit);
3268632667
32687 if (zcu.analysis_in_progress.contains(anal_unit)) {32668 if (zcu.analysis_in_progress.contains(anal_unit)) {
32688 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{32669 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{
32689 .base_node_inst = ip.getCau(cau_index).zir_index,32670 .base_node_inst = nav.analysis.?.zir_index,
32690 .offset = LazySrcLoc.Offset.nodeOffset(0),32671 .offset = LazySrcLoc.Offset.nodeOffset(0),
32691 }, "dependency loop detected", .{}));32672 }, "dependency loop detected", .{}));
32692 }32673 }
3269332674
32694 return pt.ensureCauAnalyzed(cau_index);32675 return pt.ensureNavValUpToDate(nav_index);
32695}32676}
3269632677
32697fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {32678fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
...@@ -35641,7 +35622,7 @@ pub fn resolveStructAlignment(...@@ -35641,7 +35622,7 @@ pub fn resolveStructAlignment(
35641 const ip = &zcu.intern_pool;35622 const ip = &zcu.intern_pool;
35642 const target = zcu.getTarget();35623 const target = zcu.getTarget();
3564335624
35644 assert(sema.owner.unwrap().cau == struct_type.cau);35625 assert(sema.owner.unwrap().type == ty);
3564535626
35646 assert(struct_type.layout != .@"packed");35627 assert(struct_type.layout != .@"packed");
35647 assert(struct_type.flagsUnordered(ip).alignment == .none);35628 assert(struct_type.flagsUnordered(ip).alignment == .none);
...@@ -35684,7 +35665,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -35684,7 +35665,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
35684 const ip = &zcu.intern_pool;35665 const ip = &zcu.intern_pool;
35685 const struct_type = zcu.typeToStruct(ty) orelse return;35666 const struct_type = zcu.typeToStruct(ty) orelse return;
3568635667
35687 assert(sema.owner.unwrap().cau == struct_type.cau);35668 assert(sema.owner.unwrap().type == ty.toIntern());
3568835669
35689 if (struct_type.haveLayout(ip))35670 if (struct_type.haveLayout(ip))
35690 return;35671 return;
...@@ -35831,15 +35812,13 @@ fn backingIntType(...@@ -35831,15 +35812,13 @@ fn backingIntType(
35831 const gpa = zcu.gpa;35812 const gpa = zcu.gpa;
35832 const ip = &zcu.intern_pool;35813 const ip = &zcu.intern_pool;
3583335814
35834 const cau_index = struct_type.cau;
35835
35836 var analysis_arena = std.heap.ArenaAllocator.init(gpa);35815 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
35837 defer analysis_arena.deinit();35816 defer analysis_arena.deinit();
3583835817
35839 var block: Block = .{35818 var block: Block = .{
35840 .parent = null,35819 .parent = null,
35841 .sema = sema,35820 .sema = sema,
35842 .namespace = ip.getCau(cau_index).namespace,35821 .namespace = struct_type.namespace,
35843 .instructions = .{},35822 .instructions = .{},
35844 .inlining = null,35823 .inlining = null,
35845 .is_comptime = true,35824 .is_comptime = true,
...@@ -35971,7 +35950,7 @@ pub fn resolveUnionAlignment(...@@ -35971,7 +35950,7 @@ pub fn resolveUnionAlignment(
35971 const ip = &zcu.intern_pool;35950 const ip = &zcu.intern_pool;
35972 const target = zcu.getTarget();35951 const target = zcu.getTarget();
3597335952
35974 assert(sema.owner.unwrap().cau == union_type.cau);35953 assert(sema.owner.unwrap().type == ty.toIntern());
3597535954
35976 assert(!union_type.haveLayout(ip));35955 assert(!union_type.haveLayout(ip));
3597735956
...@@ -36011,7 +35990,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {...@@ -36011,7 +35990,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
36011 // Load again, since the tag type might have changed due to resolution.35990 // Load again, since the tag type might have changed due to resolution.
36012 const union_type = ip.loadUnionType(ty.ip_index);35991 const union_type = ip.loadUnionType(ty.ip_index);
3601335992
36014 assert(sema.owner.unwrap().cau == union_type.cau);35993 assert(sema.owner.unwrap().type == ty.toIntern());
3601535994
36016 const old_flags = union_type.flagsUnordered(ip);35995 const old_flags = union_type.flagsUnordered(ip);
36017 switch (old_flags.status) {35996 switch (old_flags.status) {
...@@ -36126,7 +36105,7 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {...@@ -36126,7 +36105,7 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {
36126 const ip = &zcu.intern_pool;36105 const ip = &zcu.intern_pool;
36127 const struct_type = zcu.typeToStruct(ty).?;36106 const struct_type = zcu.typeToStruct(ty).?;
3612836107
36129 assert(sema.owner.unwrap().cau == struct_type.cau);36108 assert(sema.owner.unwrap().type == ty.toIntern());
3613036109
36131 if (struct_type.setFullyResolved(ip)) return;36110 if (struct_type.setFullyResolved(ip)) return;
36132 errdefer struct_type.clearFullyResolved(ip);36111 errdefer struct_type.clearFullyResolved(ip);
...@@ -36149,7 +36128,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {...@@ -36149,7 +36128,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {
36149 const ip = &zcu.intern_pool;36128 const ip = &zcu.intern_pool;
36150 const union_obj = zcu.typeToUnion(ty).?;36129 const union_obj = zcu.typeToUnion(ty).?;
3615136130
36152 assert(sema.owner.unwrap().cau == union_obj.cau);36131 assert(sema.owner.unwrap().type == ty.toIntern());
3615336132
36154 switch (union_obj.flagsUnordered(ip).status) {36133 switch (union_obj.flagsUnordered(ip).status) {
36155 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},36134 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
...@@ -36184,7 +36163,7 @@ pub fn resolveStructFieldTypes(...@@ -36184,7 +36163,7 @@ pub fn resolveStructFieldTypes(
36184 const zcu = pt.zcu;36163 const zcu = pt.zcu;
36185 const ip = &zcu.intern_pool;36164 const ip = &zcu.intern_pool;
3618636165
36187 assert(sema.owner.unwrap().cau == struct_type.cau);36166 assert(sema.owner.unwrap().type == ty);
3618836167
36189 if (struct_type.haveFieldTypes(ip)) return;36168 if (struct_type.haveFieldTypes(ip)) return;
3619036169
...@@ -36210,7 +36189,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {...@@ -36210,7 +36189,7 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
36210 const ip = &zcu.intern_pool;36189 const ip = &zcu.intern_pool;
36211 const struct_type = zcu.typeToStruct(ty) orelse return;36190 const struct_type = zcu.typeToStruct(ty) orelse return;
3621236191
36213 assert(sema.owner.unwrap().cau == struct_type.cau);36192 assert(sema.owner.unwrap().type == ty.toIntern());
3621436193
36215 // Inits can start as resolved36194 // Inits can start as resolved
36216 if (struct_type.haveFieldInits(ip)) return;36195 if (struct_type.haveFieldInits(ip)) return;
...@@ -36239,7 +36218,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load...@@ -36239,7 +36218,7 @@ pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.Load
36239 const zcu = pt.zcu;36218 const zcu = pt.zcu;
36240 const ip = &zcu.intern_pool;36219 const ip = &zcu.intern_pool;
3624136220
36242 assert(sema.owner.unwrap().cau == union_type.cau);36221 assert(sema.owner.unwrap().type == ty.toIntern());
3624336222
36244 switch (union_type.flagsUnordered(ip).status) {36223 switch (union_type.flagsUnordered(ip).status) {
36245 .none => {},36224 .none => {},
...@@ -36315,7 +36294,7 @@ fn resolveInferredErrorSet(...@@ -36315,7 +36294,7 @@ fn resolveInferredErrorSet(
36315 // In this case we are dealing with the actual InferredErrorSet object that36294 // In this case we are dealing with the actual InferredErrorSet object that
36316 // corresponds to the function, not one created to track an inline/comptime call.36295 // corresponds to the function, not one created to track an inline/comptime call.
36317 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = func_index }));36296 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = func_index }));
36318 try pt.ensureFuncBodyAnalyzed(func_index);36297 try pt.ensureFuncBodyUpToDate(func_index);
36319 }36298 }
3632036299
36321 // This will now have been resolved by the logic at the end of `Zcu.analyzeFnBody`36300 // This will now have been resolved by the logic at the end of `Zcu.analyzeFnBody`
...@@ -36472,8 +36451,7 @@ fn structFields(...@@ -36472,8 +36451,7 @@ fn structFields(
36472 const zcu = pt.zcu;36451 const zcu = pt.zcu;
36473 const gpa = zcu.gpa;36452 const gpa = zcu.gpa;
36474 const ip = &zcu.intern_pool;36453 const ip = &zcu.intern_pool;
36475 const cau_index = struct_type.cau;36454 const namespace_index = struct_type.namespace;
36476 const namespace_index = ip.getCau(cau_index).namespace;
36477 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;36455 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;
36478 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;36456 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
3647936457
...@@ -36671,8 +36649,7 @@ fn structFieldInits(...@@ -36671,8 +36649,7 @@ fn structFieldInits(
3667136649
36672 assert(!struct_type.haveFieldInits(ip));36650 assert(!struct_type.haveFieldInits(ip));
3667336651
36674 const cau_index = struct_type.cau;36652 const namespace_index = struct_type.namespace;
36675 const namespace_index = ip.getCau(cau_index).namespace;
36676 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;36653 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir;
36677 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;36654 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
36678 const fields_len, _, var extra_index = structZirInfo(zir, zir_index);36655 const fields_len, _, var extra_index = structZirInfo(zir, zir_index);
...@@ -38474,13 +38451,11 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {...@@ -38474,13 +38451,11 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {
38474 // just result in over-analysis since `Zcu.findOutdatedToAnalyze` would never be able to resolve38451 // just result in over-analysis since `Zcu.findOutdatedToAnalyze` would never be able to resolve
38475 // the loop.38452 // the loop.
38476 switch (sema.owner.unwrap()) {38453 switch (sema.owner.unwrap()) {
38477 .cau => |cau| switch (dependee) {38454 .nav_val => |this_nav| switch (dependee) {
38478 .nav_val => |nav| if (zcu.intern_pool.getNav(nav).analysis_owner == cau.toOptional()) {38455 .nav_val => |other_nav| if (this_nav == other_nav) return,
38479 return;
38480 },
38481 else => {},38456 else => {},
38482 },38457 },
38483 .func => {},38458 else => {},
38484 }38459 }
3848538460
38486 try zcu.intern_pool.addDependency(sema.gpa, sema.owner, dependee);38461 try zcu.intern_pool.addDependency(sema.gpa, sema.owner, dependee);
...@@ -38659,38 +38634,6 @@ pub fn flushExports(sema: *Sema) !void {...@@ -38659,38 +38634,6 @@ pub fn flushExports(sema: *Sema) !void {
38659 }38634 }
38660}38635}
3866138636
38662/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches
38663/// the corresponding `Nav`.
38664fn getOwnerCauNav(sema: *Sema) InternPool.Nav.Index {
38665 const cau = sema.owner.unwrap().cau;
38666 return sema.pt.zcu.intern_pool.getCau(cau).owner.unwrap().nav;
38667}
38668
38669/// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches
38670/// the `TrackedInst` corresponding to this `declaration` instruction.
38671fn getOwnerCauDeclInst(sema: *Sema) InternPool.TrackedInst.Index {
38672 const ip = &sema.pt.zcu.intern_pool;
38673 const cau = ip.getCau(sema.owner.unwrap().cau);
38674 assert(cau.owner.unwrap() == .nav);
38675 return cau.zir_index;
38676}
38677
38678/// Given that this `Sema` is owned by a runtime function, fetches the
38679/// `TrackedInst` corresponding to its `declaration` instruction.
38680fn getOwnerFuncDeclInst(sema: *Sema) InternPool.TrackedInst.Index {
38681 const zcu = sema.pt.zcu;
38682 const ip = &zcu.intern_pool;
38683 const func = sema.owner.unwrap().func;
38684 const func_info = zcu.funcInfo(func);
38685 const cau = if (func_info.generic_owner == .none) cau: {
38686 break :cau ip.getNav(func_info.owner_nav).analysis_owner.unwrap().?;
38687 } else cau: {
38688 const generic_owner = zcu.funcInfo(func_info.generic_owner);
38689 break :cau ip.getNav(generic_owner.owner_nav).analysis_owner.unwrap().?;
38690 };
38691 return ip.getCau(cau).zir_index;
38692}
38693
38694/// Called as soon as a `declared` enum type is created.38637/// Called as soon as a `declared` enum type is created.
38695/// Resolves the tag type and field inits.38638/// Resolves the tag type and field inits.
38696/// Marks the `src_inst` dependency on the enum's declaration, so call sites need not do this.38639/// Marks the `src_inst` dependency on the enum's declaration, so call sites need not do this.
...@@ -38701,7 +38644,6 @@ pub fn resolveDeclaredEnum(...@@ -38701,7 +38644,6 @@ pub fn resolveDeclaredEnum(
38701 tracked_inst: InternPool.TrackedInst.Index,38644 tracked_inst: InternPool.TrackedInst.Index,
38702 namespace: InternPool.NamespaceIndex,38645 namespace: InternPool.NamespaceIndex,
38703 type_name: InternPool.NullTerminatedString,38646 type_name: InternPool.NullTerminatedString,
38704 enum_cau: InternPool.Cau.Index,
38705 small: Zir.Inst.EnumDecl.Small,38647 small: Zir.Inst.EnumDecl.Small,
38706 body: []const Zir.Inst.Index,38648 body: []const Zir.Inst.Index,
38707 tag_type_ref: Zir.Inst.Ref,38649 tag_type_ref: Zir.Inst.Ref,
...@@ -38719,7 +38661,7 @@ pub fn resolveDeclaredEnum(...@@ -38719,7 +38661,7 @@ pub fn resolveDeclaredEnum(
38719 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };38661 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };
38720 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };38662 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };
3872138663
38722 const anal_unit = AnalUnit.wrap(.{ .cau = enum_cau });38664 const anal_unit = AnalUnit.wrap(.{ .type = wip_ty.index });
3872338665
38724 var arena = std.heap.ArenaAllocator.init(gpa);38666 var arena = std.heap.ArenaAllocator.init(gpa);
38725 defer arena.deinit();38667 defer arena.deinit();
...@@ -38943,6 +38885,6 @@ fn getBuiltin(sema: *Sema, name: []const u8) SemaError!Air.Inst.Ref {...@@ -38943,6 +38885,6 @@ fn getBuiltin(sema: *Sema, name: []const u8) SemaError!Air.Inst.Ref {
38943 const zcu = pt.zcu;38885 const zcu = pt.zcu;
38944 const ip = &zcu.intern_pool;38886 const ip = &zcu.intern_pool;
38945 const nav = try pt.getBuiltinNav(name);38887 const nav = try pt.getBuiltinNav(name);
38946 try pt.ensureCauAnalyzed(ip.getNav(nav).analysis_owner.unwrap().?);38888 try pt.ensureNavValUpToDate(nav);
38947 return Air.internedToRef(ip.getNav(nav).status.resolved.val);38889 return Air.internedToRef(ip.getNav(nav).status.resolved.val);
38948}38890}
src/Type.zig+2-2
...@@ -3851,7 +3851,7 @@ fn resolveStructInner(...@@ -3851,7 +3851,7 @@ fn resolveStructInner(
3851 const gpa = zcu.gpa;3851 const gpa = zcu.gpa;
38523852
3853 const struct_obj = zcu.typeToStruct(ty).?;3853 const struct_obj = zcu.typeToStruct(ty).?;
3854 const owner = InternPool.AnalUnit.wrap(.{ .cau = struct_obj.cau });3854 const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() });
38553855
3856 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {3856 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {
3857 return error.AnalysisFail;3857 return error.AnalysisFail;
...@@ -3905,7 +3905,7 @@ fn resolveUnionInner(...@@ -3905,7 +3905,7 @@ fn resolveUnionInner(
3905 const gpa = zcu.gpa;3905 const gpa = zcu.gpa;
39063906
3907 const union_obj = zcu.typeToUnion(ty).?;3907 const union_obj = zcu.typeToUnion(ty).?;
3908 const owner = InternPool.AnalUnit.wrap(.{ .cau = union_obj.cau });3908 const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() });
39093909
3910 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {3910 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {
3911 return error.AnalysisFail;3911 return error.AnalysisFail;
src/Zcu.zig+86-96
...@@ -192,7 +192,7 @@ compile_log_text: std.ArrayListUnmanaged(u8) = .empty,...@@ -192,7 +192,7 @@ compile_log_text: std.ArrayListUnmanaged(u8) = .empty,
192192
193test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,193test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
194194
195global_assembly: std.AutoArrayHashMapUnmanaged(InternPool.Cau.Index, []u8) = .empty,195global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty,
196196
197/// Key is the `AnalUnit` *performing* the reference. This representation allows197/// Key is the `AnalUnit` *performing* the reference. This representation allows
198/// incremental updates to quickly delete references caused by a specific `AnalUnit`.198/// incremental updates to quickly delete references caused by a specific `AnalUnit`.
...@@ -344,9 +344,12 @@ pub const Namespace = struct {...@@ -344,9 +344,12 @@ pub const Namespace = struct {
344 pub_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,344 pub_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
345 /// All `usingnamespace` declarations in this namespace which are *not* marked `pub`.345 /// All `usingnamespace` declarations in this namespace which are *not* marked `pub`.
346 priv_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,346 priv_usingnamespace: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
347 /// All `comptime` and `test` declarations in this namespace. We store these purely so that347 /// All `comptime` declarations in this namespace. We store these purely so that incremental
348 /// incremental compilation can re-use the existing `Cau`s when a namespace changes.348 /// compilation can re-use the existing `ComptimeUnit`s when a namespace changes.
349 other_decls: std.ArrayListUnmanaged(InternPool.Cau.Index) = .empty,349 comptime_decls: std.ArrayListUnmanaged(InternPool.ComptimeUnit.Id) = .empty,
350 /// All `test` declarations in this namespace. We store these purely so that incremental
351 /// compilation can re-use the existing `Nav`s when a namespace changes.
352 test_decls: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty,
350353
351 pub const Index = InternPool.NamespaceIndex;354 pub const Index = InternPool.NamespaceIndex;
352 pub const OptionalIndex = InternPool.OptionalNamespaceIndex;355 pub const OptionalIndex = InternPool.OptionalNamespaceIndex;
...@@ -2436,11 +2439,9 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {...@@ -2436,11 +2439,9 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
2436 // If this is a Decl, we must recursively mark dependencies on its tyval2439 // If this is a Decl, we must recursively mark dependencies on its tyval
2437 // as no longer PO.2440 // as no longer PO.
2438 switch (depender.unwrap()) {2441 switch (depender.unwrap()) {
2439 .cau => |cau| switch (zcu.intern_pool.getCau(cau).owner.unwrap()) {2442 .@"comptime" => {},
2440 .nav => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }),2443 .nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }),
2441 .type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }),2444 .type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }),
2442 .none => {},
2443 },
2444 .func => |func| try zcu.markPoDependeeUpToDate(.{ .interned = func }),2445 .func => |func| try zcu.markPoDependeeUpToDate(.{ .interned = func }),
2445 }2446 }
2446 }2447 }
...@@ -2451,11 +2452,9 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {...@@ -2451,11 +2452,9 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
2451fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void {2452fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void {
2452 const ip = &zcu.intern_pool;2453 const ip = &zcu.intern_pool;
2453 const dependee: InternPool.Dependee = switch (maybe_outdated.unwrap()) {2454 const dependee: InternPool.Dependee = switch (maybe_outdated.unwrap()) {
2454 .cau => |cau| switch (ip.getCau(cau).owner.unwrap()) {2455 .@"comptime" => return, // analysis of a comptime decl can't outdate any dependencies
2455 .nav => |nav| .{ .nav_val = nav }, // TODO: also `nav_ref` deps when introduced2456 .nav_val => |nav| .{ .nav_val = nav }, // TODO: also `nav_ref` deps when introduced
2456 .type => |ty| .{ .interned = ty },2457 .type => |ty| .{ .interned = ty },
2457 .none => return, // analysis of this `Cau` can't outdate any dependencies
2458 },
2459 .func => |func_index| .{ .interned = func_index }, // IES2458 .func => |func_index| .{ .interned = func_index }, // IES
2460 };2459 };
2461 log.debug("potentially outdated dependee: {}", .{zcu.fmtDependee(dependee)});2460 log.debug("potentially outdated dependee: {}", .{zcu.fmtDependee(dependee)});
...@@ -2512,14 +2511,14 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {...@@ -2512,14 +2511,14 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
2512 }2511 }
25132512
2514 // There is no single AnalUnit which is ready for re-analysis. Instead, we must assume that some2513 // There is no single AnalUnit which is ready for re-analysis. Instead, we must assume that some
2515 // Cau with PO dependencies is outdated -- e.g. in the above example we arbitrarily pick one of2514 // AnalUnit with PO dependencies is outdated -- e.g. in the above example we arbitrarily pick one of
2516 // A or B. We should select a Cau, since a Cau is definitely responsible for the loop in the2515 // A or B. We should definitely not select a function, since a function can't be responsible for the
2517 // dependency graph (since IES dependencies can't have loops). We should also, of course, not2516 // loop (IES dependencies can't have loops). We should also, of course, not select a `comptime`
2518 // select a Cau owned by a `comptime` declaration, since you can't depend on those!2517 // declaration, since you can't depend on those!
25192518
2520 // The choice of this Cau could have a big impact on how much total analysis we perform, since2519 // The choice of this unit could have a big impact on how much total analysis we perform, since
2521 // if analysis concludes any dependencies on its result are up-to-date, then other PO AnalUnit2520 // if analysis concludes any dependencies on its result are up-to-date, then other PO AnalUnit
2522 // may be resolved as up-to-date. To hopefully avoid doing too much work, let's find a Decl2521 // may be resolved as up-to-date. To hopefully avoid doing too much work, let's find a unit
2523 // which the most things depend on - the idea is that this will resolve a lot of loops (but this2522 // which the most things depend on - the idea is that this will resolve a lot of loops (but this
2524 // is only a heuristic).2523 // is only a heuristic).
25252524
...@@ -2530,33 +2529,28 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {...@@ -2530,33 +2529,28 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
25302529
2531 const ip = &zcu.intern_pool;2530 const ip = &zcu.intern_pool;
25322531
2533 var chosen_cau: ?InternPool.Cau.Index = null;2532 var chosen_unit: ?AnalUnit = null;
2534 var chosen_cau_dependers: u32 = undefined;2533 var chosen_unit_dependers: u32 = undefined;
25352534
2536 inline for (.{ zcu.outdated.keys(), zcu.potentially_outdated.keys() }) |outdated_units| {2535 inline for (.{ zcu.outdated.keys(), zcu.potentially_outdated.keys() }) |outdated_units| {
2537 for (outdated_units) |unit| {2536 for (outdated_units) |unit| {
2538 const cau = switch (unit.unwrap()) {
2539 .cau => |cau| cau,
2540 .func => continue, // a `func` definitely can't be causing the loop so it is a bad choice
2541 };
2542 const cau_owner = ip.getCau(cau).owner;
2543
2544 var n: u32 = 0;2537 var n: u32 = 0;
2545 var it = ip.dependencyIterator(switch (cau_owner.unwrap()) {2538 var it = ip.dependencyIterator(switch (unit.unwrap()) {
2546 .none => continue, // there can be no dependencies on this `Cau` so it is a terrible choice2539 .func => continue, // a `func` definitely can't be causing the loop so it is a bad choice
2540 .@"comptime" => continue, // a `comptime` block can't even be depended on so it is a terrible choice
2547 .type => |ty| .{ .interned = ty },2541 .type => |ty| .{ .interned = ty },
2548 .nav => |nav| .{ .nav_val = nav },2542 .nav_val => |nav| .{ .nav_val = nav },
2549 });2543 });
2550 while (it.next()) |_| n += 1;2544 while (it.next()) |_| n += 1;
25512545
2552 if (chosen_cau == null or n > chosen_cau_dependers) {2546 if (chosen_unit == null or n > chosen_unit_dependers) {
2553 chosen_cau = cau;2547 chosen_unit = unit;
2554 chosen_cau_dependers = n;2548 chosen_unit_dependers = n;
2555 }2549 }
2556 }2550 }
2557 }2551 }
25582552
2559 if (chosen_cau == null) {2553 if (chosen_unit == null) {
2560 for (zcu.outdated.keys(), zcu.outdated.values()) |o, opod| {2554 for (zcu.outdated.keys(), zcu.outdated.values()) |o, opod| {
2561 const func = o.unwrap().func;2555 const func = o.unwrap().func;
2562 const nav = zcu.funcInfo(func).owner_nav;2556 const nav = zcu.funcInfo(func).owner_nav;
...@@ -2570,11 +2564,11 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {...@@ -2570,11 +2564,11 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
2570 }2564 }
25712565
2572 log.debug("findOutdatedToAnalyze: heuristic returned '{}' ({d} dependers)", .{2566 log.debug("findOutdatedToAnalyze: heuristic returned '{}' ({d} dependers)", .{
2573 zcu.fmtAnalUnit(AnalUnit.wrap(.{ .cau = chosen_cau.? })),2567 zcu.fmtAnalUnit(chosen_unit.?),
2574 chosen_cau_dependers,2568 chosen_unit_dependers,
2575 });2569 });
25762570
2577 return AnalUnit.wrap(.{ .cau = chosen_cau.? });2571 return chosen_unit.?;
2578}2572}
25792573
2580/// During an incremental update, before semantic analysis, call this to flush all values from2574/// During an incremental update, before semantic analysis, call this to flush all values from
...@@ -3019,9 +3013,9 @@ pub fn handleUpdateExports(...@@ -3019,9 +3013,9 @@ pub fn handleUpdateExports(
3019 };3013 };
3020}3014}
30213015
3022pub fn addGlobalAssembly(zcu: *Zcu, cau: InternPool.Cau.Index, source: []const u8) !void {3016pub fn addGlobalAssembly(zcu: *Zcu, unit: AnalUnit, source: []const u8) !void {
3023 const gpa = zcu.gpa;3017 const gpa = zcu.gpa;
3024 const gop = try zcu.global_assembly.getOrPut(gpa, cau);3018 const gop = try zcu.global_assembly.getOrPut(gpa, unit);
3025 if (gop.found_existing) {3019 if (gop.found_existing) {
3026 const new_value = try std.fmt.allocPrint(gpa, "{s}\n{s}", .{ gop.value_ptr.*, source });3020 const new_value = try std.fmt.allocPrint(gpa, "{s}\n{s}", .{ gop.value_ptr.*, source });
3027 gpa.free(gop.value_ptr.*);3021 gpa.free(gop.value_ptr.*);
...@@ -3304,23 +3298,22 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3304,23 +3298,22 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
33043298
3305 log.debug("handle type '{}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});3299 log.debug("handle type '{}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});
33063300
3307 // If this type has a `Cau` for resolution, it's automatically referenced.3301 // If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced.
3308 const resolution_cau: InternPool.Cau.Index.Optional = switch (ip.indexToKey(ty)) {3302 const has_resolution: bool = switch (ip.indexToKey(ty)) {
3309 .struct_type => ip.loadStructType(ty).cau.toOptional(),3303 .struct_type, .union_type => true,
3310 .union_type => ip.loadUnionType(ty).cau.toOptional(),3304 .enum_type => |k| k != .generated_tag,
3311 .enum_type => ip.loadEnumType(ty).cau,3305 .opaque_type => false,
3312 .opaque_type => .none,
3313 else => unreachable,3306 else => unreachable,
3314 };3307 };
3315 if (resolution_cau.unwrap()) |cau| {3308 if (has_resolution) {
3316 // this should only be referenced by the type3309 // this should only be referenced by the type
3317 const unit = AnalUnit.wrap(.{ .cau = cau });3310 const unit: AnalUnit = .wrap(.{ .type = ty });
3318 assert(!result.contains(unit));3311 assert(!result.contains(unit));
3319 try unit_queue.putNoClobber(gpa, unit, referencer);3312 try unit_queue.putNoClobber(gpa, unit, referencer);
3320 }3313 }
33213314
3322 // If this is a union with a generated tag, its tag type is automatically referenced.3315 // If this is a union with a generated tag, its tag type is automatically referenced.
3323 // 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.3316 // 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.
3324 if (zcu.typeToUnion(Type.fromInterned(ty))) |union_obj| {3317 if (zcu.typeToUnion(Type.fromInterned(ty))) |union_obj| {
3325 const tag_ty = union_obj.enum_tag_ty;3318 const tag_ty = union_obj.enum_tag_ty;
3326 if (tag_ty != .none) {3319 if (tag_ty != .none) {
...@@ -3335,24 +3328,35 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3335,24 +3328,35 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3335 // Queue any decls within this type which would be automatically analyzed.3328 // Queue any decls within this type which would be automatically analyzed.
3336 // Keep in sync with analysis queueing logic in `Zcu.PerThread.ScanDeclIter.scanDecl`.3329 // Keep in sync with analysis queueing logic in `Zcu.PerThread.ScanDeclIter.scanDecl`.
3337 const ns = Type.fromInterned(ty).getNamespace(zcu).unwrap().?;3330 const ns = Type.fromInterned(ty).getNamespace(zcu).unwrap().?;
3338 for (zcu.namespacePtr(ns).other_decls.items) |cau| {3331 for (zcu.namespacePtr(ns).comptime_decls.items) |cu| {
3339 // These are `comptime` and `test` declarations.3332 // `comptime` decls are always analyzed.
3340 // `comptime` decls are always analyzed; `test` declarations are analyzed depending on the test filter.3333 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });
3341 const inst_info = ip.getCau(cau).zir_index.resolveFull(ip) orelse continue;3334 if (!result.contains(unit)) {
3335 log.debug("type '{}': ref comptime %{}", .{
3336 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
3337 @intFromEnum(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue),
3338 });
3339 try unit_queue.put(gpa, unit, referencer);
3340 }
3341 }
3342 for (zcu.namespacePtr(ns).test_decls.items) |nav_id| {
3343 const nav = ip.getNav(nav_id);
3344 // `test` declarations are analyzed depending on the test filter.
3345 const inst_info = nav.analysis.?.zir_index.resolveFull(ip) orelse continue;
3342 const file = zcu.fileByIndex(inst_info.file);3346 const file = zcu.fileByIndex(inst_info.file);
3343 // If the file failed AstGen, the TrackedInst refers to the old ZIR.3347 // If the file failed AstGen, the TrackedInst refers to the old ZIR.
3344 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;3348 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3345 const decl = zir.getDeclaration(inst_info.inst);3349 const decl = zir.getDeclaration(inst_info.inst);
3350
3351 if (!comp.config.is_test or file.mod != zcu.main_mod) continue;
3352
3346 const want_analysis = switch (decl.kind) {3353 const want_analysis = switch (decl.kind) {
3347 .@"usingnamespace" => unreachable,3354 .@"usingnamespace" => unreachable,
3348 .@"const", .@"var" => unreachable,3355 .@"const", .@"var" => unreachable,
3349 .@"comptime" => true,3356 .@"comptime" => unreachable,
3350 .unnamed_test => comp.config.is_test and file.mod == zcu.main_mod,3357 .unnamed_test => true,
3351 .@"test", .decltest => a: {3358 .@"test", .decltest => a: {
3352 if (!comp.config.is_test) break :a false;3359 const fqn_slice = nav.fqn.toSlice(ip);
3353 if (file.mod != zcu.main_mod) break :a false;
3354 const nav = ip.getCau(cau).owner.unwrap().nav;
3355 const fqn_slice = ip.getNav(nav).fqn.toSlice(ip);
3356 for (comp.test_filters) |test_filter| {3360 for (comp.test_filters) |test_filter| {
3357 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;3361 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
3358 } else break :a false;3362 } else break :a false;
...@@ -3360,28 +3364,25 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3360,28 +3364,25 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3360 },3364 },
3361 };3365 };
3362 if (want_analysis) {3366 if (want_analysis) {
3363 const unit = AnalUnit.wrap(.{ .cau = cau });3367 log.debug("type '{}': ref test %{}", .{
3364 if (!result.contains(unit)) {3368 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
3365 log.debug("type '{}': ref cau %{}", .{3369 @intFromEnum(inst_info.inst),
3366 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),3370 });
3367 @intFromEnum(inst_info.inst),3371 const unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
3368 });3372 try unit_queue.put(gpa, unit, referencer);
3369 try unit_queue.put(gpa, unit, referencer);
3370 }
3371 }3373 }
3372 }3374 }
3373 for (zcu.namespacePtr(ns).pub_decls.keys()) |nav| {3375 for (zcu.namespacePtr(ns).pub_decls.keys()) |nav| {
3374 // These are named declarations. They are analyzed only if marked `export`.3376 // These are named declarations. They are analyzed only if marked `export`.
3375 const cau = ip.getNav(nav).analysis_owner.unwrap().?;3377 const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue;
3376 const inst_info = ip.getCau(cau).zir_index.resolveFull(ip) orelse continue;
3377 const file = zcu.fileByIndex(inst_info.file);3378 const file = zcu.fileByIndex(inst_info.file);
3378 // If the file failed AstGen, the TrackedInst refers to the old ZIR.3379 // If the file failed AstGen, the TrackedInst refers to the old ZIR.
3379 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;3380 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3380 const decl = zir.getDeclaration(inst_info.inst);3381 const decl = zir.getDeclaration(inst_info.inst);
3381 if (decl.linkage == .@"export") {3382 if (decl.linkage == .@"export") {
3382 const unit = AnalUnit.wrap(.{ .cau = cau });3383 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
3383 if (!result.contains(unit)) {3384 if (!result.contains(unit)) {
3384 log.debug("type '{}': ref cau %{}", .{3385 log.debug("type '{}': ref named %{}", .{
3385 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),3386 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
3386 @intFromEnum(inst_info.inst),3387 @intFromEnum(inst_info.inst),
3387 });3388 });
...@@ -3391,16 +3392,15 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3391,16 +3392,15 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3391 }3392 }
3392 for (zcu.namespacePtr(ns).priv_decls.keys()) |nav| {3393 for (zcu.namespacePtr(ns).priv_decls.keys()) |nav| {
3393 // These are named declarations. They are analyzed only if marked `export`.3394 // These are named declarations. They are analyzed only if marked `export`.
3394 const cau = ip.getNav(nav).analysis_owner.unwrap().?;3395 const inst_info = ip.getNav(nav).analysis.?.zir_index.resolveFull(ip) orelse continue;
3395 const inst_info = ip.getCau(cau).zir_index.resolveFull(ip) orelse continue;
3396 const file = zcu.fileByIndex(inst_info.file);3396 const file = zcu.fileByIndex(inst_info.file);
3397 // If the file failed AstGen, the TrackedInst refers to the old ZIR.3397 // If the file failed AstGen, the TrackedInst refers to the old ZIR.
3398 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;3398 const zir = if (file.status == .success_zir) file.zir else file.prev_zir.?.*;
3399 const decl = zir.getDeclaration(inst_info.inst);3399 const decl = zir.getDeclaration(inst_info.inst);
3400 if (decl.linkage == .@"export") {3400 if (decl.linkage == .@"export") {
3401 const unit = AnalUnit.wrap(.{ .cau = cau });3401 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
3402 if (!result.contains(unit)) {3402 if (!result.contains(unit)) {
3403 log.debug("type '{}': ref cau %{}", .{3403 log.debug("type '{}': ref named %{}", .{
3404 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),3404 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
3405 @intFromEnum(inst_info.inst),3405 @intFromEnum(inst_info.inst),
3406 });3406 });
...@@ -3411,13 +3411,11 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv...@@ -3411,13 +3411,11 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
3411 // Incremental compilation does not support `usingnamespace`.3411 // Incremental compilation does not support `usingnamespace`.
3412 // These are only included to keep good reference traces in non-incremental updates.3412 // These are only included to keep good reference traces in non-incremental updates.
3413 for (zcu.namespacePtr(ns).pub_usingnamespace.items) |nav| {3413 for (zcu.namespacePtr(ns).pub_usingnamespace.items) |nav| {
3414 const cau = ip.getNav(nav).analysis_owner.unwrap().?;3414 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
3415 const unit = AnalUnit.wrap(.{ .cau = cau });
3416 if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);3415 if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);
3417 }3416 }
3418 for (zcu.namespacePtr(ns).priv_usingnamespace.items) |nav| {3417 for (zcu.namespacePtr(ns).priv_usingnamespace.items) |nav| {
3419 const cau = ip.getNav(nav).analysis_owner.unwrap().?;3418 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
3420 const unit = AnalUnit.wrap(.{ .cau = cau });
3421 if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);3419 if (!result.contains(unit)) try unit_queue.put(gpa, unit, referencer);
3422 }3420 }
3423 continue;3421 continue;
...@@ -3527,12 +3525,6 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File {...@@ -3527,12 +3525,6 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File {
3527 return zcu.fileByIndex(zcu.navFileScopeIndex(nav));3525 return zcu.fileByIndex(zcu.navFileScopeIndex(nav));
3528}3526}
35293527
3530pub fn cauFileScope(zcu: *Zcu, cau: InternPool.Cau.Index) *File {
3531 const ip = &zcu.intern_pool;
3532 const file_index = ip.getCau(cau).zir_index.resolveFile(ip);
3533 return zcu.fileByIndex(file_index);
3534}
3535
3536pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Formatter(formatAnalUnit) {3528pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Formatter(formatAnalUnit) {
3537 return .{ .data = .{ .unit = unit, .zcu = zcu } };3529 return .{ .data = .{ .unit = unit, .zcu = zcu } };
3538}3530}
...@@ -3545,19 +3537,17 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co...@@ -3545,19 +3537,17 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co
3545 const zcu = data.zcu;3537 const zcu = data.zcu;
3546 const ip = &zcu.intern_pool;3538 const ip = &zcu.intern_pool;
3547 switch (data.unit.unwrap()) {3539 switch (data.unit.unwrap()) {
3548 .cau => |cau_index| {3540 .@"comptime" => |cu_id| {
3549 const cau = ip.getCau(cau_index);3541 const cu = ip.getComptimeUnit(cu_id);
3550 switch (cau.owner.unwrap()) {3542 if (cu.zir_index.resolveFull(ip)) |resolved| {
3551 .nav => |nav| return writer.print("cau(decl='{}')", .{ip.getNav(nav).fqn.fmt(ip)}),3543 const file_path = zcu.fileByIndex(resolved.file).sub_file_path;
3552 .type => |ty| return writer.print("cau(ty='{}')", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}),3544 return writer.print("comptime(inst=('{s}', %{}))", .{ file_path, @intFromEnum(resolved.inst) });
3553 .none => if (cau.zir_index.resolveFull(ip)) |resolved| {3545 } else {
3554 const file_path = zcu.fileByIndex(resolved.file).sub_file_path;3546 return writer.writeAll("comptime(inst=<list>)");
3555 return writer.print("cau(inst=('{s}', %{}))", .{ file_path, @intFromEnum(resolved.inst) });
3556 } else {
3557 return writer.writeAll("cau(inst=<lost>)");
3558 },
3559 }3547 }
3560 },3548 },
3549 .nav_val => |nav| return writer.print("nav_val('{}')", .{ip.getNav(nav).fqn.fmt(ip)}),
3550 .type => |ty| return writer.print("ty('{}')", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}),
3561 .func => |func| {3551 .func => |func| {
3562 const nav = zcu.funcInfo(func).owner_nav;3552 const nav = zcu.funcInfo(func).owner_nav;
3563 return writer.print("func('{}')", .{ip.getNav(nav).fqn.fmt(ip)});3553 return writer.print("func('{}')", .{ip.getNav(nav).fqn.fmt(ip)});
src/Zcu/PerThread.zig+941-972
...@@ -545,144 +545,173 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {...@@ -545,144 +545,173 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
545pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {545pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
546 const file_root_type = pt.zcu.fileRootType(file_index);546 const file_root_type = pt.zcu.fileRootType(file_index);
547 if (file_root_type != .none) {547 if (file_root_type != .none) {
548 _ = try pt.ensureTypeUpToDate(file_root_type, false);548 _ = try pt.ensureTypeUpToDate(file_root_type);
549 } else {549 } else {
550 return pt.semaFile(file_index);550 return pt.semaFile(file_index);
551 }551 }
552}552}
553553
554/// This ensures that the state of the `Cau`, and of its corresponding `Nav` or type,554/// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis
555/// is fully up-to-date. Note that the type of the `Nav` may not be fully resolved.555/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
556/// Returns `error.AnalysisFail` if the `Cau` has an error.556/// free to ignore this, since the error is already registered.
557pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu.SemaError!void {557pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.SemaError!void {
558 const tracy = trace(@src());558 const tracy = trace(@src());
559 defer tracy.end();559 defer tracy.end();
560560
561 const zcu = pt.zcu;561 const zcu = pt.zcu;
562 const gpa = zcu.gpa;562 const gpa = zcu.gpa;
563 const ip = &zcu.intern_pool;
564563
565 const anal_unit = AnalUnit.wrap(.{ .cau = cau_index });564 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });
566 const cau = ip.getCau(cau_index);
567565
568 log.debug("ensureCauAnalyzed {}", .{zcu.fmtAnalUnit(anal_unit)});566 log.debug("ensureComptimeUnitUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});
569567
570 assert(!zcu.analysis_in_progress.contains(anal_unit));568 assert(!zcu.analysis_in_progress.contains(anal_unit));
571569
572 // Determine whether or not this Cau is outdated, i.e. requires re-analysis570 // Determine whether or not this `ComptimeUnit` is outdated. For this kind of `AnalUnit`, that's
573 // even if `complete`. If a Cau is PO, we pessismistically assume that it571 // the only indicator as to whether or not analysis is required; when a `ComptimeUnit` is first
574 // *does* require re-analysis, to ensure that the Cau is definitely572 // created, it's marked as outdated.
575 // up-to-date when this function returns.573 //
576574 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to
577 // If analysis occurs in a poor order, this could result in over-analysis.575 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could
578 // We do our best to avoid this by the other dependency logic in this file576 // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by
579 // which tries to limit re-analysis to Caus whose previously listed577 // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`.
580 // dependencies are all up-to-date.
581578
582 const cau_outdated = zcu.outdated.swapRemove(anal_unit) or579 const was_outdated = zcu.outdated.swapRemove(anal_unit) or
583 zcu.potentially_outdated.swapRemove(anal_unit);580 zcu.potentially_outdated.swapRemove(anal_unit);
584581
585 const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit);582 if (was_outdated) {
586
587 if (cau_outdated) {
588 _ = zcu.outdated_ready.swapRemove(anal_unit);583 _ = zcu.outdated_ready.swapRemove(anal_unit);
589 } else {584 // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`.
590 // We can trust the current information about this `Cau`.585 if (dev.env.supports(.incremental)) {
591 if (prev_failed) {586 zcu.deleteUnitExports(anal_unit);
592 return error.AnalysisFail;587 zcu.deleteUnitReferences(anal_unit);
593 }588 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
594 // If it wasn't failed and wasn't marked outdated, then either...589 kv.value.destroy(gpa);
595 // * it is a type and is up-to-date, or590 }
596 // * it is a `comptime` decl and is up-to-date, or591 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
597 // * it is another decl and is EITHER up-to-date OR never-referenced (so unresolved)
598 // We just need to check for that last case.
599 switch (cau.owner.unwrap()) {
600 .type, .none => return,
601 .nav => |nav| if (ip.getNav(nav).status == .resolved) return,
602 }592 }
593 } else {
594 // We can trust the current information about this unit.
595 if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail;
596 if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail;
597 return;
603 }598 }
604599
605 const sema_result: SemaCauResult, const analysis_fail = if (pt.ensureCauAnalyzedInner(cau_index, cau_outdated)) |result|600 const unit_prog_node = zcu.sema_prog_node.start("comptime", 0);
606 // This `Cau` has gone from failed to success, so even if the value of the owner `Nav` didn't actually601 defer unit_prog_node.end();
607 // change, we need to invalidate the dependencies anyway.602
608 .{ .{603 return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) {
609 .invalidate_decl_val = result.invalidate_decl_val or prev_failed,604 error.AnalysisFail => {
610 .invalidate_decl_ref = result.invalidate_decl_ref or prev_failed,
611 }, false }
612 else |err| switch (err) {
613 error.AnalysisFail => res: {
614 if (!zcu.failed_analysis.contains(anal_unit)) {605 if (!zcu.failed_analysis.contains(anal_unit)) {
615 // If this `Cau` caused the error, it would have an entry in `failed_analysis`.606 // If this unit caused the error, it would have an entry in `failed_analysis`.
616 // Since it does not, this must be a transitive failure.607 // Since it does not, this must be a transitive failure.
617 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});608 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
618 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});609 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});
619 }610 }
620 // We consider this `Cau` to be outdated if:611 return error.AnalysisFail;
621 // * Previous analysis succeeded; in this case, we need to re-analyze dependants to ensure
622 // they hit a transitive error here, rather than reporting a different error later (which
623 // may now be invalid).
624 // * The `Cau` is a type; in this case, the declaration site may require re-analysis to
625 // construct a valid type.
626 const outdated = !prev_failed or cau.owner.unwrap() == .type;
627 break :res .{ .{
628 .invalidate_decl_val = outdated,
629 .invalidate_decl_ref = outdated,
630 }, true };
631 },612 },
632 error.OutOfMemory => res: {613 error.OutOfMemory => {
633 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);614 // TODO: it's unclear how to gracefully handle this.
634 try zcu.retryable_failures.ensureUnusedCapacity(gpa, 1);615 // To report the error cleanly, we need to add a message to `failed_analysis` and a
635 const msg = try Zcu.ErrorMsg.create(616 // corresponding entry to `retryable_failures`; but either of these things is quite
636 gpa,617 // likely to OOM at this point.
637 .{ .base_node_inst = cau.zir_index, .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0) },618 // If that happens, what do we do? Perhaps we could have a special field on `Zcu`
638 "unable to analyze: OutOfMemory",619 // for reporting OOM errors without allocating.
639 .{},620 return error.OutOfMemory;
640 );
641 zcu.retryable_failures.appendAssumeCapacity(anal_unit);
642 zcu.failed_analysis.putAssumeCapacityNoClobber(anal_unit, msg);
643 break :res .{ .{
644 .invalidate_decl_val = true,
645 .invalidate_decl_ref = true,
646 }, true };
647 },621 },
622 error.GenericPoison => unreachable,
623 error.ComptimeReturn => unreachable,
624 error.ComptimeBreak => unreachable,
648 };625 };
649
650 if (cau_outdated) {
651 // TODO: we do not yet have separate dependencies for decl values vs types.
652 const invalidate = sema_result.invalidate_decl_val or sema_result.invalidate_decl_ref;
653 const dependee: InternPool.Dependee = switch (cau.owner.unwrap()) {
654 .none => return, // there are no dependencies on a `comptime` decl!
655 .nav => |nav_index| .{ .nav_val = nav_index },
656 .type => |ty| .{ .interned = ty },
657 };
658
659 if (invalidate) {
660 // This dependency was marked as PO, meaning dependees were waiting
661 // on its analysis result, and it has turned out to be outdated.
662 // Update dependees accordingly.
663 try zcu.markDependeeOutdated(.marked_po, dependee);
664 } else {
665 // This dependency was previously PO, but turned out to be up-to-date.
666 // We do not need to queue successive analysis.
667 try zcu.markPoDependeeUpToDate(dependee);
668 }
669 }
670
671 if (analysis_fail) return error.AnalysisFail;
672}626}
673627
674fn ensureCauAnalyzedInner(628/// Re-analyzes a `ComptimeUnit`. The unit has already been determined to be out-of-date, and old
675 pt: Zcu.PerThread,629/// side effects (exports/references/etc) have been dropped. If semantic analysis fails, this
676 cau_index: InternPool.Cau.Index,630/// function will return `error.AnalysisFail`, and it is the caller's reponsibility to add an entry
677 cau_outdated: bool,631/// to `transitive_failed_analysis` if necessary.
678) Zcu.SemaError!SemaCauResult {632fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void {
679 const zcu = pt.zcu;633 const zcu = pt.zcu;
634 const gpa = zcu.gpa;
680 const ip = &zcu.intern_pool;635 const ip = &zcu.intern_pool;
681636
682 const cau = ip.getCau(cau_index);637 const anal_unit: AnalUnit = .wrap(.{ .@"comptime" = cu_id });
683 const anal_unit = AnalUnit.wrap(.{ .cau = cau_index });638 const comptime_unit = ip.getComptimeUnit(cu_id);
639
640 log.debug("analyzeComptimeUnit {}", .{zcu.fmtAnalUnit(anal_unit)});
641
642 const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
643 const file = zcu.fileByIndex(inst_resolved.file);
644 // TODO: stop the compiler ever reaching Sema if there are failed files. That way, this check is
645 // unnecessary, and we can move the below `removeDependenciesForDepender` call up with its friends
646 // in `ensureComptimeUnitUpToDate`.
647 if (file.status != .success_zir) return error.AnalysisFail;
648 const zir = file.zir;
649
650 // We are about to re-analyze this unit; drop its depenndencies.
651 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
652
653 try zcu.analysis_in_progress.put(gpa, anal_unit, {});
654 defer assert(zcu.analysis_in_progress.swapRemove(anal_unit));
655
656 var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
657 defer analysis_arena.deinit();
658
659 var comptime_err_ret_trace: std.ArrayList(Zcu.LazySrcLoc) = .init(gpa);
660 defer comptime_err_ret_trace.deinit();
661
662 var sema: Sema = .{
663 .pt = pt,
664 .gpa = gpa,
665 .arena = analysis_arena.allocator(),
666 .code = zir,
667 .owner = anal_unit,
668 .func_index = .none,
669 .func_is_naked = false,
670 .fn_ret_ty = .void,
671 .fn_ret_ty_ies = null,
672 .comptime_err_ret_trace = &comptime_err_ret_trace,
673 };
674 defer sema.deinit();
675
676 // The comptime unit declares on the source of the corresponding `comptime` declaration.
677 try sema.declareDependency(.{ .src_hash = comptime_unit.zir_index });
678
679 var block: Sema.Block = .{
680 .parent = null,
681 .sema = &sema,
682 .namespace = comptime_unit.namespace,
683 .instructions = .{},
684 .inlining = null,
685 .is_comptime = true,
686 .src_base_inst = comptime_unit.zir_index,
687 .type_name_ctx = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.comptime", .{
688 Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip),
689 }, .no_embedded_nulls),
690 };
691 defer block.instructions.deinit(gpa);
692
693 const zir_decl = zir.getDeclaration(inst_resolved.inst);
694 assert(zir_decl.kind == .@"comptime");
695 assert(zir_decl.type_body == null);
696 assert(zir_decl.align_body == null);
697 assert(zir_decl.linksection_body == null);
698 assert(zir_decl.addrspace_body == null);
699 const value_body = zir_decl.value_body.?;
700
701 const result_ref = try sema.resolveInlineBody(&block, value_body, inst_resolved.inst);
702 assert(result_ref == .void_value); // AstGen should always uphold this
703
704 // Nothing else to do -- for a comptime decl, all we care about are the side effects.
705 // Just make sure to `flushExports`.
706 try sema.flushExports();
707}
684708
685 const inst_info = cau.zir_index.resolveFull(ip) orelse return error.AnalysisFail;709/// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis
710/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
711/// free to ignore this, since the error is already registered.
712pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.SemaError!void {
713 const tracy = trace(@src());
714 defer tracy.end();
686715
687 // TODO: document this elsewhere mlugg!716 // TODO: document this elsewhere mlugg!
688 // For my own benefit, here's how a namespace update for a normal (non-file-root) type works:717 // For my own benefit, here's how a namespace update for a normal (non-file-root) type works:
...@@ -692,821 +721,826 @@ fn ensureCauAnalyzedInner(...@@ -692,821 +721,826 @@ fn ensureCauAnalyzedInner(
692 // * Any change to the `struct` body -- including changing a declaration -- invalidates this721 // * Any change to the `struct` body -- including changing a declaration -- invalidates this
693 // * `S` is re-analyzed, but notes:722 // * `S` is re-analyzed, but notes:
694 // * there is an existing struct instance (at this `TrackedInst` with these captures)723 // * there is an existing struct instance (at this `TrackedInst` with these captures)
695 // * the struct's `Cau` is up-to-date (because nothing about the fields changed)724 // * the struct's resolution is up-to-date (because nothing about the fields changed)
696 // * so, it uses the same `struct`725 // * so, it uses the same `struct`
697 // * but this doesn't stop it from updating the namespace!726 // * but this doesn't stop it from updating the namespace!
698 // * we basically do `scanDecls`, updating the namespace as needed727 // * we basically do `scanDecls`, updating the namespace as needed
699 // * so everyone lived happily ever after728 // * so everyone lived happily ever after
700729
701 if (zcu.fileByIndex(inst_info.file).status != .success_zir) {
702 return error.AnalysisFail;
703 }
704
705 // `cau_outdated` can be true in the initial update for `comptime` declarations,
706 // so this isn't a `dev.check`.
707 if (cau_outdated and dev.env.supports(.incremental)) {
708 // The exports this `Cau` performs will be re-discovered, so we remove them here
709 // prior to re-analysis.
710 zcu.deleteUnitExports(anal_unit);
711 zcu.deleteUnitReferences(anal_unit);
712 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
713 kv.value.destroy(zcu.gpa);
714 }
715 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
716 }
717
718 const decl_prog_node = zcu.sema_prog_node.start(switch (cau.owner.unwrap()) {
719 .nav => |nav| ip.getNav(nav).fqn.toSlice(ip),
720 .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
721 .none => "comptime",
722 }, 0);
723 defer decl_prog_node.end();
724
725 return pt.semaCau(cau_index) catch |err| switch (err) {
726 error.GenericPoison, error.ComptimeBreak, error.ComptimeReturn => unreachable,
727 error.AnalysisFail, error.OutOfMemory => |e| return e,
728 };
729}
730
731pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: InternPool.Index) Zcu.SemaError!void {
732 dev.check(.sema);
733
734 const tracy = trace(@src());
735 defer tracy.end();
736
737 const zcu = pt.zcu;730 const zcu = pt.zcu;
738 const gpa = zcu.gpa;731 const gpa = zcu.gpa;
739 const ip = &zcu.intern_pool;732 const ip = &zcu.intern_pool;
740733
741 // We only care about the uncoerced function.734 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
742 const func_index = ip.unwrapCoercedFunc(maybe_coerced_func_index);735 const nav = ip.getNav(nav_id);
743 const anal_unit = AnalUnit.wrap(.{ .func = func_index });
744736
745 log.debug("ensureFuncBodyAnalyzed {}", .{zcu.fmtAnalUnit(anal_unit)});737 log.debug("ensureNavUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});
746738
747 const func = zcu.funcInfo(maybe_coerced_func_index);739 // Determine whether or not this `Nav`'s value is outdated. This also includes checking if the
740 // status is `.unresolved`, which indicates that the value is outdated because it has *never*
741 // been analyzed so far.
742 //
743 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to
744 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could
745 // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by
746 // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`.
748747
749 const func_outdated = zcu.outdated.swapRemove(anal_unit) or748 const was_outdated = zcu.outdated.swapRemove(anal_unit) or
750 zcu.potentially_outdated.swapRemove(anal_unit);749 zcu.potentially_outdated.swapRemove(anal_unit);
751750
752 const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit);751 const prev_failed = zcu.failed_analysis.contains(anal_unit) or
752 zcu.transitive_failed_analysis.contains(anal_unit);
753753
754 if (func_outdated) {754 if (was_outdated) {
755 dev.check(.incremental);
755 _ = zcu.outdated_ready.swapRemove(anal_unit);756 _ = zcu.outdated_ready.swapRemove(anal_unit);
756 } else {757 zcu.deleteUnitExports(anal_unit);
757 // We can trust the current information about this function.758 zcu.deleteUnitReferences(anal_unit);
758 if (prev_failed) {759 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
759 return error.AnalysisFail;760 kv.value.destroy(gpa);
760 }
761 switch (func.analysisUnordered(ip).state) {
762 .unreferenced => {}, // this is the first reference
763 .queued => {}, // we're waiting on first-time analysis
764 .analyzed => return, // up-to-date
765 }761 }
762 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
763 } else {
764 // We can trust the current information about this unit.
765 if (prev_failed) return error.AnalysisFail;
766 if (nav.status == .resolved) return;
766 }767 }
767768
768 const ies_outdated, const analysis_fail = if (pt.ensureFuncBodyAnalyzedInner(func_index, func_outdated)) |result|769 const unit_prog_node = zcu.sema_prog_node.start(nav.fqn.toSlice(ip), 0);
769 .{ result.ies_outdated, false }770 defer unit_prog_node.end();
770 else |err| switch (err) {771
772 const sema_result: SemaNavResult, const new_failed: bool = if (pt.analyzeNavVal(nav_id)) |result| res: {
773 break :res .{
774 .{
775 // If the unit has gone from failed to success, we still need to invalidate the dependencies.
776 .invalidate_nav_val = result.invalidate_nav_val or prev_failed,
777 .invalidate_nav_ref = result.invalidate_nav_ref or prev_failed,
778 },
779 false,
780 };
781 } else |err| switch (err) {
771 error.AnalysisFail => res: {782 error.AnalysisFail => res: {
772 if (!zcu.failed_analysis.contains(anal_unit)) {783 if (!zcu.failed_analysis.contains(anal_unit)) {
773 // If this function caused the error, it would have an entry in `failed_analysis`.784 // If this unit caused the error, it would have an entry in `failed_analysis`.
774 // Since it does not, this must be a transitive failure.785 // Since it does not, this must be a transitive failure.
775 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});786 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
776 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});787 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});
777 }788 }
778 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,789 break :res .{ .{
779 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting790 .invalidate_nav_val = !prev_failed,
780 // a different error later (which may now be invalid).791 .invalidate_nav_ref = !prev_failed,
781 break :res .{ !prev_failed, true };792 }, true };
782 },793 },
783 error.OutOfMemory => return error.OutOfMemory, // TODO: graceful handling like `ensureCauAnalyzed`794 error.OutOfMemory => {
795 // TODO: it's unclear how to gracefully handle this.
796 // To report the error cleanly, we need to add a message to `failed_analysis` and a
797 // corresponding entry to `retryable_failures`; but either of these things is quite
798 // likely to OOM at this point.
799 // If that happens, what do we do? Perhaps we could have a special field on `Zcu`
800 // for reporting OOM errors without allocating.
801 return error.OutOfMemory;
802 },
803 error.GenericPoison => unreachable,
804 error.ComptimeReturn => unreachable,
805 error.ComptimeBreak => unreachable,
784 };806 };
785807
786 if (func_outdated) {808 if (was_outdated) {
787 if (ies_outdated) {809 // TODO: we do not yet have separate dependencies for Nav values vs types.
788 try zcu.markDependeeOutdated(.marked_po, .{ .interned = func_index });810 const invalidate = sema_result.invalidate_nav_val or sema_result.invalidate_nav_ref;
811 const dependee: InternPool.Dependee = .{ .nav_val = nav_id };
812 if (invalidate) {
813 // This dependency was marked as PO, meaning dependees were waiting
814 // on its analysis result, and it has turned out to be outdated.
815 // Update dependees accordingly.
816 try zcu.markDependeeOutdated(.marked_po, dependee);
789 } else {817 } else {
790 try zcu.markPoDependeeUpToDate(.{ .interned = func_index });818 // This dependency was previously PO, but turned out to be up-to-date.
819 // We do not need to queue successive analysis.
820 try zcu.markPoDependeeUpToDate(dependee);
791 }821 }
792 }822 }
793823
794 if (analysis_fail) return error.AnalysisFail;824 if (new_failed) return error.AnalysisFail;
795}825}
796826
797fn ensureFuncBodyAnalyzedInner(827const SemaNavResult = packed struct {
798 pt: Zcu.PerThread,828 /// Whether the value of a `decl_val` of the corresponding Nav changed.
799 func_index: InternPool.Index,829 invalidate_nav_val: bool,
800 func_outdated: bool,830 /// Whether the type of a `decl_ref` of the corresponding Nav changed.
801) Zcu.SemaError!struct { ies_outdated: bool } {831 invalidate_nav_ref: bool,
832};
833
834fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!SemaNavResult {
802 const zcu = pt.zcu;835 const zcu = pt.zcu;
803 const gpa = zcu.gpa;836 const gpa = zcu.gpa;
804 const ip = &zcu.intern_pool;837 const ip = &zcu.intern_pool;
805838
806 const func = zcu.funcInfo(func_index);839 const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id });
807 const anal_unit = AnalUnit.wrap(.{ .func = func_index });840 const old_nav = ip.getNav(nav_id);
808841
809 // Make sure that this function is still owned by the same `Nav`. Otherwise, analyzing842 log.debug("analyzeNavVal {}", .{zcu.fmtAnalUnit(anal_unit)});
810 // it would be a waste of time in the best case, and could cause codegen to give bogus
811 // results in the worst case.
812843
813 if (func.generic_owner == .none) {844 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
814 // Among another things, this ensures that the function's `zir_body_inst` is correct.845 const file = zcu.fileByIndex(inst_resolved.file);
815 try pt.ensureCauAnalyzed(ip.getNav(func.owner_nav).analysis_owner.unwrap().?);846 // TODO: stop the compiler ever reaching Sema if there are failed files. That way, this check is
816 if (ip.getNav(func.owner_nav).status.resolved.val != func_index) {847 // unnecessary, and we can move the below `removeDependenciesForDepender` call up with its friends
817 // This function is no longer referenced! There's no point in re-analyzing it.848 // in `ensureComptimeUnitUpToDate`.
818 // Just mark a transitive failure and move on.849 if (file.status != .success_zir) return error.AnalysisFail;
819 return error.AnalysisFail;850 const zir = file.zir;
820 }
821 } else {
822 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
823 // Among another things, this ensures that the function's `zir_body_inst` is correct.
824 try pt.ensureCauAnalyzed(ip.getNav(go_nav).analysis_owner.unwrap().?);
825 if (ip.getNav(go_nav).status.resolved.val != func.generic_owner) {
826 // The generic owner is no longer referenced, so this function is also unreferenced.
827 // There's no point in re-analyzing it. Just mark a transitive failure and move on.
828 return error.AnalysisFail;
829 }
830 }
831851
832 // We'll want to remember what the IES used to be before the update for852 // We are about to re-analyze this unit; drop its depenndencies.
833 // dependency invalidation purposes.853 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
834 const old_resolved_ies = if (func.analysisUnordered(ip).inferred_error_set)
835 func.resolvedErrorSetUnordered(ip)
836 else
837 .none;
838854
839 if (func_outdated) {855 try zcu.analysis_in_progress.put(gpa, anal_unit, {});
840 dev.check(.incremental);856 errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit);
841 zcu.deleteUnitExports(anal_unit);
842 zcu.deleteUnitReferences(anal_unit);
843 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
844 kv.value.destroy(gpa);
845 }
846 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
847 }
848857
849 if (!func_outdated) {858 var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
850 // We can trust the current information about this function.859 defer analysis_arena.deinit();
851 if (zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit)) {
852 return error.AnalysisFail;
853 }
854 switch (func.analysisUnordered(ip).state) {
855 .unreferenced => {}, // this is the first reference
856 .queued => {}, // we're waiting on first-time analysis
857 .analyzed => return .{ .ies_outdated = false }, // up-to-date
858 }
859 }
860860
861 log.debug("analyze and generate fn body {}; reason='{s}'", .{861 var comptime_err_ret_trace: std.ArrayList(Zcu.LazySrcLoc) = .init(gpa);
862 zcu.fmtAnalUnit(anal_unit),862 defer comptime_err_ret_trace.deinit();
863 if (func_outdated) "outdated" else "never analyzed",
864 });
865863
866 var air = try pt.analyzeFnBody(func_index);864 var sema: Sema = .{
867 errdefer air.deinit(gpa);865 .pt = pt,
866 .gpa = gpa,
867 .arena = analysis_arena.allocator(),
868 .code = zir,
869 .owner = anal_unit,
870 .func_index = .none,
871 .func_is_naked = false,
872 .fn_ret_ty = .void,
873 .fn_ret_ty_ies = null,
874 .comptime_err_ret_trace = &comptime_err_ret_trace,
875 };
876 defer sema.deinit();
868877
869 const ies_outdated = func_outdated and878 // The comptime unit declares on the source of the corresponding declaration.
870 (!func.analysisUnordered(ip).inferred_error_set or func.resolvedErrorSetUnordered(ip) != old_resolved_ies);879 try sema.declareDependency(.{ .src_hash = old_nav.analysis.?.zir_index });
871880
872 const comp = zcu.comp;881 var block: Sema.Block = .{
882 .parent = null,
883 .sema = &sema,
884 .namespace = old_nav.analysis.?.namespace,
885 .instructions = .{},
886 .inlining = null,
887 .is_comptime = true,
888 .src_base_inst = old_nav.analysis.?.zir_index,
889 .type_name_ctx = old_nav.fqn,
890 };
891 defer block.instructions.deinit(gpa);
873892
874 const dump_air = build_options.enable_debug_extensions and comp.verbose_air;893 const zir_decl = zir.getDeclaration(inst_resolved.inst);
875 const dump_llvm_ir = build_options.enable_debug_extensions and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
876894
877 if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) {895 assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));
878 air.deinit(gpa);
879 return .{ .ies_outdated = ies_outdated };
880 }
881896
882 // This job depends on any resolve_type_fully jobs queued up before it.897 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
883 try comp.queueJob(.{ .codegen_func = .{898 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
884 .func = func_index,899 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
885 .air = air,900 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
886 } });901 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });
887902
888 return .{ .ies_outdated = ies_outdated };903 // First, we must resolve the declaration's type. To do this, we analyze the type body if available,
889}904 // or otherwise, we analyze the value body, populating `early_val` in the process.
890905
891/// Takes ownership of `air`, even on error.906 const nav_ty: Type, const early_val: ?Value = if (zir_decl.type_body) |type_body| ty: {
892/// If any types referenced by `air` are unresolved, marks the codegen as failed.907 // We evaluate only the type now; no need for the value yet.
893pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Air) Allocator.Error!void {908 const uncoerced_type_ref = try sema.resolveInlineBody(&block, type_body, inst_resolved.inst);
894 const zcu = pt.zcu;909 const type_ref = try sema.coerce(&block, .type, uncoerced_type_ref, ty_src);
895 const gpa = zcu.gpa;910 break :ty .{ .fromInterned(type_ref.toInterned().?), null };
896 const ip = &zcu.intern_pool;911 } else ty: {
897 const comp = zcu.comp;912 // We don't have a type body, so we need to evaluate the value immediately.
913 const value_body = zir_decl.value_body.?;
914 const result_ref = try sema.resolveInlineBody(&block, value_body, inst_resolved.inst);
915 const val = try sema.resolveFinalDeclValue(&block, init_src, result_ref);
916 break :ty .{ val.typeOf(zcu), val };
917 };
898918
899 defer {919 switch (zir_decl.kind) {
900 var air_mut = air;920 .@"comptime" => unreachable, // this is not a Nav
901 air_mut.deinit(gpa);921 .unnamed_test, .@"test", .decltest => assert(nav_ty.zigTypeTag(zcu) == .@"fn"),
922 .@"usingnamespace" => {},
923 .@"const" => {},
924 .@"var" => try sema.validateVarType(
925 &block,
926 if (zir_decl.type_body != null) ty_src else init_src,
927 nav_ty,
928 zir_decl.linkage == .@"extern",
929 ),
902 }930 }
903931
904 const func = zcu.funcInfo(func_index);932 // Now that we know the type, we can evaluate the alignment, linksection, and addrspace, to determine
905 const nav_index = func.owner_nav;933 // the full pointer type of this declaration.
906 const nav = ip.getNav(nav_index);
907
908 var liveness = try Liveness.analyze(gpa, air, ip);
909 defer liveness.deinit(gpa);
910934
911 if (build_options.enable_debug_extensions and comp.verbose_air) {935 const alignment: InternPool.Alignment = a: {
912 std.debug.print("# Begin Function AIR: {}:\n", .{nav.fqn.fmt(ip)});936 const align_body = zir_decl.align_body orelse break :a .none;
913 @import("../print_air.zig").dump(pt, air, liveness);937 const align_ref = try sema.resolveInlineBody(&block, align_body, inst_resolved.inst);
914 std.debug.print("# End Function AIR: {}\n\n", .{nav.fqn.fmt(ip)});938 break :a try sema.analyzeAsAlign(&block, align_src, align_ref);
915 }939 };
916940
917 if (std.debug.runtime_safety) {941 const @"linksection": InternPool.OptionalNullTerminatedString = ls: {
918 var verify: Liveness.Verify = .{942 const linksection_body = zir_decl.linksection_body orelse break :ls .none;
919 .gpa = gpa,943 const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_resolved.inst);
920 .air = air,944 const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{
921 .liveness = liveness,945 .needed_comptime_reason = "linksection must be comptime-known",
922 .intern_pool = ip,946 });
923 };947 if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
924 defer verify.deinit();948 return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{});
949 } else if (bytes.len == 0) {
950 return sema.fail(&block, section_src, "linksection cannot be empty", .{});
951 }
952 break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);
953 };
925954
926 verify.verify() catch |err| switch (err) {955 const @"addrspace": std.builtin.AddressSpace = as: {
927 error.OutOfMemory => return error.OutOfMemory,956 const addrspace_ctx: Sema.AddressSpaceContext = switch (zir_decl.kind) {
928 else => {957 .@"var" => .variable,
929 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(958 else => switch (nav_ty.zigTypeTag(zcu)) {
930 gpa,959 .@"fn" => .function,
931 zcu.navSrcLoc(nav_index),960 else => .constant,
932 "invalid liveness: {s}",
933 .{@errorName(err)},
934 ));
935 return;
936 },961 },
937 };962 };
963 const target = zcu.getTarget();
964 const addrspace_body = zir_decl.addrspace_body orelse break :as switch (addrspace_ctx) {
965 .function => target_util.defaultAddressSpace(target, .function),
966 .variable => target_util.defaultAddressSpace(target, .global_mutable),
967 .constant => target_util.defaultAddressSpace(target, .global_constant),
968 else => unreachable,
969 };
970 const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_resolved.inst);
971 break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);
972 };
973
974 // Lastly, we must evaluate the value if we have not already done so. Note, however, that extern declarations
975 // don't have an associated value body.
976
977 const final_val: ?Value = early_val orelse if (zir_decl.value_body) |value_body| val: {
978 // Put the resolved type into `inst_map` to be used as the result type of the init.
979 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{inst_resolved.inst});
980 sema.inst_map.putAssumeCapacity(inst_resolved.inst, Air.internedToRef(nav_ty.toIntern()));
981 const uncoerced_result_ref = try sema.resolveInlineBody(&block, value_body, inst_resolved.inst);
982 assert(sema.inst_map.remove(inst_resolved.inst));
983
984 const result_ref = try sema.coerce(&block, nav_ty, uncoerced_result_ref, init_src);
985 break :val try sema.resolveFinalDeclValue(&block, init_src, result_ref);
986 } else null;
987
988 const nav_val: Value = switch (zir_decl.linkage) {
989 .normal, .@"export" => switch (zir_decl.kind) {
990 .@"var" => .fromInterned(try pt.intern(.{ .variable = .{
991 .ty = nav_ty.toIntern(),
992 .init = final_val.?.toIntern(),
993 .owner_nav = nav_id,
994 .is_threadlocal = zir_decl.is_threadlocal,
995 .is_weak_linkage = false,
996 } })),
997 else => final_val.?,
998 },
999 .@"extern" => val: {
1000 assert(final_val == null); // extern decls do not have a value body
1001 const lib_name: ?[]const u8 = if (zir_decl.lib_name != .empty) l: {
1002 break :l zir.nullTerminatedString(zir_decl.lib_name);
1003 } else null;
1004 if (lib_name) |l| {
1005 const lib_name_src = block.src(.{ .node_offset_lib_name = 0 });
1006 try sema.handleExternLibName(&block, lib_name_src, l);
1007 }
1008 break :val .fromInterned(try pt.getExtern(.{
1009 .name = old_nav.name,
1010 .ty = nav_ty.toIntern(),
1011 .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, lib_name, .no_embedded_nulls),
1012 .is_const = zir_decl.kind == .@"const",
1013 .is_threadlocal = zir_decl.is_threadlocal,
1014 .is_weak_linkage = false,
1015 .is_dll_import = false,
1016 .alignment = alignment,
1017 .@"addrspace" = @"addrspace",
1018 .zir_index = old_nav.analysis.?.zir_index, // `declaration` instruction
1019 .owner_nav = undefined, // ignored by `getExtern`
1020 }));
1021 },
1022 };
1023
1024 switch (nav_val.toIntern()) {
1025 .generic_poison => unreachable, // assertion failure
1026 .unreachable_value => unreachable, // assertion failure
1027 else => {},
938 }1028 }
9391029
940 const codegen_prog_node = zcu.codegen_prog_node.start(nav.fqn.toSlice(ip), 0);1030 // This resolves the type of the resolved value, not that value itself. If `nav_val` is a struct type,
941 defer codegen_prog_node.end();1031 // this resolves the type `type` (which needs no resolution), not the struct itself.
1032 try nav_ty.resolveLayout(pt);
9421033
943 if (!air.typesFullyResolved(zcu)) {1034 // TODO: this is jank. If #20663 is rejected, let's think about how to better model `usingnamespace`.
944 // A type we depend on failed to resolve. This is a transitive failure.1035 if (zir_decl.kind == .@"usingnamespace") {
945 // Correcting this failure will involve changing a type this function1036 if (nav_ty.toIntern() != .type_type) {
946 // depends on, hence triggering re-analysis of this function, so this1037 return sema.fail(&block, ty_src, "expected type, found {}", .{nav_ty.fmt(pt)});
947 // interacts correctly with incremental compilation.1038 }
948 // TODO: do we need to mark this failure anywhere? I don't think so, since compilation1039 if (nav_val.toType().getNamespace(zcu) == .none) {
949 // will fail due to the type error anyway.1040 return sema.fail(&block, ty_src, "type {} has no namespace", .{nav_val.toType().fmt(pt)});
950 } else if (comp.bin_file) |lf| {1041 }
951 lf.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {1042 ip.resolveNavValue(nav_id, .{
952 error.OutOfMemory => return error.OutOfMemory,1043 .val = nav_val.toIntern(),
953 error.AnalysisFail => {1044 .alignment = .none,
954 assert(zcu.failed_codegen.contains(nav_index));1045 .@"linksection" = .none,
955 },1046 .@"addrspace" = .generic,
956 else => {1047 });
957 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(1048 // TODO: usingnamespace cannot participate in incremental compilation
958 gpa,1049 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
959 zcu.navSrcLoc(nav_index),1050 return .{
960 "unable to codegen: {s}",1051 .invalidate_nav_val = true,
961 .{@errorName(err)},1052 .invalidate_nav_ref = true,
962 ));
963 try zcu.retryable_failures.append(zcu.gpa, AnalUnit.wrap(.{ .func = func_index }));
964 },
965 };
966 } else if (zcu.llvm_object) |llvm_object| {
967 llvm_object.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {
968 error.OutOfMemory => return error.OutOfMemory,
969 };1053 };
970 }1054 }
971}
9721055
973/// https://github.com/ziglang/zig/issues/143071056 const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) {
974pub fn semaPkg(pt: Zcu.PerThread, pkg: *Module) !void {1057 .func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen
975 dev.check(.sema);1058 .variable => |v| .{ v.owner_nav == nav_id, false },
976 const import_file_result = try pt.importPkg(pkg);1059 .@"extern" => |e| .{
977 const root_type = pt.zcu.fileRootType(import_file_result.file_index);1060 false,
978 if (root_type == .none) {1061 Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn" and zir_decl.linkage == .@"extern",
979 return pt.semaFile(import_file_result.file_index);1062 },
980 }1063 else => .{ true, false },
981}1064 };
9821065
983fn createFileRootStruct(1066 if (is_owned_fn) {
984 pt: Zcu.PerThread,1067 // linksection etc are legal, except some targets do not support function alignment.
985 file_index: Zcu.File.Index,1068 if (zir_decl.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) {
986 namespace_index: Zcu.Namespace.Index,1069 return sema.fail(&block, align_src, "target does not support function alignment", .{});
987 replace_existing: bool,1070 }
988) Allocator.Error!InternPool.Index {1071 } else if (try nav_ty.comptimeOnlySema(pt)) {
989 const zcu = pt.zcu;1072 // alignment, linksection, addrspace annotations are not allowed for comptime-only types.
990 const gpa = zcu.gpa;1073 const reason: []const u8 = switch (ip.indexToKey(nav_val.toIntern())) {
991 const ip = &zcu.intern_pool;1074 .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations*
992 const file = zcu.fileByIndex(file_index);1075 else => "comptime-only type",
993 const extended = file.zir.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended;1076 };
994 assert(extended.opcode == .struct_decl);1077 if (zir_decl.align_body != null) {
995 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);1078 return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason});
996 assert(!small.has_captures_len);1079 }
997 assert(!small.has_backing_int);1080 if (zir_decl.linksection_body != null) {
998 assert(small.layout == .auto);1081 return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason});
999 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len;1082 }
1000 const fields_len = if (small.has_fields_len) blk: {1083 if (zir_decl.addrspace_body != null) {
1001 const fields_len = file.zir.extra[extra_index];1084 return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason});
1002 extra_index += 1;1085 }
1003 break :blk fields_len;1086 }
1004 } else 0;
1005 const decls_len = if (small.has_decls_len) blk: {
1006 const decls_len = file.zir.extra[extra_index];
1007 extra_index += 1;
1008 break :blk decls_len;
1009 } else 0;
1010 const decls = file.zir.bodySlice(extra_index, decls_len);
1011 extra_index += decls_len;
10121087
1013 const tracked_inst = try ip.trackZir(gpa, pt.tid, .{1088 ip.resolveNavValue(nav_id, .{
1014 .file = file_index,1089 .val = nav_val.toIntern(),
1015 .inst = .main_struct_inst,1090 .alignment = alignment,
1091 .@"linksection" = @"linksection",
1092 .@"addrspace" = @"addrspace",
1016 });1093 });
1017 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{
1018 .layout = .auto,
1019 .fields_len = fields_len,
1020 .known_non_opv = small.known_non_opv,
1021 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,
1022 .any_comptime_fields = small.any_comptime_fields,
1023 .any_default_inits = small.any_default_inits,
1024 .inits_resolved = false,
1025 .any_aligned_fields = small.any_aligned_fields,
1026 .key = .{ .declared = .{
1027 .zir_index = tracked_inst,
1028 .captures = &.{},
1029 } },
1030 }, replace_existing)) {
1031 .existing => unreachable, // we wouldn't be analysing the file root if this type existed
1032 .wip => |wip| wip,
1033 };
1034 errdefer wip_ty.cancel(ip, pt.tid);
1035
1036 wip_ty.setName(ip, try file.internFullyQualifiedName(pt));
1037 ip.namespacePtr(namespace_index).owner_type = wip_ty.index;
1038 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, tracked_inst, namespace_index, wip_ty.index);
10391094
1040 if (zcu.comp.incremental) {1095 // Mark the unit as completed before evaluating the export!
1041 try ip.addDependency(1096 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1042 gpa,
1043 AnalUnit.wrap(.{ .cau = new_cau_index }),
1044 .{ .src_hash = tracked_inst },
1045 );
1046 }
10471097
1048 try pt.scanNamespace(namespace_index, decls);1098 if (zir_decl.linkage == .@"export") {
1049 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });1099 const export_src = block.src(.{ .token_offset = @intFromBool(zir_decl.is_pub) });
1050 codegen_type: {1100 const name_slice = zir.nullTerminatedString(zir_decl.name);
1051 if (zcu.comp.config.use_llvm) break :codegen_type;1101 const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls);
1052 if (file.mod.strip) break :codegen_type;1102 try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_id);
1053 // This job depends on any resolve_type_fully jobs queued up before it.
1054 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
1055 }1103 }
1056 zcu.setFileRootType(file_index, wip_ty.index);
1057 return wip_ty.finish(ip, new_cau_index.toOptional(), namespace_index);
1058}
10591104
1060/// Re-scan the namespace of a file's root struct type on an incremental update.1105 try sema.flushExports();
1061/// The file must have successfully populated ZIR.
1062/// If the file's root struct type is not populated (the file is unreferenced), nothing is done.
1063/// This is called by `updateZirRefs` for all updated files before the main work loop.
1064/// This function does not perform any semantic analysis.
1065fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!void {
1066 const zcu = pt.zcu;
10671106
1068 const file = zcu.fileByIndex(file_index);1107 queue_codegen: {
1069 assert(file.status == .success_zir);1108 if (!queue_linker_work) break :queue_codegen;
1070 const file_root_type = zcu.fileRootType(file_index);
1071 if (file_root_type == .none) return;
10721109
1073 log.debug("updateFileNamespace mod={s} sub_file_path={s}", .{1110 if (!try nav_ty.hasRuntimeBitsSema(pt)) {
1074 file.mod.fully_qualified_name,1111 if (zcu.comp.config.use_llvm) break :queue_codegen;
1075 file.sub_file_path,1112 if (file.mod.strip) break :queue_codegen;
1076 });1113 }
10771114
1078 const namespace_index = Type.fromInterned(file_root_type).getNamespaceIndex(zcu);1115 // This job depends on any resolve_type_fully jobs queued up before it.
1079 const decls = decls: {1116 try zcu.comp.queueJob(.{ .codegen_nav = nav_id });
1080 const extended = file.zir.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended;1117 }
1081 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
10821118
1083 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len;1119 switch (old_nav.status) {
1084 extra_index += @intFromBool(small.has_fields_len);1120 .unresolved => return .{
1085 const decls_len = if (small.has_decls_len) blk: {1121 .invalidate_nav_val = true,
1086 const decls_len = file.zir.extra[extra_index];1122 .invalidate_nav_ref = true,
1087 extra_index += 1;1123 },
1088 break :blk decls_len;1124 .resolved => |old| {
1089 } else 0;1125 const new = ip.getNav(nav_id).status.resolved;
1090 break :decls file.zir.bodySlice(extra_index, decls_len);1126 return .{
1091 };1127 .invalidate_nav_val = new.val != old.val,
1092 try pt.scanNamespace(namespace_index, decls);1128 .invalidate_nav_ref = ip.typeOf(new.val) != ip.typeOf(old.val) or
1093 zcu.namespacePtr(namespace_index).generation = zcu.generation;1129 new.alignment != old.alignment or
1130 new.@"linksection" != old.@"linksection" or
1131 new.@"addrspace" != old.@"addrspace",
1132 };
1133 },
1134 }
1094}1135}
10951136
1096fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {1137pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, maybe_coerced_func_index: InternPool.Index) Zcu.SemaError!void {
1138 dev.check(.sema);
1139
1097 const tracy = trace(@src());1140 const tracy = trace(@src());
1098 defer tracy.end();1141 defer tracy.end();
10991142
1100 const zcu = pt.zcu;1143 const zcu = pt.zcu;
1101 const gpa = zcu.gpa;1144 const gpa = zcu.gpa;
1102 const file = zcu.fileByIndex(file_index);1145 const ip = &zcu.intern_pool;
1103 assert(zcu.fileRootType(file_index) == .none);
11041146
1105 if (file.status != .success_zir) {1147 // We only care about the uncoerced function.
1106 return error.AnalysisFail;1148 const func_index = ip.unwrapCoercedFunc(maybe_coerced_func_index);
1107 }1149 const anal_unit: AnalUnit = .wrap(.{ .func = func_index });
1108 assert(file.zir_loaded);
11091150
1110 const new_namespace_index = try pt.createNamespace(.{1151 log.debug("ensureFuncBodyUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)});
1111 .parent = .none,
1112 .owner_type = undefined, // set in `createFileRootStruct`
1113 .file_scope = file_index,
1114 .generation = zcu.generation,
1115 });
1116 const struct_ty = try pt.createFileRootStruct(file_index, new_namespace_index, false);
1117 errdefer zcu.intern_pool.remove(pt.tid, struct_ty);
11181152
1119 switch (zcu.comp.cache_use) {1153 const func = zcu.funcInfo(maybe_coerced_func_index);
1120 .whole => |whole| if (whole.cache_manifest) |man| {
1121 const source = file.getSource(gpa) catch |err| {
1122 try pt.reportRetryableFileError(file_index, "unable to load source: {s}", .{@errorName(err)});
1123 return error.AnalysisFail;
1124 };
11251154
1126 const resolved_path = std.fs.path.resolve(gpa, &.{1155 const was_outdated = zcu.outdated.swapRemove(anal_unit) or
1127 file.mod.root.root_dir.path orelse ".",1156 zcu.potentially_outdated.swapRemove(anal_unit);
1128 file.mod.root.sub_path,
1129 file.sub_file_path,
1130 }) catch |err| {
1131 try pt.reportRetryableFileError(file_index, "unable to resolve path: {s}", .{@errorName(err)});
1132 return error.AnalysisFail;
1133 };
1134 errdefer gpa.free(resolved_path);
11351157
1136 whole.cache_manifest_mutex.lock();1158 const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit);
1137 defer whole.cache_manifest_mutex.unlock();1159
1138 man.addFilePostContents(resolved_path, source.bytes, source.stat) catch |err| switch (err) {1160 if (was_outdated) {
1139 error.OutOfMemory => |e| return e,1161 dev.check(.incremental);
1140 else => {1162 _ = zcu.outdated_ready.swapRemove(anal_unit);
1141 try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)});1163 zcu.deleteUnitExports(anal_unit);
1142 return error.AnalysisFail;1164 zcu.deleteUnitReferences(anal_unit);
1143 },1165 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
1144 };1166 kv.value.destroy(gpa);
1167 }
1168 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
1169 } else {
1170 // We can trust the current information about this function.
1171 if (prev_failed) {
1172 return error.AnalysisFail;
1173 }
1174 switch (func.analysisUnordered(ip).state) {
1175 .unreferenced => {}, // this is the first reference
1176 .queued => {}, // we're waiting on first-time analysis
1177 .analyzed => return, // up-to-date
1178 }
1179 }
1180
1181 const func_prog_node = zcu.sema_prog_node.start(ip.getNav(func.owner_nav).fqn.toSlice(ip), 0);
1182 defer func_prog_node.end();
1183
1184 const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index)) |result|
1185 .{ prev_failed or result.ies_outdated, false }
1186 else |err| switch (err) {
1187 error.AnalysisFail => res: {
1188 if (!zcu.failed_analysis.contains(anal_unit)) {
1189 // If this function caused the error, it would have an entry in `failed_analysis`.
1190 // Since it does not, this must be a transitive failure.
1191 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1192 log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(anal_unit)});
1193 }
1194 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,
1195 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting
1196 // a different error later (which may now be invalid).
1197 break :res .{ !prev_failed, true };
1145 },1198 },
1146 .incremental => {},1199 error.OutOfMemory => {
1200 // TODO: it's unclear how to gracefully handle this.
1201 // To report the error cleanly, we need to add a message to `failed_analysis` and a
1202 // corresponding entry to `retryable_failures`; but either of these things is quite
1203 // likely to OOM at this point.
1204 // If that happens, what do we do? Perhaps we could have a special field on `Zcu`
1205 // for reporting OOM errors without allocating.
1206 return error.OutOfMemory;
1207 },
1208 };
1209
1210 if (was_outdated) {
1211 if (ies_outdated) {
1212 try zcu.markDependeeOutdated(.marked_po, .{ .interned = func_index });
1213 } else {
1214 try zcu.markPoDependeeUpToDate(.{ .interned = func_index });
1215 }
1147 }1216 }
1148}
11491217
1150const SemaCauResult = packed struct {1218 if (new_failed) return error.AnalysisFail;
1151 /// Whether the value of a `decl_val` of the corresponding Nav changed.1219}
1152 invalidate_decl_val: bool,
1153 /// Whether the type of a `decl_ref` of the corresponding Nav changed.
1154 invalidate_decl_ref: bool,
1155};
11561220
1157/// Performs semantic analysis on the given `Cau`, storing results to its owner `Nav` if needed.1221fn analyzeFuncBody(
1158/// If analysis fails, returns `error.AnalysisFail`, storing an error in `zcu.failed_analysis` unless1222 pt: Zcu.PerThread,
1159/// the error is transitive.1223 func_index: InternPool.Index,
1160/// On success, returns information about whether the `Nav` value changed.1224) Zcu.SemaError!struct { ies_outdated: bool } {
1161fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
1162 const zcu = pt.zcu;1225 const zcu = pt.zcu;
1163 const gpa = zcu.gpa;1226 const gpa = zcu.gpa;
1164 const ip = &zcu.intern_pool;1227 const ip = &zcu.intern_pool;
11651228
1166 const anal_unit = AnalUnit.wrap(.{ .cau = cau_index });1229 const func = zcu.funcInfo(func_index);
11671230 const anal_unit = AnalUnit.wrap(.{ .func = func_index });
1168 const cau = ip.getCau(cau_index);
1169 const inst_info = cau.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
1170 const file = zcu.fileByIndex(inst_info.file);
1171 const zir = file.zir;
1172
1173 if (file.status != .success_zir) {
1174 return error.AnalysisFail;
1175 }
11761231
1177 // We are about to re-analyze this `Cau`; drop its depenndencies.1232 // Make sure that this function is still owned by the same `Nav`. Otherwise, analyzing
1178 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);1233 // it would be a waste of time in the best case, and could cause codegen to give bogus
1234 // results in the worst case.
11791235
1180 switch (cau.owner.unwrap()) {1236 if (func.generic_owner == .none) {
1181 .none => {}, // `comptime` decl -- we will re-analyze its body.1237 // Among another things, this ensures that the function's `zir_body_inst` is correct.
1182 .nav => {}, // Other decl -- we will re-analyze its value.1238 try pt.ensureNavValUpToDate(func.owner_nav);
1183 .type => |ty| {1239 if (ip.getNav(func.owner_nav).status.resolved.val != func_index) {
1184 // This is an incremental update, and this type is being re-analyzed because it is outdated.1240 // This function is no longer referenced! There's no point in re-analyzing it.
1185 // Create a new type in its place, and mark the old one as outdated so that use sites will1241 // Just mark a transitive failure and move on.
1186 // be re-analyzed and discover an up-to-date type.1242 return error.AnalysisFail;
1187 const new_ty = try pt.ensureTypeUpToDate(ty, true);1243 }
1188 assert(new_ty != ty);1244 } else {
1189 return .{1245 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
1190 .invalidate_decl_val = true,1246 // Among another things, this ensures that the function's `zir_body_inst` is correct.
1191 .invalidate_decl_ref = true,1247 try pt.ensureNavValUpToDate(go_nav);
1192 };1248 if (ip.getNav(go_nav).status.resolved.val != func.generic_owner) {
1193 },1249 // The generic owner is no longer referenced, so this function is also unreferenced.
1250 // There's no point in re-analyzing it. Just mark a transitive failure and move on.
1251 return error.AnalysisFail;
1252 }
1194 }1253 }
11951254
1196 const is_usingnamespace = switch (cau.owner.unwrap()) {1255 // We'll want to remember what the IES used to be before the update for
1197 .nav => |nav| ip.getNav(nav).is_usingnamespace,1256 // dependency invalidation purposes.
1198 .none, .type => false,1257 const old_resolved_ies = if (func.analysisUnordered(ip).inferred_error_set)
1199 };1258 func.resolvedErrorSetUnordered(ip)
1259 else
1260 .none;
12001261
1201 log.debug("semaCau {}", .{zcu.fmtAnalUnit(anal_unit)});1262 log.debug("analyze and generate fn body {}", .{zcu.fmtAnalUnit(anal_unit)});
12021263
1203 try zcu.analysis_in_progress.put(gpa, anal_unit, {});1264 var air = try pt.analyzeFnBodyInner(func_index);
1204 errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit);1265 errdefer air.deinit(gpa);
12051266
1206 var analysis_arena = std.heap.ArenaAllocator.init(gpa);1267 const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or
1207 defer analysis_arena.deinit();1268 func.resolvedErrorSetUnordered(ip) != old_resolved_ies;
12081269
1209 var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa);1270 const comp = zcu.comp;
1210 defer comptime_err_ret_trace.deinit();
12111271
1212 var sema: Sema = .{1272 const dump_air = build_options.enable_debug_extensions and comp.verbose_air;
1213 .pt = pt,1273 const dump_llvm_ir = build_options.enable_debug_extensions and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
1214 .gpa = gpa,
1215 .arena = analysis_arena.allocator(),
1216 .code = zir,
1217 .owner = anal_unit,
1218 .func_index = .none,
1219 .func_is_naked = false,
1220 .fn_ret_ty = Type.void,
1221 .fn_ret_ty_ies = null,
1222 .comptime_err_ret_trace = &comptime_err_ret_trace,
1223 };
1224 defer sema.deinit();
12251274
1226 // Every `Cau` has a dependency on the source of its own ZIR instruction.1275 if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) {
1227 try sema.declareDependency(.{ .src_hash = cau.zir_index });1276 air.deinit(gpa);
1277 return .{ .ies_outdated = ies_outdated };
1278 }
12281279
1229 var block: Sema.Block = .{1280 // This job depends on any resolve_type_fully jobs queued up before it.
1230 .parent = null,1281 try comp.queueJob(.{ .codegen_func = .{
1231 .sema = &sema,1282 .func = func_index,
1232 .namespace = cau.namespace,1283 .air = air,
1233 .instructions = .{},1284 } });
1234 .inlining = null,
1235 .is_comptime = true,
1236 .src_base_inst = cau.zir_index,
1237 .type_name_ctx = switch (cau.owner.unwrap()) {
1238 .nav => |nav| ip.getNav(nav).fqn,
1239 .type => |ty| Type.fromInterned(ty).containerTypeName(ip),
1240 .none => try ip.getOrPutStringFmt(gpa, pt.tid, "{}.comptime", .{
1241 Type.fromInterned(zcu.namespacePtr(cau.namespace).owner_type).containerTypeName(ip).fmt(ip),
1242 }, .no_embedded_nulls),
1243 },
1244 };
1245 defer block.instructions.deinit(gpa);
12461285
1247 const zir_decl = zir.getDeclaration(inst_info.inst);1286 return .{ .ies_outdated = ies_outdated };
1287}
12481288
1249 // We have to fetch this state before resolving the body because of the `nav_already_populated`1289/// Takes ownership of `air`, even on error.
1250 // case below. We might change the language in future so that align/linksection/etc for functions1290/// If any types referenced by `air` are unresolved, marks the codegen as failed.
1251 // work in a way more in line with other declarations, in which case that logic will go away.1291pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Air) Allocator.Error!void {
1252 const old_nav_info = switch (cau.owner.unwrap()) {1292 const zcu = pt.zcu;
1253 .none, .type => undefined, // we'll never use `old_nav_info`1293 const gpa = zcu.gpa;
1254 .nav => |nav| ip.getNav(nav),1294 const ip = &zcu.intern_pool;
1255 };1295 const comp = zcu.comp;
12561296
1257 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });1297 defer {
1258 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });1298 var air_mut = air;
1259 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });1299 air_mut.deinit(gpa);
1260 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });1300 }
1261 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });
12621301
1263 // First, we must resolve the declaration's type. To do this, we analyze the type body if available,1302 const func = zcu.funcInfo(func_index);
1264 // or otherwise, we analyze the value body, populating `early_val` in the process.1303 const nav_index = func.owner_nav;
1304 const nav = ip.getNav(nav_index);
12651305
1266 const decl_ty: Type, const early_val: ?Value = if (zir_decl.type_body) |type_body| ty: {1306 var liveness = try Liveness.analyze(gpa, air, ip);
1267 // We evaluate only the type now; no need for the value yet.1307 defer liveness.deinit(gpa);
1268 const uncoerced_type_ref = try sema.resolveInlineBody(&block, type_body, inst_info.inst);
1269 const type_ref = try sema.coerce(&block, .type, uncoerced_type_ref, ty_src);
1270 break :ty .{ .fromInterned(type_ref.toInterned().?), null };
1271 } else ty: {
1272 // We don't have a type body, so we need to evaluate the value immediately.
1273 const value_body = zir_decl.value_body.?;
1274 const result_ref = try sema.resolveInlineBody(&block, value_body, inst_info.inst);
1275 const val = try sema.resolveFinalDeclValue(&block, init_src, result_ref);
1276 break :ty .{ val.typeOf(zcu), val };
1277 };
12781308
1279 switch (zir_decl.kind) {1309 if (build_options.enable_debug_extensions and comp.verbose_air) {
1280 .unnamed_test, .@"test", .decltest => assert(decl_ty.zigTypeTag(zcu) == .@"fn"),1310 std.debug.print("# Begin Function AIR: {}:\n", .{nav.fqn.fmt(ip)});
1281 .@"comptime" => assert(decl_ty.toIntern() == .void_type),1311 @import("../print_air.zig").dump(pt, air, liveness);
1282 .@"usingnamespace" => {},1312 std.debug.print("# End Function AIR: {}\n\n", .{nav.fqn.fmt(ip)});
1283 .@"const" => {},
1284 .@"var" => try sema.validateVarType(
1285 &block,
1286 if (zir_decl.type_body != null) ty_src else init_src,
1287 decl_ty,
1288 zir_decl.linkage == .@"extern",
1289 ),
1290 }1313 }
12911314
1292 // Now that we know the type, we can evaluate the alignment, linksection, and addrspace, to determine1315 if (std.debug.runtime_safety) {
1293 // the full pointer type of this declaration.1316 var verify: Liveness.Verify = .{
1317 .gpa = gpa,
1318 .air = air,
1319 .liveness = liveness,
1320 .intern_pool = ip,
1321 };
1322 defer verify.deinit();
12941323
1295 const alignment: InternPool.Alignment = a: {1324 verify.verify() catch |err| switch (err) {
1296 const align_body = zir_decl.align_body orelse break :a .none;1325 error.OutOfMemory => return error.OutOfMemory,
1297 const align_ref = try sema.resolveInlineBody(&block, align_body, inst_info.inst);1326 else => {
1298 break :a try sema.analyzeAsAlign(&block, align_src, align_ref);1327 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
1299 };1328 gpa,
1329 zcu.navSrcLoc(nav_index),
1330 "invalid liveness: {s}",
1331 .{@errorName(err)},
1332 ));
1333 return;
1334 },
1335 };
1336 }
13001337
1301 const @"linksection": InternPool.OptionalNullTerminatedString = ls: {1338 const codegen_prog_node = zcu.codegen_prog_node.start(nav.fqn.toSlice(ip), 0);
1302 const linksection_body = zir_decl.linksection_body orelse break :ls .none;1339 defer codegen_prog_node.end();
1303 const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_info.inst);
1304 const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{
1305 .needed_comptime_reason = "linksection must be comptime-known",
1306 });
1307 if (std.mem.indexOfScalar(u8, bytes, 0) != null) {
1308 return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{});
1309 } else if (bytes.len == 0) {
1310 return sema.fail(&block, section_src, "linksection cannot be empty", .{});
1311 }
1312 break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);
1313 };
13141340
1315 const @"addrspace": std.builtin.AddressSpace = as: {1341 if (!air.typesFullyResolved(zcu)) {
1316 const addrspace_ctx: Sema.AddressSpaceContext = switch (zir_decl.kind) {1342 // A type we depend on failed to resolve. This is a transitive failure.
1317 .@"var" => .variable,1343 // Correcting this failure will involve changing a type this function
1318 else => switch (decl_ty.zigTypeTag(zcu)) {1344 // depends on, hence triggering re-analysis of this function, so this
1319 .@"fn" => .function,1345 // interacts correctly with incremental compilation.
1320 else => .constant,1346 // TODO: do we need to mark this failure anywhere? I don't think so, since compilation
1347 // will fail due to the type error anyway.
1348 } else if (comp.bin_file) |lf| {
1349 lf.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {
1350 error.OutOfMemory => return error.OutOfMemory,
1351 error.AnalysisFail => {
1352 assert(zcu.failed_codegen.contains(nav_index));
1353 },
1354 else => {
1355 try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
1356 gpa,
1357 zcu.navSrcLoc(nav_index),
1358 "unable to codegen: {s}",
1359 .{@errorName(err)},
1360 ));
1361 try zcu.retryable_failures.append(zcu.gpa, AnalUnit.wrap(.{ .func = func_index }));
1321 },1362 },
1322 };1363 };
1323 const target = zcu.getTarget();1364 } else if (zcu.llvm_object) |llvm_object| {
1324 const addrspace_body = zir_decl.addrspace_body orelse break :as switch (addrspace_ctx) {1365 llvm_object.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {
1325 .function => target_util.defaultAddressSpace(target, .function),1366 error.OutOfMemory => return error.OutOfMemory,
1326 .variable => target_util.defaultAddressSpace(target, .global_mutable),
1327 .constant => target_util.defaultAddressSpace(target, .global_constant),
1328 else => unreachable,
1329 };1367 };
1330 const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_info.inst);1368 }
1331 break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx);1369}
1332 };
1333
1334 // Lastly, we must evaluate the value if we have not already done so. Note, however, that extern declarations
1335 // don't have an associated value body.
1336
1337 const final_val: ?Value = early_val orelse if (zir_decl.value_body) |value_body| val: {
1338 // Put the resolved type into `inst_map` to be used as the result type of the init.
1339 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{inst_info.inst});
1340 sema.inst_map.putAssumeCapacity(inst_info.inst, Air.internedToRef(decl_ty.toIntern()));
1341 const uncoerced_result_ref = try sema.resolveInlineBody(&block, value_body, inst_info.inst);
1342 assert(sema.inst_map.remove(inst_info.inst));
13431370
1344 const result_ref = try sema.coerce(&block, decl_ty, uncoerced_result_ref, init_src);1371/// https://github.com/ziglang/zig/issues/14307
1345 break :val try sema.resolveFinalDeclValue(&block, init_src, result_ref);1372pub fn semaPkg(pt: Zcu.PerThread, pkg: *Module) !void {
1346 } else null;1373 dev.check(.sema);
1374 const import_file_result = try pt.importPkg(pkg);
1375 const root_type = pt.zcu.fileRootType(import_file_result.file_index);
1376 if (root_type == .none) {
1377 return pt.semaFile(import_file_result.file_index);
1378 }
1379}
13471380
1348 // TODO: missing validation?1381fn createFileRootStruct(
1382 pt: Zcu.PerThread,
1383 file_index: Zcu.File.Index,
1384 namespace_index: Zcu.Namespace.Index,
1385 replace_existing: bool,
1386) Allocator.Error!InternPool.Index {
1387 const zcu = pt.zcu;
1388 const gpa = zcu.gpa;
1389 const ip = &zcu.intern_pool;
1390 const file = zcu.fileByIndex(file_index);
1391 const extended = file.zir.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended;
1392 assert(extended.opcode == .struct_decl);
1393 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
1394 assert(!small.has_captures_len);
1395 assert(!small.has_backing_int);
1396 assert(small.layout == .auto);
1397 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len;
1398 const fields_len = if (small.has_fields_len) blk: {
1399 const fields_len = file.zir.extra[extra_index];
1400 extra_index += 1;
1401 break :blk fields_len;
1402 } else 0;
1403 const decls_len = if (small.has_decls_len) blk: {
1404 const decls_len = file.zir.extra[extra_index];
1405 extra_index += 1;
1406 break :blk decls_len;
1407 } else 0;
1408 const decls = file.zir.bodySlice(extra_index, decls_len);
1409 extra_index += decls_len;
13491410
1350 const decl_val: Value = switch (zir_decl.linkage) {1411 const tracked_inst = try ip.trackZir(gpa, pt.tid, .{
1351 .normal, .@"export" => switch (zir_decl.kind) {1412 .file = file_index,
1352 .@"var" => .fromInterned(try pt.intern(.{ .variable = .{1413 .inst = .main_struct_inst,
1353 .ty = decl_ty.toIntern(),1414 });
1354 .init = final_val.?.toIntern(),1415 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{
1355 .owner_nav = cau.owner.unwrap().nav,1416 .layout = .auto,
1356 .is_threadlocal = zir_decl.is_threadlocal,1417 .fields_len = fields_len,
1357 .is_weak_linkage = false,1418 .known_non_opv = small.known_non_opv,
1358 } })),1419 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,
1359 else => final_val.?,1420 .any_comptime_fields = small.any_comptime_fields,
1360 },1421 .any_default_inits = small.any_default_inits,
1361 .@"extern" => val: {1422 .inits_resolved = false,
1362 assert(final_val == null); // extern decls do not have a value body1423 .any_aligned_fields = small.any_aligned_fields,
1363 const lib_name: ?[]const u8 = if (zir_decl.lib_name != .empty) l: {1424 .key = .{ .declared = .{
1364 break :l zir.nullTerminatedString(zir_decl.lib_name);1425 .zir_index = tracked_inst,
1365 } else null;1426 .captures = &.{},
1366 if (lib_name) |l| {1427 } },
1367 const lib_name_src = block.src(.{ .node_offset_lib_name = 0 });1428 }, replace_existing)) {
1368 try sema.handleExternLibName(&block, lib_name_src, l);1429 .existing => unreachable, // we wouldn't be analysing the file root if this type existed
1369 }1430 .wip => |wip| wip,
1370 break :val .fromInterned(try pt.getExtern(.{
1371 .name = old_nav_info.name,
1372 .ty = decl_ty.toIntern(),
1373 .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, lib_name, .no_embedded_nulls),
1374 .is_const = zir_decl.kind == .@"const",
1375 .is_threadlocal = zir_decl.is_threadlocal,
1376 .is_weak_linkage = false,
1377 .is_dll_import = false,
1378 .alignment = alignment,
1379 .@"addrspace" = @"addrspace",
1380 .zir_index = cau.zir_index, // `declaration` instruction
1381 .owner_nav = undefined, // ignored by `getExtern`
1382 }));
1383 },
1384 };1431 };
1432 errdefer wip_ty.cancel(ip, pt.tid);
13851433
1386 const nav_index = switch (cau.owner.unwrap()) {1434 wip_ty.setName(ip, try file.internFullyQualifiedName(pt));
1387 .none => {1435 ip.namespacePtr(namespace_index).owner_type = wip_ty.index;
1388 // This is a `comptime` decl, so we are done -- the side effects are all we care about.
1389 // Just make sure to `flushExports`.
1390 try sema.flushExports();
1391 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1392 return .{
1393 .invalidate_decl_val = false,
1394 .invalidate_decl_ref = false,
1395 };
1396 },
1397 .nav => |nav| nav, // We will resolve this `Nav` below.
1398 .type => unreachable, // Handled at top of function.
1399 };
14001436
1401 switch (decl_val.toIntern()) {1437 if (zcu.comp.incremental) {
1402 .generic_poison => unreachable, // assertion failure1438 try ip.addDependency(
1403 .unreachable_value => unreachable, // assertion failure1439 gpa,
1404 else => {},1440 .wrap(.{ .type = wip_ty.index }),
1441 .{ .src_hash = tracked_inst },
1442 );
1405 }1443 }
14061444
1407 // This resolves the type of the resolved value, not that value itself. If `decl_val` is a struct type,1445 try pt.scanNamespace(namespace_index, decls);
1408 // this resolves the type `type` (which needs no resolution), not the struct itself.1446 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
1409 try decl_ty.resolveLayout(pt);1447 codegen_type: {
14101448 if (zcu.comp.config.use_llvm) break :codegen_type;
1411 // TODO: this is jank. If #20663 is rejected, let's think about how to better model `usingnamespace`.1449 if (file.mod.strip) break :codegen_type;
1412 if (is_usingnamespace) {1450 // This job depends on any resolve_type_fully jobs queued up before it.
1413 if (decl_ty.toIntern() != .type_type) {1451 try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
1414 return sema.fail(&block, ty_src, "expected type, found {}", .{decl_ty.fmt(pt)});
1415 }
1416 if (decl_val.toType().getNamespace(zcu) == .none) {
1417 return sema.fail(&block, ty_src, "type {} has no namespace", .{decl_val.toType().fmt(pt)});
1418 }
1419 ip.resolveNavValue(nav_index, .{
1420 .val = decl_val.toIntern(),
1421 .alignment = .none,
1422 .@"linksection" = .none,
1423 .@"addrspace" = .generic,
1424 });
1425 // TODO: usingnamespace cannot participate in incremental compilation
1426 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1427 return .{
1428 .invalidate_decl_val = true,
1429 .invalidate_decl_ref = true,
1430 };
1431 }1452 }
1453 zcu.setFileRootType(file_index, wip_ty.index);
1454 return wip_ty.finish(ip, namespace_index);
1455}
14321456
1433 const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(decl_val.toIntern())) {1457/// Re-scan the namespace of a file's root struct type on an incremental update.
1434 .func => |f| .{ true, f.owner_nav == nav_index }, // note that this lets function aliases reach codegen1458/// The file must have successfully populated ZIR.
1435 .variable => |v| .{ v.owner_nav == nav_index, false },1459/// If the file's root struct type is not populated (the file is unreferenced), nothing is done.
1436 .@"extern" => |e| .{ false, Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn" },1460/// This is called by `updateZirRefs` for all updated files before the main work loop.
1437 else => .{ true, false },1461/// This function does not perform any semantic analysis.
1438 };1462fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!void {
14391463 const zcu = pt.zcu;
1440 // Keep in sync with logic in `Sema.zirVarExtended`.
14411464
1442 if (is_owned_fn) {1465 const file = zcu.fileByIndex(file_index);
1443 // linksection etc are legal, except some targets do not support function alignment.1466 assert(file.status == .success_zir);
1444 if (zir_decl.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) {1467 const file_root_type = zcu.fileRootType(file_index);
1445 return sema.fail(&block, align_src, "target does not support function alignment", .{});1468 if (file_root_type == .none) return;
1446 }
1447 } else if (try decl_ty.comptimeOnlySema(pt)) {
1448 // alignment, linksection, addrspace annotations are not allowed for comptime-only types.
1449 const reason: []const u8 = switch (ip.indexToKey(decl_val.toIntern())) {
1450 .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations*
1451 else => "comptime-only type",
1452 };
1453 if (zir_decl.align_body != null) {
1454 return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason});
1455 }
1456 if (zir_decl.linksection_body != null) {
1457 return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason});
1458 }
1459 if (zir_decl.addrspace_body != null) {
1460 return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason});
1461 }
1462 }
14631469
1464 ip.resolveNavValue(nav_index, .{1470 log.debug("updateFileNamespace mod={s} sub_file_path={s}", .{
1465 .val = decl_val.toIntern(),1471 file.mod.fully_qualified_name,
1466 .alignment = alignment,1472 file.sub_file_path,
1467 .@"linksection" = @"linksection",
1468 .@"addrspace" = @"addrspace",
1469 });1473 });
14701474
1471 // Mark the `Cau` as completed before evaluating the export!1475 const namespace_index = Type.fromInterned(file_root_type).getNamespaceIndex(zcu);
1472 assert(zcu.analysis_in_progress.swapRemove(anal_unit));1476 const decls = decls: {
14731477 const extended = file.zir.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended;
1474 if (zir_decl.linkage == .@"export") {1478 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
1475 const export_src = block.src(.{ .token_offset = @intFromBool(zir_decl.is_pub) });
1476 const name_slice = zir.nullTerminatedString(zir_decl.name);
1477 const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls);
1478 try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_index);
1479 }
14801479
1481 try sema.flushExports();1480 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len;
1481 extra_index += @intFromBool(small.has_fields_len);
1482 const decls_len = if (small.has_decls_len) blk: {
1483 const decls_len = file.zir.extra[extra_index];
1484 extra_index += 1;
1485 break :blk decls_len;
1486 } else 0;
1487 break :decls file.zir.bodySlice(extra_index, decls_len);
1488 };
1489 try pt.scanNamespace(namespace_index, decls);
1490 zcu.namespacePtr(namespace_index).generation = zcu.generation;
1491}
14821492
1483 queue_codegen: {1493fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
1484 if (!queue_linker_work) break :queue_codegen;1494 const tracy = trace(@src());
1495 defer tracy.end();
14851496
1486 if (!try decl_ty.hasRuntimeBitsSema(pt)) {1497 const zcu = pt.zcu;
1487 if (zcu.comp.config.use_llvm) break :queue_codegen;1498 const gpa = zcu.gpa;
1488 if (file.mod.strip) break :queue_codegen;1499 const file = zcu.fileByIndex(file_index);
1489 }1500 assert(zcu.fileRootType(file_index) == .none);
14901501
1491 // This job depends on any resolve_type_fully jobs queued up before it.1502 if (file.status != .success_zir) {
1492 try zcu.comp.queueJob(.{ .codegen_nav = nav_index });1503 return error.AnalysisFail;
1493 }1504 }
1505 assert(file.zir_loaded);
14941506
1495 switch (old_nav_info.status) {1507 const new_namespace_index = try pt.createNamespace(.{
1496 .unresolved => return .{1508 .parent = .none,
1497 .invalidate_decl_val = true,1509 .owner_type = undefined, // set in `createFileRootStruct`
1498 .invalidate_decl_ref = true,1510 .file_scope = file_index,
1499 },1511 .generation = zcu.generation,
1500 .resolved => |old| {1512 });
1501 const new = ip.getNav(nav_index).status.resolved;1513 const struct_ty = try pt.createFileRootStruct(file_index, new_namespace_index, false);
1502 return .{1514 errdefer zcu.intern_pool.remove(pt.tid, struct_ty);
1503 .invalidate_decl_val = new.val != old.val,1515
1504 .invalidate_decl_ref = ip.typeOf(new.val) != ip.typeOf(old.val) or1516 switch (zcu.comp.cache_use) {
1505 new.alignment != old.alignment or1517 .whole => |whole| if (whole.cache_manifest) |man| {
1506 new.@"linksection" != old.@"linksection" or1518 const source = file.getSource(gpa) catch |err| {
1507 new.@"addrspace" != old.@"addrspace",1519 try pt.reportRetryableFileError(file_index, "unable to load source: {s}", .{@errorName(err)});
1520 return error.AnalysisFail;
1521 };
1522
1523 const resolved_path = std.fs.path.resolve(gpa, &.{
1524 file.mod.root.root_dir.path orelse ".",
1525 file.mod.root.sub_path,
1526 file.sub_file_path,
1527 }) catch |err| {
1528 try pt.reportRetryableFileError(file_index, "unable to resolve path: {s}", .{@errorName(err)});
1529 return error.AnalysisFail;
1530 };
1531 errdefer gpa.free(resolved_path);
1532
1533 whole.cache_manifest_mutex.lock();
1534 defer whole.cache_manifest_mutex.unlock();
1535 man.addFilePostContents(resolved_path, source.bytes, source.stat) catch |err| switch (err) {
1536 error.OutOfMemory => |e| return e,
1537 else => {
1538 try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)});
1539 return error.AnalysisFail;
1540 },
1508 };1541 };
1509 },1542 },
1543 .incremental => {},
1510 }1544 }
1511}1545}
15121546
...@@ -1880,45 +1914,42 @@ pub fn scanNamespace(...@@ -1880,45 +1914,42 @@ pub fn scanNamespace(
18801914
1881 // For incremental updates, `scanDecl` wants to look up existing decls by their ZIR index rather1915 // For incremental updates, `scanDecl` wants to look up existing decls by their ZIR index rather
1882 // than their name. We'll build an efficient mapping now, then discard the current `decls`.1916 // than their name. We'll build an efficient mapping now, then discard the current `decls`.
1883 // We map to the `Cau`, since not every declaration has a `Nav`.1917 // We map to the `AnalUnit`, since not every declaration has a `Nav`.
1884 var existing_by_inst: std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, InternPool.Cau.Index) = .empty;1918 var existing_by_inst: std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, InternPool.AnalUnit) = .empty;
1885 defer existing_by_inst.deinit(gpa);1919 defer existing_by_inst.deinit(gpa);
18861920
1887 try existing_by_inst.ensureTotalCapacity(gpa, @intCast(1921 try existing_by_inst.ensureTotalCapacity(gpa, @intCast(
1888 namespace.pub_decls.count() + namespace.priv_decls.count() +1922 namespace.pub_decls.count() + namespace.priv_decls.count() +
1889 namespace.pub_usingnamespace.items.len + namespace.priv_usingnamespace.items.len +1923 namespace.pub_usingnamespace.items.len + namespace.priv_usingnamespace.items.len +
1890 namespace.other_decls.items.len,1924 namespace.comptime_decls.items.len +
1925 namespace.test_decls.items.len,
1891 ));1926 ));
18921927
1893 for (namespace.pub_decls.keys()) |nav| {1928 for (namespace.pub_decls.keys()) |nav| {
1894 const cau_index = ip.getNav(nav).analysis_owner.unwrap().?;1929 const zir_index = ip.getNav(nav).analysis.?.zir_index;
1895 const zir_index = ip.getCau(cau_index).zir_index;1930 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
1896 existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index);
1897 }1931 }
1898 for (namespace.priv_decls.keys()) |nav| {1932 for (namespace.priv_decls.keys()) |nav| {
1899 const cau_index = ip.getNav(nav).analysis_owner.unwrap().?;1933 const zir_index = ip.getNav(nav).analysis.?.zir_index;
1900 const zir_index = ip.getCau(cau_index).zir_index;1934 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
1901 existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index);
1902 }1935 }
1903 for (namespace.pub_usingnamespace.items) |nav| {1936 for (namespace.pub_usingnamespace.items) |nav| {
1904 const cau_index = ip.getNav(nav).analysis_owner.unwrap().?;1937 const zir_index = ip.getNav(nav).analysis.?.zir_index;
1905 const zir_index = ip.getCau(cau_index).zir_index;1938 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
1906 existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index);
1907 }1939 }
1908 for (namespace.priv_usingnamespace.items) |nav| {1940 for (namespace.priv_usingnamespace.items) |nav| {
1909 const cau_index = ip.getNav(nav).analysis_owner.unwrap().?;1941 const zir_index = ip.getNav(nav).analysis.?.zir_index;
1910 const zir_index = ip.getCau(cau_index).zir_index;1942 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
1911 existing_by_inst.putAssumeCapacityNoClobber(zir_index, cau_index);1943 }
1912 }1944 for (namespace.comptime_decls.items) |cu| {
1913 for (namespace.other_decls.items) |cau_index| {1945 const zir_index = ip.getComptimeUnit(cu).zir_index;
1914 const cau = ip.getCau(cau_index);1946 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .@"comptime" = cu }));
1915 existing_by_inst.putAssumeCapacityNoClobber(cau.zir_index, cau_index);1947 }
1916 // If this is a test, it'll be re-added to `test_functions` later on1948 for (namespace.test_decls.items) |nav| {
1917 // if still alive. Remove it for now.1949 const zir_index = ip.getNav(nav).analysis.?.zir_index;
1918 switch (cau.owner.unwrap()) {1950 existing_by_inst.putAssumeCapacityNoClobber(zir_index, .wrap(.{ .nav_val = nav }));
1919 .none, .type => {},1951 // This test will be re-added to `test_functions` later on if it's still alive. Remove it for now.
1920 .nav => |nav| _ = zcu.test_functions.swapRemove(nav),1952 _ = zcu.test_functions.swapRemove(nav);
1921 }
1922 }1953 }
19231954
1924 var seen_decls: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;1955 var seen_decls: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;
...@@ -1928,7 +1959,8 @@ pub fn scanNamespace(...@@ -1928,7 +1959,8 @@ pub fn scanNamespace(
1928 namespace.priv_decls.clearRetainingCapacity();1959 namespace.priv_decls.clearRetainingCapacity();
1929 namespace.pub_usingnamespace.clearRetainingCapacity();1960 namespace.pub_usingnamespace.clearRetainingCapacity();
1930 namespace.priv_usingnamespace.clearRetainingCapacity();1961 namespace.priv_usingnamespace.clearRetainingCapacity();
1931 namespace.other_decls.clearRetainingCapacity();1962 namespace.comptime_decls.clearRetainingCapacity();
1963 namespace.test_decls.clearRetainingCapacity();
19321964
1933 var scan_decl_iter: ScanDeclIter = .{1965 var scan_decl_iter: ScanDeclIter = .{
1934 .pt = pt,1966 .pt = pt,
...@@ -1950,7 +1982,7 @@ const ScanDeclIter = struct {...@@ -1950,7 +1982,7 @@ const ScanDeclIter = struct {
1950 pt: Zcu.PerThread,1982 pt: Zcu.PerThread,
1951 namespace_index: Zcu.Namespace.Index,1983 namespace_index: Zcu.Namespace.Index,
1952 seen_decls: *std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),1984 seen_decls: *std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
1953 existing_by_inst: *const std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, InternPool.Cau.Index),1985 existing_by_inst: *const std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, InternPool.AnalUnit),
1954 /// Decl scanning is run in two passes, so that we can detect when a generated1986 /// Decl scanning is run in two passes, so that we can detect when a generated
1955 /// name would clash with an explicit name and use a different one.1987 /// name would clash with an explicit name and use a different one.
1956 pass: enum { named, unnamed },1988 pass: enum { named, unnamed },
...@@ -1988,48 +2020,30 @@ const ScanDeclIter = struct {...@@ -1988,48 +2020,30 @@ const ScanDeclIter = struct {
19882020
1989 const decl = zir.getDeclaration(decl_inst);2021 const decl = zir.getDeclaration(decl_inst);
19902022
1991 const Kind = enum { @"comptime", @"usingnamespace", @"test", named };2023 const maybe_name: InternPool.OptionalNullTerminatedString = switch (decl.kind) {
19922024 .@"comptime" => name: {
1993 const maybe_name: InternPool.OptionalNullTerminatedString, const kind: Kind, const is_named_test: bool = switch (decl.kind) {
1994 .@"comptime" => info: {
1995 if (iter.pass != .unnamed) return;2025 if (iter.pass != .unnamed) return;
1996 break :info .{2026 break :name .none;
1997 .none,
1998 .@"comptime",
1999 false,
2000 };
2001 },2027 },
2002 .@"usingnamespace" => info: {2028 .@"usingnamespace" => name: {
2003 if (iter.pass != .unnamed) return;2029 if (iter.pass != .unnamed) return;
2004 const i = iter.usingnamespace_index;2030 const i = iter.usingnamespace_index;
2005 iter.usingnamespace_index += 1;2031 iter.usingnamespace_index += 1;
2006 break :info .{2032 break :name (try iter.avoidNameConflict("usingnamespace_{d}", .{i})).toOptional();
2007 (try iter.avoidNameConflict("usingnamespace_{d}", .{i})).toOptional(),
2008 .@"usingnamespace",
2009 false,
2010 };
2011 },2033 },
2012 .unnamed_test => info: {2034 .unnamed_test => name: {
2013 if (iter.pass != .unnamed) return;2035 if (iter.pass != .unnamed) return;
2014 const i = iter.unnamed_test_index;2036 const i = iter.unnamed_test_index;
2015 iter.unnamed_test_index += 1;2037 iter.unnamed_test_index += 1;
2016 break :info .{2038 break :name (try iter.avoidNameConflict("test_{d}", .{i})).toOptional();
2017 (try iter.avoidNameConflict("test_{d}", .{i})).toOptional(),
2018 .@"test",
2019 false,
2020 };
2021 },2039 },
2022 .@"test", .decltest => |kind| info: {2040 .@"test", .decltest => |kind| name: {
2023 // We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.2041 // We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.
2024 if (iter.pass != .unnamed) return;2042 if (iter.pass != .unnamed) return;
2025 const prefix = @tagName(kind);2043 const prefix = @tagName(kind);
2026 break :info .{2044 break :name (try iter.avoidNameConflict("{s}.{s}", .{ prefix, zir.nullTerminatedString(decl.name) })).toOptional();
2027 (try iter.avoidNameConflict("{s}.{s}", .{ prefix, zir.nullTerminatedString(decl.name) })).toOptional(),
2028 .@"test",
2029 true,
2030 };
2031 },2045 },
2032 .@"const", .@"var" => info: {2046 .@"const", .@"var" => name: {
2033 if (iter.pass != .named) return;2047 if (iter.pass != .named) return;
2034 const name = try ip.getOrPutString(2048 const name = try ip.getOrPutString(
2035 gpa,2049 gpa,
...@@ -2038,11 +2052,7 @@ const ScanDeclIter = struct {...@@ -2038,11 +2052,7 @@ const ScanDeclIter = struct {
2038 .no_embedded_nulls,2052 .no_embedded_nulls,
2039 );2053 );
2040 try iter.seen_decls.putNoClobber(gpa, name, {});2054 try iter.seen_decls.putNoClobber(gpa, name, {});
2041 break :info .{2055 break :name name.toOptional();
2042 name.toOptional(),
2043 .named,
2044 false,
2045 };
2046 },2056 },
2047 };2057 };
20482058
...@@ -2051,46 +2061,44 @@ const ScanDeclIter = struct {...@@ -2051,46 +2061,44 @@ const ScanDeclIter = struct {
2051 .inst = decl_inst,2061 .inst = decl_inst,
2052 });2062 });
20532063
2054 const existing_cau = iter.existing_by_inst.get(tracked_inst);2064 const existing_unit = iter.existing_by_inst.get(tracked_inst);
20552065
2056 const cau, const want_analysis = switch (kind) {2066 const unit, const want_analysis = switch (decl.kind) {
2057 .@"comptime" => cau: {2067 .@"comptime" => unit: {
2058 const cau = existing_cau orelse try ip.createComptimeCau(gpa, pt.tid, tracked_inst, namespace_index);2068 const cu = if (existing_unit) |eu|
2069 eu.unwrap().@"comptime"
2070 else
2071 try ip.createComptimeUnit(gpa, pt.tid, tracked_inst, namespace_index);
20592072
2060 try namespace.other_decls.append(gpa, cau);2073 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });
20612074
2062 if (existing_cau == null) {2075 try namespace.comptime_decls.append(gpa, cu);
2063 // For a `comptime` declaration, whether to analyze is based solely on whether the2076
2064 // `Cau` is outdated. So, add this one to `outdated` and `outdated_ready` if not already.2077 if (existing_unit == null) {
2065 const unit = AnalUnit.wrap(.{ .cau = cau });2078 // For a `comptime` declaration, whether to analyze is based solely on whether the unit
2066 if (zcu.potentially_outdated.fetchSwapRemove(unit)) |kv| {2079 // is outdated. So, add this fresh one to `outdated` and `outdated_ready`.
2067 try zcu.outdated.ensureUnusedCapacity(gpa, 1);2080 try zcu.outdated.ensureUnusedCapacity(gpa, 1);
2068 try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1);2081 try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1);
2069 zcu.outdated.putAssumeCapacityNoClobber(unit, kv.value);2082 zcu.outdated.putAssumeCapacityNoClobber(unit, 0);
2070 if (kv.value == 0) { // no PO deps2083 zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {});
2071 zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {});
2072 }
2073 } else if (!zcu.outdated.contains(unit)) {
2074 try zcu.outdated.ensureUnusedCapacity(gpa, 1);
2075 try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1);
2076 zcu.outdated.putAssumeCapacityNoClobber(unit, 0);
2077 zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {});
2078 }
2079 }2084 }
20802085
2081 break :cau .{ cau, true };2086 break :unit .{ unit, true };
2082 },2087 },
2083 else => cau: {2088 else => unit: {
2084 const name = maybe_name.unwrap().?;2089 const name = maybe_name.unwrap().?;
2085 const fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, name);2090 const fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, name);
2086 const cau, const nav = if (existing_cau) |cau_index| cau_nav: {2091 const nav = if (existing_unit) |eu|
2087 const nav_index = ip.getCau(cau_index).owner.unwrap().nav;2092 eu.unwrap().nav_val
2088 const nav = ip.getNav(nav_index);2093 else
2089 assert(nav.name == name);2094 try ip.createDeclNav(gpa, pt.tid, name, fqn, tracked_inst, namespace_index, decl.kind == .@"usingnamespace");
2090 assert(nav.fqn == fqn);2095
2091 break :cau_nav .{ cau_index, nav_index };2096 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
2092 } else try ip.createPairedCauNav(gpa, pt.tid, name, fqn, tracked_inst, namespace_index, kind == .@"usingnamespace");2097
2093 const want_analysis = switch (kind) {2098 assert(ip.getNav(nav).name == name);
2099 assert(ip.getNav(nav).fqn == fqn);
2100
2101 const want_analysis = switch (decl.kind) {
2094 .@"comptime" => unreachable,2102 .@"comptime" => unreachable,
2095 .@"usingnamespace" => a: {2103 .@"usingnamespace" => a: {
2096 if (comp.incremental) {2104 if (comp.incremental) {
...@@ -2103,8 +2111,9 @@ const ScanDeclIter = struct {...@@ -2103,8 +2111,9 @@ const ScanDeclIter = struct {
2103 }2111 }
2104 break :a true;2112 break :a true;
2105 },2113 },
2106 .@"test" => a: {2114 .unnamed_test, .@"test", .decltest => a: {
2107 try namespace.other_decls.append(gpa, cau);2115 const is_named = decl.kind != .unnamed_test;
2116 try namespace.test_decls.append(gpa, nav);
2108 // TODO: incremental compilation!2117 // TODO: incremental compilation!
2109 // * remove from `test_functions` if no longer matching filter2118 // * remove from `test_functions` if no longer matching filter
2110 // * add to `test_functions` if newly passing filter2119 // * add to `test_functions` if newly passing filter
...@@ -2112,7 +2121,7 @@ const ScanDeclIter = struct {...@@ -2112,7 +2121,7 @@ const ScanDeclIter = struct {
2112 // Perhaps we should add all test indiscriminately and filter at the end of the update.2121 // Perhaps we should add all test indiscriminately and filter at the end of the update.
2113 if (!comp.config.is_test) break :a false;2122 if (!comp.config.is_test) break :a false;
2114 if (file.mod != zcu.main_mod) break :a false;2123 if (file.mod != zcu.main_mod) break :a false;
2115 if (is_named_test and comp.test_filters.len > 0) {2124 if (is_named and comp.test_filters.len > 0) {
2116 const fqn_slice = fqn.toSlice(ip);2125 const fqn_slice = fqn.toSlice(ip);
2117 for (comp.test_filters) |test_filter| {2126 for (comp.test_filters) |test_filter| {
2118 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;2127 if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break;
...@@ -2121,7 +2130,7 @@ const ScanDeclIter = struct {...@@ -2121,7 +2130,7 @@ const ScanDeclIter = struct {
2121 try zcu.test_functions.put(gpa, nav, {});2130 try zcu.test_functions.put(gpa, nav, {});
2122 break :a true;2131 break :a true;
2123 },2132 },
2124 .named => a: {2133 .@"const", .@"var" => a: {
2125 if (decl.is_pub) {2134 if (decl.is_pub) {
2126 try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });2135 try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu });
2127 } else {2136 } else {
...@@ -2130,23 +2139,23 @@ const ScanDeclIter = struct {...@@ -2130,23 +2139,23 @@ const ScanDeclIter = struct {
2130 break :a false;2139 break :a false;
2131 },2140 },
2132 };2141 };
2133 break :cau .{ cau, want_analysis };2142 break :unit .{ unit, want_analysis };
2134 },2143 },
2135 };2144 };
21362145
2137 if (existing_cau == null and (want_analysis or decl.linkage == .@"export")) {2146 if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) {
2138 log.debug(2147 log.debug(
2139 "scanDecl queue analyze_cau file='{s}' cau_index={d}",2148 "scanDecl queue analyze_comptime_unit file='{s}' unit={}",
2140 .{ namespace.fileScope(zcu).sub_file_path, cau },2149 .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) },
2141 );2150 );
2142 try comp.queueJob(.{ .analyze_cau = cau });2151 try comp.queueJob(.{ .analyze_comptime_unit = unit });
2143 }2152 }
21442153
2145 // TODO: we used to do line number updates here, but this is an inappropriate place for this logic to live.2154 // TODO: we used to do line number updates here, but this is an inappropriate place for this logic to live.
2146 }2155 }
2147};2156};
21482157
2149fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air {2158fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air {
2150 const tracy = trace(@src());2159 const tracy = trace(@src());
2151 defer tracy.end();2160 defer tracy.end();
21522161
...@@ -2168,21 +2177,14 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!...@@ -2168,21 +2177,14 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!
2168 func.setResolvedErrorSet(ip, .none);2177 func.setResolvedErrorSet(ip, .none);
2169 }2178 }
21702179
2171 // This is the `Cau` corresponding to the `declaration` instruction which the function or its generic owner originates from.2180 // This is the `Nau` corresponding to the `declaration` instruction which the function or its generic owner originates from.
2172 const decl_cau = ip.getCau(cau: {2181 const decl_nav = ip.getNav(if (func.generic_owner == .none)
2173 const orig_nav = if (func.generic_owner == .none)2182 func.owner_nav
2174 func.owner_nav2183 else
2175 else2184 zcu.funcInfo(func.generic_owner).owner_nav);
2176 zcu.funcInfo(func.generic_owner).owner_nav;
2177
2178 break :cau ip.getNav(orig_nav).analysis_owner.unwrap().?;
2179 });
21802185
2181 const func_nav = ip.getNav(func.owner_nav);2186 const func_nav = ip.getNav(func.owner_nav);
21822187
2183 const decl_prog_node = zcu.sema_prog_node.start(func_nav.fqn.toSlice(ip), 0);
2184 defer decl_prog_node.end();
2185
2186 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);2188 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
21872189
2188 var analysis_arena = std.heap.ArenaAllocator.init(gpa);2190 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
...@@ -2216,7 +2218,7 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!...@@ -2216,7 +2218,7 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!
22162218
2217 // Every runtime function has a dependency on the source of the Decl it originates from.2219 // Every runtime function has a dependency on the source of the Decl it originates from.
2218 // It also depends on the value of its owner Decl.2220 // It also depends on the value of its owner Decl.
2219 try sema.declareDependency(.{ .src_hash = decl_cau.zir_index });2221 try sema.declareDependency(.{ .src_hash = decl_nav.analysis.?.zir_index });
2220 try sema.declareDependency(.{ .nav_val = func.owner_nav });2222 try sema.declareDependency(.{ .nav_val = func.owner_nav });
22212223
2222 if (func.analysisUnordered(ip).inferred_error_set) {2224 if (func.analysisUnordered(ip).inferred_error_set) {
...@@ -2236,11 +2238,11 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!...@@ -2236,11 +2238,11 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!
2236 var inner_block: Sema.Block = .{2238 var inner_block: Sema.Block = .{
2237 .parent = null,2239 .parent = null,
2238 .sema = &sema,2240 .sema = &sema,
2239 .namespace = decl_cau.namespace,2241 .namespace = decl_nav.analysis.?.namespace,
2240 .instructions = .{},2242 .instructions = .{},
2241 .inlining = null,2243 .inlining = null,
2242 .is_comptime = false,2244 .is_comptime = false,
2243 .src_base_inst = decl_cau.zir_index,2245 .src_base_inst = decl_nav.analysis.?.zir_index,
2244 .type_name_ctx = func_nav.fqn,2246 .type_name_ctx = func_nav.fqn,
2245 };2247 };
2246 defer inner_block.instructions.deinit(gpa);2248 defer inner_block.instructions.deinit(gpa);
...@@ -2542,10 +2544,10 @@ fn processExportsInner(...@@ -2542,10 +2544,10 @@ fn processExportsInner(
2542 .nav => |nav_index| if (failed: {2544 .nav => |nav_index| if (failed: {
2543 const nav = ip.getNav(nav_index);2545 const nav = ip.getNav(nav_index);
2544 if (zcu.failed_codegen.contains(nav_index)) break :failed true;2546 if (zcu.failed_codegen.contains(nav_index)) break :failed true;
2545 if (nav.analysis_owner.unwrap()) |cau| {2547 if (nav.analysis != null) {
2546 const cau_unit = AnalUnit.wrap(.{ .cau = cau });2548 const unit: AnalUnit = .wrap(.{ .nav_val = nav_index });
2547 if (zcu.failed_analysis.contains(cau_unit)) break :failed true;2549 if (zcu.failed_analysis.contains(unit)) break :failed true;
2548 if (zcu.transitive_failed_analysis.contains(cau_unit)) break :failed true;2550 if (zcu.transitive_failed_analysis.contains(unit)) break :failed true;
2549 }2551 }
2550 const val = switch (nav.status) {2552 const val = switch (nav.status) {
2551 .unresolved => break :failed true,2553 .unresolved => break :failed true,
...@@ -2593,15 +2595,14 @@ pub fn populateTestFunctions(...@@ -2593,15 +2595,14 @@ pub fn populateTestFunctions(
2593 Zcu.Namespace.NameAdapter{ .zcu = zcu },2595 Zcu.Namespace.NameAdapter{ .zcu = zcu },
2594 ).?;2596 ).?;
2595 {2597 {
2596 // We have to call `ensureCauAnalyzed` here in case `builtin.test_functions`2598 // We have to call `ensureNavValUpToDate` here in case `builtin.test_functions`
2597 // was not referenced by start code.2599 // was not referenced by start code.
2598 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);2600 zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
2599 defer {2601 defer {
2600 zcu.sema_prog_node.end();2602 zcu.sema_prog_node.end();
2601 zcu.sema_prog_node = std.Progress.Node.none;2603 zcu.sema_prog_node = std.Progress.Node.none;
2602 }2604 }
2603 const cau_index = ip.getNav(nav_index).analysis_owner.unwrap().?;2605 pt.ensureNavValUpToDate(nav_index) catch |err| switch (err) {
2604 pt.ensureCauAnalyzed(cau_index) catch |err| switch (err) {
2605 error.AnalysisFail => return,2606 error.AnalysisFail => return,
2606 error.OutOfMemory => return error.OutOfMemory,2607 error.OutOfMemory => return error.OutOfMemory,
2607 };2608 };
...@@ -2622,8 +2623,7 @@ pub fn populateTestFunctions(...@@ -2622,8 +2623,7 @@ pub fn populateTestFunctions(
2622 {2623 {
2623 // The test declaration might have failed; if that's the case, just return, as we'll2624 // The test declaration might have failed; if that's the case, just return, as we'll
2624 // be emitting a compile error anyway.2625 // be emitting a compile error anyway.
2625 const cau = test_nav.analysis_owner.unwrap().?;2626 const anal_unit: AnalUnit = .wrap(.{ .nav_val = test_nav_index });
2626 const anal_unit: AnalUnit = .wrap(.{ .cau = cau });
2627 if (zcu.failed_analysis.contains(anal_unit) or2627 if (zcu.failed_analysis.contains(anal_unit) or
2628 zcu.transitive_failed_analysis.contains(anal_unit))2628 zcu.transitive_failed_analysis.contains(anal_unit))
2629 {2629 {
...@@ -2748,8 +2748,8 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error...@@ -2748,8 +2748,8 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error
2748 "unable to codegen: {s}",2748 "unable to codegen: {s}",
2749 .{@errorName(err)},2749 .{@errorName(err)},
2750 ));2750 ));
2751 if (nav.analysis_owner.unwrap()) |cau| {2751 if (nav.analysis != null) {
2752 try zcu.retryable_failures.append(zcu.gpa, AnalUnit.wrap(.{ .cau = cau }));2752 try zcu.retryable_failures.append(zcu.gpa, .wrap(.{ .nav_val = nav_index }));
2753 } else {2753 } else {
2754 // TODO: we don't have a way to indicate that this failure is retryable!2754 // TODO: we don't have a way to indicate that this failure is retryable!
2755 // Since these are really rare, we could as a cop-out retry the whole build next update.2755 // Since these are really rare, we could as a cop-out retry the whole build next update.
...@@ -3255,7 +3255,7 @@ pub fn getBuiltinNav(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Intern...@@ -3255,7 +3255,7 @@ pub fn getBuiltinNav(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Intern
3255 const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);3255 const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);
3256 const builtin_nav = std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse3256 const builtin_nav = std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse
3257 @panic("lib/std.zig is corrupt and missing 'builtin'");3257 @panic("lib/std.zig is corrupt and missing 'builtin'");
3258 pt.ensureCauAnalyzed(ip.getNav(builtin_nav).analysis_owner.unwrap().?) catch @panic("std.builtin is corrupt");3258 pt.ensureNavValUpToDate(builtin_nav) catch @panic("std.builtin is corrupt");
3259 const builtin_type = Type.fromInterned(ip.getNav(builtin_nav).status.resolved.val);3259 const builtin_type = Type.fromInterned(ip.getNav(builtin_nav).status.resolved.val);
3260 const builtin_namespace = zcu.namespacePtr(builtin_type.getNamespace(zcu).unwrap() orelse @panic("std.builtin is corrupt"));3260 const builtin_namespace = zcu.namespacePtr(builtin_type.getNamespace(zcu).unwrap() orelse @panic("std.builtin is corrupt"));
3261 const name_str = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);3261 const name_str = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);
...@@ -3307,68 +3307,45 @@ pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPo...@@ -3307,68 +3307,45 @@ pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPo
3307/// Given a container type requiring resolution, ensures that it is up-to-date.3307/// Given a container type requiring resolution, ensures that it is up-to-date.
3308/// If not, the type is recreated at a new `InternPool.Index`.3308/// If not, the type is recreated at a new `InternPool.Index`.
3309/// The new index is returned. This is the same as the old index if the fields were up-to-date.3309/// The new index is returned. This is the same as the old index if the fields were up-to-date.
3310/// If `already_updating` is set, assumes the type is already outdated and undergoing re-analysis rather than checking `zcu.outdated`.3310pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError!InternPool.Index {
3311pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index, already_updating: bool) Zcu.SemaError!InternPool.Index {
3312 const zcu = pt.zcu;3311 const zcu = pt.zcu;
3312 const gpa = zcu.gpa;
3313 const ip = &zcu.intern_pool;3313 const ip = &zcu.intern_pool;
3314
3315 const anal_unit: AnalUnit = .wrap(.{ .type = ty });
3316 const outdated = zcu.outdated.swapRemove(anal_unit) or
3317 zcu.potentially_outdated.swapRemove(anal_unit);
3318
3319 if (!outdated) return ty;
3320
3321 // We will recreate the type at a new `InternPool.Index`.
3322
3323 _ = zcu.outdated_ready.swapRemove(anal_unit);
3324 try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty });
3325
3326 // Delete old state which is no longer in use. Technically, this is not necessary: these exports,
3327 // references, etc, will be ignored because the type itself is unreferenced. However, it allows
3328 // reusing the memory which is currently being used to track this state.
3329 zcu.deleteUnitExports(anal_unit);
3330 zcu.deleteUnitReferences(anal_unit);
3331 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
3332 kv.value.destroy(gpa);
3333 }
3334 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
3335 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
3336
3314 switch (ip.indexToKey(ty)) {3337 switch (ip.indexToKey(ty)) {
3315 .struct_type => |key| {3338 .struct_type => |key| return pt.recreateStructType(ty, key),
3316 const struct_obj = ip.loadStructType(ty);3339 .union_type => |key| return pt.recreateUnionType(ty, key),
3317 const outdated = already_updating or o: {3340 .enum_type => |key| return pt.recreateEnumType(ty, key),
3318 const anal_unit = AnalUnit.wrap(.{ .cau = struct_obj.cau });
3319 const o = zcu.outdated.swapRemove(anal_unit) or
3320 zcu.potentially_outdated.swapRemove(anal_unit);
3321 if (o) {
3322 _ = zcu.outdated_ready.swapRemove(anal_unit);
3323 try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty });
3324 }
3325 break :o o;
3326 };
3327 if (!outdated) return ty;
3328 return pt.recreateStructType(key, struct_obj);
3329 },
3330 .union_type => |key| {
3331 const union_obj = ip.loadUnionType(ty);
3332 const outdated = already_updating or o: {
3333 const anal_unit = AnalUnit.wrap(.{ .cau = union_obj.cau });
3334 const o = zcu.outdated.swapRemove(anal_unit) or
3335 zcu.potentially_outdated.swapRemove(anal_unit);
3336 if (o) {
3337 _ = zcu.outdated_ready.swapRemove(anal_unit);
3338 try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty });
3339 }
3340 break :o o;
3341 };
3342 if (!outdated) return ty;
3343 return pt.recreateUnionType(key, union_obj);
3344 },
3345 .enum_type => |key| {
3346 const enum_obj = ip.loadEnumType(ty);
3347 const outdated = already_updating or o: {
3348 const anal_unit = AnalUnit.wrap(.{ .cau = enum_obj.cau.unwrap().? });
3349 const o = zcu.outdated.swapRemove(anal_unit) or
3350 zcu.potentially_outdated.swapRemove(anal_unit);
3351 if (o) {
3352 _ = zcu.outdated_ready.swapRemove(anal_unit);
3353 try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty });
3354 }
3355 break :o o;
3356 };
3357 if (!outdated) return ty;
3358 return pt.recreateEnumType(key, enum_obj);
3359 },
3360 .opaque_type => {
3361 assert(!already_updating);
3362 return ty;
3363 },
3364 else => unreachable,3341 else => unreachable,
3365 }3342 }
3366}3343}
33673344
3368fn recreateStructType(3345fn recreateStructType(
3369 pt: Zcu.PerThread,3346 pt: Zcu.PerThread,
3347 old_ty: InternPool.Index,
3370 full_key: InternPool.Key.NamespaceType,3348 full_key: InternPool.Key.NamespaceType,
3371 struct_obj: InternPool.LoadedStructType,
3372) Zcu.SemaError!InternPool.Index {3349) Zcu.SemaError!InternPool.Index {
3373 const zcu = pt.zcu;3350 const zcu = pt.zcu;
3374 const gpa = zcu.gpa;3351 const gpa = zcu.gpa;
...@@ -3405,8 +3382,7 @@ fn recreateStructType(...@@ -3405,8 +3382,7 @@ fn recreateStructType(
34053382
3406 if (captures_len != key.captures.owned.len) return error.AnalysisFail;3383 if (captures_len != key.captures.owned.len) return error.AnalysisFail;
34073384
3408 // The old type will be unused, so drop its dependency information.3385 const struct_obj = ip.loadStructType(old_ty);
3409 ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .cau = struct_obj.cau }));
34103386
3411 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{3387 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{
3412 .layout = small.layout,3388 .layout = small.layout,
...@@ -3428,17 +3404,16 @@ fn recreateStructType(...@@ -3428,17 +3404,16 @@ fn recreateStructType(
3428 errdefer wip_ty.cancel(ip, pt.tid);3404 errdefer wip_ty.cancel(ip, pt.tid);
34293405
3430 wip_ty.setName(ip, struct_obj.name);3406 wip_ty.setName(ip, struct_obj.name);
3431 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, key.zir_index, struct_obj.namespace, wip_ty.index);
3432 try ip.addDependency(3407 try ip.addDependency(
3433 gpa,3408 gpa,
3434 AnalUnit.wrap(.{ .cau = new_cau_index }),3409 .wrap(.{ .type = wip_ty.index }),
3435 .{ .src_hash = key.zir_index },3410 .{ .src_hash = key.zir_index },
3436 );3411 );
3437 zcu.namespacePtr(struct_obj.namespace).owner_type = wip_ty.index;3412 zcu.namespacePtr(struct_obj.namespace).owner_type = wip_ty.index;
3438 // No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive.3413 // No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive.
3439 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });3414 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
34403415
3441 const new_ty = wip_ty.finish(ip, new_cau_index.toOptional(), struct_obj.namespace);3416 const new_ty = wip_ty.finish(ip, struct_obj.namespace);
3442 if (inst_info.inst == .main_struct_inst) {3417 if (inst_info.inst == .main_struct_inst) {
3443 // This is the root type of a file! Update the reference.3418 // This is the root type of a file! Update the reference.
3444 zcu.setFileRootType(inst_info.file, new_ty);3419 zcu.setFileRootType(inst_info.file, new_ty);
...@@ -3448,8 +3423,8 @@ fn recreateStructType(...@@ -3448,8 +3423,8 @@ fn recreateStructType(
34483423
3449fn recreateUnionType(3424fn recreateUnionType(
3450 pt: Zcu.PerThread,3425 pt: Zcu.PerThread,
3426 old_ty: InternPool.Index,
3451 full_key: InternPool.Key.NamespaceType,3427 full_key: InternPool.Key.NamespaceType,
3452 union_obj: InternPool.LoadedUnionType,
3453) Zcu.SemaError!InternPool.Index {3428) Zcu.SemaError!InternPool.Index {
3454 const zcu = pt.zcu;3429 const zcu = pt.zcu;
3455 const gpa = zcu.gpa;3430 const gpa = zcu.gpa;
...@@ -3488,8 +3463,7 @@ fn recreateUnionType(...@@ -3488,8 +3463,7 @@ fn recreateUnionType(
34883463
3489 if (captures_len != key.captures.owned.len) return error.AnalysisFail;3464 if (captures_len != key.captures.owned.len) return error.AnalysisFail;
34903465
3491 // The old type will be unused, so drop its dependency information.3466 const union_obj = ip.loadUnionType(old_ty);
3492 ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .cau = union_obj.cau }));
34933467
3494 const namespace_index = union_obj.namespace;3468 const namespace_index = union_obj.namespace;
34953469
...@@ -3526,22 +3500,21 @@ fn recreateUnionType(...@@ -3526,22 +3500,21 @@ fn recreateUnionType(
3526 errdefer wip_ty.cancel(ip, pt.tid);3500 errdefer wip_ty.cancel(ip, pt.tid);
35273501
3528 wip_ty.setName(ip, union_obj.name);3502 wip_ty.setName(ip, union_obj.name);
3529 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, key.zir_index, namespace_index, wip_ty.index);
3530 try ip.addDependency(3503 try ip.addDependency(
3531 gpa,3504 gpa,
3532 AnalUnit.wrap(.{ .cau = new_cau_index }),3505 .wrap(.{ .type = wip_ty.index }),
3533 .{ .src_hash = key.zir_index },3506 .{ .src_hash = key.zir_index },
3534 );3507 );
3535 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;3508 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;
3536 // No need to re-scan the namespace -- `zirUnionDecl` will ultimately do that if the type is still alive.3509 // No need to re-scan the namespace -- `zirUnionDecl` will ultimately do that if the type is still alive.
3537 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });3510 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
3538 return wip_ty.finish(ip, new_cau_index.toOptional(), namespace_index);3511 return wip_ty.finish(ip, namespace_index);
3539}3512}
35403513
3541fn recreateEnumType(3514fn recreateEnumType(
3542 pt: Zcu.PerThread,3515 pt: Zcu.PerThread,
3516 old_ty: InternPool.Index,
3543 full_key: InternPool.Key.NamespaceType,3517 full_key: InternPool.Key.NamespaceType,
3544 enum_obj: InternPool.LoadedEnumType,
3545) Zcu.SemaError!InternPool.Index {3518) Zcu.SemaError!InternPool.Index {
3546 const zcu = pt.zcu;3519 const zcu = pt.zcu;
3547 const gpa = zcu.gpa;3520 const gpa = zcu.gpa;
...@@ -3610,8 +3583,7 @@ fn recreateEnumType(...@@ -3610,8 +3583,7 @@ fn recreateEnumType(
3610 if (bag != 0) break true;3583 if (bag != 0) break true;
3611 } else false;3584 } else false;
36123585
3613 // The old type will be unused, so drop its dependency information.3586 const enum_obj = ip.loadEnumType(old_ty);
3614 ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .cau = enum_obj.cau.unwrap().? }));
36153587
3616 const namespace_index = enum_obj.namespace;3588 const namespace_index = enum_obj.namespace;
36173589
...@@ -3637,12 +3609,10 @@ fn recreateEnumType(...@@ -3637,12 +3609,10 @@ fn recreateEnumType(
36373609
3638 wip_ty.setName(ip, enum_obj.name);3610 wip_ty.setName(ip, enum_obj.name);
36393611
3640 const new_cau_index = try ip.createTypeCau(gpa, pt.tid, key.zir_index, namespace_index, wip_ty.index);
3641
3642 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;3612 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;
3643 // No need to re-scan the namespace -- `zirEnumDecl` will ultimately do that if the type is still alive.3613 // No need to re-scan the namespace -- `zirEnumDecl` will ultimately do that if the type is still alive.
36443614
3645 wip_ty.prepare(ip, new_cau_index, namespace_index);3615 wip_ty.prepare(ip, namespace_index);
3646 done = true;3616 done = true;
36473617
3648 Sema.resolveDeclaredEnum(3618 Sema.resolveDeclaredEnum(
...@@ -3652,7 +3622,6 @@ fn recreateEnumType(...@@ -3652,7 +3622,6 @@ fn recreateEnumType(
3652 key.zir_index,3622 key.zir_index,
3653 namespace_index,3623 namespace_index,
3654 enum_obj.name,3624 enum_obj.name,
3655 new_cau_index,
3656 small,3625 small,
3657 body,3626 body,
3658 tag_type_ref,3627 tag_type_ref,
src/link/Dwarf.zig+8-8
...@@ -2261,8 +2261,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In...@@ -2261,8 +2261,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
2261 assert(file.zir_loaded);2261 assert(file.zir_loaded);
2262 const decl = file.zir.getDeclaration(inst_info.inst);2262 const decl = file.zir.getDeclaration(inst_info.inst);
22632263
2264 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {2264 const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
2265 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2265 const parent_namespace_ptr = ip.namespacePtr(a.namespace);
2266 break :parent .{2266 break :parent .{
2267 parent_namespace_ptr.owner_type,2267 parent_namespace_ptr.owner_type,
2268 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,2268 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...@@ -2292,8 +2292,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
2292 assert(file.zir_loaded);2292 assert(file.zir_loaded);
2293 const decl = file.zir.getDeclaration(inst_info.inst);2293 const decl = file.zir.getDeclaration(inst_info.inst);
22942294
2295 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {2295 const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
2296 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2296 const parent_namespace_ptr = ip.namespacePtr(a.namespace);
2297 break :parent .{2297 break :parent .{
2298 parent_namespace_ptr.owner_type,2298 parent_namespace_ptr.owner_type,
2299 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,2299 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...@@ -2321,8 +2321,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
2321 assert(file.zir_loaded);2321 assert(file.zir_loaded);
2322 const decl = file.zir.getDeclaration(inst_info.inst);2322 const decl = file.zir.getDeclaration(inst_info.inst);
23232323
2324 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {2324 const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
2325 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2325 const parent_namespace_ptr = ip.namespacePtr(a.namespace);
2326 break :parent .{2326 break :parent .{
2327 parent_namespace_ptr.owner_type,2327 parent_namespace_ptr.owner_type,
2328 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,2328 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...@@ -2563,8 +2563,8 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2563 return;2563 return;
2564 }2564 }
25652565
2566 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {2566 const parent_type, const accessibility: u8 = if (nav.analysis) |a| parent: {
2567 const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);2567 const parent_namespace_ptr = ip.namespacePtr(a.namespace);
2568 break :parent .{2568 break :parent .{
2569 parent_namespace_ptr.owner_type,2569 parent_namespace_ptr.owner_type,
2570 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,2570 if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private,