authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-28 02:41:22-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:56-07:00
log3b6ca1d35b950d67fff5964f0063dadf01f30e2d
tree953815632535b965c7d32318ca515d8926cf4c4b
parentd40b83de45db27c8c3e7a1f2ccf892563df43637

Module: move memoized data to the intern pool

This avoids memory management bugs with the previous implementation.

11 files changed, 264 insertions(+), 140 deletions(-)

src/InternPool.zig+106-3
...@@ -217,6 +217,11 @@ pub const Key = union(enum) {...@@ -217,6 +217,11 @@ pub const Key = union(enum) {
217 /// An instance of a union.217 /// An instance of a union.
218 un: Union,218 un: Union,
219219
220 /// A declaration with a memoized value.
221 memoized_decl: MemoizedDecl,
222 /// A comptime function call with a memoized result.
223 memoized_call: Key.MemoizedCall,
224
220 pub const IntType = std.builtin.Type.Int;225 pub const IntType = std.builtin.Type.Int;
221226
222 pub const ErrorUnionType = struct {227 pub const ErrorUnionType = struct {
...@@ -609,6 +614,17 @@ pub const Key = union(enum) {...@@ -609,6 +614,17 @@ pub const Key = union(enum) {
609 };614 };
610 };615 };
611616
617 pub const MemoizedDecl = struct {
618 val: Index,
619 decl: Module.Decl.Index,
620 };
621
622 pub const MemoizedCall = struct {
623 func: Module.Fn.Index,
624 arg_values: []const Index,
625 result: Index,
626 };
627
612 pub fn hash32(key: Key, ip: *const InternPool) u32 {628 pub fn hash32(key: Key, ip: *const InternPool) u32 {
613 return @truncate(u32, key.hash64(ip));629 return @truncate(u32, key.hash64(ip));
614 }630 }
...@@ -786,6 +802,13 @@ pub const Key = union(enum) {...@@ -786,6 +802,13 @@ pub const Key = union(enum) {
786 std.hash.autoHash(hasher, func_type.is_generic);802 std.hash.autoHash(hasher, func_type.is_generic);
787 std.hash.autoHash(hasher, func_type.is_noinline);803 std.hash.autoHash(hasher, func_type.is_noinline);
788 },804 },
805
806 .memoized_decl => |memoized_decl| std.hash.autoHash(hasher, memoized_decl.val),
807
808 .memoized_call => |memoized_call| {
809 std.hash.autoHash(hasher, memoized_call.func);
810 for (memoized_call.arg_values) |arg| std.hash.autoHash(hasher, arg);
811 },
789 }812 }
790 }813 }
791814
...@@ -1054,6 +1077,17 @@ pub const Key = union(enum) {...@@ -1054,6 +1077,17 @@ pub const Key = union(enum) {
1054 a_info.is_generic == b_info.is_generic and1077 a_info.is_generic == b_info.is_generic and
1055 a_info.is_noinline == b_info.is_noinline;1078 a_info.is_noinline == b_info.is_noinline;
1056 },1079 },
1080
1081 .memoized_decl => |a_info| {
1082 const b_info = b.memoized_decl;
1083 return a_info.val == b_info.val;
1084 },
1085
1086 .memoized_call => |a_info| {
1087 const b_info = b.memoized_call;
1088 return a_info.func == b_info.func and
1089 std.mem.eql(Index, a_info.arg_values, b_info.arg_values);
1090 },
1057 }1091 }
1058 }1092 }
10591093
...@@ -1105,6 +1139,10 @@ pub const Key = union(enum) {...@@ -1105,6 +1139,10 @@ pub const Key = union(enum) {
1105 .@"unreachable" => .noreturn_type,1139 .@"unreachable" => .noreturn_type,
1106 .generic_poison => .generic_poison_type,1140 .generic_poison => .generic_poison_type,
1107 },1141 },
1142
1143 .memoized_decl,
1144 .memoized_call,
1145 => unreachable,
1108 };1146 };
1109 }1147 }
1110};1148};
...@@ -1380,6 +1418,14 @@ pub const Index = enum(u32) {...@@ -1380,6 +1418,14 @@ pub const Index = enum(u32) {
1380 bytes: struct { data: *Bytes },1418 bytes: struct { data: *Bytes },
1381 aggregate: struct { data: *Aggregate },1419 aggregate: struct { data: *Aggregate },
1382 repeated: struct { data: *Repeated },1420 repeated: struct { data: *Repeated },
1421
1422 memoized_decl: struct { data: *Key.MemoizedDecl },
1423 memoized_call: struct {
1424 const @"data.args_len" = opaque {};
1425 data: *MemoizedCall,
1426 @"trailing.arg_values.len": *@"data.args_len",
1427 trailing: struct { arg_values: []Index },
1428 },
1383 }) void {1429 }) void {
1384 _ = self;1430 _ = self;
1385 const map_fields = @typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).Pointer.child).Struct.fields;1431 const map_fields = @typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).Pointer.child).Struct.fields;
...@@ -1875,6 +1921,13 @@ pub const Tag = enum(u8) {...@@ -1875,6 +1921,13 @@ pub const Tag = enum(u8) {
1875 /// An instance of an array or vector with every element being the same value.1921 /// An instance of an array or vector with every element being the same value.
1876 /// data is extra index to `Repeated`.1922 /// data is extra index to `Repeated`.
1877 repeated,1923 repeated,
1924
1925 /// A memoized declaration value.
1926 /// data is extra index to `Key.MemoizedDecl`
1927 memoized_decl,
1928 /// A memoized comptime function call result.
1929 /// data is extra index to `MemoizedFunc`
1930 memoized_call,
1878};1931};
18791932
1880/// Trailing:1933/// Trailing:
...@@ -2271,6 +2324,14 @@ pub const Float128 = struct {...@@ -2271,6 +2324,14 @@ pub const Float128 = struct {
2271 }2324 }
2272};2325};
22732326
2327/// Trailing:
2328/// 0. arg value: Index for each args_len
2329pub const MemoizedCall = struct {
2330 func: Module.Fn.Index,
2331 args_len: u32,
2332 result: Index,
2333};
2334
2274pub fn init(ip: *InternPool, gpa: Allocator) !void {2335pub fn init(ip: *InternPool, gpa: Allocator) !void {
2275 assert(ip.items.len == 0);2336 assert(ip.items.len == 0);
22762337
...@@ -2758,6 +2819,16 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2758,6 +2819,16 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2758 },2819 },
2759 .enum_literal => .{ .enum_literal = @intToEnum(NullTerminatedString, data) },2820 .enum_literal => .{ .enum_literal = @intToEnum(NullTerminatedString, data) },
2760 .enum_tag => .{ .enum_tag = ip.extraData(Key.EnumTag, data) },2821 .enum_tag => .{ .enum_tag = ip.extraData(Key.EnumTag, data) },
2822
2823 .memoized_decl => .{ .memoized_decl = ip.extraData(Key.MemoizedDecl, data) },
2824 .memoized_call => {
2825 const extra = ip.extraDataTrail(MemoizedCall, data);
2826 return .{ .memoized_call = .{
2827 .func = extra.data.func,
2828 .arg_values = @ptrCast([]const Index, ip.extra.items[extra.end..][0..extra.data.args_len]),
2829 .result = extra.data.result,
2830 } };
2831 },
2761 };2832 };
2762}2833}
27632834
...@@ -3724,6 +3795,29 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3724,6 +3795,29 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3724 .data = try ip.addExtra(gpa, un),3795 .data = try ip.addExtra(gpa, un),
3725 });3796 });
3726 },3797 },
3798
3799 .memoized_decl => |memoized_decl| {
3800 assert(memoized_decl.val != .none);
3801 ip.items.appendAssumeCapacity(.{
3802 .tag = .memoized_decl,
3803 .data = try ip.addExtra(gpa, memoized_decl),
3804 });
3805 },
3806
3807 .memoized_call => |memoized_call| {
3808 for (memoized_call.arg_values) |arg| assert(arg != .none);
3809 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(MemoizedCall).Struct.fields.len +
3810 memoized_call.arg_values.len);
3811 ip.items.appendAssumeCapacity(.{
3812 .tag = .memoized_call,
3813 .data = ip.addExtraAssumeCapacity(MemoizedCall{
3814 .func = memoized_call.func,
3815 .args_len = @intCast(u32, memoized_call.arg_values.len),
3816 .result = memoized_call.result,
3817 }),
3818 });
3819 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, memoized_call.arg_values));
3820 },
3727 }3821 }
3728 return @intToEnum(Index, ip.items.len - 1);3822 return @intToEnum(Index, ip.items.len - 1);
3729}3823}
...@@ -3788,7 +3882,7 @@ pub fn getIncompleteEnum(...@@ -3788,7 +3882,7 @@ pub fn getIncompleteEnum(
3788 ip: *InternPool,3882 ip: *InternPool,
3789 gpa: Allocator,3883 gpa: Allocator,
3790 enum_type: Key.IncompleteEnumType,3884 enum_type: Key.IncompleteEnumType,
3791) Allocator.Error!InternPool.IncompleteEnumType {3885) Allocator.Error!IncompleteEnumType {
3792 switch (enum_type.tag_mode) {3886 switch (enum_type.tag_mode) {
3793 .auto => return getIncompleteEnumAuto(ip, gpa, enum_type),3887 .auto => return getIncompleteEnumAuto(ip, gpa, enum_type),
3794 .explicit => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_explicit),3888 .explicit => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_explicit),
...@@ -3800,7 +3894,7 @@ pub fn getIncompleteEnumAuto(...@@ -3800,7 +3894,7 @@ pub fn getIncompleteEnumAuto(
3800 ip: *InternPool,3894 ip: *InternPool,
3801 gpa: Allocator,3895 gpa: Allocator,
3802 enum_type: Key.IncompleteEnumType,3896 enum_type: Key.IncompleteEnumType,
3803) Allocator.Error!InternPool.IncompleteEnumType {3897) Allocator.Error!IncompleteEnumType {
3804 // Although the integer tag type will not be stored in the `EnumAuto` struct,3898 // Although the integer tag type will not be stored in the `EnumAuto` struct,
3805 // `InternPool` logic depends on it being present so that `typeOf` can be infallible.3899 // `InternPool` logic depends on it being present so that `typeOf` can be infallible.
3806 // Ensure it is present here:3900 // Ensure it is present here:
...@@ -3849,7 +3943,7 @@ fn getIncompleteEnumExplicit(...@@ -3849,7 +3943,7 @@ fn getIncompleteEnumExplicit(
3849 gpa: Allocator,3943 gpa: Allocator,
3850 enum_type: Key.IncompleteEnumType,3944 enum_type: Key.IncompleteEnumType,
3851 tag: Tag,3945 tag: Tag,
3852) Allocator.Error!InternPool.IncompleteEnumType {3946) Allocator.Error!IncompleteEnumType {
3853 // We must keep the map in sync with `items`. The hash and equality functions3947 // We must keep the map in sync with `items`. The hash and equality functions
3854 // for enum types only look at the decl field, which is present even in3948 // for enum types only look at the decl field, which is present even in
3855 // an `IncompleteEnumType`.3949 // an `IncompleteEnumType`.
...@@ -4704,6 +4798,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -4704,6 +4798,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
4704 .func => @sizeOf(Key.Func) + @sizeOf(Module.Fn) + @sizeOf(Module.Decl),4798 .func => @sizeOf(Key.Func) + @sizeOf(Module.Fn) + @sizeOf(Module.Decl),
4705 .only_possible_value => 0,4799 .only_possible_value => 0,
4706 .union_value => @sizeOf(Key.Union),4800 .union_value => @sizeOf(Key.Union),
4801
4802 .memoized_decl => @sizeOf(Key.MemoizedDecl),
4803 .memoized_call => b: {
4804 const info = ip.extraData(MemoizedCall, data);
4805 break :b @sizeOf(MemoizedCall) + (@sizeOf(Index) * info.args_len);
4806 },
4707 });4807 });
4708 }4808 }
4709 const SortContext = struct {4809 const SortContext = struct {
...@@ -5215,6 +5315,9 @@ pub fn zigTypeTagOrPoison(ip: InternPool, index: Index) error{GenericPoison}!std...@@ -5215,6 +5315,9 @@ pub fn zigTypeTagOrPoison(ip: InternPool, index: Index) error{GenericPoison}!std
5215 .bytes,5315 .bytes,
5216 .aggregate,5316 .aggregate,
5217 .repeated,5317 .repeated,
5318 // memoization, not types
5319 .memoized_decl,
5320 .memoized_call,
5218 => unreachable,5321 => unreachable,
5219 },5322 },
5220 .none => unreachable, // special tag5323 .none => unreachable, // special tag
src/Module.zig+12-58
...@@ -88,18 +88,10 @@ embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{},...@@ -88,18 +88,10 @@ embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{},
88/// Stores all Type and Value objects; periodically garbage collected.88/// Stores all Type and Value objects; periodically garbage collected.
89intern_pool: InternPool = .{},89intern_pool: InternPool = .{},
9090
91/// This is currently only used for string literals, however the end-game once the lang spec
92/// is settled will be to make this behavior consistent across all types.
93memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{},
94
95/// The set of all the generic function instantiations. This is used so that when a generic91/// The set of all the generic function instantiations. This is used so that when a generic
96/// function is called twice with the same comptime parameter arguments, both calls dispatch92/// function is called twice with the same comptime parameter arguments, both calls dispatch
97/// to the same function.93/// to the same function.
98monomorphed_funcs: MonomorphedFuncsSet = .{},94monomorphed_funcs: MonomorphedFuncsSet = .{},
99/// The set of all comptime function calls that have been cached so that future calls
100/// with the same parameters will get the same return value.
101memoized_calls: MemoizedCallSet = .{},
102memoized_call_args: MemoizedCall.Args = .{},
103/// Contains the values from `@setAlignStack`. A sparse table is used here95/// Contains the values from `@setAlignStack`. A sparse table is used here
104/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while96/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while
105/// functions are many.97/// functions are many.
...@@ -223,42 +215,6 @@ const MonomorphedFuncsContext = struct {...@@ -223,42 +215,6 @@ const MonomorphedFuncsContext = struct {
223 }215 }
224};216};
225217
226pub const MemoizedCallSet = std.HashMapUnmanaged(
227 MemoizedCall.Key,
228 MemoizedCall.Result,
229 MemoizedCall,
230 std.hash_map.default_max_load_percentage,
231);
232
233pub const MemoizedCall = struct {
234 args: *const Args,
235
236 pub const Args = std.ArrayListUnmanaged(InternPool.Index);
237
238 pub const Key = struct {
239 func: Fn.Index,
240 args_index: u32,
241 args_count: u32,
242
243 pub fn args(key: Key, ctx: MemoizedCall) []InternPool.Index {
244 return ctx.args.items[key.args_index..][0..key.args_count];
245 }
246 };
247
248 pub const Result = InternPool.Index;
249
250 pub fn eql(ctx: MemoizedCall, a: Key, b: Key) bool {
251 return a.func == b.func and mem.eql(InternPool.Index, a.args(ctx), b.args(ctx));
252 }
253
254 pub fn hash(ctx: MemoizedCall, key: Key) u64 {
255 var hasher = std.hash.Wyhash.init(0);
256 std.hash.autoHash(&hasher, key.func);
257 std.hash.autoHashStrat(&hasher, key.args(ctx), .Deep);
258 return hasher.final();
259 }
260};
261
262pub const SetAlignStack = struct {218pub const SetAlignStack = struct {
263 alignment: u32,219 alignment: u32,
264 /// TODO: This needs to store a non-lazy source location for the case of an inline function220 /// TODO: This needs to store a non-lazy source location for the case of an inline function
...@@ -605,7 +561,6 @@ pub const Decl = struct {...@@ -605,7 +561,6 @@ pub const Decl = struct {
605 }561 }
606 mod.destroyFunc(func);562 mod.destroyFunc(func);
607 }563 }
608 _ = mod.memoized_decls.remove(decl.val.ip_index);
609 if (decl.value_arena) |value_arena| {564 if (decl.value_arena) |value_arena| {
610 value_arena.deinit(gpa);565 value_arena.deinit(gpa);
611 decl.value_arena = null;566 decl.value_arena = null;
...@@ -3314,8 +3269,6 @@ pub fn deinit(mod: *Module) void {...@@ -3314,8 +3269,6 @@ pub fn deinit(mod: *Module) void {
3314 mod.test_functions.deinit(gpa);3269 mod.test_functions.deinit(gpa);
3315 mod.align_stack_fns.deinit(gpa);3270 mod.align_stack_fns.deinit(gpa);
3316 mod.monomorphed_funcs.deinit(gpa);3271 mod.monomorphed_funcs.deinit(gpa);
3317 mod.memoized_call_args.deinit(gpa);
3318 mod.memoized_calls.deinit(gpa);
33193272
3320 mod.decls_free_list.deinit(gpa);3273 mod.decls_free_list.deinit(gpa);
3321 mod.allocated_decls.deinit(gpa);3274 mod.allocated_decls.deinit(gpa);
...@@ -3325,8 +3278,6 @@ pub fn deinit(mod: *Module) void {...@@ -3325,8 +3278,6 @@ pub fn deinit(mod: *Module) void {
3325 mod.namespaces_free_list.deinit(gpa);3278 mod.namespaces_free_list.deinit(gpa);
3326 mod.allocated_namespaces.deinit(gpa);3279 mod.allocated_namespaces.deinit(gpa);
33273280
3328 mod.memoized_decls.deinit(gpa);
3329
3330 mod.intern_pool.deinit(gpa);3281 mod.intern_pool.deinit(gpa);
3331}3282}
33323283
...@@ -5438,6 +5389,17 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -5438,6 +5389,17 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
5438 mod.destroyDecl(decl_index);5389 mod.destroyDecl(decl_index);
5439}5390}
54405391
5392/// Finalize the creation of an anon decl.
5393pub fn finalizeAnonDecl(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
5394 // The Decl starts off with alive=false and the codegen backend will set alive=true
5395 // if the Decl is referenced by an instruction or another constant. Otherwise,
5396 // the Decl will be garbage collected by the `codegen_decl` task instead of sent
5397 // to the linker.
5398 if (mod.declPtr(decl_index).ty.isFnOrHasRuntimeBits(mod)) {
5399 try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = decl_index });
5400 }
5401}
5402
5441/// Delete all the Export objects that are caused by this Decl. Re-analysis of5403/// Delete all the Export objects that are caused by this Decl. Re-analysis of
5442/// this Decl will cause them to be re-created (or not).5404/// this Decl will cause them to be re-created (or not).
5443fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {5405fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
...@@ -5875,7 +5837,7 @@ pub fn initNewAnonDecl(...@@ -5875,7 +5837,7 @@ pub fn initNewAnonDecl(
5875 namespace: Namespace.Index,5837 namespace: Namespace.Index,
5876 typed_value: TypedValue,5838 typed_value: TypedValue,
5877 name: [:0]u8,5839 name: [:0]u8,
5878) !void {5840) Allocator.Error!void {
5879 assert(typed_value.ty.toIntern() == mod.intern_pool.typeOf(typed_value.val.toIntern()));5841 assert(typed_value.ty.toIntern() == mod.intern_pool.typeOf(typed_value.val.toIntern()));
5880 errdefer mod.gpa.free(name);5842 errdefer mod.gpa.free(name);
58815843
...@@ -5892,14 +5854,6 @@ pub fn initNewAnonDecl(...@@ -5892,14 +5854,6 @@ pub fn initNewAnonDecl(
5892 new_decl.generation = mod.generation;5854 new_decl.generation = mod.generation;
58935855
5894 try mod.namespacePtr(namespace).anon_decls.putNoClobber(mod.gpa, new_decl_index, {});5856 try mod.namespacePtr(namespace).anon_decls.putNoClobber(mod.gpa, new_decl_index, {});
5895
5896 // The Decl starts off with alive=false and the codegen backend will set alive=true
5897 // if the Decl is referenced by an instruction or another constant. Otherwise,
5898 // the Decl will be garbage collected by the `codegen_decl` task instead of sent
5899 // to the linker.
5900 if (typed_value.ty.isFnOrHasRuntimeBits(mod)) {
5901 try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl_index });
5902 }
5903}5857}
59045858
5905pub fn errNoteNonLazy(5859pub fn errNoteNonLazy(
src/Sema.zig+95-78
...@@ -734,6 +734,7 @@ pub const Block = struct {...@@ -734,6 +734,7 @@ pub const Block = struct {
734 errdefer sema.mod.abortAnonDecl(new_decl_index);734 errdefer sema.mod.abortAnonDecl(new_decl_index);
735 try new_decl.finalizeNewArena(&wad.new_decl_arena);735 try new_decl.finalizeNewArena(&wad.new_decl_arena);
736 wad.finished = true;736 wad.finished = true;
737 try sema.mod.finalizeAnonDecl(new_decl_index);
737 return new_decl_index;738 return new_decl_index;
738 }739 }
739 };740 };
...@@ -2292,7 +2293,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {...@@ -2292,7 +2293,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
2292 defer reference_stack.deinit();2293 defer reference_stack.deinit();
22932294
2294 // Avoid infinite loops.2295 // Avoid infinite loops.
2295 var seen = std.AutoHashMap(Module.Decl.Index, void).init(gpa);2296 var seen = std.AutoHashMap(Decl.Index, void).init(gpa);
2296 defer seen.deinit();2297 defer seen.deinit();
22972298
2298 var cur_reference_trace: u32 = 0;2299 var cur_reference_trace: u32 = 0;
...@@ -2742,7 +2743,9 @@ fn zirStructDecl(...@@ -2742,7 +2743,9 @@ fn zirStructDecl(
27422743
2743 try sema.analyzeStructDecl(new_decl, inst, struct_index);2744 try sema.analyzeStructDecl(new_decl, inst, struct_index);
2744 try new_decl.finalizeNewArena(&new_decl_arena);2745 try new_decl.finalizeNewArena(&new_decl_arena);
2745 return sema.analyzeDeclVal(block, src, new_decl_index);2746 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
2747 try mod.finalizeAnonDecl(new_decl_index);
2748 return decl_val;
2746}2749}
27472750
2748fn createAnonymousDeclTypeNamed(2751fn createAnonymousDeclTypeNamed(
...@@ -2941,6 +2944,7 @@ fn zirEnumDecl(...@@ -2941,6 +2944,7 @@ fn zirEnumDecl(
2941 new_namespace.ty = incomplete_enum.index.toType();2944 new_namespace.ty = incomplete_enum.index.toType();
29422945
2943 const decl_val = try sema.analyzeDeclVal(block, src, new_decl_index);2946 const decl_val = try sema.analyzeDeclVal(block, src, new_decl_index);
2947 try mod.finalizeAnonDecl(new_decl_index);
2944 done = true;2948 done = true;
29452949
2946 const int_tag_ty = ty: {2950 const int_tag_ty = ty: {
...@@ -3193,7 +3197,9 @@ fn zirUnionDecl(...@@ -3193,7 +3197,9 @@ fn zirUnionDecl(
3193 _ = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);3197 _ = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);
31943198
3195 try new_decl.finalizeNewArena(&new_decl_arena);3199 try new_decl.finalizeNewArena(&new_decl_arena);
3196 return sema.analyzeDeclVal(block, src, new_decl_index);3200 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
3201 try mod.finalizeAnonDecl(new_decl_index);
3202 return decl_val;
3197}3203}
31983204
3199fn zirOpaqueDecl(3205fn zirOpaqueDecl(
...@@ -3257,7 +3263,9 @@ fn zirOpaqueDecl(...@@ -3257,7 +3263,9 @@ fn zirOpaqueDecl(
3257 extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);3263 extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);
32583264
3259 try new_decl.finalizeNewArena(&new_decl_arena);3265 try new_decl.finalizeNewArena(&new_decl_arena);
3260 return sema.analyzeDeclVal(block, src, new_decl_index);3266 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
3267 try mod.finalizeAnonDecl(new_decl_index);
3268 return decl_val;
3261}3269}
32623270
3263fn zirErrorSetDecl(3271fn zirErrorSetDecl(
...@@ -3298,7 +3306,9 @@ fn zirErrorSetDecl(...@@ -3298,7 +3306,9 @@ fn zirErrorSetDecl(
3298 new_decl.owns_tv = true;3306 new_decl.owns_tv = true;
3299 errdefer mod.abortAnonDecl(new_decl_index);3307 errdefer mod.abortAnonDecl(new_decl_index);
33003308
3301 return sema.analyzeDeclVal(block, src, new_decl_index);3309 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
3310 try mod.finalizeAnonDecl(new_decl_index);
3311 return decl_val;
3302}3312}
33033313
3304fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {3314fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
...@@ -5133,32 +5143,35 @@ fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -5133,32 +5143,35 @@ fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
5133 return sema.addStrLit(block, bytes);5143 return sema.addStrLit(block, bytes);
5134}5144}
51355145
5136fn addStrLit(sema: *Sema, block: *Block, zir_bytes: []const u8) CompileError!Air.Inst.Ref {5146fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Inst.Ref {
5137 // `zir_bytes` references memory inside the ZIR module, which can get deallocated
5138 // after semantic analysis is complete, for example in the case of the initialization
5139 // expression of a variable declaration.
5140 const mod = sema.mod;5147 const mod = sema.mod;
5141 const gpa = sema.gpa;5148 const memoized_decl_index = memoized: {
5142 const ty = try mod.arrayType(.{5149 const ty = try mod.arrayType(.{
5143 .len = zir_bytes.len,5150 .len = bytes.len,
5144 .child = .u8_type,5151 .child = .u8_type,
5145 .sentinel = .zero_u8,5152 .sentinel = .zero_u8,
5146 });5153 });
5147 const val = try mod.intern(.{ .aggregate = .{5154 const val = try mod.intern(.{ .aggregate = .{
5148 .ty = ty.toIntern(),5155 .ty = ty.toIntern(),
5149 .storage = .{ .bytes = zir_bytes },5156 .storage = .{ .bytes = bytes },
5150 } });5157 } });
5151 const gop = try mod.memoized_decls.getOrPut(gpa, val);
5152 if (!gop.found_existing) {
5153 var anon_decl = try block.startAnonDecl();
5154 defer anon_decl.deinit();
51555158
5156 const decl_index = try anon_decl.finish(ty, val.toValue(), 0);5159 _ = try sema.typeHasRuntimeBits(ty);
5160 const new_decl_index = try mod.createAnonymousDecl(block, .{ .ty = ty, .val = val.toValue() });
5161 errdefer mod.abortAnonDecl(new_decl_index);
51575162
5158 gop.key_ptr.* = val;5163 const memoized_index = try mod.intern(.{ .memoized_decl = .{
5159 gop.value_ptr.* = decl_index;5164 .val = val,
5160 }5165 .decl = new_decl_index,
5161 return sema.analyzeDeclRef(gop.value_ptr.*);5166 } });
5167 const memoized_decl_index = mod.intern_pool.indexToKey(memoized_index).memoized_decl.decl;
5168 if (memoized_decl_index != new_decl_index)
5169 mod.abortAnonDecl(new_decl_index)
5170 else
5171 try mod.finalizeAnonDecl(new_decl_index);
5172 break :memoized memoized_decl_index;
5173 };
5174 return sema.analyzeDeclRef(memoized_decl_index);
5162}5175}
51635176
5164fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5177fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -6868,30 +6881,15 @@ fn analyzeCall(...@@ -6868,30 +6881,15 @@ fn analyzeCall(
6868 defer child_block.instructions.deinit(gpa);6881 defer child_block.instructions.deinit(gpa);
6869 defer merges.deinit(gpa);6882 defer merges.deinit(gpa);
68706883
6871 // If it's a comptime function call, we need to memoize it as long as no external
6872 // comptime memory is mutated.
6873 var memoized_call_key = Module.MemoizedCall.Key{
6874 .func = module_fn_index,
6875 .args_index = @intCast(u32, mod.memoized_call_args.items.len),
6876 .args_count = @intCast(u32, func_ty_info.param_types.len),
6877 };
6878 var delete_memoized_call_key = false;
6879 defer if (delete_memoized_call_key) {
6880 assert(mod.memoized_call_args.items.len >= memoized_call_key.args_index and
6881 mod.memoized_call_args.items.len < memoized_call_key.args_index + memoized_call_key.args_count);
6882 mod.memoized_call_args.shrinkRetainingCapacity(memoized_call_key.args_index);
6883 };
6884 if (is_comptime_call) {
6885 try mod.memoized_call_args.ensureUnusedCapacity(gpa, memoized_call_key.args_count);
6886 delete_memoized_call_key = true;
6887 }
6888
6889 try sema.emitBackwardBranch(block, call_src);6884 try sema.emitBackwardBranch(block, call_src);
68906885
6891 // Whether this call should be memoized, set to false if the call can mutate6886 // Whether this call should be memoized, set to false if the call can mutate comptime state.
6892 // comptime state.
6893 var should_memoize = true;6887 var should_memoize = true;
68946888
6889 // If it's a comptime function call, we need to memoize it as long as no external
6890 // comptime memory is mutated.
6891 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
6892
6895 var new_fn_info = mod.typeToFunc(fn_owner_decl.ty).?;6893 var new_fn_info = mod.typeToFunc(fn_owner_decl.ty).?;
6896 new_fn_info.param_types = try sema.arena.alloc(InternPool.Index, new_fn_info.param_types.len);6894 new_fn_info.param_types = try sema.arena.alloc(InternPool.Index, new_fn_info.param_types.len);
6897 new_fn_info.comptime_bits = 0;6895 new_fn_info.comptime_bits = 0;
...@@ -6918,6 +6916,7 @@ fn analyzeCall(...@@ -6918,6 +6916,7 @@ fn analyzeCall(
6918 uncasted_args,6916 uncasted_args,
6919 is_comptime_call,6917 is_comptime_call,
6920 &should_memoize,6918 &should_memoize,
6919 memoized_arg_values,
6921 mod.typeToFunc(func_ty).?.param_types,6920 mod.typeToFunc(func_ty).?.param_types,
6922 func,6921 func,
6923 &has_comptime_args,6922 &has_comptime_args,
...@@ -6935,6 +6934,7 @@ fn analyzeCall(...@@ -6935,6 +6934,7 @@ fn analyzeCall(
6935 uncasted_args,6934 uncasted_args,
6936 is_comptime_call,6935 is_comptime_call,
6937 &should_memoize,6936 &should_memoize,
6937 memoized_arg_values,
6938 mod.typeToFunc(func_ty).?.param_types,6938 mod.typeToFunc(func_ty).?.param_types,
6939 func,6939 func,
6940 &has_comptime_args,6940 &has_comptime_args,
...@@ -6988,28 +6988,18 @@ fn analyzeCall(...@@ -6988,28 +6988,18 @@ fn analyzeCall(
6988 // bug generating invalid LLVM IR.6988 // bug generating invalid LLVM IR.
6989 const res2: Air.Inst.Ref = res2: {6989 const res2: Air.Inst.Ref = res2: {
6990 if (should_memoize and is_comptime_call) {6990 if (should_memoize and is_comptime_call) {
6991 const gop = try mod.memoized_calls.getOrPutContext(6991 if (mod.intern_pool.getIfExists(.{ .memoized_call = .{
6992 gpa,6992 .func = module_fn_index,
6993 memoized_call_key,6993 .arg_values = memoized_arg_values,
6994 .{ .args = &mod.memoized_call_args },6994 .result = .none,
6995 );6995 } })) |memoized_call_index| {
6996 if (gop.found_existing) {6996 const memoized_call = mod.intern_pool.indexToKey(memoized_call_index).memoized_call;
6997 assert(mod.memoized_call_args.items.len == memoized_call_key.args_index + memoized_call_key.args_count);6997 break :res2 try sema.addConstant(
6998 mod.memoized_call_args.shrinkRetainingCapacity(memoized_call_key.args_index);6998 mod.intern_pool.typeOf(memoized_call.result).toType(),
6999 delete_memoized_call_key = false;6999 memoized_call.result.toValue(),
70007000 );
7001 // We need to use the original memoized error set instead of fn_ret_ty.
7002 const result = gop.value_ptr.*;
7003 assert(result != .none); // recursive memoization?
7004
7005 break :res2 try sema.addConstant(mod.intern_pool.typeOf(result).toType(), result.toValue());
7006 }7001 }
7007 gop.value_ptr.* = .none;
7008 } else if (delete_memoized_call_key) {
7009 assert(mod.memoized_call_args.items.len == memoized_call_key.args_index + memoized_call_key.args_count);
7010 mod.memoized_call_args.shrinkRetainingCapacity(memoized_call_key.args_index);
7011 }7002 }
7012 delete_memoized_call_key = false;
70137003
7014 const new_func_resolved_ty = try mod.funcType(new_fn_info);7004 const new_func_resolved_ty = try mod.funcType(new_fn_info);
7015 if (!is_comptime_call and !block.is_typeof) {7005 if (!is_comptime_call and !block.is_typeof) {
...@@ -7067,10 +7057,14 @@ fn analyzeCall(...@@ -7067,10 +7057,14 @@ fn analyzeCall(
70677057
7068 if (should_memoize and is_comptime_call) {7058 if (should_memoize and is_comptime_call) {
7069 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");7059 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");
7070 mod.memoized_calls.getPtrContext(7060
7071 memoized_call_key,7061 // TODO: check whether any external comptime memory was mutated by the
7072 .{ .args = &mod.memoized_call_args },7062 // comptime function call. If so, then do not memoize the call here.
7073 ).?.* = try result_val.intern(fn_ret_ty, mod);7063 _ = try mod.intern(.{ .memoized_call = .{
7064 .func = module_fn_index,
7065 .arg_values = memoized_arg_values,
7066 .result = try result_val.intern(fn_ret_ty, mod),
7067 } });
7074 }7068 }
70757069
7076 break :res2 result;7070 break :res2 result;
...@@ -7216,6 +7210,7 @@ fn analyzeInlineCallArg(...@@ -7216,6 +7210,7 @@ fn analyzeInlineCallArg(
7216 uncasted_args: []const Air.Inst.Ref,7210 uncasted_args: []const Air.Inst.Ref,
7217 is_comptime_call: bool,7211 is_comptime_call: bool,
7218 should_memoize: *bool,7212 should_memoize: *bool,
7213 memoized_arg_values: []InternPool.Index,
7219 raw_param_types: []const InternPool.Index,7214 raw_param_types: []const InternPool.Index,
7220 func_inst: Air.Inst.Ref,7215 func_inst: Air.Inst.Ref,
7221 has_comptime_args: *bool,7216 has_comptime_args: *bool,
...@@ -7279,7 +7274,7 @@ fn analyzeInlineCallArg(...@@ -7279,7 +7274,7 @@ fn analyzeInlineCallArg(
7279 },7274 },
7280 }7275 }
7281 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(mod);7276 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(mod);
7282 mod.memoized_call_args.appendAssumeCapacity(try arg_val.intern(param_ty.toType(), mod));7277 memoized_arg_values[arg_i.*] = try arg_val.intern(param_ty.toType(), mod);
7283 } else {7278 } else {
7284 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);7279 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
7285 }7280 }
...@@ -7315,7 +7310,7 @@ fn analyzeInlineCallArg(...@@ -7315,7 +7310,7 @@ fn analyzeInlineCallArg(
7315 },7310 },
7316 }7311 }
7317 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(mod);7312 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(mod);
7318 mod.memoized_call_args.appendAssumeCapacity(try arg_val.intern(sema.typeOf(uncasted_arg), mod));7313 memoized_arg_values[arg_i.*] = try arg_val.intern(sema.typeOf(uncasted_arg), mod);
7319 } else {7314 } else {
7320 if (zir_tags[inst] == .param_anytype_comptime) {7315 if (zir_tags[inst] == .param_anytype_comptime) {
7321 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");7316 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
...@@ -19363,7 +19358,9 @@ fn zirReify(...@@ -19363,7 +19358,9 @@ fn zirReify(
19363 }19358 }
19364 }19359 }
1936519360
19366 return sema.analyzeDeclVal(block, src, new_decl_index);19361 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
19362 try mod.finalizeAnonDecl(new_decl_index);
19363 return decl_val;
19367 },19364 },
19368 .Opaque => {19365 .Opaque => {
19369 const fields = ip.typeOf(union_val.val).toType().structFields(mod);19366 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
...@@ -19407,7 +19404,9 @@ fn zirReify(...@@ -19407,7 +19404,9 @@ fn zirReify(
19407 new_namespace.ty = opaque_ty.toType();19404 new_namespace.ty = opaque_ty.toType();
1940819405
19409 try new_decl.finalizeNewArena(&new_decl_arena);19406 try new_decl.finalizeNewArena(&new_decl_arena);
19410 return sema.analyzeDeclVal(block, src, new_decl_index);19407 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
19408 try mod.finalizeAnonDecl(new_decl_index);
19409 return decl_val;
19411 },19410 },
19412 .Union => {19411 .Union => {
19413 const fields = ip.typeOf(union_val.val).toType().structFields(mod);19412 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
...@@ -19604,7 +19603,9 @@ fn zirReify(...@@ -19604,7 +19603,9 @@ fn zirReify(
19604 }19603 }
1960519604
19606 try new_decl.finalizeNewArena(&new_decl_arena);19605 try new_decl.finalizeNewArena(&new_decl_arena);
19607 return sema.analyzeDeclVal(block, src, new_decl_index);19606 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
19607 try mod.finalizeAnonDecl(new_decl_index);
19608 return decl_val;
19608 },19609 },
19609 .Fn => {19610 .Fn => {
19610 const fields = ip.typeOf(union_val.val).toType().structFields(mod);19611 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
...@@ -19902,7 +19903,9 @@ fn reifyStruct(...@@ -19902,7 +19903,9 @@ fn reifyStruct(
19902 }19903 }
1990319904
19904 try new_decl.finalizeNewArena(&new_decl_arena);19905 try new_decl.finalizeNewArena(&new_decl_arena);
19905 return sema.analyzeDeclVal(block, src, new_decl_index);19906 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
19907 try mod.finalizeAnonDecl(new_decl_index);
19908 return decl_val;
19906}19909}
1990719910
19908fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {19911fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
...@@ -31865,6 +31868,9 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31865,6 +31868,9 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31865 .opt,31868 .opt,
31866 .aggregate,31869 .aggregate,
31867 .un,31870 .un,
31871 // memoization, not types
31872 .memoized_decl,
31873 .memoized_call,
31868 => unreachable,31874 => unreachable,
31869 },31875 },
31870 };31876 };
...@@ -32997,6 +33003,8 @@ fn generateUnionTagTypeNumbered(...@@ -32997,6 +33003,8 @@ fn generateUnionTagTypeNumbered(
32997 .ty = Type.type,33003 .ty = Type.type,
32998 .val = undefined,33004 .val = undefined,
32999 }, name);33005 }, name);
33006 errdefer mod.abortAnonDecl(new_decl_index);
33007
33000 const new_decl = mod.declPtr(new_decl_index);33008 const new_decl = mod.declPtr(new_decl_index);
33001 new_decl.name_fully_qualified = true;33009 new_decl.name_fully_qualified = true;
33002 new_decl.owns_tv = true;33010 new_decl.owns_tv = true;
...@@ -33016,6 +33024,7 @@ fn generateUnionTagTypeNumbered(...@@ -33016,6 +33024,7 @@ fn generateUnionTagTypeNumbered(
3301633024
33017 new_decl.val = enum_ty.toValue();33025 new_decl.val = enum_ty.toValue();
3301833026
33027 try mod.finalizeAnonDecl(new_decl_index);
33019 return enum_ty.toType();33028 return enum_ty.toType();
33020}33029}
3302133030
...@@ -33049,6 +33058,7 @@ fn generateUnionTagTypeSimple(...@@ -33049,6 +33058,7 @@ fn generateUnionTagTypeSimple(
33049 mod.declPtr(new_decl_index).name_fully_qualified = true;33058 mod.declPtr(new_decl_index).name_fully_qualified = true;
33050 break :new_decl_index new_decl_index;33059 break :new_decl_index new_decl_index;
33051 };33060 };
33061 errdefer mod.abortAnonDecl(new_decl_index);
3305233062
33053 const enum_ty = try mod.intern(.{ .enum_type = .{33063 const enum_ty = try mod.intern(.{ .enum_type = .{
33054 .decl = new_decl_index,33064 .decl = new_decl_index,
...@@ -33066,6 +33076,7 @@ fn generateUnionTagTypeSimple(...@@ -33066,6 +33076,7 @@ fn generateUnionTagTypeSimple(
33066 new_decl.owns_tv = true;33076 new_decl.owns_tv = true;
33067 new_decl.val = enum_ty.toValue();33077 new_decl.val = enum_ty.toValue();
3306833078
33079 try mod.finalizeAnonDecl(new_decl_index);
33069 return enum_ty.toType();33080 return enum_ty.toType();
33070}33081}
3307133082
...@@ -33358,6 +33369,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33358,6 +33369,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33358 .opt,33369 .opt,
33359 .aggregate,33370 .aggregate,
33360 .un,33371 .un,
33372 // memoization, not types
33373 .memoized_decl,
33374 .memoized_call,
33361 => unreachable,33375 => unreachable,
33362 },33376 },
33363 };33377 };
...@@ -33843,6 +33857,9 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33843,6 +33857,9 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33843 .opt,33857 .opt,
33844 .aggregate,33858 .aggregate,
33845 .un,33859 .un,
33860 // memoization, not types
33861 .memoized_decl,
33862 .memoized_call,
33846 => unreachable,33863 => unreachable,
33847 },33864 },
33848 };33865 };
src/TypedValue.zig+3
...@@ -278,6 +278,9 @@ pub fn print(...@@ -278,6 +278,9 @@ pub fn print(
278 } else try writer.writeAll("...");278 } else try writer.writeAll("...");
279 return writer.writeAll(" }");279 return writer.writeAll(" }");
280 },280 },
281 .memoized_decl,
282 .memoized_call,
283 => unreachable,
281 },284 },
282 };285 };
283}286}
src/arch/wasm/CodeGen.zig+3
...@@ -3254,6 +3254,9 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {...@@ -3254,6 +3254,9 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
3254 else => unreachable,3254 else => unreachable,
3255 },3255 },
3256 .un => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(mod)}),3256 .un => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(mod)}),
3257 .memoized_decl,
3258 .memoized_call,
3259 => unreachable,
3257 }3260 }
3258}3261}
32593262
src/codegen.zig+3
...@@ -605,6 +605,9 @@ pub fn generateSymbol(...@@ -605,6 +605,9 @@ pub fn generateSymbol(
605 }605 }
606 }606 }
607 },607 },
608 .memoized_decl,
609 .memoized_call,
610 => unreachable,
608 }611 }
609 return .ok;612 return .ok;
610}613}
src/codegen/c.zig+5-1
...@@ -1090,6 +1090,7 @@ pub const DeclGen = struct {...@@ -1090,6 +1090,7 @@ pub const DeclGen = struct {
1090 };1090 };
10911091
1092 switch (mod.intern_pool.indexToKey(val.ip_index)) {1092 switch (mod.intern_pool.indexToKey(val.ip_index)) {
1093 // types, not values
1093 .int_type,1094 .int_type,
1094 .ptr_type,1095 .ptr_type,
1095 .array_type,1096 .array_type,
...@@ -1106,7 +1107,10 @@ pub const DeclGen = struct {...@@ -1106,7 +1107,10 @@ pub const DeclGen = struct {
1106 .func_type,1107 .func_type,
1107 .error_set_type,1108 .error_set_type,
1108 .inferred_error_set_type,1109 .inferred_error_set_type,
1109 => unreachable, // types, not values1110 // memoization, not values
1111 .memoized_decl,
1112 .memoized_call,
1113 => unreachable,
11101114
1111 .undef, .runtime_value => unreachable, // handled above1115 .undef, .runtime_value => unreachable, // handled above
1112 .simple_value => |simple_value| switch (simple_value) {1116 .simple_value => |simple_value| switch (simple_value) {
src/codegen/llvm.zig+3
...@@ -3793,6 +3793,9 @@ pub const DeclGen = struct {...@@ -3793,6 +3793,9 @@ pub const DeclGen = struct {
3793 return llvm_union_ty.constNamedStruct(&fields, fields_len);3793 return llvm_union_ty.constNamedStruct(&fields, fields_len);
3794 }3794 }
3795 },3795 },
3796 .memoized_decl,
3797 .memoized_call,
3798 => unreachable,
3796 }3799 }
3797 }3800 }
37983801
src/codegen/spirv.zig+3
...@@ -830,6 +830,9 @@ pub const DeclGen = struct {...@@ -830,6 +830,9 @@ pub const DeclGen = struct {
830830
831 try self.addUndef(layout.padding);831 try self.addUndef(layout.padding);
832 },832 },
833 .memoized_decl,
834 .memoized_call,
835 => unreachable,
833 }836 }
834 }837 }
835 };838 };
src/type.zig+27
...@@ -400,6 +400,9 @@ pub const Type = struct {...@@ -400,6 +400,9 @@ pub const Type = struct {
400 .opt,400 .opt,
401 .aggregate,401 .aggregate,
402 .un,402 .un,
403 // memoization, not types
404 .memoized_decl,
405 .memoized_call,
403 => unreachable,406 => unreachable,
404 }407 }
405 }408 }
...@@ -613,6 +616,9 @@ pub const Type = struct {...@@ -613,6 +616,9 @@ pub const Type = struct {
613 .opt,616 .opt,
614 .aggregate,617 .aggregate,
615 .un,618 .un,
619 // memoization, not types
620 .memoized_decl,
621 .memoized_call,
616 => unreachable,622 => unreachable,
617 },623 },
618 };624 };
...@@ -719,6 +725,9 @@ pub const Type = struct {...@@ -719,6 +725,9 @@ pub const Type = struct {
719 .opt,725 .opt,
720 .aggregate,726 .aggregate,
721 .un,727 .un,
728 // memoization, not types
729 .memoized_decl,
730 .memoized_call,
722 => unreachable,731 => unreachable,
723 };732 };
724 }733 }
...@@ -1050,6 +1059,9 @@ pub const Type = struct {...@@ -1050,6 +1059,9 @@ pub const Type = struct {
1050 .opt,1059 .opt,
1051 .aggregate,1060 .aggregate,
1052 .un,1061 .un,
1062 // memoization, not types
1063 .memoized_decl,
1064 .memoized_call,
1053 => unreachable,1065 => unreachable,
1054 },1066 },
1055 }1067 }
...@@ -1464,6 +1476,9 @@ pub const Type = struct {...@@ -1464,6 +1476,9 @@ pub const Type = struct {
1464 .opt,1476 .opt,
1465 .aggregate,1477 .aggregate,
1466 .un,1478 .un,
1479 // memoization, not types
1480 .memoized_decl,
1481 .memoized_call,
1467 => unreachable,1482 => unreachable,
1468 },1483 },
1469 }1484 }
...@@ -1695,6 +1710,9 @@ pub const Type = struct {...@@ -1695,6 +1710,9 @@ pub const Type = struct {
1695 .opt,1710 .opt,
1696 .aggregate,1711 .aggregate,
1697 .un,1712 .un,
1713 // memoization, not types
1714 .memoized_decl,
1715 .memoized_call,
1698 => unreachable,1716 => unreachable,
1699 }1717 }
1700 }1718 }
...@@ -2250,6 +2268,9 @@ pub const Type = struct {...@@ -2250,6 +2268,9 @@ pub const Type = struct {
2250 .opt,2268 .opt,
2251 .aggregate,2269 .aggregate,
2252 .un,2270 .un,
2271 // memoization, not types
2272 .memoized_decl,
2273 .memoized_call,
2253 => unreachable,2274 => unreachable,
2254 },2275 },
2255 };2276 };
...@@ -2586,6 +2607,9 @@ pub const Type = struct {...@@ -2586,6 +2607,9 @@ pub const Type = struct {
2586 .opt,2607 .opt,
2587 .aggregate,2608 .aggregate,
2588 .un,2609 .un,
2610 // memoization, not types
2611 .memoized_decl,
2612 .memoized_call,
2589 => unreachable,2613 => unreachable,
2590 },2614 },
2591 };2615 };
...@@ -2728,6 +2752,9 @@ pub const Type = struct {...@@ -2728,6 +2752,9 @@ pub const Type = struct {
2728 .opt,2752 .opt,
2729 .aggregate,2753 .aggregate,
2730 .un,2754 .un,
2755 // memoization, not types
2756 .memoized_decl,
2757 .memoized_call,
2731 => unreachable,2758 => unreachable,
2732 },2759 },
2733 };2760 };
src/value.zig+4
...@@ -476,6 +476,10 @@ pub const Value = struct {...@@ -476,6 +476,10 @@ pub const Value = struct {
476 .tag = un.tag.toValue(),476 .tag = un.tag.toValue(),
477 .val = un.val.toValue(),477 .val = un.val.toValue(),
478 }),478 }),
479
480 .memoized_decl,
481 .memoized_call,
482 => unreachable,
479 };483 };
480 }484 }
481485