@@ -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.
5151namespace_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+
437458pub 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
774796pub 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