| 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,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, |
| 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 | pub const IntType = std.builtin.Type.Int; | 225 | pub const IntType = std.builtin.Type.Int; |
| 221 | 226 | ||
| 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 | }; |
| 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 | 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 | } |
| 791 | 814 | ||
| ... | @@ -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 and | 1077 | 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 | } |
| 1059 | 1093 | ||
| ... | @@ -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 | }; |
| 1879 | 1932 | ||
| 1880 | /// Trailing: | 1933 | /// Trailing: |
| ... | @@ -2271,6 +2324,14 @@ pub const Float128 = struct { | ... | @@ -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 | pub fn init(ip: *InternPool, gpa: Allocator) !void { | 2335 | pub fn init(ip: *InternPool, gpa: Allocator) !void { |
| 2275 | assert(ip.items.len == 0); | 2336 | assert(ip.items.len == 0); |
| 2276 | 2337 | ||
| ... | @@ -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 | } |
| 2763 | 2834 | ||
| ... | @@ -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 functions | 3947 | // 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 in | 3948 | // 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 tag | 5323 | .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. |
| 89 | intern_pool: InternPool = .{}, | 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 | /// The set of all the generic function instantiations. This is used so that when a generic | 91 | /// 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 dispatch | 92 | /// function is called twice with the same comptime parameter arguments, both calls dispatch |
| 97 | /// to the same function. | 93 | /// to the same function. |
| 98 | monomorphed_funcs: MonomorphedFuncsSet = .{}, | 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 | /// Contains the values from `@setAlignStack`. A sparse table is used here | 95 | /// Contains the values from `@setAlignStack`. A sparse table is used here |
| 104 | /// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while | 96 | /// 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 | }; |
| 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 | pub const SetAlignStack = struct { | 218 | pub 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 function | 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,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); | ||
| 3319 | 3272 | ||
| 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); |
| 3327 | 3280 | ||
| 3328 | mod.memoized_decls.deinit(gpa); | ||
| 3329 | |||
| 3330 | mod.intern_pool.deinit(gpa); | 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,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 | } |
| 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 | /// Delete all the Export objects that are caused by this Decl. Re-analysis of | 5403 | /// 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). |
| 5443 | fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void { | 5405 | fn 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); |
| 5881 | 5843 | ||
| ... | @@ -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; |
| 5893 | 5855 | ||
| 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 | } |
| 5904 | 5858 | ||
| 5905 | pub fn errNoteNonLazy( | 5859 | pub 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(); |
| 2293 | 2294 | ||
| 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(); |
| 2297 | 2298 | ||
| 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( |
| 2742 | 2743 | ||
| 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 | } |
| 2747 | 2750 | ||
| 2748 | fn createAnonymousDeclTypeNamed( | 2751 | fn 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(); |
| 2942 | 2945 | ||
| 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; |
| 2945 | 2949 | ||
| 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); |
| 3194 | 3198 | ||
| 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 | } |
| 3198 | 3204 | ||
| 3199 | fn zirOpaqueDecl( | 3205 | fn 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); |
| 3258 | 3264 | ||
| 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 | } |
| 3262 | 3270 | ||
| 3263 | fn zirErrorSetDecl( | 3271 | fn 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); |
| 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 | fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { | 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,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 | } |
| 5135 | 5145 | ||
| 5136 | fn addStrLit(sema: *Sema, block: *Block, zir_bytes: []const u8) CompileError!Air.Inst.Ref { | 5146 | fn 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(); | ||
| 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; | 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 | } |
| 5163 | 5176 | ||
| 5164 | fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 5177 | fn 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); |
| 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 | try sema.emitBackwardBranch(block, call_src); | 6884 | try sema.emitBackwardBranch(block, call_src); |
| 6890 | 6885 | ||
| 6891 | // Whether this call should be memoized, set to false if the call can mutate | 6886 | // 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; |
| 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 | 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(), |
| 7000 | 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()); | ||
| 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 | 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( |
| 7067 | 7057 | ||
| 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 | } |
| 7075 | 7069 | ||
| 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 | } |
| 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 | .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(); |
| 19408 | 19405 | ||
| 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 | } |
| 19605 | 19604 | ||
| 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 | } |
| 19903 | 19904 | ||
| 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 | } |
| 19907 | 19910 | ||
| 19908 | fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 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,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( |
| 33016 | 33024 | ||
| 33017 | new_decl.val = enum_ty.toValue(); | 33025 | new_decl.val = enum_ty.toValue(); |
| 33018 | 33026 | ||
| 33027 | try mod.finalizeAnonDecl(new_decl_index); | ||
| 33019 | return enum_ty.toType(); | 33028 | return enum_ty.toType(); |
| 33020 | } | 33029 | } |
| 33021 | 33030 | ||
| ... | @@ -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); | ||
| 33052 | 33062 | ||
| 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(); |
| 33068 | 33078 | ||
| 33079 | try mod.finalizeAnonDecl(new_decl_index); | ||
| 33069 | return enum_ty.toType(); | 33080 | return enum_ty.toType(); |
| 33070 | } | 33081 | } |
| 33071 | 33082 | ||
| ... | @@ -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 | } |
| 3259 | 3262 |
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 | }; |
| 1091 | 1091 | ||
| 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 values | 1110 | // memoization, not values |
| 1111 | .memoized_decl, | ||
| 1112 | .memoized_call, | ||
| 1113 | => unreachable, | ||
| 1110 | 1114 | ||
| 1111 | .undef, .runtime_value => unreachable, // handled above | 1115 | .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 | } |
| 3798 | 3801 |
src/codegen/spirv.zig+3| ... | @@ -830,6 +830,9 @@ pub const DeclGen = struct { | ... | @@ -830,6 +830,9 @@ pub const DeclGen = struct { |
| 830 | 830 | ||
| 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 | } |
| 481 | 485 |