Skip to content

Commit 136c5a9

Browse files
authored
Merge pull request #22403 from mlugg/incremental
incremental: fixes
2 parents ff4f275 + 6cc848e commit 136c5a9

File tree

9 files changed

+839
-319
lines changed

9 files changed

+839
-319
lines changed

lib/std/zig/Zir.zig

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5066,3 +5066,35 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void {
50665066
else => unreachable, // assertion failure; not trackable
50675067
}
50685068
}
5069+
5070+
pub fn typeCapturesLen(zir: Zir, type_decl: Inst.Index) u32 {
5071+
const inst = zir.instructions.get(@intFromEnum(type_decl));
5072+
assert(inst.tag == .extended);
5073+
switch (inst.data.extended.opcode) {
5074+
.struct_decl => {
5075+
const small: Inst.StructDecl.Small = @bitCast(inst.data.extended.small);
5076+
if (!small.has_captures_len) return 0;
5077+
const extra = zir.extraData(Inst.StructDecl, inst.data.extended.operand);
5078+
return zir.extra[extra.end];
5079+
},
5080+
.union_decl => {
5081+
const small: Inst.UnionDecl.Small = @bitCast(inst.data.extended.small);
5082+
if (!small.has_captures_len) return 0;
5083+
const extra = zir.extraData(Inst.UnionDecl, inst.data.extended.operand);
5084+
return zir.extra[extra.end + @intFromBool(small.has_tag_type)];
5085+
},
5086+
.enum_decl => {
5087+
const small: Inst.EnumDecl.Small = @bitCast(inst.data.extended.small);
5088+
if (!small.has_captures_len) return 0;
5089+
const extra = zir.extraData(Inst.EnumDecl, inst.data.extended.operand);
5090+
return zir.extra[extra.end + @intFromBool(small.has_tag_type)];
5091+
},
5092+
.opaque_decl => {
5093+
const small: Inst.OpaqueDecl.Small = @bitCast(inst.data.extended.small);
5094+
if (!small.has_captures_len) return 0;
5095+
const extra = zir.extraData(Inst.OpaqueDecl, inst.data.extended.operand);
5096+
return zir.extra[extra.end];
5097+
},
5098+
else => unreachable,
5099+
}
5100+
}

src/Compilation.zig

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3158,16 +3158,19 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
31583158
if (!refs.contains(anal_unit)) continue;
31593159
}
31603160

3161-
const file_index = switch (anal_unit.unwrap()) {
3162-
.@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index.resolveFile(ip),
3163-
.nav_val, .nav_ty => |nav| ip.getNav(nav).analysis.?.zir_index.resolveFile(ip),
3164-
.type => |ty| Type.fromInterned(ty).typeDeclInst(zcu).?.resolveFile(ip),
3165-
.func => |ip_index| zcu.funcInfo(ip_index).zir_body_inst.resolveFile(ip),
3166-
};
3161+
report_ok: {
3162+
const file_index = switch (anal_unit.unwrap()) {
3163+
.@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index.resolveFile(ip),
3164+
.nav_val, .nav_ty => |nav| ip.getNav(nav).analysis.?.zir_index.resolveFile(ip),
3165+
.type => |ty| Type.fromInterned(ty).typeDeclInst(zcu).?.resolveFile(ip),
3166+
.func => |ip_index| zcu.funcInfo(ip_index).zir_body_inst.resolveFile(ip),
3167+
.memoized_state => break :report_ok, // always report std.builtin errors
3168+
};
31673169

3168-
// Skip errors for AnalUnits within files that had a parse failure.
3169-
// We'll try again once parsing succeeds.
3170-
if (!zcu.fileByIndex(file_index).okToReportErrors()) continue;
3170+
// Skip errors for AnalUnits within files that had a parse failure.
3171+
// We'll try again once parsing succeeds.
3172+
if (!zcu.fileByIndex(file_index).okToReportErrors()) continue;
3173+
}
31713174

31723175
std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{
31733176
error_msg.msg,
@@ -3391,7 +3394,7 @@ pub fn addModuleErrorMsg(
33913394
const ref = maybe_ref orelse break;
33923395
const gop = try seen.getOrPut(gpa, ref.referencer);
33933396
if (gop.found_existing) break;
3394-
if (ref_traces.items.len < max_references) {
3397+
if (ref_traces.items.len < max_references) skip: {
33953398
const src = ref.src.upgrade(zcu);
33963399
const source = try src.file_scope.getSource(gpa);
33973400
const span = try src.span(gpa);
@@ -3403,6 +3406,7 @@ pub fn addModuleErrorMsg(
34033406
.nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip),
34043407
.type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
34053408
.func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
3409+
.memoized_state => break :skip,
34063410
};
34073411
try ref_traces.append(gpa, .{
34083412
.decl_name = try eb.addString(name),
@@ -3670,6 +3674,7 @@ fn performAllTheWorkInner(
36703674
if (try zcu.findOutdatedToAnalyze()) |outdated| {
36713675
try comp.queueJob(switch (outdated.unwrap()) {
36723676
.func => |f| .{ .analyze_func = f },
3677+
.memoized_state,
36733678
.@"comptime",
36743679
.nav_ty,
36753680
.nav_val,
@@ -3737,6 +3742,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
37373742
.nav_ty => |nav| pt.ensureNavTypeUpToDate(nav),
37383743
.nav_val => |nav| pt.ensureNavValUpToDate(nav),
37393744
.type => |ty| if (pt.ensureTypeUpToDate(ty)) |_| {} else |err| err,
3745+
.memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage),
37403746
.func => unreachable,
37413747
};
37423748
maybe_err catch |err| switch (err) {

src/InternPool.zig

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ namespace_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index)
4949
/// Dependencies on the (non-)existence of some name in a namespace.
5050
/// Value is index into `dep_entries` of the first dependency on this name.
5151
namespace_name_deps: std.AutoArrayHashMapUnmanaged(NamespaceNameKey, DepEntry.Index),
52+
// Dependencies on the value of fields memoized on `Zcu` (`panic_messages` etc).
53+
// If set, these are indices into `dep_entries` of the first dependency on this state.
54+
memoized_state_main_deps: DepEntry.Index.Optional,
55+
memoized_state_panic_deps: DepEntry.Index.Optional,
56+
memoized_state_va_list_deps: DepEntry.Index.Optional,
5257

5358
/// Given a `Depender`, points to an entry in `dep_entries` whose `depender`
5459
/// matches. The `next_dependee` field can be used to iterate all such entries
@@ -87,6 +92,9 @@ pub const empty: InternPool = .{
8792
.interned_deps = .empty,
8893
.namespace_deps = .empty,
8994
.namespace_name_deps = .empty,
95+
.memoized_state_main_deps = .none,
96+
.memoized_state_panic_deps = .none,
97+
.memoized_state_va_list_deps = .none,
9098
.first_dependency = .empty,
9199
.dep_entries = .empty,
92100
.free_dep_entries = .empty,
@@ -385,6 +393,7 @@ pub const AnalUnit = packed struct(u64) {
385393
nav_ty,
386394
type,
387395
func,
396+
memoized_state,
388397
};
389398

390399
pub const Unwrapped = union(Kind) {
@@ -399,6 +408,8 @@ pub const AnalUnit = packed struct(u64) {
399408
type: InternPool.Index,
400409
/// This `AnalUnit` analyzes the body of the given runtime function.
401410
func: InternPool.Index,
411+
/// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`.
412+
memoized_state: MemoizedStateStage,
402413
};
403414

404415
pub fn unwrap(au: AnalUnit) Unwrapped {
@@ -434,6 +445,16 @@ pub const AnalUnit = packed struct(u64) {
434445
};
435446
};
436447

448+
pub const MemoizedStateStage = enum(u32) {
449+
/// Everything other than panics and `VaList`.
450+
main,
451+
/// Everything within `std.builtin.Panic`.
452+
/// Since the panic handler is user-provided, this must be able to reference the other memoized state.
453+
panic,
454+
/// Specifically `std.builtin.VaList`. See `Zcu.BuiltinDecl.stage`.
455+
va_list,
456+
};
457+
437458
pub const ComptimeUnit = extern struct {
438459
zir_index: TrackedInst.Index,
439460
namespace: NamespaceIndex,
@@ -769,6 +790,7 @@ pub const Dependee = union(enum) {
769790
interned: Index,
770791
namespace: TrackedInst.Index,
771792
namespace_name: NamespaceNameKey,
793+
memoized_state: MemoizedStateStage,
772794
};
773795

774796
pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender: AnalUnit) void {
@@ -819,6 +841,11 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI
819841
.interned => |x| ip.interned_deps.get(x),
820842
.namespace => |x| ip.namespace_deps.get(x),
821843
.namespace_name => |x| ip.namespace_name_deps.get(x),
844+
.memoized_state => |stage| switch (stage) {
845+
.main => ip.memoized_state_main_deps.unwrap(),
846+
.panic => ip.memoized_state_panic_deps.unwrap(),
847+
.va_list => ip.memoized_state_va_list_deps.unwrap(),
848+
},
822849
} orelse return .{
823850
.ip = ip,
824851
.next_entry = .none,
@@ -848,6 +875,33 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend
848875
// This block should allocate an entry and prepend it to the relevant `*_deps` list.
849876
// The `next` field should be correctly initialized; all other fields may be undefined.
850877
const new_index: DepEntry.Index = switch (dependee) {
878+
.memoized_state => |stage| new_index: {
879+
const deps = switch (stage) {
880+
.main => &ip.memoized_state_main_deps,
881+
.panic => &ip.memoized_state_panic_deps,
882+
.va_list => &ip.memoized_state_va_list_deps,
883+
};
884+
885+
if (deps.unwrap()) |first| {
886+
if (ip.dep_entries.items[@intFromEnum(first)].depender == .none) {
887+
// Dummy entry, so we can reuse it rather than allocating a new one!
888+
break :new_index first;
889+
}
890+
}
891+
892+
// Prepend a new dependency.
893+
const new_index: DepEntry.Index, const ptr = if (ip.free_dep_entries.popOrNull()) |new_index| new: {
894+
break :new .{ new_index, &ip.dep_entries.items[@intFromEnum(new_index)] };
895+
} else .{ @enumFromInt(ip.dep_entries.items.len), ip.dep_entries.addOneAssumeCapacity() };
896+
if (deps.unwrap()) |old_first| {
897+
ptr.next = old_first.toOptional();
898+
ip.dep_entries.items[@intFromEnum(old_first)].prev = new_index.toOptional();
899+
} else {
900+
ptr.next = .none;
901+
}
902+
deps.* = new_index.toOptional();
903+
break :new_index new_index;
904+
},
851905
inline else => |dependee_payload, tag| new_index: {
852906
const gop = try switch (tag) {
853907
.file => ip.file_deps,
@@ -857,6 +911,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend
857911
.interned => ip.interned_deps,
858912
.namespace => ip.namespace_deps,
859913
.namespace_name => ip.namespace_name_deps,
914+
.memoized_state => comptime unreachable,
860915
}.getOrPut(gpa, dependee_payload);
861916

862917
if (gop.found_existing and ip.dep_entries.items[@intFromEnum(gop.value_ptr.*)].depender == .none) {
@@ -2029,15 +2084,7 @@ pub const Key = union(enum) {
20292084
pub const NamespaceType = union(enum) {
20302085
/// This type corresponds to an actual source declaration, e.g. `struct { ... }`.
20312086
/// It is hashed based on its ZIR instruction index and set of captures.
2032-
declared: struct {
2033-
/// A `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl` instruction.
2034-
zir_index: TrackedInst.Index,
2035-
/// The captured values of this type. These values must be fully resolved per the language spec.
2036-
captures: union(enum) {
2037-
owned: CaptureValue.Slice,
2038-
external: []const CaptureValue,
2039-
},
2040-
},
2087+
declared: Declared,
20412088
/// This type is an automatically-generated enum tag type for a union.
20422089
/// It is hashed based on the index of the union type it corresponds to.
20432090
generated_tag: struct {
@@ -2053,6 +2100,16 @@ pub const Key = union(enum) {
20532100
/// A hash of this type's attributes, fields, etc, generated by Sema.
20542101
type_hash: u64,
20552102
},
2103+
2104+
pub const Declared = struct {
2105+
/// A `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl` instruction.
2106+
zir_index: TrackedInst.Index,
2107+
/// The captured values of this type. These values must be fully resolved per the language spec.
2108+
captures: union(enum) {
2109+
owned: CaptureValue.Slice,
2110+
external: []const CaptureValue,
2111+
},
2112+
};
20562113
};
20572114

20582115
pub const FuncType = struct {

0 commit comments

Comments
 (0)