diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2024-02-16 03:13:25 +0100 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-02-16 00:27:25 -0800 |
| commit | 6f08e172299320a3b243998878b38b0b3f43d8d5 (patch) | |
| tree | 22ca949d513aa57651081ce831875e322666eb2a | |
| parent | 0183b44bb10751c46bd520e673726a66c027b477 (diff) | |
| download | zig-6f08e172299320a3b243998878b38b0b3f43d8d5.tar.gz zig-6f08e172299320a3b243998878b38b0b3f43d8d5.zip | |
InternPool: make more use of `NullTerminatedString.Slice`
This should avoid the random pointer invalidation crashes.
Closes #18954
| -rw-r--r-- | src/Sema.zig | 23 | ||||
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 16 | ||||
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 13 | ||||
| -rw-r--r-- | src/codegen.zig | 6 | ||||
| -rw-r--r-- | src/codegen/c.zig | 24 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 5 | ||||
| -rw-r--r-- | src/link/Dwarf.zig | 2 | ||||
| -rw-r--r-- | src/type.zig | 11 | ||||
| -rw-r--r-- | test/cbe.zig | 31 |
9 files changed, 70 insertions, 61 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index d0b0efcf19..874c83ae0c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -12619,8 +12619,9 @@ fn analyzeSwitchRuntimeBlock( operand_ty.fmt(mod), }); } - for (0..operand_ty.errorSetNames(mod).len) |i| { - const error_name = operand_ty.errorSetNames(mod)[i]; + const error_names = operand_ty.errorSetNames(mod); + for (0..error_names.len) |name_index| { + const error_name = error_names.get(ip)[name_index]; if (seen_errors.contains(error_name)) continue; cases_len += 1; @@ -22362,8 +22363,9 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData if (!operand_ty.isAnyError(mod) and operand_ty.errorSetIsEmpty(mod)) break :disjoint true; if (dest_ty.isAnyError(mod)) break :disjoint false; if (operand_ty.isAnyError(mod)) break :disjoint false; - for (dest_ty.errorSetNames(mod)) |dest_err_name| { - if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name)) + const dest_err_names = dest_ty.errorSetNames(mod); + for (0..dest_err_names.len) |dest_err_index| { + if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_names.get(ip)[dest_err_index])) break :disjoint false; } @@ -22375,8 +22377,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData _ = try sema.resolveInferredErrorSetTy(block, src, dest_ty.toIntern()); _ = try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty.toIntern()); - for (dest_ty.errorSetNames(mod)) |dest_err_name| { - if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name)) + for (0..dest_err_names.len) |dest_err_index| { + if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_names.get(ip)[dest_err_index])) break :disjoint false; } @@ -38780,17 +38782,18 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type { /// Asserts that lhs and rhs are both error sets and are resolved. fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type { const mod = sema.mod; + const ip = &mod.intern_pool; const arena = sema.arena; const lhs_names = lhs.errorSetNames(mod); const rhs_names = rhs.errorSetNames(mod); var names: InferredErrorSet.NameMap = .{}; try names.ensureUnusedCapacity(arena, lhs_names.len); - for (lhs_names) |name| { - names.putAssumeCapacityNoClobber(name, {}); + for (0..lhs_names.len) |lhs_index| { + names.putAssumeCapacityNoClobber(lhs_names.get(ip)[lhs_index], {}); } - for (rhs_names) |name| { - try names.put(arena, name, {}); + for (0..rhs_names.len) |rhs_index| { + try names.put(arena, rhs_names.get(ip)[rhs_index], {}); } return mod.errorSetFromUnsortedNames(names.keys()); diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 3ee36690e4..4540724778 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -7216,13 +7216,14 @@ fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { const mod = func.bin_file.base.comp.module.?; + const ip = &mod.intern_pool; const enum_decl_index = enum_ty.getOwnerDecl(mod); var arena_allocator = std.heap.ArenaAllocator.init(func.gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const fqn = mod.intern_pool.stringToSlice(try mod.declPtr(enum_decl_index).getFullyQualifiedName(mod)); + const fqn = ip.stringToSlice(try mod.declPtr(enum_decl_index).getFullyQualifiedName(mod)); const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn}); // check if we already generated code for this. @@ -7252,9 +7253,9 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { // TODO: Make switch implementation generic so we can use a jump table for this when the tags are not sparse. // generate an if-else chain for each tag value as well as constant. - for (enum_ty.enumFields(mod), 0..) |tag_name_ip, field_index_usize| { - const field_index = @as(u32, @intCast(field_index_usize)); - const tag_name = mod.intern_pool.stringToSlice(tag_name_ip); + const tag_names = enum_ty.enumFields(mod); + for (0..tag_names.len) |tag_index| { + const tag_name = ip.stringToSlice(tag_names.get(ip)[tag_index]); // for each tag name, create an unnamed const, // and then get a pointer to its value. const name_ty = try mod.arrayType(.{ @@ -7279,7 +7280,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { try writer.writeByte(std.wasm.opcode(.local_get)); try leb.writeULEB128(writer, @as(u32, 1)); - const tag_val = try mod.enumValueFieldIndex(enum_ty, field_index); + const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index)); const tag_value = try func.lowerConstant(tag_val, enum_ty); switch (tag_value) { @@ -7372,6 +7373,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const mod = func.bin_file.base.comp.module.?; + const ip = &mod.intern_pool; const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try func.resolveInst(ty_op.operand); @@ -7384,8 +7386,8 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { var lowest: ?u32 = null; var highest: ?u32 = null; - for (names) |name| { - const err_int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(name).?)); + for (0..names.len) |name_index| { + const err_int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[name_index]).?); if (lowest) |*l| { if (err_int < l.*) { l.* = err_int; diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 33b8623183..857b980aad 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -2187,6 +2187,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { const mod = self.bin_file.comp.module.?; + const ip = &mod.intern_pool; switch (lazy_sym.ty.zigTypeTag(mod)) { .Enum => { const enum_ty = lazy_sym.ty; @@ -2209,10 +2210,10 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty }); var data_off: i32 = 0; - for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, index_usize| { - const index: u32 = @intCast(index_usize); - const tag_name = mod.intern_pool.stringToSlice(enum_ty.enumFields(mod)[index_usize]); - const tag_val = try mod.enumValueFieldIndex(enum_ty, index); + const tag_names = enum_ty.enumFields(mod); + for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| { + const tag_name_len = ip.stringToSlice(tag_names.get(ip)[tag_index]).len; + const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index)); const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val }); try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv); const skip_reloc = try self.asmJccReloc(.ne, undefined); @@ -2228,14 +2229,14 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { .{ .reg = ret_reg }, 8, Type.usize, - .{ .immediate = tag_name.len }, + .{ .immediate = tag_name_len }, .{}, ); exitlude_jump_reloc.* = try self.asmJmpReloc(undefined); self.performReloc(skip_reloc); - data_off += @intCast(tag_name.len + 1); + data_off += @intCast(tag_name_len + 1); } try self.airTrap(); diff --git a/src/codegen.zig b/src/codegen.zig index f16bf301a8..118bab4be9 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -119,6 +119,7 @@ pub fn generateLazySymbol( const comp = bin_file.comp; const zcu = comp.module.?; + const ip = &zcu.intern_pool; const target = comp.root_mod.resolved_target.result; const endian = target.cpu.arch.endian(); const gpa = comp.gpa; @@ -151,8 +152,9 @@ pub fn generateLazySymbol( return Result.ok; } else if (lazy_sym.ty.zigTypeTag(zcu) == .Enum) { alignment.* = .@"1"; - for (lazy_sym.ty.enumFields(zcu)) |tag_name_ip| { - const tag_name = zcu.intern_pool.stringToSlice(tag_name_ip); + const tag_names = lazy_sym.ty.enumFields(zcu); + for (0..tag_names.len) |tag_index| { + const tag_name = zcu.intern_pool.stringToSlice(tag_names.get(ip)[tag_index]); try code.ensureUnusedCapacity(tag_name.len + 1); code.appendSliceAssumeCapacity(tag_name); code.appendAssumeCapacity(0); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 4adabea7bb..405d97bbd3 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -2595,6 +2595,7 @@ pub fn genGlobalAsm(mod: *Module, writer: anytype) !void { pub fn genErrDecls(o: *Object) !void { const mod = o.dg.module; + const ip = &mod.intern_pool; const writer = o.writer(); var max_name_len: usize = 0; @@ -2603,7 +2604,7 @@ pub fn genErrDecls(o: *Object) !void { try writer.writeAll("enum {\n"); o.indent_writer.pushIndent(); for (mod.global_error_set.keys()[1..], 1..) |name_nts, value| { - const name = mod.intern_pool.stringToSlice(name_nts); + const name = ip.stringToSlice(name_nts); max_name_len = @max(name.len, max_name_len); const err_val = try mod.intern(.{ .err = .{ .ty = .anyerror_type, @@ -2621,8 +2622,8 @@ pub fn genErrDecls(o: *Object) !void { defer o.dg.gpa.free(name_buf); @memcpy(name_buf[0..name_prefix.len], name_prefix); - for (mod.global_error_set.keys()) |name_nts| { - const name = mod.intern_pool.stringToSlice(name_nts); + for (mod.global_error_set.keys()) |name_ip| { + const name = ip.stringToSlice(name_ip); @memcpy(name_buf[name_prefix.len..][0..name.len], name); const identifier = name_buf[0 .. name_prefix.len + name.len]; @@ -2652,7 +2653,7 @@ pub fn genErrDecls(o: *Object) !void { try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = array_identifier }, Const, .none, .complete); try writer.writeAll(" = {"); for (mod.global_error_set.keys(), 0..) |name_nts, value| { - const name = mod.intern_pool.stringToSlice(name_nts); + const name = ip.stringToSlice(name_nts); if (value != 0) try writer.writeByte(','); const len_val = try mod.intValue(Type.usize, name.len); @@ -2730,6 +2731,7 @@ fn genExports(o: *Object) !void { pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { const mod = o.dg.module; + const ip = &mod.intern_pool; const w = o.writer(); const key = lazy_fn.key_ptr.*; const val = lazy_fn.value_ptr; @@ -2747,23 +2749,23 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { try w.writeByte('('); try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); try w.writeAll(") {\n switch (tag) {\n"); - for (enum_ty.enumFields(mod), 0..) |name_ip, index_usize| { - const index = @as(u32, @intCast(index_usize)); - const name = mod.intern_pool.stringToSlice(name_ip); - const tag_val = try mod.enumValueFieldIndex(enum_ty, index); + const tag_names = enum_ty.enumFields(mod); + for (0..tag_names.len) |tag_index| { + const tag_name = ip.stringToSlice(tag_names.get(ip)[tag_index]); + const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index)); const int_val = try tag_val.intFromEnum(enum_ty, mod); const name_ty = try mod.arrayType(.{ - .len = name.len, + .len = tag_name.len, .child = .u8_type, .sentinel = .zero_u8, }); const name_val = try mod.intern(.{ .aggregate = .{ .ty = name_ty.toIntern(), - .storage = .{ .bytes = name }, + .storage = .{ .bytes = tag_name }, } }); - const len_val = try mod.intValue(Type.usize, name.len); + const len_val = try mod.intValue(Type.usize, tag_name.len); try w.print(" case {}: {{\n static ", .{ try o.dg.fmtIntLiteral(enum_ty, int_val, .Other), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index f5b4aa540f..017abf8eaf 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -9574,6 +9574,7 @@ pub const FuncGen = struct { fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const o = self.dg.object; const mod = o.module; + const ip = &mod.intern_pool; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const error_set_ty = ty_op.ty.toType(); @@ -9585,8 +9586,8 @@ pub const FuncGen = struct { var wip_switch = try self.wip.@"switch"(operand, invalid_block, @intCast(names.len)); defer wip_switch.finish(&self.wip); - for (names) |name| { - const err_int = mod.global_error_set.getIndex(name).?; + for (0..names.len) |name_index| { + const err_int = mod.global_error_set.getIndex(names.get(ip)[name_index]).?; const this_tag_int_value = try o.builder.intConst(try o.errorIntType(), err_int); try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip); } diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index a5dd57a406..51a8e5aa61 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -2828,7 +2828,7 @@ fn addDbgInfoErrorSet( target: std.Target, dbg_info_buffer: *std.ArrayList(u8), ) !void { - return addDbgInfoErrorSetNames(mod, ty, ty.errorSetNames(mod), target, dbg_info_buffer); + return addDbgInfoErrorSetNames(mod, ty, ty.errorSetNames(mod).get(&mod.intern_pool), target, dbg_info_buffer); } fn addDbgInfoErrorSetNames( diff --git a/src/type.zig b/src/type.zig index 43eaa9132a..a6265692c2 100644 --- a/src/type.zig +++ b/src/type.zig @@ -2908,22 +2908,21 @@ pub const Type = struct { // Asserts that `ty` is an error set and not `anyerror`. // Asserts that `ty` is resolved if it is an inferred error set. - pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString { + pub fn errorSetNames(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice { const ip = &mod.intern_pool; return switch (ip.indexToKey(ty.toIntern())) { - .error_set_type => |x| x.names.get(ip), + .error_set_type => |x| x.names, .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) { .none => unreachable, // unresolved inferred error set .anyerror_type => unreachable, - else => |t| ip.indexToKey(t).error_set_type.names.get(ip), + else => |t| ip.indexToKey(t).error_set_type.names, }, else => unreachable, }; } - pub fn enumFields(ty: Type, mod: *Module) []const InternPool.NullTerminatedString { - const ip = &mod.intern_pool; - return ip.indexToKey(ty.toIntern()).enum_type.names.get(ip); + pub fn enumFields(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice { + return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names; } pub fn enumFieldCount(ty: Type, mod: *Module) usize { diff --git a/test/cbe.zig b/test/cbe.zig index 99a62c0ad5..35c2d8e8f9 100644 --- a/test/cbe.zig +++ b/test/cbe.zig @@ -219,23 +219,22 @@ pub fn addCases(ctx: *Cases, b: *std.Build) !void { , ""); } - // https://github.com/ziglang/zig/issues/18954 - //{ - // var case = ctx.exeFromCompiledC("inferred local const and var", .{}, b); + { + var case = ctx.exeFromCompiledC("inferred local const and var", .{}, b); - // case.addCompareOutput( - // \\fn add(a: i32, b: i32) i32 { - // \\ return a + b; - // \\} - // \\ - // \\pub export fn main() c_int { - // \\ const x = add(1, 2); - // \\ var y = add(3, 0); - // \\ y -= x; - // \\ return y; - // \\} - // , ""); - //} + case.addCompareOutput( + \\fn add(a: i32, b: i32) i32 { + \\ return a + b; + \\} + \\ + \\pub export fn main() c_int { + \\ const x = add(1, 2); + \\ var y = add(3, 0); + \\ y -= x; + \\ return y; + \\} + , ""); + } { var case = ctx.exeFromCompiledC("control flow", .{}, b); |
