| author | |
| committer | |
| log | 3b6ca1d35b950d67fff5964f0063dadf01f30e2d |
| tree | 953815632535b965c7d32318ca515d8926cf4c4b |
| parent | d40b83de45db27c8c3e7a1f2ccf892563df43637 |
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 | 217 | /// An instance of a union. |
| 218 | 218 | un: Union, |
| 219 | 219 | |
| 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 | 225 | pub const IntType = std.builtin.Type.Int; |
| 221 | 226 | |
| 222 | 227 | pub const ErrorUnionType = struct { |
| ... | ... | @@ -609,6 +614,17 @@ pub const Key = union(enum) { |
| 609 | 614 | }; |
| 610 | 615 | }; |
| 611 | 616 | |
| 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 | 628 | pub fn hash32(key: Key, ip: *const InternPool) u32 { |
| 613 | 629 | return @truncate(u32, key.hash64(ip)); |
| 614 | 630 | } |
| ... | ... | @@ -786,6 +802,13 @@ pub const Key = union(enum) { |
| 786 | 802 | std.hash.autoHash(hasher, func_type.is_generic); |
| 787 | 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 | } |
| 791 | 814 | |
| ... | ... | @@ -1054,6 +1077,17 @@ pub const Key = union(enum) { |
| 1054 | 1077 | a_info.is_generic == b_info.is_generic and |
| 1055 | 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 | } |
| 1059 | 1093 | |
| ... | ... | @@ -1105,6 +1139,10 @@ pub const Key = union(enum) { |
| 1105 | 1139 | .@"unreachable" => .noreturn_type, |
| 1106 | 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 | 1418 | bytes: struct { data: *Bytes }, |
| 1381 | 1419 | aggregate: struct { data: *Aggregate }, |
| 1382 | 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 | 1429 | }) void { |
| 1384 | 1430 | _ = self; |
| 1385 | 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 | 1921 | /// An instance of an array or vector with every element being the same value. |
| 1876 | 1922 | /// data is extra index to `Repeated`. |
| 1877 | 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 | }; |
| 1879 | 1932 | |
| 1880 | 1933 | /// Trailing: |
| ... | ... | @@ -2271,6 +2324,14 @@ pub const Float128 = struct { |
| 2271 | 2324 | } |
| 2272 | 2325 | }; |
| 2273 | 2326 | |
| 2327 | /// Trailing: | |
| 2328 | /// 0. arg value: Index for each args_len | |
| 2329 | pub const MemoizedCall = struct { | |
| 2330 | func: Module.Fn.Index, | |
| 2331 | args_len: u32, | |
| 2332 | result: Index, | |
| 2333 | }; | |
| 2334 | ||
| 2274 | 2335 | pub fn init(ip: *InternPool, gpa: Allocator) !void { |
| 2275 | 2336 | assert(ip.items.len == 0); |
| 2276 | 2337 | |
| ... | ... | @@ -2758,6 +2819,16 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 2758 | 2819 | }, |
| 2759 | 2820 | .enum_literal => .{ .enum_literal = @intToEnum(NullTerminatedString, data) }, |
| 2760 | 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 | } |
| 2763 | 2834 | |
| ... | ... | @@ -3724,6 +3795,29 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 3724 | 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 | 3822 | return @intToEnum(Index, ip.items.len - 1); |
| 3729 | 3823 | } |
| ... | ... | @@ -3788,7 +3882,7 @@ pub fn getIncompleteEnum( |
| 3788 | 3882 | ip: *InternPool, |
| 3789 | 3883 | gpa: Allocator, |
| 3790 | 3884 | enum_type: Key.IncompleteEnumType, |
| 3791 | ) Allocator.Error!InternPool.IncompleteEnumType { | |
| 3885 | ) Allocator.Error!IncompleteEnumType { | |
| 3792 | 3886 | switch (enum_type.tag_mode) { |
| 3793 | 3887 | .auto => return getIncompleteEnumAuto(ip, gpa, enum_type), |
| 3794 | 3888 | .explicit => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_explicit), |
| ... | ... | @@ -3800,7 +3894,7 @@ pub fn getIncompleteEnumAuto( |
| 3800 | 3894 | ip: *InternPool, |
| 3801 | 3895 | gpa: Allocator, |
| 3802 | 3896 | enum_type: Key.IncompleteEnumType, |
| 3803 | ) Allocator.Error!InternPool.IncompleteEnumType { | |
| 3897 | ) Allocator.Error!IncompleteEnumType { | |
| 3804 | 3898 | // Although the integer tag type will not be stored in the `EnumAuto` struct, |
| 3805 | 3899 | // `InternPool` logic depends on it being present so that `typeOf` can be infallible. |
| 3806 | 3900 | // Ensure it is present here: |
| ... | ... | @@ -3849,7 +3943,7 @@ fn getIncompleteEnumExplicit( |
| 3849 | 3943 | gpa: Allocator, |
| 3850 | 3944 | enum_type: Key.IncompleteEnumType, |
| 3851 | 3945 | tag: Tag, |
| 3852 | ) Allocator.Error!InternPool.IncompleteEnumType { | |
| 3946 | ) Allocator.Error!IncompleteEnumType { | |
| 3853 | 3947 | // We must keep the map in sync with `items`. The hash and equality functions |
| 3854 | 3948 | // for enum types only look at the decl field, which is present even in |
| 3855 | 3949 | // an `IncompleteEnumType`. |
| ... | ... | @@ -4704,6 +4798,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void { |
| 4704 | 4798 | .func => @sizeOf(Key.Func) + @sizeOf(Module.Fn) + @sizeOf(Module.Decl), |
| 4705 | 4799 | .only_possible_value => 0, |
| 4706 | 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 | 4809 | const SortContext = struct { |
| ... | ... | @@ -5215,6 +5315,9 @@ pub fn zigTypeTagOrPoison(ip: InternPool, index: Index) error{GenericPoison}!std |
| 5215 | 5315 | .bytes, |
| 5216 | 5316 | .aggregate, |
| 5217 | 5317 | .repeated, |
| 5318 | // memoization, not types | |
| 5319 | .memoized_decl, | |
| 5320 | .memoized_call, | |
| 5218 | 5321 | => unreachable, |
| 5219 | 5322 | }, |
| 5220 | 5323 | .none => unreachable, // special tag |
src/Module.zig+12-58| ... | ... | @@ -88,18 +88,10 @@ embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{}, |
| 88 | 88 | /// Stores all Type and Value objects; periodically garbage collected. |
| 89 | 89 | intern_pool: InternPool = .{}, |
| 90 | 90 | |
| 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. | |
| 93 | memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{}, | |
| 94 | ||
| 95 | 91 | /// The set of all the generic function instantiations. This is used so that when a generic |
| 96 | 92 | /// function is called twice with the same comptime parameter arguments, both calls dispatch |
| 97 | 93 | /// to the same function. |
| 98 | 94 | monomorphed_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. | |
| 101 | memoized_calls: MemoizedCallSet = .{}, | |
| 102 | memoized_call_args: MemoizedCall.Args = .{}, | |
| 103 | 95 | /// Contains the values from `@setAlignStack`. A sparse table is used here |
| 104 | 96 | /// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while |
| 105 | 97 | /// functions are many. |
| ... | ... | @@ -223,42 +215,6 @@ const MonomorphedFuncsContext = struct { |
| 223 | 215 | } |
| 224 | 216 | }; |
| 225 | 217 | |
| 226 | pub const MemoizedCallSet = std.HashMapUnmanaged( | |
| 227 | MemoizedCall.Key, | |
| 228 | MemoizedCall.Result, | |
| 229 | MemoizedCall, | |
| 230 | std.hash_map.default_max_load_percentage, | |
| 231 | ); | |
| 232 | ||
| 233 | pub 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 | ||
| 262 | 218 | pub const SetAlignStack = struct { |
| 263 | 219 | alignment: u32, |
| 264 | 220 | /// 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 | 561 | } |
| 606 | 562 | mod.destroyFunc(func); |
| 607 | 563 | } |
| 608 | _ = mod.memoized_decls.remove(decl.val.ip_index); | |
| 609 | 564 | if (decl.value_arena) |value_arena| { |
| 610 | 565 | value_arena.deinit(gpa); |
| 611 | 566 | decl.value_arena = null; |
| ... | ... | @@ -3314,8 +3269,6 @@ pub fn deinit(mod: *Module) void { |
| 3314 | 3269 | mod.test_functions.deinit(gpa); |
| 3315 | 3270 | mod.align_stack_fns.deinit(gpa); |
| 3316 | 3271 | mod.monomorphed_funcs.deinit(gpa); |
| 3317 | mod.memoized_call_args.deinit(gpa); | |
| 3318 | mod.memoized_calls.deinit(gpa); | |
| 3319 | 3272 | |
| 3320 | 3273 | mod.decls_free_list.deinit(gpa); |
| 3321 | 3274 | mod.allocated_decls.deinit(gpa); |
| ... | ... | @@ -3325,8 +3278,6 @@ pub fn deinit(mod: *Module) void { |
| 3325 | 3278 | mod.namespaces_free_list.deinit(gpa); |
| 3326 | 3279 | mod.allocated_namespaces.deinit(gpa); |
| 3327 | 3280 | |
| 3328 | mod.memoized_decls.deinit(gpa); | |
| 3329 | ||
| 3330 | 3281 | mod.intern_pool.deinit(gpa); |
| 3331 | 3282 | } |
| 3332 | 3283 | |
| ... | ... | @@ -5438,6 +5389,17 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { |
| 5438 | 5389 | mod.destroyDecl(decl_index); |
| 5439 | 5390 | } |
| 5440 | 5391 | |
| 5392 | /// Finalize the creation of an anon decl. | |
| 5393 | pub 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 | 5403 | /// Delete all the Export objects that are caused by this Decl. Re-analysis of |
| 5442 | 5404 | /// this Decl will cause them to be re-created (or not). |
| 5443 | 5405 | fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void { |
| ... | ... | @@ -5875,7 +5837,7 @@ pub fn initNewAnonDecl( |
| 5875 | 5837 | namespace: Namespace.Index, |
| 5876 | 5838 | typed_value: TypedValue, |
| 5877 | 5839 | name: [:0]u8, |
| 5878 | ) !void { | |
| 5840 | ) Allocator.Error!void { | |
| 5879 | 5841 | assert(typed_value.ty.toIntern() == mod.intern_pool.typeOf(typed_value.val.toIntern())); |
| 5880 | 5842 | errdefer mod.gpa.free(name); |
| 5881 | 5843 | |
| ... | ... | @@ -5892,14 +5854,6 @@ pub fn initNewAnonDecl( |
| 5892 | 5854 | new_decl.generation = mod.generation; |
| 5893 | 5855 | |
| 5894 | 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 | } |
| 5904 | 5858 | |
| 5905 | 5859 | pub fn errNoteNonLazy( |
src/Sema.zig+95-78| ... | ... | @@ -734,6 +734,7 @@ pub const Block = struct { |
| 734 | 734 | errdefer sema.mod.abortAnonDecl(new_decl_index); |
| 735 | 735 | try new_decl.finalizeNewArena(&wad.new_decl_arena); |
| 736 | 736 | wad.finished = true; |
| 737 | try sema.mod.finalizeAnonDecl(new_decl_index); | |
| 737 | 738 | return new_decl_index; |
| 738 | 739 | } |
| 739 | 740 | }; |
| ... | ... | @@ -2292,7 +2293,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError { |
| 2292 | 2293 | defer reference_stack.deinit(); |
| 2293 | 2294 | |
| 2294 | 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 | 2297 | defer seen.deinit(); |
| 2297 | 2298 | |
| 2298 | 2299 | var cur_reference_trace: u32 = 0; |
| ... | ... | @@ -2742,7 +2743,9 @@ fn zirStructDecl( |
| 2742 | 2743 | |
| 2743 | 2744 | try sema.analyzeStructDecl(new_decl, inst, struct_index); |
| 2744 | 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 | } |
| 2747 | 2750 | |
| 2748 | 2751 | fn createAnonymousDeclTypeNamed( |
| ... | ... | @@ -2941,6 +2944,7 @@ fn zirEnumDecl( |
| 2941 | 2944 | new_namespace.ty = incomplete_enum.index.toType(); |
| 2942 | 2945 | |
| 2943 | 2946 | const decl_val = try sema.analyzeDeclVal(block, src, new_decl_index); |
| 2947 | try mod.finalizeAnonDecl(new_decl_index); | |
| 2944 | 2948 | done = true; |
| 2945 | 2949 | |
| 2946 | 2950 | const int_tag_ty = ty: { |
| ... | ... | @@ -3193,7 +3197,9 @@ fn zirUnionDecl( |
| 3193 | 3197 | _ = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl); |
| 3194 | 3198 | |
| 3195 | 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 | } |
| 3198 | 3204 | |
| 3199 | 3205 | fn zirOpaqueDecl( |
| ... | ... | @@ -3257,7 +3263,9 @@ fn zirOpaqueDecl( |
| 3257 | 3263 | extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl); |
| 3258 | 3264 | |
| 3259 | 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 | } |
| 3262 | 3270 | |
| 3263 | 3271 | fn zirErrorSetDecl( |
| ... | ... | @@ -3298,7 +3306,9 @@ fn zirErrorSetDecl( |
| 3298 | 3306 | new_decl.owns_tv = true; |
| 3299 | 3307 | errdefer mod.abortAnonDecl(new_decl_index); |
| 3300 | 3308 | |
| 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 | } |
| 3303 | 3313 | |
| 3304 | 3314 | fn 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 | 5143 | return sema.addStrLit(block, bytes); |
| 5134 | 5144 | } |
| 5135 | 5145 | |
| 5136 | fn addStrLit(sema: *Sema, block: *Block, zir_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. | |
| 5146 | fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Inst.Ref { | |
| 5140 | 5147 | const mod = sema.mod; |
| 5141 | const gpa = sema.gpa; | |
| 5142 | const ty = try mod.arrayType(.{ | |
| 5143 | .len = zir_bytes.len, | |
| 5144 | .child = .u8_type, | |
| 5145 | .sentinel = .zero_u8, | |
| 5146 | }); | |
| 5147 | const val = try mod.intern(.{ .aggregate = .{ | |
| 5148 | .ty = ty.toIntern(), | |
| 5149 | .storage = .{ .bytes = zir_bytes }, | |
| 5150 | } }); | |
| 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(); | |
| 5148 | const memoized_decl_index = memoized: { | |
| 5149 | const ty = try mod.arrayType(.{ | |
| 5150 | .len = bytes.len, | |
| 5151 | .child = .u8_type, | |
| 5152 | .sentinel = .zero_u8, | |
| 5153 | }); | |
| 5154 | const val = try mod.intern(.{ .aggregate = .{ | |
| 5155 | .ty = ty.toIntern(), | |
| 5156 | .storage = .{ .bytes = bytes }, | |
| 5157 | } }); | |
| 5155 | 5158 | |
| 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); | |
| 5157 | 5162 | |
| 5158 | gop.key_ptr.* = val; | |
| 5159 | gop.value_ptr.* = decl_index; | |
| 5160 | } | |
| 5161 | return sema.analyzeDeclRef(gop.value_ptr.*); | |
| 5163 | const memoized_index = try mod.intern(.{ .memoized_decl = .{ | |
| 5164 | .val = val, | |
| 5165 | .decl = new_decl_index, | |
| 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 | } |
| 5163 | 5176 | |
| 5164 | 5177 | fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -6868,30 +6881,15 @@ fn analyzeCall( |
| 6868 | 6881 | defer child_block.instructions.deinit(gpa); |
| 6869 | 6882 | defer merges.deinit(gpa); |
| 6870 | 6883 | |
| 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 | 6884 | try sema.emitBackwardBranch(block, call_src); |
| 6890 | 6885 | |
| 6891 | // Whether this call should be memoized, set to false if the call can mutate | |
| 6892 | // comptime state. | |
| 6886 | // Whether this call should be memoized, set to false if the call can mutate comptime state. | |
| 6893 | 6887 | var should_memoize = true; |
| 6894 | 6888 | |
| 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 | 6893 | var new_fn_info = mod.typeToFunc(fn_owner_decl.ty).?; |
| 6896 | 6894 | new_fn_info.param_types = try sema.arena.alloc(InternPool.Index, new_fn_info.param_types.len); |
| 6897 | 6895 | new_fn_info.comptime_bits = 0; |
| ... | ... | @@ -6918,6 +6916,7 @@ fn analyzeCall( |
| 6918 | 6916 | uncasted_args, |
| 6919 | 6917 | is_comptime_call, |
| 6920 | 6918 | &should_memoize, |
| 6919 | memoized_arg_values, | |
| 6921 | 6920 | mod.typeToFunc(func_ty).?.param_types, |
| 6922 | 6921 | func, |
| 6923 | 6922 | &has_comptime_args, |
| ... | ... | @@ -6935,6 +6934,7 @@ fn analyzeCall( |
| 6935 | 6934 | uncasted_args, |
| 6936 | 6935 | is_comptime_call, |
| 6937 | 6936 | &should_memoize, |
| 6937 | memoized_arg_values, | |
| 6938 | 6938 | mod.typeToFunc(func_ty).?.param_types, |
| 6939 | 6939 | func, |
| 6940 | 6940 | &has_comptime_args, |
| ... | ... | @@ -6988,28 +6988,18 @@ fn analyzeCall( |
| 6988 | 6988 | // bug generating invalid LLVM IR. |
| 6989 | 6989 | const res2: Air.Inst.Ref = res2: { |
| 6990 | 6990 | if (should_memoize and is_comptime_call) { |
| 6991 | const gop = try mod.memoized_calls.getOrPutContext( | |
| 6992 | gpa, | |
| 6993 | memoized_call_key, | |
| 6994 | .{ .args = &mod.memoized_call_args }, | |
| 6995 | ); | |
| 6996 | if (gop.found_existing) { | |
| 6997 | assert(mod.memoized_call_args.items.len == memoized_call_key.args_index + memoized_call_key.args_count); | |
| 6998 | mod.memoized_call_args.shrinkRetainingCapacity(memoized_call_key.args_index); | |
| 6999 | delete_memoized_call_key = false; | |
| 7000 | ||
| 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()); | |
| 6991 | if (mod.intern_pool.getIfExists(.{ .memoized_call = .{ | |
| 6992 | .func = module_fn_index, | |
| 6993 | .arg_values = memoized_arg_values, | |
| 6994 | .result = .none, | |
| 6995 | } })) |memoized_call_index| { | |
| 6996 | const memoized_call = mod.intern_pool.indexToKey(memoized_call_index).memoized_call; | |
| 6997 | break :res2 try sema.addConstant( | |
| 6998 | mod.intern_pool.typeOf(memoized_call.result).toType(), | |
| 6999 | memoized_call.result.toValue(), | |
| 7000 | ); | |
| 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; | |
| 7013 | 7003 | |
| 7014 | 7004 | const new_func_resolved_ty = try mod.funcType(new_fn_info); |
| 7015 | 7005 | if (!is_comptime_call and !block.is_typeof) { |
| ... | ... | @@ -7067,10 +7057,14 @@ fn analyzeCall( |
| 7067 | 7057 | |
| 7068 | 7058 | if (should_memoize and is_comptime_call) { |
| 7069 | 7059 | const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, ""); |
| 7070 | mod.memoized_calls.getPtrContext( | |
| 7071 | memoized_call_key, | |
| 7072 | .{ .args = &mod.memoized_call_args }, | |
| 7073 | ).?.* = try result_val.intern(fn_ret_ty, mod); | |
| 7060 | ||
| 7061 | // TODO: check whether any external comptime memory was mutated by the | |
| 7062 | // comptime function call. If so, then do not memoize the call here. | |
| 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 | } |
| 7075 | 7069 | |
| 7076 | 7070 | break :res2 result; |
| ... | ... | @@ -7216,6 +7210,7 @@ fn analyzeInlineCallArg( |
| 7216 | 7210 | uncasted_args: []const Air.Inst.Ref, |
| 7217 | 7211 | is_comptime_call: bool, |
| 7218 | 7212 | should_memoize: *bool, |
| 7213 | memoized_arg_values: []InternPool.Index, | |
| 7219 | 7214 | raw_param_types: []const InternPool.Index, |
| 7220 | 7215 | func_inst: Air.Inst.Ref, |
| 7221 | 7216 | has_comptime_args: *bool, |
| ... | ... | @@ -7279,7 +7274,7 @@ fn analyzeInlineCallArg( |
| 7279 | 7274 | }, |
| 7280 | 7275 | } |
| 7281 | 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 | 7278 | } else { |
| 7284 | 7279 | sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg); |
| 7285 | 7280 | } |
| ... | ... | @@ -7315,7 +7310,7 @@ fn analyzeInlineCallArg( |
| 7315 | 7310 | }, |
| 7316 | 7311 | } |
| 7317 | 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 | 7314 | } else { |
| 7320 | 7315 | if (zir_tags[inst] == .param_anytype_comptime) { |
| 7321 | 7316 | _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime"); |
| ... | ... | @@ -19363,7 +19358,9 @@ fn zirReify( |
| 19363 | 19358 | } |
| 19364 | 19359 | } |
| 19365 | 19360 | |
| 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 | 19365 | .Opaque => { |
| 19369 | 19366 | const fields = ip.typeOf(union_val.val).toType().structFields(mod); |
| ... | ... | @@ -19407,7 +19404,9 @@ fn zirReify( |
| 19407 | 19404 | new_namespace.ty = opaque_ty.toType(); |
| 19408 | 19405 | |
| 19409 | 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 | 19411 | .Union => { |
| 19413 | 19412 | const fields = ip.typeOf(union_val.val).toType().structFields(mod); |
| ... | ... | @@ -19604,7 +19603,9 @@ fn zirReify( |
| 19604 | 19603 | } |
| 19605 | 19604 | |
| 19606 | 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 | 19610 | .Fn => { |
| 19610 | 19611 | const fields = ip.typeOf(union_val.val).toType().structFields(mod); |
| ... | ... | @@ -19902,7 +19903,9 @@ fn reifyStruct( |
| 19902 | 19903 | } |
| 19903 | 19904 | |
| 19904 | 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 | } |
| 19907 | 19910 | |
| 19908 | 19911 | fn 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 | 31868 | .opt, |
| 31866 | 31869 | .aggregate, |
| 31867 | 31870 | .un, |
| 31871 | // memoization, not types | |
| 31872 | .memoized_decl, | |
| 31873 | .memoized_call, | |
| 31868 | 31874 | => unreachable, |
| 31869 | 31875 | }, |
| 31870 | 31876 | }; |
| ... | ... | @@ -32997,6 +33003,8 @@ fn generateUnionTagTypeNumbered( |
| 32997 | 33003 | .ty = Type.type, |
| 32998 | 33004 | .val = undefined, |
| 32999 | 33005 | }, name); |
| 33006 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 33007 | ||
| 33000 | 33008 | const new_decl = mod.declPtr(new_decl_index); |
| 33001 | 33009 | new_decl.name_fully_qualified = true; |
| 33002 | 33010 | new_decl.owns_tv = true; |
| ... | ... | @@ -33016,6 +33024,7 @@ fn generateUnionTagTypeNumbered( |
| 33016 | 33024 | |
| 33017 | 33025 | new_decl.val = enum_ty.toValue(); |
| 33018 | 33026 | |
| 33027 | try mod.finalizeAnonDecl(new_decl_index); | |
| 33019 | 33028 | return enum_ty.toType(); |
| 33020 | 33029 | } |
| 33021 | 33030 | |
| ... | ... | @@ -33049,6 +33058,7 @@ fn generateUnionTagTypeSimple( |
| 33049 | 33058 | mod.declPtr(new_decl_index).name_fully_qualified = true; |
| 33050 | 33059 | break :new_decl_index new_decl_index; |
| 33051 | 33060 | }; |
| 33061 | errdefer mod.abortAnonDecl(new_decl_index); | |
| 33052 | 33062 | |
| 33053 | 33063 | const enum_ty = try mod.intern(.{ .enum_type = .{ |
| 33054 | 33064 | .decl = new_decl_index, |
| ... | ... | @@ -33066,6 +33076,7 @@ fn generateUnionTagTypeSimple( |
| 33066 | 33076 | new_decl.owns_tv = true; |
| 33067 | 33077 | new_decl.val = enum_ty.toValue(); |
| 33068 | 33078 | |
| 33079 | try mod.finalizeAnonDecl(new_decl_index); | |
| 33069 | 33080 | return enum_ty.toType(); |
| 33070 | 33081 | } |
| 33071 | 33082 | |
| ... | ... | @@ -33358,6 +33369,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 33358 | 33369 | .opt, |
| 33359 | 33370 | .aggregate, |
| 33360 | 33371 | .un, |
| 33372 | // memoization, not types | |
| 33373 | .memoized_decl, | |
| 33374 | .memoized_call, | |
| 33361 | 33375 | => unreachable, |
| 33362 | 33376 | }, |
| 33363 | 33377 | }; |
| ... | ... | @@ -33843,6 +33857,9 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 33843 | 33857 | .opt, |
| 33844 | 33858 | .aggregate, |
| 33845 | 33859 | .un, |
| 33860 | // memoization, not types | |
| 33861 | .memoized_decl, | |
| 33862 | .memoized_call, | |
| 33846 | 33863 | => unreachable, |
| 33847 | 33864 | }, |
| 33848 | 33865 | }; |
src/TypedValue.zig+3| ... | ... | @@ -278,6 +278,9 @@ pub fn print( |
| 278 | 278 | } else try writer.writeAll("..."); |
| 279 | 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 | 3254 | else => unreachable, |
| 3255 | 3255 | }, |
| 3256 | 3256 | .un => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(mod)}), |
| 3257 | .memoized_decl, | |
| 3258 | .memoized_call, | |
| 3259 | => unreachable, | |
| 3257 | 3260 | } |
| 3258 | 3261 | } |
| 3259 | 3262 |
src/codegen.zig+3| ... | ... | @@ -605,6 +605,9 @@ pub fn generateSymbol( |
| 605 | 605 | } |
| 606 | 606 | } |
| 607 | 607 | }, |
| 608 | .memoized_decl, | |
| 609 | .memoized_call, | |
| 610 | => unreachable, | |
| 608 | 611 | } |
| 609 | 612 | return .ok; |
| 610 | 613 | } |
src/codegen/c.zig+5-1| ... | ... | @@ -1090,6 +1090,7 @@ pub const DeclGen = struct { |
| 1090 | 1090 | }; |
| 1091 | 1091 | |
| 1092 | 1092 | switch (mod.intern_pool.indexToKey(val.ip_index)) { |
| 1093 | // types, not values | |
| 1093 | 1094 | .int_type, |
| 1094 | 1095 | .ptr_type, |
| 1095 | 1096 | .array_type, |
| ... | ... | @@ -1106,7 +1107,10 @@ pub const DeclGen = struct { |
| 1106 | 1107 | .func_type, |
| 1107 | 1108 | .error_set_type, |
| 1108 | 1109 | .inferred_error_set_type, |
| 1109 | => unreachable, // types, not values | |
| 1110 | // memoization, not values | |
| 1111 | .memoized_decl, | |
| 1112 | .memoized_call, | |
| 1113 | => unreachable, | |
| 1110 | 1114 | |
| 1111 | 1115 | .undef, .runtime_value => unreachable, // handled above |
| 1112 | 1116 | .simple_value => |simple_value| switch (simple_value) { |
src/codegen/llvm.zig+3| ... | ... | @@ -3793,6 +3793,9 @@ pub const DeclGen = struct { |
| 3793 | 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 | } |
| 3798 | 3801 |
src/codegen/spirv.zig+3| ... | ... | @@ -830,6 +830,9 @@ pub const DeclGen = struct { |
| 830 | 830 | |
| 831 | 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 | 400 | .opt, |
| 401 | 401 | .aggregate, |
| 402 | 402 | .un, |
| 403 | // memoization, not types | |
| 404 | .memoized_decl, | |
| 405 | .memoized_call, | |
| 403 | 406 | => unreachable, |
| 404 | 407 | } |
| 405 | 408 | } |
| ... | ... | @@ -613,6 +616,9 @@ pub const Type = struct { |
| 613 | 616 | .opt, |
| 614 | 617 | .aggregate, |
| 615 | 618 | .un, |
| 619 | // memoization, not types | |
| 620 | .memoized_decl, | |
| 621 | .memoized_call, | |
| 616 | 622 | => unreachable, |
| 617 | 623 | }, |
| 618 | 624 | }; |
| ... | ... | @@ -719,6 +725,9 @@ pub const Type = struct { |
| 719 | 725 | .opt, |
| 720 | 726 | .aggregate, |
| 721 | 727 | .un, |
| 728 | // memoization, not types | |
| 729 | .memoized_decl, | |
| 730 | .memoized_call, | |
| 722 | 731 | => unreachable, |
| 723 | 732 | }; |
| 724 | 733 | } |
| ... | ... | @@ -1050,6 +1059,9 @@ pub const Type = struct { |
| 1050 | 1059 | .opt, |
| 1051 | 1060 | .aggregate, |
| 1052 | 1061 | .un, |
| 1062 | // memoization, not types | |
| 1063 | .memoized_decl, | |
| 1064 | .memoized_call, | |
| 1053 | 1065 | => unreachable, |
| 1054 | 1066 | }, |
| 1055 | 1067 | } |
| ... | ... | @@ -1464,6 +1476,9 @@ pub const Type = struct { |
| 1464 | 1476 | .opt, |
| 1465 | 1477 | .aggregate, |
| 1466 | 1478 | .un, |
| 1479 | // memoization, not types | |
| 1480 | .memoized_decl, | |
| 1481 | .memoized_call, | |
| 1467 | 1482 | => unreachable, |
| 1468 | 1483 | }, |
| 1469 | 1484 | } |
| ... | ... | @@ -1695,6 +1710,9 @@ pub const Type = struct { |
| 1695 | 1710 | .opt, |
| 1696 | 1711 | .aggregate, |
| 1697 | 1712 | .un, |
| 1713 | // memoization, not types | |
| 1714 | .memoized_decl, | |
| 1715 | .memoized_call, | |
| 1698 | 1716 | => unreachable, |
| 1699 | 1717 | } |
| 1700 | 1718 | } |
| ... | ... | @@ -2250,6 +2268,9 @@ pub const Type = struct { |
| 2250 | 2268 | .opt, |
| 2251 | 2269 | .aggregate, |
| 2252 | 2270 | .un, |
| 2271 | // memoization, not types | |
| 2272 | .memoized_decl, | |
| 2273 | .memoized_call, | |
| 2253 | 2274 | => unreachable, |
| 2254 | 2275 | }, |
| 2255 | 2276 | }; |
| ... | ... | @@ -2586,6 +2607,9 @@ pub const Type = struct { |
| 2586 | 2607 | .opt, |
| 2587 | 2608 | .aggregate, |
| 2588 | 2609 | .un, |
| 2610 | // memoization, not types | |
| 2611 | .memoized_decl, | |
| 2612 | .memoized_call, | |
| 2589 | 2613 | => unreachable, |
| 2590 | 2614 | }, |
| 2591 | 2615 | }; |
| ... | ... | @@ -2728,6 +2752,9 @@ pub const Type = struct { |
| 2728 | 2752 | .opt, |
| 2729 | 2753 | .aggregate, |
| 2730 | 2754 | .un, |
| 2755 | // memoization, not types | |
| 2756 | .memoized_decl, | |
| 2757 | .memoized_call, | |
| 2731 | 2758 | => unreachable, |
| 2732 | 2759 | }, |
| 2733 | 2760 | }; |
src/value.zig+4| ... | ... | @@ -476,6 +476,10 @@ pub const Value = struct { |
| 476 | 476 | .tag = un.tag.toValue(), |
| 477 | 477 | .val = un.val.toValue(), |
| 478 | 478 | }), |
| 479 | ||
| 480 | .memoized_decl, | |
| 481 | .memoized_call, | |
| 482 | => unreachable, | |
| 479 | 483 | }; |
| 480 | 484 | } |
| 481 | 485 |