diff options
Diffstat (limited to 'src/InternPool.zig')
| -rw-r--r-- | src/InternPool.zig | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig index c0b4d2f446..c34e21a4d3 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -49,6 +49,11 @@ namespace_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index) /// Dependencies on the (non-)existence of some name in a namespace. /// Value is index into `dep_entries` of the first dependency on this name. namespace_name_deps: std.AutoArrayHashMapUnmanaged(NamespaceNameKey, DepEntry.Index), +// Dependencies on the value of fields memoized on `Zcu` (`panic_messages` etc). +// If set, these are indices into `dep_entries` of the first dependency on this state. +memoized_state_main_deps: DepEntry.Index.Optional, +memoized_state_panic_deps: DepEntry.Index.Optional, +memoized_state_va_list_deps: DepEntry.Index.Optional, /// Given a `Depender`, points to an entry in `dep_entries` whose `depender` /// matches. The `next_dependee` field can be used to iterate all such entries @@ -87,6 +92,9 @@ pub const empty: InternPool = .{ .interned_deps = .empty, .namespace_deps = .empty, .namespace_name_deps = .empty, + .memoized_state_main_deps = .none, + .memoized_state_panic_deps = .none, + .memoized_state_va_list_deps = .none, .first_dependency = .empty, .dep_entries = .empty, .free_dep_entries = .empty, @@ -385,6 +393,7 @@ pub const AnalUnit = packed struct(u64) { nav_ty, type, func, + memoized_state, }; pub const Unwrapped = union(Kind) { @@ -399,6 +408,8 @@ pub const AnalUnit = packed struct(u64) { type: InternPool.Index, /// This `AnalUnit` analyzes the body of the given runtime function. func: InternPool.Index, + /// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`. + memoized_state: MemoizedStateStage, }; pub fn unwrap(au: AnalUnit) Unwrapped { @@ -434,6 +445,16 @@ pub const AnalUnit = packed struct(u64) { }; }; +pub const MemoizedStateStage = enum(u32) { + /// Everything other than panics and `VaList`. + main, + /// Everything within `std.builtin.Panic`. + /// Since the panic handler is user-provided, this must be able to reference the other memoized state. + panic, + /// Specifically `std.builtin.VaList`. See `Zcu.BuiltinDecl.stage`. + va_list, +}; + pub const ComptimeUnit = extern struct { zir_index: TrackedInst.Index, namespace: NamespaceIndex, @@ -769,6 +790,7 @@ pub const Dependee = union(enum) { interned: Index, namespace: TrackedInst.Index, namespace_name: NamespaceNameKey, + memoized_state: MemoizedStateStage, }; pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender: AnalUnit) void { @@ -819,6 +841,11 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI .interned => |x| ip.interned_deps.get(x), .namespace => |x| ip.namespace_deps.get(x), .namespace_name => |x| ip.namespace_name_deps.get(x), + .memoized_state => |stage| switch (stage) { + .main => ip.memoized_state_main_deps.unwrap(), + .panic => ip.memoized_state_panic_deps.unwrap(), + .va_list => ip.memoized_state_va_list_deps.unwrap(), + }, } orelse return .{ .ip = ip, .next_entry = .none, @@ -848,6 +875,33 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend // This block should allocate an entry and prepend it to the relevant `*_deps` list. // The `next` field should be correctly initialized; all other fields may be undefined. const new_index: DepEntry.Index = switch (dependee) { + .memoized_state => |stage| new_index: { + const deps = switch (stage) { + .main => &ip.memoized_state_main_deps, + .panic => &ip.memoized_state_panic_deps, + .va_list => &ip.memoized_state_va_list_deps, + }; + + if (deps.unwrap()) |first| { + if (ip.dep_entries.items[@intFromEnum(first)].depender == .none) { + // Dummy entry, so we can reuse it rather than allocating a new one! + break :new_index first; + } + } + + // Prepend a new dependency. + const new_index: DepEntry.Index, const ptr = if (ip.free_dep_entries.popOrNull()) |new_index| new: { + break :new .{ new_index, &ip.dep_entries.items[@intFromEnum(new_index)] }; + } else .{ @enumFromInt(ip.dep_entries.items.len), ip.dep_entries.addOneAssumeCapacity() }; + if (deps.unwrap()) |old_first| { + ptr.next = old_first.toOptional(); + ip.dep_entries.items[@intFromEnum(old_first)].prev = new_index.toOptional(); + } else { + ptr.next = .none; + } + deps.* = new_index.toOptional(); + break :new_index new_index; + }, inline else => |dependee_payload, tag| new_index: { const gop = try switch (tag) { .file => ip.file_deps, @@ -857,6 +911,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend .interned => ip.interned_deps, .namespace => ip.namespace_deps, .namespace_name => ip.namespace_name_deps, + .memoized_state => comptime unreachable, }.getOrPut(gpa, dependee_payload); if (gop.found_existing and ip.dep_entries.items[@intFromEnum(gop.value_ptr.*)].depender == .none) { |
