authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-16 03:13:25+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-16 00:27:25-08:00
log6f08e172299320a3b243998878b38b0b3f43d8d5
tree22ca949d513aa57651081ce831875e322666eb2a
parent0183b44bb10751c46bd520e673726a66c027b477

InternPool: make more use of `NullTerminatedString.Slice`

This should avoid the random pointer invalidation crashes. Closes #18954

9 files changed, 70 insertions(+), 61 deletions(-)

src/Sema.zig+13-10
......@@ -12619,8 +12619,9 @@ fn analyzeSwitchRuntimeBlock(
1261912619 operand_ty.fmt(mod),
1262012620 });
1262112621 }
12622 for (0..operand_ty.errorSetNames(mod).len) |i| {
12623 const error_name = operand_ty.errorSetNames(mod)[i];
12622 const error_names = operand_ty.errorSetNames(mod);
12623 for (0..error_names.len) |name_index| {
12624 const error_name = error_names.get(ip)[name_index];
1262412625 if (seen_errors.contains(error_name)) continue;
1262512626 cases_len += 1;
1262612627
......@@ -22362,8 +22363,9 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2236222363 if (!operand_ty.isAnyError(mod) and operand_ty.errorSetIsEmpty(mod)) break :disjoint true;
2236322364 if (dest_ty.isAnyError(mod)) break :disjoint false;
2236422365 if (operand_ty.isAnyError(mod)) break :disjoint false;
22365 for (dest_ty.errorSetNames(mod)) |dest_err_name| {
22366 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name))
22366 const dest_err_names = dest_ty.errorSetNames(mod);
22367 for (0..dest_err_names.len) |dest_err_index| {
22368 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_names.get(ip)[dest_err_index]))
2236722369 break :disjoint false;
2236822370 }
2236922371
......@@ -22375,8 +22377,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2237522377
2237622378 _ = try sema.resolveInferredErrorSetTy(block, src, dest_ty.toIntern());
2237722379 _ = try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty.toIntern());
22378 for (dest_ty.errorSetNames(mod)) |dest_err_name| {
22379 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name))
22380 for (0..dest_err_names.len) |dest_err_index| {
22381 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_names.get(ip)[dest_err_index]))
2238022382 break :disjoint false;
2238122383 }
2238222384
......@@ -38780,17 +38782,18 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
3878038782/// Asserts that lhs and rhs are both error sets and are resolved.
3878138783fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {
3878238784 const mod = sema.mod;
38785 const ip = &mod.intern_pool;
3878338786 const arena = sema.arena;
3878438787 const lhs_names = lhs.errorSetNames(mod);
3878538788 const rhs_names = rhs.errorSetNames(mod);
3878638789 var names: InferredErrorSet.NameMap = .{};
3878738790 try names.ensureUnusedCapacity(arena, lhs_names.len);
3878838791
38789 for (lhs_names) |name| {
38790 names.putAssumeCapacityNoClobber(name, {});
38792 for (0..lhs_names.len) |lhs_index| {
38793 names.putAssumeCapacityNoClobber(lhs_names.get(ip)[lhs_index], {});
3879138794 }
38792 for (rhs_names) |name| {
38793 try names.put(arena, name, {});
38795 for (0..rhs_names.len) |rhs_index| {
38796 try names.put(arena, rhs_names.get(ip)[rhs_index], {});
3879438797 }
3879538798
3879638799 return mod.errorSetFromUnsortedNames(names.keys());
src/arch/wasm/CodeGen.zig+9-7
......@@ -7216,13 +7216,14 @@ fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
72167216
72177217fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
72187218 const mod = func.bin_file.base.comp.module.?;
7219 const ip = &mod.intern_pool;
72197220 const enum_decl_index = enum_ty.getOwnerDecl(mod);
72207221
72217222 var arena_allocator = std.heap.ArenaAllocator.init(func.gpa);
72227223 defer arena_allocator.deinit();
72237224 const arena = arena_allocator.allocator();
72247225
7225 const fqn = mod.intern_pool.stringToSlice(try mod.declPtr(enum_decl_index).getFullyQualifiedName(mod));
7226 const fqn = ip.stringToSlice(try mod.declPtr(enum_decl_index).getFullyQualifiedName(mod));
72267227 const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});
72277228
72287229 // check if we already generated code for this.
......@@ -7252,9 +7253,9 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
72527253
72537254 // TODO: Make switch implementation generic so we can use a jump table for this when the tags are not sparse.
72547255 // generate an if-else chain for each tag value as well as constant.
7255 for (enum_ty.enumFields(mod), 0..) |tag_name_ip, field_index_usize| {
7256 const field_index = @as(u32, @intCast(field_index_usize));
7257 const tag_name = mod.intern_pool.stringToSlice(tag_name_ip);
7256 const tag_names = enum_ty.enumFields(mod);
7257 for (0..tag_names.len) |tag_index| {
7258 const tag_name = ip.stringToSlice(tag_names.get(ip)[tag_index]);
72587259 // for each tag name, create an unnamed const,
72597260 // and then get a pointer to its value.
72607261 const name_ty = try mod.arrayType(.{
......@@ -7279,7 +7280,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
72797280 try writer.writeByte(std.wasm.opcode(.local_get));
72807281 try leb.writeULEB128(writer, @as(u32, 1));
72817282
7282 const tag_val = try mod.enumValueFieldIndex(enum_ty, field_index);
7283 const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index));
72837284 const tag_value = try func.lowerConstant(tag_val, enum_ty);
72847285
72857286 switch (tag_value) {
......@@ -7372,6 +7373,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
73727373
73737374fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
73747375 const mod = func.bin_file.base.comp.module.?;
7376 const ip = &mod.intern_pool;
73757377 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
73767378
73777379 const operand = try func.resolveInst(ty_op.operand);
......@@ -7384,8 +7386,8 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
73847386
73857387 var lowest: ?u32 = null;
73867388 var highest: ?u32 = null;
7387 for (names) |name| {
7388 const err_int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(name).?));
7389 for (0..names.len) |name_index| {
7390 const err_int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[name_index]).?);
73897391 if (lowest) |*l| {
73907392 if (err_int < l.*) {
73917393 l.* = err_int;
src/arch/x86_64/CodeGen.zig+7-6
......@@ -2187,6 +2187,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
21872187
21882188fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
21892189 const mod = self.bin_file.comp.module.?;
2190 const ip = &mod.intern_pool;
21902191 switch (lazy_sym.ty.zigTypeTag(mod)) {
21912192 .Enum => {
21922193 const enum_ty = lazy_sym.ty;
......@@ -2209,10 +2210,10 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
22092210 try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });
22102211
22112212 var data_off: i32 = 0;
2212 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, index_usize| {
2213 const index: u32 = @intCast(index_usize);
2214 const tag_name = mod.intern_pool.stringToSlice(enum_ty.enumFields(mod)[index_usize]);
2215 const tag_val = try mod.enumValueFieldIndex(enum_ty, index);
2213 const tag_names = enum_ty.enumFields(mod);
2214 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| {
2215 const tag_name_len = ip.stringToSlice(tag_names.get(ip)[tag_index]).len;
2216 const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index));
22162217 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });
22172218 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);
22182219 const skip_reloc = try self.asmJccReloc(.ne, undefined);
......@@ -2228,14 +2229,14 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
22282229 .{ .reg = ret_reg },
22292230 8,
22302231 Type.usize,
2231 .{ .immediate = tag_name.len },
2232 .{ .immediate = tag_name_len },
22322233 .{},
22332234 );
22342235
22352236 exitlude_jump_reloc.* = try self.asmJmpReloc(undefined);
22362237 self.performReloc(skip_reloc);
22372238
2238 data_off += @intCast(tag_name.len + 1);
2239 data_off += @intCast(tag_name_len + 1);
22392240 }
22402241
22412242 try self.airTrap();
src/codegen.zig+4-2
......@@ -119,6 +119,7 @@ pub fn generateLazySymbol(
119119
120120 const comp = bin_file.comp;
121121 const zcu = comp.module.?;
122 const ip = &zcu.intern_pool;
122123 const target = comp.root_mod.resolved_target.result;
123124 const endian = target.cpu.arch.endian();
124125 const gpa = comp.gpa;
......@@ -151,8 +152,9 @@ pub fn generateLazySymbol(
151152 return Result.ok;
152153 } else if (lazy_sym.ty.zigTypeTag(zcu) == .Enum) {
153154 alignment.* = .@"1";
154 for (lazy_sym.ty.enumFields(zcu)) |tag_name_ip| {
155 const tag_name = zcu.intern_pool.stringToSlice(tag_name_ip);
155 const tag_names = lazy_sym.ty.enumFields(zcu);
156 for (0..tag_names.len) |tag_index| {
157 const tag_name = zcu.intern_pool.stringToSlice(tag_names.get(ip)[tag_index]);
156158 try code.ensureUnusedCapacity(tag_name.len + 1);
157159 code.appendSliceAssumeCapacity(tag_name);
158160 code.appendAssumeCapacity(0);
src/codegen/c.zig+13-11
......@@ -2595,6 +2595,7 @@ pub fn genGlobalAsm(mod: *Module, writer: anytype) !void {
25952595
25962596pub fn genErrDecls(o: *Object) !void {
25972597 const mod = o.dg.module;
2598 const ip = &mod.intern_pool;
25982599 const writer = o.writer();
25992600
26002601 var max_name_len: usize = 0;
......@@ -2603,7 +2604,7 @@ pub fn genErrDecls(o: *Object) !void {
26032604 try writer.writeAll("enum {\n");
26042605 o.indent_writer.pushIndent();
26052606 for (mod.global_error_set.keys()[1..], 1..) |name_nts, value| {
2606 const name = mod.intern_pool.stringToSlice(name_nts);
2607 const name = ip.stringToSlice(name_nts);
26072608 max_name_len = @max(name.len, max_name_len);
26082609 const err_val = try mod.intern(.{ .err = .{
26092610 .ty = .anyerror_type,
......@@ -2621,8 +2622,8 @@ pub fn genErrDecls(o: *Object) !void {
26212622 defer o.dg.gpa.free(name_buf);
26222623
26232624 @memcpy(name_buf[0..name_prefix.len], name_prefix);
2624 for (mod.global_error_set.keys()) |name_nts| {
2625 const name = mod.intern_pool.stringToSlice(name_nts);
2625 for (mod.global_error_set.keys()) |name_ip| {
2626 const name = ip.stringToSlice(name_ip);
26262627 @memcpy(name_buf[name_prefix.len..][0..name.len], name);
26272628 const identifier = name_buf[0 .. name_prefix.len + name.len];
26282629
......@@ -2652,7 +2653,7 @@ pub fn genErrDecls(o: *Object) !void {
26522653 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = array_identifier }, Const, .none, .complete);
26532654 try writer.writeAll(" = {");
26542655 for (mod.global_error_set.keys(), 0..) |name_nts, value| {
2655 const name = mod.intern_pool.stringToSlice(name_nts);
2656 const name = ip.stringToSlice(name_nts);
26562657 if (value != 0) try writer.writeByte(',');
26572658
26582659 const len_val = try mod.intValue(Type.usize, name.len);
......@@ -2730,6 +2731,7 @@ fn genExports(o: *Object) !void {
27302731
27312732pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
27322733 const mod = o.dg.module;
2734 const ip = &mod.intern_pool;
27332735 const w = o.writer();
27342736 const key = lazy_fn.key_ptr.*;
27352737 const val = lazy_fn.value_ptr;
......@@ -2747,23 +2749,23 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
27472749 try w.writeByte('(');
27482750 try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete);
27492751 try w.writeAll(") {\n switch (tag) {\n");
2750 for (enum_ty.enumFields(mod), 0..) |name_ip, index_usize| {
2751 const index = @as(u32, @intCast(index_usize));
2752 const name = mod.intern_pool.stringToSlice(name_ip);
2753 const tag_val = try mod.enumValueFieldIndex(enum_ty, index);
2752 const tag_names = enum_ty.enumFields(mod);
2753 for (0..tag_names.len) |tag_index| {
2754 const tag_name = ip.stringToSlice(tag_names.get(ip)[tag_index]);
2755 const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index));
27542756
27552757 const int_val = try tag_val.intFromEnum(enum_ty, mod);
27562758
27572759 const name_ty = try mod.arrayType(.{
2758 .len = name.len,
2760 .len = tag_name.len,
27592761 .child = .u8_type,
27602762 .sentinel = .zero_u8,
27612763 });
27622764 const name_val = try mod.intern(.{ .aggregate = .{
27632765 .ty = name_ty.toIntern(),
2764 .storage = .{ .bytes = name },
2766 .storage = .{ .bytes = tag_name },
27652767 } });
2766 const len_val = try mod.intValue(Type.usize, name.len);
2768 const len_val = try mod.intValue(Type.usize, tag_name.len);
27672769
27682770 try w.print(" case {}: {{\n static ", .{
27692771 try o.dg.fmtIntLiteral(enum_ty, int_val, .Other),
src/codegen/llvm.zig+3-2
......@@ -9574,6 +9574,7 @@ pub const FuncGen = struct {
95749574 fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
95759575 const o = self.dg.object;
95769576 const mod = o.module;
9577 const ip = &mod.intern_pool;
95779578 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
95789579 const operand = try self.resolveInst(ty_op.operand);
95799580 const error_set_ty = ty_op.ty.toType();
......@@ -9585,8 +9586,8 @@ pub const FuncGen = struct {
95859586 var wip_switch = try self.wip.@"switch"(operand, invalid_block, @intCast(names.len));
95869587 defer wip_switch.finish(&self.wip);
95879588
9588 for (names) |name| {
9589 const err_int = mod.global_error_set.getIndex(name).?;
9589 for (0..names.len) |name_index| {
9590 const err_int = mod.global_error_set.getIndex(names.get(ip)[name_index]).?;
95909591 const this_tag_int_value = try o.builder.intConst(try o.errorIntType(), err_int);
95919592 try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
95929593 }
src/link/Dwarf.zig+1-1
......@@ -2828,7 +2828,7 @@ fn addDbgInfoErrorSet(
28282828 target: std.Target,
28292829 dbg_info_buffer: *std.ArrayList(u8),
28302830) !void {
2831 return addDbgInfoErrorSetNames(mod, ty, ty.errorSetNames(mod), target, dbg_info_buffer);
2831 return addDbgInfoErrorSetNames(mod, ty, ty.errorSetNames(mod).get(&mod.intern_pool), target, dbg_info_buffer);
28322832}
28332833
28342834fn addDbgInfoErrorSetNames(
src/type.zig+5-6
......@@ -2908,22 +2908,21 @@ pub const Type = struct {
29082908
29092909 // Asserts that `ty` is an error set and not `anyerror`.
29102910 // Asserts that `ty` is resolved if it is an inferred error set.
2911 pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
2911 pub fn errorSetNames(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice {
29122912 const ip = &mod.intern_pool;
29132913 return switch (ip.indexToKey(ty.toIntern())) {
2914 .error_set_type => |x| x.names.get(ip),
2914 .error_set_type => |x| x.names,
29152915 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
29162916 .none => unreachable, // unresolved inferred error set
29172917 .anyerror_type => unreachable,
2918 else => |t| ip.indexToKey(t).error_set_type.names.get(ip),
2918 else => |t| ip.indexToKey(t).error_set_type.names,
29192919 },
29202920 else => unreachable,
29212921 };
29222922 }
29232923
2924 pub fn enumFields(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
2925 const ip = &mod.intern_pool;
2926 return ip.indexToKey(ty.toIntern()).enum_type.names.get(ip);
2924 pub fn enumFields(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice {
2925 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names;
29272926 }
29282927
29292928 pub fn enumFieldCount(ty: Type, mod: *Module) usize {
test/cbe.zig+15-16
......@@ -219,23 +219,22 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void {
219219 , "");
220220 }
221221
222 // https://github.com/ziglang/zig/issues/18954
223 //{
224 // var case = ctx.exeFromCompiledC("inferred local const and var", .{}, b);
222 {
223 var case = ctx.exeFromCompiledC("inferred local const and var", .{}, b);
225224
226 // case.addCompareOutput(
227 // \\fn add(a: i32, b: i32) i32 {
228 // \\ return a + b;
229 // \\}
230 // \\
231 // \\pub export fn main() c_int {
232 // \\ const x = add(1, 2);
233 // \\ var y = add(3, 0);
234 // \\ y -= x;
235 // \\ return y;
236 // \\}
237 // , "");
238 //}
225 case.addCompareOutput(
226 \\fn add(a: i32, b: i32) i32 {
227 \\ return a + b;
228 \\}
229 \\
230 \\pub export fn main() c_int {
231 \\ const x = add(1, 2);
232 \\ var y = add(3, 0);
233 \\ y -= x;
234 \\ return y;
235 \\}
236 , "");
237 }
239238 {
240239 var case = ctx.exeFromCompiledC("control flow", .{}, b);
241240