authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-06-02 18:49:40-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:59-07:00
loge23b0a01e6357252eb2c08a83eff9169ce49042c
tree86742fd9ad29116eddc61c1e093ae8155a435fb4
parent6a15fc87ad62ec0509017c960f6983ce1493c31d

InternPool: fix yet more key lifetime issues


6 files changed, 52 insertions(+), 44 deletions(-)

src/Module.zig+7-8
......@@ -5448,7 +5448,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
54485448 defer comptime_mutable_decls.deinit();
54495449
54505450 const fn_ty = decl.ty;
5451 const fn_ty_info = mod.typeToFunc(fn_ty).?;
54525451
54535452 var sema: Sema = .{
54545453 .mod = mod,
......@@ -5459,7 +5458,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
54595458 .owner_decl_index = decl_index,
54605459 .func = func,
54615460 .func_index = func_index.toOptional(),
5462 .fn_ret_ty = fn_ty_info.return_type.toType(),
5461 .fn_ret_ty = mod.typeToFunc(fn_ty).?.return_type.toType(),
54635462 .owner_func = func,
54645463 .owner_func_index = func_index.toOptional(),
54655464 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
......@@ -5499,7 +5498,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
54995498 // This could be a generic function instantiation, however, in which case we need to
55005499 // map the comptime parameters to constant values and only emit arg AIR instructions
55015500 // for the runtime ones.
5502 const runtime_params_len = @intCast(u32, fn_ty_info.param_types.len);
5501 const runtime_params_len = @intCast(u32, mod.typeToFunc(fn_ty).?.param_types.len);
55035502 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
55045503 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`
55055504 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
......@@ -5525,7 +5524,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
55255524 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
55265525 total_param_index += 1;
55275526 continue;
5528 } else fn_ty_info.param_types[runtime_param_index].toType();
5527 } else mod.typeToFunc(fn_ty).?.param_types[runtime_param_index].toType();
55295528
55305529 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
55315530 error.NeededSourceLocation => unreachable,
......@@ -5623,7 +5622,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
56235622 // Crucially, this happens *after* we set the function state to success above,
56245623 // so that dependencies on the function body will now be satisfied rather than
56255624 // result in circular dependency errors.
5626 sema.resolveFnTypes(mod.typeToFunc(fn_ty).?) catch |err| switch (err) {
5625 sema.resolveFnTypes(fn_ty) catch |err| switch (err) {
56275626 error.NeededSourceLocation => unreachable,
56285627 error.GenericPoison => unreachable,
56295628 error.ComptimeReturn => unreachable,
......@@ -6378,9 +6377,9 @@ pub fn populateTestFunctions(
63786377
63796378 for (test_fn_vals, mod.test_functions.keys()) |*test_fn_val, test_decl_index| {
63806379 const test_decl = mod.declPtr(test_decl_index);
6381 // Protects test_decl_name from being invalidated during call to intern() below.
6382 try ip.string_bytes.ensureUnusedCapacity(gpa, ip.stringToSlice(test_decl.name).len + 10);
6383 const test_decl_name = ip.stringToSlice(test_decl.name);
6380 // TODO: write something like getCoercedInts to avoid needing to dupe
6381 const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(test_decl.name));
6382 defer gpa.free(test_decl_name);
63846383 const test_name_decl_index = n: {
63856384 const test_name_decl_ty = try mod.arrayType(.{
63866385 .len = test_decl_name.len,
src/Sema.zig+35-26
......@@ -5227,6 +5227,8 @@ fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
52275227fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Inst.Ref {
52285228 const mod = sema.mod;
52295229 const gpa = sema.gpa;
5230 // TODO: write something like getCoercedInts to avoid needing to dupe
5231 const duped_bytes = try sema.arena.dupe(u8, bytes);
52305232 const ty = try mod.arrayType(.{
52315233 .len = bytes.len,
52325234 .child = .u8_type,
......@@ -5234,7 +5236,7 @@ fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Ins
52345236 });
52355237 const val = try mod.intern(.{ .aggregate = .{
52365238 .ty = ty.toIntern(),
5237 .storage = .{ .bytes = bytes },
5239 .storage = .{ .bytes = duped_bytes },
52385240 } });
52395241 const gop = try mod.memoized_decls.getOrPut(gpa, val);
52405242 if (!gop.found_existing) {
......@@ -11478,7 +11480,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1147811480 operand_ty.fmt(mod),
1147911481 });
1148011482 }
11481 for (operand_ty.errorSetNames(mod)) |error_name_ip| {
11483 for (0..operand_ty.errorSetNames(mod).len) |i| {
11484 const error_name_ip = operand_ty.errorSetNames(mod)[i];
1148211485 const error_name = mod.intern_pool.stringToSlice(error_name_ip);
1148311486 if (seen_errors.contains(error_name)) continue;
1148411487 cases_len += 1;
......@@ -15851,7 +15854,8 @@ fn zirBuiltinSrc(
1585115854 const func_name_val = blk: {
1585215855 var anon_decl = try block.startAnonDecl();
1585315856 defer anon_decl.deinit();
15854 const name = mod.intern_pool.stringToSlice(fn_owner_decl.name);
15857 // TODO: write something like getCoercedInts to avoid needing to dupe
15858 const name = try sema.arena.dupe(u8, mod.intern_pool.stringToSlice(fn_owner_decl.name));
1585515859 const new_decl_ty = try mod.arrayType(.{
1585615860 .len = name.len,
1585715861 .child = .u8_type,
......@@ -16287,7 +16291,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1628716291 const error_field_vals = if (ty.isAnyError(mod)) null else blk: {
1628816292 const vals = try sema.arena.alloc(InternPool.Index, ty.errorSetNames(mod).len);
1628916293 for (vals, 0..) |*field_val, i| {
16290 const name = ip.stringToSlice(ty.errorSetNames(mod)[i]);
16294 // TODO: write something like getCoercedInts to avoid needing to dupe
16295 const name = try sema.arena.dupe(u8, ip.stringToSlice(ty.errorSetNames(mod)[i]));
1629116296 const name_val = v: {
1629216297 var anon_decl = try block.startAnonDecl();
1629316298 defer anon_decl.deinit();
......@@ -16417,8 +16422,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1641716422
1641816423 const enum_field_vals = try sema.arena.alloc(InternPool.Index, enum_type.names.len);
1641916424 for (enum_field_vals, 0..) |*field_val, i| {
16420 const name_ip = ip.indexToKey(ty.toIntern()).enum_type.names[i];
16421 const name = ip.stringToSlice(name_ip);
16425 // TODO: write something like getCoercedInts to avoid needing to dupe
16426 const name = try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(ty.toIntern()).enum_type.names[i]));
1642216427 const name_val = v: {
1642316428 var anon_decl = try block.startAnonDecl();
1642416429 defer anon_decl.deinit();
......@@ -16556,7 +16561,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1655616561
1655716562 for (union_field_vals, 0..) |*field_val, i| {
1655816563 const field = union_fields.values()[i];
16559 const name = ip.stringToSlice(union_fields.keys()[i]);
16564 // TODO: write something like getCoercedInts to avoid needing to dupe
16565 const name = try sema.arena.dupe(u8, ip.stringToSlice(union_fields.keys()[i]));
1656016566 const name_val = v: {
1656116567 var anon_decl = try block.startAnonDecl();
1656216568 defer anon_decl.deinit();
......@@ -16714,9 +16720,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1671416720 const name_val = v: {
1671516721 var anon_decl = try block.startAnonDecl();
1671616722 defer anon_decl.deinit();
16723 // TODO: write something like getCoercedInts to avoid needing to dupe
1671716724 const bytes = if (tuple.names.len != 0)
1671816725 // https://github.com/ziglang/zig/issues/15709
16719 @as([]const u8, ip.stringToSlice(tuple.names[i]))
16726 try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(struct_ty.toIntern()).anon_struct_type.names[i]))
1672016727 else
1672116728 try std.fmt.allocPrint(sema.arena, "{d}", .{i});
1672216729 const new_decl_ty = try mod.arrayType(.{
......@@ -16771,7 +16778,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1677116778 struct_obj.fields.keys(),
1677216779 struct_obj.fields.values(),
1677316780 ) |*field_val, name_nts, field| {
16774 const name = ip.stringToSlice(name_nts);
16781 // TODO: write something like getCoercedInts to avoid needing to dupe
16782 const name = try sema.arena.dupe(u8, ip.stringToSlice(name_nts));
1677516783 const name_val = v: {
1677616784 var anon_decl = try block.startAnonDecl();
1677716785 defer anon_decl.deinit();
......@@ -17020,9 +17028,8 @@ fn typeInfoNamespaceDecls(
1702017028 const name_val = v: {
1702117029 var anon_decl = try block.startAnonDecl();
1702217030 defer anon_decl.deinit();
17023 // Protects the decl name slice from being invalidated at the call to intern().
17024 try ip.string_bytes.ensureUnusedCapacity(sema.gpa, ip.stringToSlice(decl.name).len + 1);
17025 const name = ip.stringToSlice(decl.name);
17031 // TODO: write something like getCoercedInts to avoid needing to dupe
17032 const name = try sema.arena.dupe(u8, ip.stringToSlice(decl.name));
1702617033 const new_decl_ty = try mod.arrayType(.{
1702717034 .len = name.len,
1702817035 .child = .u8_type,
......@@ -19060,6 +19067,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1906019067 };
1906119068 return sema.failWithOwnedErrorMsg(msg);
1906219069 };
19070 // TODO: write something like getCoercedInts to avoid needing to dupe
1906319071 const field_name = enum_ty.enumFieldName(field_index, mod);
1906419072 return sema.addStrLit(block, ip.stringToSlice(field_name));
1906519073 }
......@@ -19601,7 +19609,6 @@ fn zirReify(
1960119609 // Tag type
1960219610 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
1960319611 var explicit_tags_seen: []bool = &.{};
19604 var explicit_enum_info: ?InternPool.Key.EnumType = null;
1960519612 var enum_field_names: []InternPool.NullTerminatedString = &.{};
1960619613 if (tag_type_val.optionalValue(mod)) |payload_val| {
1960719614 union_obj.tag_ty = payload_val.toType();
......@@ -19611,7 +19618,6 @@ fn zirReify(
1961119618 else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),
1961219619 };
1961319620
19614 explicit_enum_info = enum_type;
1961519621 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
1961619622 @memset(explicit_tags_seen, false);
1961719623 } else {
......@@ -19640,7 +19646,8 @@ fn zirReify(
1964019646 enum_field_names[i] = field_name;
1964119647 }
1964219648
19643 if (explicit_enum_info) |tag_info| {
19649 if (explicit_tags_seen.len > 0) {
19650 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
1964419651 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
1964519652 const msg = msg: {
1964619653 const msg = try sema.errMsg(block, src, "no field named '{s}' in enum '{}'", .{ ip.stringToSlice(field_name), union_obj.tag_ty.fmt(mod) });
......@@ -19705,7 +19712,8 @@ fn zirReify(
1970519712 }
1970619713 }
1970719714
19708 if (explicit_enum_info) |tag_info| {
19715 if (explicit_tags_seen.len > 0) {
19716 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
1970919717 if (tag_info.names.len > fields_len) {
1971019718 const msg = msg: {
1971119719 const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{});
......@@ -31625,17 +31633,17 @@ fn resolvePeerTypes(
3162531633 return chosen_ty;
3162631634}
3162731635
31628pub fn resolveFnTypes(sema: *Sema, fn_info: InternPool.Key.FuncType) CompileError!void {
31636pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
3162931637 const mod = sema.mod;
31630 try sema.resolveTypeFully(fn_info.return_type.toType());
31638 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.return_type.toType());
3163131639
31632 if (mod.comp.bin_file.options.error_return_tracing and fn_info.return_type.toType().isError(mod)) {
31640 if (mod.comp.bin_file.options.error_return_tracing and mod.typeToFunc(fn_ty).?.return_type.toType().isError(mod)) {
3163331641 // Ensure the type exists so that backends can assume that.
3163431642 _ = try sema.getBuiltinType("StackTrace");
3163531643 }
3163631644
31637 for (fn_info.param_types) |param_ty| {
31638 try sema.resolveTypeFully(param_ty.toType());
31645 for (0..mod.typeToFunc(fn_ty).?.param_types.len) |i| {
31646 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.param_types[i].toType());
3163931647 }
3164031648}
3164131649
......@@ -33077,7 +33085,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3307733085 var enum_field_names: []InternPool.NullTerminatedString = &.{};
3307833086 var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{};
3307933087 var explicit_tags_seen: []bool = &.{};
33080 var explicit_enum_info: ?InternPool.Key.EnumType = null;
3308133088 if (tag_type_ref != .none) {
3308233089 const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x };
3308333090 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);
......@@ -33114,7 +33121,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3311433121 };
3311533122 // The fields of the union must match the enum exactly.
3311633123 // A flag per field is used to check for missing and extraneous fields.
33117 explicit_enum_info = enum_type;
3311833124 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
3311933125 @memset(explicit_tags_seen, false);
3312033126 }
......@@ -33256,7 +33262,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3325633262 return sema.failWithOwnedErrorMsg(msg);
3325733263 }
3325833264
33259 if (explicit_enum_info) |tag_info| {
33265 if (explicit_tags_seen.len > 0) {
33266 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
3326033267 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
3326133268 const msg = msg: {
3326233269 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
......@@ -33346,7 +33353,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3334633353 }
3334733354 }
3334833355
33349 if (explicit_enum_info) |tag_info| {
33356 if (explicit_tags_seen.len > 0) {
33357 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
3335033358 if (tag_info.names.len > fields_len) {
3335133359 const msg = msg: {
3335233360 const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{});
......@@ -33706,9 +33714,10 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3370633714 }
3370733715 // In this case the struct has all comptime-known fields and
3370833716 // therefore has one possible value.
33717 // TODO: write something like getCoercedInts to avoid needing to dupe
3370933718 return (try mod.intern(.{ .aggregate = .{
3371033719 .ty = ty.toIntern(),
33711 .storage = .{ .elems = tuple.values },
33720 .storage = .{ .elems = try sema.arena.dupe(InternPool.Index, tuple.values) },
3371233721 } })).toValue();
3371333722 },
3371433723
src/arch/x86_64/CodeGen.zig+2-6
......@@ -2026,13 +2026,9 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
20262026 try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });
20272027
20282028 var data_off: i32 = 0;
2029 for (
2030 exitlude_jump_relocs,
2031 enum_ty.enumFields(mod),
2032 0..,
2033 ) |*exitlude_jump_reloc, tag_name_ip, index_usize| {
2029 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, index_usize| {
20342030 const index = @intCast(u32, index_usize);
2035 const tag_name = mod.intern_pool.stringToSlice(tag_name_ip);
2031 const tag_name = mod.intern_pool.stringToSlice(enum_ty.enumFields(mod)[index_usize]);
20362032 const tag_val = try mod.enumValueFieldIndex(enum_ty, index);
20372033 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });
20382034 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);
src/codegen.zig+1-1
......@@ -517,7 +517,7 @@ pub fn generateSymbol(
517517 const field_ty = field.ty;
518518 if (!field_ty.hasRuntimeBits(mod)) continue;
519519
520 const field_val = switch (aggregate.storage) {
520 const field_val = switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).aggregate.storage) {
521521 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
522522 .ty = field_ty.toIntern(),
523523 .storage = .{ .u64 = bytes[index] },
src/type.zig+4-1
......@@ -2576,9 +2576,12 @@ pub const Type = struct {
25762576 }
25772577 // In this case the struct has all comptime-known fields and
25782578 // therefore has one possible value.
2579 // TODO: write something like getCoercedInts to avoid needing to dupe
2580 const duped_values = try mod.gpa.dupe(InternPool.Index, tuple.values);
2581 defer mod.gpa.free(duped_values);
25792582 return (try mod.intern(.{ .aggregate = .{
25802583 .ty = ty.toIntern(),
2581 .storage = .{ .elems = tuple.values },
2584 .storage = .{ .elems = duped_values },
25822585 } })).toValue();
25832586 },
25842587
src/value.zig+3-2
......@@ -1904,6 +1904,7 @@ pub const Value = struct {
19041904 start: usize,
19051905 end: usize,
19061906 ) error{OutOfMemory}!Value {
1907 // TODO: write something like getCoercedInts to avoid needing to dupe
19071908 return switch (val.ip_index) {
19081909 .none => switch (val.tag()) {
19091910 .slice => val.castTag(.slice).?.data.ptr.sliceArray(mod, arena, start, end),
......@@ -1937,8 +1938,8 @@ pub const Value = struct {
19371938 else => unreachable,
19381939 }.toIntern(),
19391940 .storage = switch (aggregate.storage) {
1940 .bytes => |bytes| .{ .bytes = bytes[start..end] },
1941 .elems => |elems| .{ .elems = elems[start..end] },
1941 .bytes => .{ .bytes = try arena.dupe(u8, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.bytes[start..end]) },
1942 .elems => .{ .elems = try arena.dupe(InternPool.Index, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.elems[start..end]) },
19421943 .repeated_elem => |elem| .{ .repeated_elem = elem },
19431944 },
19441945 } })).toValue(),