| author | |
| committer | |
| log | 40aafcd6a85d3c517f445f17149c17523c832420 |
| tree | b8e1a5361c6a20ce9e3ba568b61b199aff1c8f13 |
| parent | 18362ebe13ece2ea7c4f57303ec4687f55d2dba5 |
| signature |
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 | } |
| 3142 | 3145 | ||
| 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 | }; |
| 3147 | 3152 | ||
| 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 outdated | 3644 | // 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 |
| 3688 | 3694 | ||
| 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 | }; | ||
| 3705 | 3727 | ||
| 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 | } |
| 3716 | 3733 | ||
| 3717 | // Tests are always emitted in test binaries. The decl_refs are created by | 3734 | // Tests are always emitted in test binaries. The decl_refs are created by |
| 3718 | // Zcu.populateTestFunctions, but this will not queue body analysis, so do | 3735 | // 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 | } |
| 364 | 364 | ||
| 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. |
| 369 | pub const AnalUnit = packed struct(u32) { | 367 | pub 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 | }; |
| 402 | 422 | ||
| 403 | /// Comptime Analysis Unit. This is the "subject" of semantic analysis where the root context is | 423 | pub 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. | ||
| 415 | pub 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 | }; | ||
| 442 | 426 | ||
| 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 | }; | ||
| 461 | 430 | ||
| 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, |
| 482 | 436 | 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 | } |
| 496 | 449 | ||
| ... | @@ -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. |
| 511 | pub const Nav = struct { | 469 | pub 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 / @extern | 519 | .@"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 | }; |
| 601 | 561 | ||
| 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, | ||
| 867 | 836 | ||
| 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, | ||
| 881 | 850 | ||
| 882 | namespaces: Namespaces, | 851 | namespaces: Namespaces, |
| 883 | 852 | ||
| ... | @@ -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 }); | ||
| 904 | 873 | ||
| 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 | } |
| 1277 | 1246 | ||
| 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 | } |
| 1286 | 1255 | ||
| 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 | } |
| 1295 | 1264 | ||
| ... | @@ -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 structure | 3021 | // 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 structure | 3353 | // 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 structure | 4113 | // 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_union | 4193 | 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: PackedU64 | 4196 | 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_union | 4227 | 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: PackedU64 | 4230 | 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_layout | 5623 | /// 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_inits | 5652 | /// 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_resolved | 5699 | /// 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 { |
| 6088 | 6028 | ||
| 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 order | 6034 | /// 4. tag value: Index for each fields_len; declaration order |
| 6095 | /// 5. tag value: Index for each fields_len; declaration order | ||
| 6096 | pub const EnumExplicit = struct { | 6035 | pub 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 { |
| 6115 | 6054 | ||
| 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 | ||
| 6122 | pub const EnumAuto = struct { | 6060 | pub 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, |
| 6420 | 6358 | ||
| 6421 | .namespaces = Local.Namespaces.empty, | 6359 | .namespaces = .empty, |
| 6422 | }, | 6360 | }, |
| 6423 | .mutate = .{ | 6361 | .mutate = .{ |
| 6424 | .arena = .{}, | 6362 | .arena = .{}, |
| 6425 | 6363 | ||
| 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, |
| 6435 | 6373 | ||
| 6436 | .namespaces = Local.BucketListMutate.empty, | 6374 | .namespaces = .empty, |
| 6437 | }, | 6375 | }, |
| 6438 | }); | 6376 | }); |
| 6439 | 6377 | ||
| ... | @@ -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, |
| 8389 | 8323 | ||
| 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"); |
| 8408 | 8341 | ||
| 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); |
| 8416 | 8343 | ||
| 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); // inits | 8437 | 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_map | 8503 | 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; |
| 9387 | 9310 | ||
| 9388 | // TODO: improve this name | 9311 | // 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"); |
| 9457 | 9378 | ||
| 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 | } |
| 9461 | 9381 | ||
| ... | @@ -9556,7 +9476,6 @@ pub fn getEnumType( | ... | @@ -9556,7 +9476,6 @@ pub fn getEnumType( |
| 9556 | .reified => 2, // type_hash: PackedU64 | 9476 | .reified => 2, // type_hash: PackedU64 |
| 9557 | } + | 9477 | } + |
| 9558 | // zig fmt: on | 9478 | // zig fmt: on |
| 9559 | 1 + // cau | ||
| 9560 | ini.fields_len); // field types | 9479 | ini.fields_len); // field types |
| 9561 | 9480 | ||
| 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: PackedU64 | 9532 | .reified => 2, // type_hash: PackedU64 |
| 9617 | } + | 9533 | } + |
| 9618 | // zig fmt: on | 9534 | // zig fmt: on |
| 9619 | 1 + // cau | ||
| 9620 | ini.fields_len + // field types | 9535 | ini.fields_len + // field types |
| 9621 | ini.fields_len * @intFromBool(ini.has_values)); // field values | 9536 | ini.fields_len * @intFromBool(ini.has_values)); // field values |
| 9622 | 9537 | ||
| ... | @@ -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 | } |
| 11060 | 10969 | ||
| 11061 | pub 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 | |||
| 11067 | pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav { | 10970 | pub 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 | } |
| 11079 | 10982 | ||
| 11080 | /// Create a `Cau` associated with the type at the given `InternPool.Index`. | 10983 | /// Create a `ComptimeUnit`, forming an `AnalUnit` for a `comptime` declaration. |
| 11081 | pub fn createTypeCau( | 10984 | pub 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 | } |
| 11101 | 11002 | ||
| 11102 | /// Create a `Cau` for a `comptime` declaration. | 11003 | pub fn getComptimeUnit(ip: *const InternPool, id: ComptimeUnit.Id) ComptimeUnit { |
| 11103 | pub 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 | } |
| 11122 | 11008 | ||
| 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. |
| 11125 | pub fn createNav( | 11011 | pub 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 | } |
| 11157 | 11043 | ||
| 11158 | /// Create a `Cau` and `Nav` which are paired. The value of the `Nav` is | 11044 | /// 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. | 11046 | pub fn createDeclNav( |
| 11161 | pub 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); |
| 11174 | 11058 | ||
| 11175 | try caus.ensureUnusedCapacity(1); | ||
| 11176 | try navs.ensureUnusedCapacity(1); | 11059 | try navs.ensureUnusedCapacity(1); |
| 11177 | 11060 | ||
| 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); |
| 11186 | 11065 | ||
| 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 | })); |
| 11199 | 11076 | ||
| 11200 | return .{ cau, nav }; | 11077 | return nav; |
| 11201 | } | 11078 | } |
| 11202 | 11079 | ||
| 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( |
| 11220 | 11097 | ||
| 11221 | const navs = local.shared.navs.view(); | 11098 | const navs = local.shared.navs.view(); |
| 11222 | 11099 | ||
| 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); |
| 11227 | 11105 | ||
| 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); | ||
| 11229 | 11108 | ||
| 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); |
| 2874 | 2874 | ||
| 2875 | // Make sure we update the namespace if the declaration is re-analyzed, to pick | 2875 | // 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); |
| 2902 | 2902 | ||
| 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 | } |
| 2927 | 2925 | ||
| 2928 | fn createTypeName( | 2926 | fn 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); |
| 3104 | 3102 | ||
| 3105 | // Make sure we update the namespace if the declaration is re-analyzed, to pick | 3103 | // 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); |
| 3138 | 3136 | ||
| 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); |
| 3142 | 3138 | ||
| 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); |
| 3145 | 3141 | ||
| 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; |
| 3150 | 3146 | ||
| 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); |
| 3249 | 3244 | ||
| 3250 | // Make sure we update the namespace if the declaration is re-analyzed, to pick | 3245 | // 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); |
| 3277 | 3272 | ||
| 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 | } |
| 3302 | 3295 | ||
| 3303 | fn zirOpaqueDecl( | 3296 | fn 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 | } |
| 3387 | 3380 | ||
| 3388 | fn zirErrorSetDecl( | 3381 | fn 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 function | 6543 | .@"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( |
| 6868 | 6864 | ||
| 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); |
| 7133 | 7126 | ||
| 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 trace | 7130 | // 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 }); |
| 7749 | 7742 | ||
| 7750 | // This is not a function instance, so the function's `Nav` has a | 7743 | // 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); | ||
| 7755 | 7746 | ||
| 7756 | // We effectively want a child Sema here, but can't literally do that, because we need AIR | 7747 | // 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 in | 7748 | // 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 | }; |
| 7786 | 7777 | ||
| ... | @@ -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 compilation | 7787 | // 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 should | 7788 | // 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; |
| 7800 | 7791 | ||
| 7801 | // If it's a comptime function call, we need to memoize it as long as no external | 7792 | // 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( |
| 7904 | 7895 | ||
| 7905 | // Since we're doing an inline call, we depend on the source code of the whole | 7896 | // 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 }); |
| 7908 | 7899 | ||
| 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); |
| 8017 | 8008 | ||
| 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` to | 8259 | // The actual monomorphization happens via adding `func_instance` to |
| 8269 | // `InternPool`. | 8260 | // `InternPool`. |
| 8270 | 8261 | ||
| 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); |
| 8276 | 8266 | ||
| 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); |
| 8482 | 8472 | ||
| 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 defaults | 9500 | // 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, |
| 9995 | 9982 | ||
| 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( |
| 10040 | 10027 | ||
| 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 | } |
| 17670 | 17657 | ||
| ... | @@ -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 | } |
| 19322 | 19309 | ||
| 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 | }); |
| 22297 | 22281 | ||
| 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 | }); |
| 22507 | 22491 | ||
| 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; |
| 22515 | 22497 | ||
| ... | @@ -22811,8 +22793,6 @@ fn reifyUnion( | ... | @@ -22811,8 +22793,6 @@ fn reifyUnion( |
| 22811 | .generation = zcu.generation, | 22793 | .generation = zcu.generation, |
| 22812 | }); | 22794 | }); |
| 22813 | 22795 | ||
| 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 | } |
| 22827 | 22807 | ||
| 22828 | fn reifyTuple( | 22808 | fn reifyTuple( |
| ... | @@ -23170,8 +23150,6 @@ fn reifyStruct( | ... | @@ -23170,8 +23150,6 @@ fn reifyStruct( |
| 23170 | .generation = zcu.generation, | 23150 | .generation = zcu.generation, |
| 23171 | }); | 23151 | }); |
| 23172 | 23152 | ||
| 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 | } |
| 23186 | 23164 | ||
| 23187 | fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { | 23165 | fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { |
| ... | @@ -26713,15 +26691,13 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -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 to | 26695 | // 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 Cau | 26700 | 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 similar | 26703 | // 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; |
| 32671 | 32655 | ||
| 32672 | const nav = ip.getNav(nav_index); | 32656 | const nav = ip.getNav(nav_index); |
| 32673 | 32657 | 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 | } |
| 32678 | 32661 | ||
| 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. |
| 32681 | 32664 | ||
| 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); |
| 32686 | 32667 | ||
| 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 | } |
| 32693 | 32674 | ||
| 32694 | return pt.ensureCauAnalyzed(cau_index); | 32675 | return pt.ensureNavValUpToDate(nav_index); |
| 32695 | } | 32676 | } |
| 32696 | 32677 | ||
| 32697 | fn optRefValue(sema: *Sema, opt_val: ?Value) !Value { | 32678 | fn 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(); |
| 35643 | 35624 | ||
| 35644 | assert(sema.owner.unwrap().cau == struct_type.cau); | 35625 | assert(sema.owner.unwrap().type == ty); |
| 35645 | 35626 | ||
| 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; |
| 35686 | 35667 | ||
| 35687 | assert(sema.owner.unwrap().cau == struct_type.cau); | 35668 | assert(sema.owner.unwrap().type == ty.toIntern()); |
| 35688 | 35669 | ||
| 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; |
| 35833 | 35814 | ||
| 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(); |
| 35838 | 35817 | ||
| 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(); |
| 35973 | 35952 | ||
| 35974 | assert(sema.owner.unwrap().cau == union_type.cau); | 35953 | assert(sema.owner.unwrap().type == ty.toIntern()); |
| 35975 | 35954 | ||
| 35976 | assert(!union_type.haveLayout(ip)); | 35955 | assert(!union_type.haveLayout(ip)); |
| 35977 | 35956 | ||
| ... | @@ -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); |
| 36013 | 35992 | ||
| 36014 | assert(sema.owner.unwrap().cau == union_type.cau); | 35993 | assert(sema.owner.unwrap().type == ty.toIntern()); |
| 36015 | 35994 | ||
| 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).?; |
| 36128 | 36107 | ||
| 36129 | assert(sema.owner.unwrap().cau == struct_type.cau); | 36108 | assert(sema.owner.unwrap().type == ty.toIntern()); |
| 36130 | 36109 | ||
| 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).?; |
| 36151 | 36130 | ||
| 36152 | assert(sema.owner.unwrap().cau == union_obj.cau); | 36131 | assert(sema.owner.unwrap().type == ty.toIntern()); |
| 36153 | 36132 | ||
| 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; |
| 36186 | 36165 | ||
| 36187 | assert(sema.owner.unwrap().cau == struct_type.cau); | 36166 | assert(sema.owner.unwrap().type == ty); |
| 36188 | 36167 | ||
| 36189 | if (struct_type.haveFieldTypes(ip)) return; | 36168 | if (struct_type.haveFieldTypes(ip)) return; |
| 36190 | 36169 | ||
| ... | @@ -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; |
| 36212 | 36191 | ||
| 36213 | assert(sema.owner.unwrap().cau == struct_type.cau); | 36192 | assert(sema.owner.unwrap().type == ty.toIntern()); |
| 36214 | 36193 | ||
| 36215 | // Inits can start as resolved | 36194 | // 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; |
| 36241 | 36220 | ||
| 36242 | assert(sema.owner.unwrap().cau == union_type.cau); | 36221 | assert(sema.owner.unwrap().type == ty.toIntern()); |
| 36243 | 36222 | ||
| 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 that | 36294 | // 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 | } |
| 36320 | 36299 | ||
| 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; |
| 36479 | 36457 | ||
| ... | @@ -36671,8 +36649,7 @@ fn structFieldInits( | ... | @@ -36671,8 +36649,7 @@ fn structFieldInits( |
| 36671 | 36649 | ||
| 36672 | assert(!struct_type.haveFieldInits(ip)); | 36650 | assert(!struct_type.haveFieldInits(ip)); |
| 36673 | 36651 | ||
| 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 resolve | 38451 | // 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 | } |
| 38485 | 38460 | ||
| 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 | } |
| 38661 | 38636 | ||
| 38662 | /// Given that this `Sema` is owned by the `Cau` of a `declaration`, fetches | ||
| 38663 | /// the corresponding `Nav`. | ||
| 38664 | fn 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. | ||
| 38671 | fn 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. | ||
| 38680 | fn 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 } }; |
| 38721 | 38663 | ||
| 38722 | const anal_unit = AnalUnit.wrap(.{ .cau = enum_cau }); | 38664 | const anal_unit = AnalUnit.wrap(.{ .type = wip_ty.index }); |
| 38723 | 38665 | ||
| 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; |
| 3852 | 3852 | ||
| 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() }); |
| 3855 | 3855 | ||
| 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; |
| 3906 | 3906 | ||
| 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() }); |
| 3909 | 3909 | ||
| 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, |
| 192 | 192 | ||
| 193 | test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty, | 193 | test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty, |
| 194 | 194 | ||
| 195 | global_assembly: std.AutoArrayHashMapUnmanaged(InternPool.Cau.Index, []u8) = .empty, | 195 | global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty, |
| 196 | 196 | ||
| 197 | /// Key is the `AnalUnit` *performing* the reference. This representation allows | 197 | /// 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 that | 347 | /// 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, | ||
| 350 | 353 | ||
| 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 tyval | 2439 | // 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 { |
| 2451 | fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void { | 2452 | fn 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 introduced | 2456 | .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 }, // IES | 2458 | .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 | } |
| 2513 | 2512 | ||
| 2514 | // There is no single AnalUnit which is ready for re-analysis. Instead, we must assume that some | 2513 | // 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 of | 2514 | // 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 the | 2515 | // 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, not | 2516 | // 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! |
| 2519 | 2518 | ||
| 2520 | // The choice of this Cau could have a big impact on how much total analysis we perform, since | 2519 | // 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 AnalUnit | 2520 | // 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 Decl | 2521 | // 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 this | 2522 | // 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). |
| 2525 | 2524 | ||
| ... | @@ -2530,33 +2529,28 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { | ... | @@ -2530,33 +2529,28 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { |
| 2530 | 2529 | ||
| 2531 | const ip = &zcu.intern_pool; | 2530 | const ip = &zcu.intern_pool; |
| 2532 | 2531 | ||
| 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; |
| 2535 | 2534 | ||
| 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 choice | 2539 | .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; |
| 2551 | 2545 | ||
| 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 | } |
| 2558 | 2552 | ||
| 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 | } |
| 2571 | 2565 | ||
| 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 | }); |
| 2576 | 2570 | ||
| 2577 | return AnalUnit.wrap(.{ .cau = chosen_cau.? }); | 2571 | return chosen_unit.?; |
| 2578 | } | 2572 | } |
| 2579 | 2573 | ||
| 2580 | /// During an incremental update, before semantic analysis, call this to flush all values from | 2574 | /// 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 | } |
| 3021 | 3015 | ||
| 3022 | pub fn addGlobalAssembly(zcu: *Zcu, cau: InternPool.Cau.Index, source: []const u8) !void { | 3016 | pub 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 |
| 3304 | 3298 | ||
| 3305 | log.debug("handle type '{}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}); | 3299 | log.debug("handle type '{}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}); |
| 3306 | 3300 | ||
| 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 type | 3309 | // 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 | } |
| 3321 | 3314 | ||
| 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 | } |
| 3529 | 3527 | ||
| 3530 | pub 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 | |||
| 3536 | pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Formatter(formatAnalUnit) { | 3528 | pub 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 { |
| 545 | pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { | 545 | pub 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 | } |
| 553 | 553 | ||
| 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. |
| 557 | pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu.SemaError!void { | 557 | pub 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(); |
| 560 | 560 | ||
| 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; | ||
| 564 | 563 | ||
| 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); | ||
| 567 | 565 | ||
| 568 | log.debug("ensureCauAnalyzed {}", .{zcu.fmtAnalUnit(anal_unit)}); | 566 | log.debug("ensureComptimeUnitUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)}); |
| 569 | 567 | ||
| 570 | assert(!zcu.analysis_in_progress.contains(anal_unit)); | 568 | assert(!zcu.analysis_in_progress.contains(anal_unit)); |
| 571 | 569 | ||
| 572 | // Determine whether or not this Cau is outdated, i.e. requires re-analysis | 570 | // 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 it | 571 | // 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 definitely | 572 | // created, it's marked as outdated. |
| 575 | // up-to-date when this function returns. | 573 | // |
| 576 | 574 | // 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 file | 576 | // 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 listed | 577 | // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`. |
| 580 | // dependencies are all up-to-date. | ||
| 581 | 578 | ||
| 582 | const cau_outdated = zcu.outdated.swapRemove(anal_unit) or | 579 | const was_outdated = zcu.outdated.swapRemove(anal_unit) or |
| 583 | zcu.potentially_outdated.swapRemove(anal_unit); | 580 | zcu.potentially_outdated.swapRemove(anal_unit); |
| 584 | 581 | ||
| 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, or | 590 | } |
| 596 | // * it is a `comptime` decl and is up-to-date, or | 591 | _ = 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 | } |
| 604 | 599 | ||
| 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 actually | 601 | 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 | } |
| 673 | 627 | ||
| 674 | fn 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 { | 632 | fn 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; |
| 681 | 636 | ||
| 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 | } | ||
| 684 | 708 | ||
| 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. | ||
| 712 | pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.SemaError!void { | ||
| 713 | const tracy = trace(@src()); | ||
| 714 | defer tracy.end(); | ||
| 686 | 715 | ||
| 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 this | 721 | // * 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 needed | 727 | // * we basically do `scanDecls`, updating the namespace as needed |
| 699 | // * so everyone lived happily ever after | 728 | // * so everyone lived happily ever after |
| 700 | 729 | ||
| 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 | |||
| 731 | pub 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; |
| 740 | 733 | ||
| 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 }); | ||
| 744 | 736 | ||
| 745 | log.debug("ensureFuncBodyAnalyzed {}", .{zcu.fmtAnalUnit(anal_unit)}); | 737 | log.debug("ensureNavUpToDate {}", .{zcu.fmtAnalUnit(anal_unit)}); |
| 746 | 738 | ||
| 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`. | ||
| 748 | 747 | ||
| 749 | const func_outdated = zcu.outdated.swapRemove(anal_unit) or | 748 | const was_outdated = zcu.outdated.swapRemove(anal_unit) or |
| 750 | zcu.potentially_outdated.swapRemove(anal_unit); | 749 | zcu.potentially_outdated.swapRemove(anal_unit); |
| 751 | 750 | ||
| 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); | ||
| 753 | 753 | ||
| 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 | } |
| 767 | 768 | ||
| 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 reporting | 790 | .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 | }; |
| 785 | 807 | ||
| 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 | } |
| 793 | 823 | ||
| 794 | if (analysis_fail) return error.AnalysisFail; | 824 | if (new_failed) return error.AnalysisFail; |
| 795 | } | 825 | } |
| 796 | 826 | ||
| 797 | fn ensureFuncBodyAnalyzedInner( | 827 | const 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 | |||
| 834 | fn 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; |
| 805 | 838 | ||
| 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); |
| 808 | 841 | ||
| 809 | // Make sure that this function is still owned by the same `Nav`. Otherwise, analyzing | 842 | 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. | ||
| 812 | 843 | ||
| 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 | } | ||
| 831 | 851 | ||
| 832 | // We'll want to remember what the IES used to be before the update for | 852 | // 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; | ||
| 838 | 854 | ||
| 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 | } | ||
| 848 | 857 | ||
| 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 | } | ||
| 860 | 860 | ||
| 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 | }); | ||
| 865 | 863 | ||
| 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(); | ||
| 868 | 877 | ||
| 869 | const ies_outdated = func_outdated and | 878 | // 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 }); |
| 871 | 880 | ||
| 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); | ||
| 873 | 892 | ||
| 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); | ||
| 876 | 894 | ||
| 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 | } | ||
| 881 | 896 | ||
| 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 }); |
| 887 | 902 | ||
| 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. |
| 890 | 905 | ||
| 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. |
| 893 | pub 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 | }; | ||
| 898 | 918 | ||
| 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 | } |
| 903 | 931 | ||
| 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); | ||
| 910 | 934 | ||
| 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 | }; |
| 916 | 940 | ||
| 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 | }; | ||
| 925 | 954 | ||
| 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 | } |
| 939 | 1029 | ||
| 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); | ||
| 942 | 1033 | ||
| 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 function | 1036 | if (nav_ty.toIntern() != .type_type) { |
| 946 | // depends on, hence triggering re-analysis of this function, so this | 1037 | 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 compilation | 1039 | 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 | } | ||
| 972 | 1055 | ||
| 973 | /// https://github.com/ziglang/zig/issues/14307 | 1056 | const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) { |
| 974 | pub 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 | }; |
| 982 | 1065 | ||
| 983 | fn 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; | ||
| 1012 | 1087 | ||
| 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); | ||
| 1039 | 1094 | ||
| 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 | } | ||
| 1047 | 1097 | ||
| 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 | } | ||
| 1059 | 1104 | ||
| 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. | ||
| 1065 | fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!void { | ||
| 1066 | const zcu = pt.zcu; | ||
| 1067 | 1106 | ||
| 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; | ||
| 1072 | 1109 | ||
| 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 | } |
| 1077 | 1114 | ||
| 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); | ||
| 1082 | 1118 | ||
| 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 | } |
| 1095 | 1136 | ||
| 1096 | fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { | 1137 | pub 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(); |
| 1099 | 1142 | ||
| 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); | ||
| 1104 | 1146 | ||
| 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); | ||
| 1109 | 1150 | ||
| 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); | ||
| 1118 | 1152 | ||
| 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 | }; | ||
| 1125 | 1154 | ||
| 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); | ||
| 1135 | 1157 | ||
| 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 | } | ||
| 1149 | 1217 | ||
| 1150 | const 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 | }; | ||
| 1156 | 1220 | ||
| 1157 | /// Performs semantic analysis on the given `Cau`, storing results to its owner `Nav` if needed. | 1221 | fn analyzeFuncBody( |
| 1158 | /// If analysis fails, returns `error.AnalysisFail`, storing an error in `zcu.failed_analysis` unless | 1222 | 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 } { |
| 1161 | fn 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; |
| 1165 | 1228 | ||
| 1166 | const anal_unit = AnalUnit.wrap(.{ .cau = cau_index }); | 1229 | const func = zcu.funcInfo(func_index); |
| 1167 | 1230 | 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 | } | ||
| 1176 | 1231 | ||
| 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. | ||
| 1179 | 1235 | ||
| 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 will | 1241 | // 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 | } |
| 1195 | 1254 | ||
| 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; | ||
| 1200 | 1261 | ||
| 1201 | log.debug("semaCau {}", .{zcu.fmtAnalUnit(anal_unit)}); | 1262 | log.debug("analyze and generate fn body {}", .{zcu.fmtAnalUnit(anal_unit)}); |
| 1202 | 1263 | ||
| 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); |
| 1205 | 1266 | ||
| 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; |
| 1208 | 1269 | ||
| 1209 | var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa); | 1270 | const comp = zcu.comp; |
| 1210 | defer comptime_err_ret_trace.deinit(); | ||
| 1211 | 1271 | ||
| 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(); | ||
| 1225 | 1274 | ||
| 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 | } | ||
| 1228 | 1279 | ||
| 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); | ||
| 1246 | 1285 | ||
| 1247 | const zir_decl = zir.getDeclaration(inst_info.inst); | 1286 | return .{ .ies_outdated = ies_outdated }; |
| 1287 | } | ||
| 1248 | 1288 | ||
| 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 functions | 1290 | /// 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. | 1291 | pub 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; |
| 1256 | 1296 | ||
| 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 }); | ||
| 1262 | 1301 | ||
| 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); | ||
| 1265 | 1305 | ||
| 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 | }; | ||
| 1278 | 1308 | ||
| 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 | } |
| 1291 | 1314 | ||
| 1292 | // Now that we know the type, we can evaluate the alignment, linksection, and addrspace, to determine | 1315 | 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(); | ||
| 1294 | 1323 | ||
| 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 | } | ||
| 1300 | 1337 | ||
| 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 | }; | ||
| 1314 | 1340 | ||
| 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)); | ||
| 1343 | 1370 | ||
| 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); | 1372 | pub 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 | } | ||
| 1347 | 1380 | ||
| 1348 | // TODO: missing validation? | 1381 | fn 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; | ||
| 1349 | 1410 | ||
| 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 body | 1423 | .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); | ||
| 1385 | 1433 | ||
| 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 | }; | ||
| 1400 | 1436 | ||
| 1401 | switch (decl_val.toIntern()) { | 1437 | if (zcu.comp.incremental) { |
| 1402 | .generic_poison => unreachable, // assertion failure | 1438 | try ip.addDependency( |
| 1403 | .unreachable_value => unreachable, // assertion failure | 1439 | gpa, |
| 1404 | else => {}, | 1440 | .wrap(.{ .type = wip_ty.index }), |
| 1441 | .{ .src_hash = tracked_inst }, | ||
| 1442 | ); | ||
| 1405 | } | 1443 | } |
| 1406 | 1444 | ||
| 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: { |
| 1410 | 1448 | 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 | } | ||
| 1432 | 1456 | ||
| 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 codegen | 1458 | /// 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 | }; | 1462 | fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!void { |
| 1439 | 1463 | const zcu = pt.zcu; | |
| 1440 | // Keep in sync with logic in `Sema.zirVarExtended`. | ||
| 1441 | 1464 | ||
| 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 | } | ||
| 1463 | 1469 | ||
| 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 | }); |
| 1470 | 1474 | ||
| 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: { |
| 1473 | 1477 | 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 | } | ||
| 1480 | 1479 | ||
| 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 | } | ||
| 1482 | 1492 | ||
| 1483 | queue_codegen: { | 1493 | fn 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(); | ||
| 1485 | 1496 | ||
| 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); |
| 1490 | 1501 | ||
| 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); | ||
| 1494 | 1506 | ||
| 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) or | 1516 | switch (zcu.comp.cache_use) { |
| 1505 | new.alignment != old.alignment or | 1517 | .whole => |whole| if (whole.cache_manifest) |man| { |
| 1506 | new.@"linksection" != old.@"linksection" or | 1518 | 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 | } |
| 1512 | 1546 | ||
| ... | @@ -1880,45 +1914,42 @@ pub fn scanNamespace( | ... | @@ -1880,45 +1914,42 @@ pub fn scanNamespace( |
| 1880 | 1914 | ||
| 1881 | // For incremental updates, `scanDecl` wants to look up existing decls by their ZIR index rather | 1915 | // 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); |
| 1886 | 1920 | ||
| 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 | )); |
| 1892 | 1927 | ||
| 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 on | 1948 | 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 | } |
| 1923 | 1954 | ||
| 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(); | ||
| 1932 | 1964 | ||
| 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 generated | 1986 | /// 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 { |
| 1988 | 2020 | ||
| 1989 | const decl = zir.getDeclaration(decl_inst); | 2021 | const decl = zir.getDeclaration(decl_inst); |
| 1990 | 2022 | ||
| 1991 | const Kind = enum { @"comptime", @"usingnamespace", @"test", named }; | 2023 | const maybe_name: InternPool.OptionalNullTerminatedString = switch (decl.kind) { |
| 1992 | 2024 | .@"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 | }; |
| 2048 | 2058 | ||
| ... | @@ -2051,46 +2061,44 @@ const ScanDeclIter = struct { | ... | @@ -2051,46 +2061,44 @@ const ScanDeclIter = struct { |
| 2051 | .inst = decl_inst, | 2061 | .inst = decl_inst, |
| 2052 | }); | 2062 | }); |
| 2053 | 2063 | ||
| 2054 | const existing_cau = iter.existing_by_inst.get(tracked_inst); | 2064 | const existing_unit = iter.existing_by_inst.get(tracked_inst); |
| 2055 | 2065 | ||
| 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); | ||
| 2059 | 2072 | ||
| 2060 | try namespace.other_decls.append(gpa, cau); | 2073 | const unit: AnalUnit = .wrap(.{ .@"comptime" = cu }); |
| 2061 | 2074 | ||
| 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 the | 2076 | |
| 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 deps | 2083 | 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 | } |
| 2080 | 2085 | ||
| 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 filter | 2118 | // * remove from `test_functions` if no longer matching filter |
| 2110 | // * add to `test_functions` if newly passing filter | 2119 | // * 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 | }; |
| 2136 | 2145 | ||
| 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 | } |
| 2144 | 2153 | ||
| 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 | }; |
| 2148 | 2157 | ||
| 2149 | fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air { | 2158 | fn 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(); |
| 2152 | 2161 | ||
| ... | @@ -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 | } |
| 2170 | 2179 | ||
| 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_nav | 2183 | else |
| 2175 | else | 2184 | 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 | }); | ||
| 2180 | 2185 | ||
| 2181 | const func_nav = ip.getNav(func.owner_nav); | 2186 | const func_nav = ip.getNav(func.owner_nav); |
| 2182 | 2187 | ||
| 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); |
| 2187 | 2189 | ||
| 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! |
| 2216 | 2218 | ||
| 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 }); |
| 2221 | 2223 | ||
| 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'll | 2624 | // 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) or | 2627 | 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 }) orelse | 3256 | 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`. | 3310 | pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError!InternPool.Index { |
| 3311 | pub 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 | } |
| 3367 | 3344 | ||
| 3368 | fn recreateStructType( | 3345 | fn 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( |
| 3405 | 3382 | ||
| 3406 | if (captures_len != key.captures.owned.len) return error.AnalysisFail; | 3383 | if (captures_len != key.captures.owned.len) return error.AnalysisFail; |
| 3407 | 3384 | ||
| 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 })); | ||
| 3410 | 3386 | ||
| 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); |
| 3429 | 3405 | ||
| 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 }); |
| 3440 | 3415 | ||
| 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( |
| 3448 | 3423 | ||
| 3449 | fn recreateUnionType( | 3424 | fn 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( |
| 3488 | 3463 | ||
| 3489 | if (captures_len != key.captures.owned.len) return error.AnalysisFail; | 3464 | if (captures_len != key.captures.owned.len) return error.AnalysisFail; |
| 3490 | 3465 | ||
| 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 })); | ||
| 3493 | 3467 | ||
| 3494 | const namespace_index = union_obj.namespace; | 3468 | const namespace_index = union_obj.namespace; |
| 3495 | 3469 | ||
| ... | @@ -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); |
| 3527 | 3501 | ||
| 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 | } |
| 3540 | 3513 | ||
| 3541 | fn recreateEnumType( | 3514 | fn 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; |
| 3612 | 3585 | ||
| 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().? })); | ||
| 3615 | 3587 | ||
| 3616 | const namespace_index = enum_obj.namespace; | 3588 | const namespace_index = enum_obj.namespace; |
| 3617 | 3589 | ||
| ... | @@ -3637,12 +3609,10 @@ fn recreateEnumType( | ... | @@ -3637,12 +3609,10 @@ fn recreateEnumType( |
| 3637 | 3609 | ||
| 3638 | wip_ty.setName(ip, enum_obj.name); | 3610 | wip_ty.setName(ip, enum_obj.name); |
| 3639 | 3611 | ||
| 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. |
| 3644 | 3614 | ||
| 3645 | wip_ty.prepare(ip, new_cau_index, namespace_index); | 3615 | wip_ty.prepare(ip, namespace_index); |
| 3646 | done = true; | 3616 | done = true; |
| 3647 | 3617 | ||
| 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); |
| 2263 | 2263 | ||
| 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); |
| 2294 | 2294 | ||
| 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); |
| 2323 | 2323 | ||
| 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 | } |
| 2565 | 2565 | ||
| 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, |