diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index db082b7f8e..64e8a1c805 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -106,12 +106,8 @@ pub const NullTerminatedString = enum(u32) { /// Given an index into `string_bytes` returns the null-terminated string found there. pub fn nullTerminatedString(code: Zir, index: NullTerminatedString) [:0]const u8 { - const start = @intFromEnum(index); - var end: u32 = start; - while (code.string_bytes[end] != 0) { - end += 1; - } - return code.string_bytes[start..end :0]; + const slice = code.string_bytes[@intFromEnum(index)..]; + return slice[0..std.mem.indexOfScalar(u8, slice, 0).? :0]; } pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref { diff --git a/src/Compilation.zig b/src/Compilation.zig index c533f2fae7..5395be9f32 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3159,7 +3159,7 @@ pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Mod const rt_file_path = try module_reference.src_loc.file_scope.fullPath(gpa); defer gpa.free(rt_file_path); ref_traces.appendAssumeCapacity(.{ - .decl_name = try eb.addString(ip.stringToSlice(module_reference.decl)), + .decl_name = try eb.addString(module_reference.decl.toSlice(ip)), .src_loc = try eb.addSourceLocation(.{ .src_path = try eb.addString(rt_file_path), .span_start = span.start, @@ -4074,8 +4074,7 @@ fn workerCheckEmbedFile( fn detectEmbedFileUpdate(comp: *Compilation, embed_file: *Module.EmbedFile) !void { const mod = comp.module.?; const ip = &mod.intern_pool; - const sub_file_path = ip.stringToSlice(embed_file.sub_file_path); - var file = try embed_file.owner.root.openFile(sub_file_path, .{}); + var file = try embed_file.owner.root.openFile(embed_file.sub_file_path.toSlice(ip), .{}); defer file.close(); const stat = try file.stat(); @@ -4444,7 +4443,7 @@ fn reportRetryableEmbedFileError( const ip = &mod.intern_pool; const err_msg = try Module.ErrorMsg.create(gpa, src_loc, "unable to load '{}{s}': {s}", .{ embed_file.owner.root, - ip.stringToSlice(embed_file.sub_file_path), + embed_file.sub_file_path.toSlice(ip), @errorName(err), }); diff --git a/src/InternPool.zig b/src/InternPool.zig index 1155d8c5ad..15dba62e07 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -351,7 +351,7 @@ const KeyAdapter = struct { pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool { _ = b_void; if (ctx.intern_pool.items.items(.tag)[b_map_index] == .removed) return false; - return ctx.intern_pool.indexToKey(@as(Index, @enumFromInt(b_map_index))).eql(a, ctx.intern_pool); + return ctx.intern_pool.indexToKey(@enumFromInt(b_map_index)).eql(a, ctx.intern_pool); } pub fn hash(ctx: @This(), a: Key) u32 { @@ -385,7 +385,7 @@ pub const RuntimeIndex = enum(u32) { _, pub fn increment(ri: *RuntimeIndex) void { - ri.* = @as(RuntimeIndex, @enumFromInt(@intFromEnum(ri.*) + 1)); + ri.* = @enumFromInt(@intFromEnum(ri.*) + 1); } }; @@ -418,12 +418,44 @@ pub const OptionalNamespaceIndex = enum(u32) { /// An index into `string_bytes`. pub const String = enum(u32) { + /// An empty string. + empty = 0, _, + + pub fn toSlice(string: String, len: u64, ip: *const InternPool) []const u8 { + return ip.string_bytes.items[@intFromEnum(string)..][0..@intCast(len)]; + } + + pub fn at(string: String, index: u64, ip: *const InternPool) u8 { + return ip.string_bytes.items[@intCast(@intFromEnum(string) + index)]; + } + + pub fn toNullTerminatedString(string: String, len: u64, ip: *const InternPool) NullTerminatedString { + assert(std.mem.indexOfScalar(u8, string.toSlice(len, ip), 0) == null); + assert(string.at(len, ip) == 0); + return @enumFromInt(@intFromEnum(string)); + } +}; + +/// An index into `string_bytes` which might be `none`. +pub const OptionalString = enum(u32) { + /// This is distinct from `none` - it is a valid index that represents empty string. + empty = 0, + none = std.math.maxInt(u32), + _, + + pub fn unwrap(string: OptionalString) ?String { + return if (string != .none) @enumFromInt(@intFromEnum(string)) else null; + } + + pub fn toSlice(string: OptionalString, len: u64, ip: *const InternPool) ?[]const u8 { + return (string.unwrap() orelse return null).toSlice(len, ip); + } }; /// An index into `string_bytes`. pub const NullTerminatedString = enum(u32) { - /// This is distinct from `none` - it is a valid index that represents empty string. + /// An empty string. empty = 0, _, @@ -447,6 +479,19 @@ pub const NullTerminatedString = enum(u32) { return @enumFromInt(@intFromEnum(self)); } + pub fn toSlice(string: NullTerminatedString, ip: *const InternPool) [:0]const u8 { + const slice = ip.string_bytes.items[@intFromEnum(string)..]; + return slice[0..std.mem.indexOfScalar(u8, slice, 0).? :0]; + } + + pub fn length(string: NullTerminatedString, ip: *const InternPool) u32 { + return @intCast(string.toSlice(ip).len); + } + + pub fn eqlSlice(string: NullTerminatedString, slice: []const u8, ip: *const InternPool) bool { + return std.mem.eql(u8, string.toSlice(ip), slice); + } + const Adapter = struct { strings: []const NullTerminatedString, @@ -467,11 +512,11 @@ pub const NullTerminatedString = enum(u32) { return @intFromEnum(a) < @intFromEnum(b); } - pub fn toUnsigned(self: NullTerminatedString, ip: *const InternPool) ?u32 { - const s = ip.stringToSlice(self); - if (s.len > 1 and s[0] == '0') return null; - if (std.mem.indexOfScalar(u8, s, '_')) |_| return null; - return std.fmt.parseUnsigned(u32, s, 10) catch null; + pub fn toUnsigned(string: NullTerminatedString, ip: *const InternPool) ?u32 { + const slice = string.toSlice(ip); + if (slice.len > 1 and slice[0] == '0') return null; + if (std.mem.indexOfScalar(u8, slice, '_')) |_| return null; + return std.fmt.parseUnsigned(u32, slice, 10) catch null; } const FormatData = struct { @@ -484,11 +529,11 @@ pub const NullTerminatedString = enum(u32) { _: std.fmt.FormatOptions, writer: anytype, ) @TypeOf(writer).Error!void { - const s = data.ip.stringToSlice(data.string); + const slice = data.string.toSlice(data.ip); if (comptime std.mem.eql(u8, specifier, "")) { - try writer.writeAll(s); + try writer.writeAll(slice); } else if (comptime std.mem.eql(u8, specifier, "i")) { - try writer.print("{p}", .{std.zig.fmtId(s)}); + try writer.print("{p}", .{std.zig.fmtId(slice)}); } else @compileError("invalid format string '" ++ specifier ++ "' for '" ++ @typeName(NullTerminatedString) ++ "'"); } @@ -504,9 +549,12 @@ pub const OptionalNullTerminatedString = enum(u32) { none = std.math.maxInt(u32), _, - pub fn unwrap(oi: OptionalNullTerminatedString) ?NullTerminatedString { - if (oi == .none) return null; - return @enumFromInt(@intFromEnum(oi)); + pub fn unwrap(string: OptionalNullTerminatedString) ?NullTerminatedString { + return if (string != .none) @enumFromInt(@intFromEnum(string)) else null; + } + + pub fn toSlice(string: OptionalNullTerminatedString, ip: *const InternPool) ?[:0]const u8 { + return (string.unwrap() orelse return null).toSlice(ip); } }; @@ -690,6 +738,10 @@ pub const Key = union(enum) { len: u64, child: Index, sentinel: Index = .none, + + pub fn lenIncludingSentinel(array_type: ArrayType) u64 { + return array_type.len + @intFromBool(array_type.sentinel != .none); + } }; /// Extern so that hashing can be done via memory reinterpreting. @@ -1043,7 +1095,7 @@ pub const Key = union(enum) { storage: Storage, pub const Storage = union(enum) { - bytes: []const u8, + bytes: String, elems: []const Index, repeated_elem: Index, @@ -1203,7 +1255,7 @@ pub const Key = union(enum) { if (child == .u8_type) { switch (aggregate.storage) { - .bytes => |bytes| for (bytes[0..@intCast(len)]) |byte| { + .bytes => |bytes| for (bytes.toSlice(len, ip)) |byte| { std.hash.autoHash(&hasher, KeyTag.int); std.hash.autoHash(&hasher, byte); }, @@ -1240,7 +1292,7 @@ pub const Key = union(enum) { switch (aggregate.storage) { .bytes => unreachable, - .elems => |elems| for (elems[0..@as(usize, @intCast(len))]) |elem| + .elems => |elems| for (elems[0..@intCast(len)]) |elem| std.hash.autoHash(&hasher, elem), .repeated_elem => |elem| { var remaining = len; @@ -1505,11 +1557,11 @@ pub const Key = union(enum) { if (a_info.ty == .c_longdouble_type and a_info.storage != .f80) { // These are strange: we'll sometimes represent them as f128, even if the // underlying type is smaller. f80 is an exception: see float_c_longdouble_f80. - const a_val = switch (a_info.storage) { - inline else => |val| @as(u128, @bitCast(@as(f128, @floatCast(val)))), + const a_val: u128 = switch (a_info.storage) { + inline else => |val| @bitCast(@as(f128, @floatCast(val))), }; - const b_val = switch (b_info.storage) { - inline else => |val| @as(u128, @bitCast(@as(f128, @floatCast(val)))), + const b_val: u128 = switch (b_info.storage) { + inline else => |val| @bitCast(@as(f128, @floatCast(val))), }; return a_val == b_val; } @@ -1560,11 +1612,11 @@ pub const Key = union(enum) { const len = ip.aggregateTypeLen(a_info.ty); const StorageTag = @typeInfo(Key.Aggregate.Storage).Union.tag_type.?; if (@as(StorageTag, a_info.storage) != @as(StorageTag, b_info.storage)) { - for (0..@as(usize, @intCast(len))) |elem_index| { + for (0..@intCast(len)) |elem_index| { const a_elem = switch (a_info.storage) { .bytes => |bytes| ip.getIfExists(.{ .int = .{ .ty = .u8_type, - .storage = .{ .u64 = bytes[elem_index] }, + .storage = .{ .u64 = bytes.at(elem_index, ip) }, } }) orelse return false, .elems => |elems| elems[elem_index], .repeated_elem => |elem| elem, @@ -1572,7 +1624,7 @@ pub const Key = union(enum) { const b_elem = switch (b_info.storage) { .bytes => |bytes| ip.getIfExists(.{ .int = .{ .ty = .u8_type, - .storage = .{ .u64 = bytes[elem_index] }, + .storage = .{ .u64 = bytes.at(elem_index, ip) }, } }) orelse return false, .elems => |elems| elems[elem_index], .repeated_elem => |elem| elem, @@ -1585,18 +1637,15 @@ pub const Key = union(enum) { switch (a_info.storage) { .bytes => |a_bytes| { const b_bytes = b_info.storage.bytes; - return std.mem.eql( - u8, - a_bytes[0..@as(usize, @intCast(len))], - b_bytes[0..@as(usize, @intCast(len))], - ); + return a_bytes == b_bytes or + std.mem.eql(u8, a_bytes.toSlice(len, ip), b_bytes.toSlice(len, ip)); }, .elems => |a_elems| { const b_elems = b_info.storage.elems; return std.mem.eql( Index, - a_elems[0..@as(usize, @intCast(len))], - b_elems[0..@as(usize, @intCast(len))], + a_elems[0..@intCast(len)], + b_elems[0..@intCast(len)], ); }, .repeated_elem => |a_elem| { @@ -4175,10 +4224,10 @@ pub const Float64 = struct { } fn pack(val: f64) Float64 { - const bits = @as(u64, @bitCast(val)); + const bits: u64 = @bitCast(val); return .{ - .piece0 = @as(u32, @truncate(bits)), - .piece1 = @as(u32, @truncate(bits >> 32)), + .piece0 = @truncate(bits), + .piece1 = @truncate(bits >> 32), }; } }; @@ -4197,11 +4246,11 @@ pub const Float80 = struct { } fn pack(val: f80) Float80 { - const bits = @as(u80, @bitCast(val)); + const bits: u80 = @bitCast(val); return .{ - .piece0 = @as(u32, @truncate(bits)), - .piece1 = @as(u32, @truncate(bits >> 32)), - .piece2 = @as(u16, @truncate(bits >> 64)), + .piece0 = @truncate(bits), + .piece1 = @truncate(bits >> 32), + .piece2 = @truncate(bits >> 64), }; } }; @@ -4222,12 +4271,12 @@ pub const Float128 = struct { } fn pack(val: f128) Float128 { - const bits = @as(u128, @bitCast(val)); + const bits: u128 = @bitCast(val); return .{ - .piece0 = @as(u32, @truncate(bits)), - .piece1 = @as(u32, @truncate(bits >> 32)), - .piece2 = @as(u32, @truncate(bits >> 64)), - .piece3 = @as(u32, @truncate(bits >> 96)), + .piece0 = @truncate(bits), + .piece1 = @truncate(bits >> 32), + .piece2 = @truncate(bits >> 64), + .piece3 = @truncate(bits >> 96), }; } }; @@ -4244,7 +4293,7 @@ pub fn init(ip: *InternPool, gpa: Allocator) !void { assert(ip.items.len == 0); // Reserve string index 0 for an empty string. - assert((try ip.getOrPutString(gpa, "")) == .empty); + assert((try ip.getOrPutString(gpa, "", .no_embedded_nulls)) == .empty); // So that we can use `catch unreachable` below. try ip.items.ensureUnusedCapacity(gpa, static_keys.len); @@ -4329,13 +4378,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .type_int_signed => .{ .int_type = .{ .signedness = .signed, - .bits = @as(u16, @intCast(data)), + .bits = @intCast(data), }, }, .type_int_unsigned => .{ .int_type = .{ .signedness = .unsigned, - .bits = @as(u16, @intCast(data)), + .bits = @intCast(data), }, }, .type_array_big => { @@ -4354,8 +4403,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .sentinel = .none, } }; }, - .simple_type => .{ .simple_type = @as(SimpleType, @enumFromInt(data)) }, - .simple_value => .{ .simple_value = @as(SimpleValue, @enumFromInt(data)) }, + .simple_type => .{ .simple_type = @enumFromInt(data) }, + .simple_value => .{ .simple_value = @enumFromInt(data) }, .type_vector => { const vector_info = ip.extraData(Vector, data); @@ -4506,9 +4555,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { } }, .type_function => .{ .func_type = ip.extraFuncType(data) }, - .undef => .{ .undef = @as(Index, @enumFromInt(data)) }, + .undef => .{ .undef = @enumFromInt(data) }, .opt_null => .{ .opt = .{ - .ty = @as(Index, @enumFromInt(data)), + .ty = @enumFromInt(data), .val = .none, } }, .opt_payload => { @@ -4670,11 +4719,11 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { }, .float_f16 => .{ .float = .{ .ty = .f16_type, - .storage = .{ .f16 = @as(f16, @bitCast(@as(u16, @intCast(data)))) }, + .storage = .{ .f16 = @bitCast(@as(u16, @intCast(data))) }, } }, .float_f32 => .{ .float = .{ .ty = .f32_type, - .storage = .{ .f32 = @as(f32, @bitCast(data)) }, + .storage = .{ .f32 = @bitCast(data) }, } }, .float_f64 => .{ .float = .{ .ty = .f64_type, @@ -4771,10 +4820,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { }, .bytes => { const extra = ip.extraData(Bytes, data); - const len: u32 = @intCast(ip.aggregateTypeLenIncludingSentinel(extra.ty)); return .{ .aggregate = .{ .ty = extra.ty, - .storage = .{ .bytes = ip.string_bytes.items[@intFromEnum(extra.bytes)..][0..len] }, + .storage = .{ .bytes = extra.bytes }, } }; }, .aggregate => { @@ -4809,14 +4857,14 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .val = .{ .payload = extra.val }, } }; }, - .enum_literal => .{ .enum_literal = @as(NullTerminatedString, @enumFromInt(data)) }, + .enum_literal => .{ .enum_literal = @enumFromInt(data) }, .enum_tag => .{ .enum_tag = ip.extraData(Tag.EnumTag, data) }, .memoized_call => { const extra = ip.extraDataTrail(MemoizedCall, data); return .{ .memoized_call = .{ .func = extra.data.func, - .arg_values = @as([]const Index, @ptrCast(ip.extra.items[extra.end..][0..extra.data.args_len])), + .arg_values = @ptrCast(ip.extra.items[extra.end..][0..extra.data.args_len]), .result = extra.data.result, } }; }, @@ -5596,9 +5644,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { switch (aggregate.storage) { .bytes => |bytes| { assert(child == .u8_type); - if (bytes.len != len) { - assert(bytes.len == len_including_sentinel); - assert(bytes[@intCast(len)] == ip.indexToKey(sentinel).int.storage.u64); + if (sentinel != .none) { + assert(bytes.at(@intCast(len), ip) == ip.indexToKey(sentinel).int.storage.u64); } }, .elems => |elems| { @@ -5641,11 +5688,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { switch (ty_key) { .anon_struct_type => |anon_struct_type| opv: { switch (aggregate.storage) { - .bytes => |bytes| for (anon_struct_type.values.get(ip), bytes) |value, byte| { - if (value != ip.getIfExists(.{ .int = .{ - .ty = .u8_type, - .storage = .{ .u64 = byte }, - } })) break :opv; + .bytes => |bytes| for (anon_struct_type.values.get(ip), bytes.at(0, ip)..) |value, byte| { + if (value == .none) break :opv; + switch (ip.indexToKey(value)) { + .undef => break :opv, + .int => |int| switch (int.storage) { + .u64 => |x| if (x != byte) break :opv, + else => break :opv, + }, + else => unreachable, + } }, .elems => |elems| if (!std.mem.eql( Index, @@ -5670,9 +5722,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { repeated: { switch (aggregate.storage) { - .bytes => |bytes| for (bytes[1..@as(usize, @intCast(len))]) |byte| - if (byte != bytes[0]) break :repeated, - .elems => |elems| for (elems[1..@as(usize, @intCast(len))]) |elem| + .bytes => |bytes| for (bytes.toSlice(len, ip)[1..]) |byte| + if (byte != bytes.at(0, ip)) break :repeated, + .elems => |elems| for (elems[1..@intCast(len)]) |elem| if (elem != elems[0]) break :repeated, .repeated_elem => {}, } @@ -5681,7 +5733,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { _ = ip.map.pop(); const elem = try ip.get(gpa, .{ .int = .{ .ty = .u8_type, - .storage = .{ .u64 = bytes[0] }, + .storage = .{ .u64 = bytes.at(0, ip) }, } }); assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing); try ip.items.ensureUnusedCapacity(gpa, 1); @@ -5710,7 +5762,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { try ip.string_bytes.ensureUnusedCapacity(gpa, @intCast(len_including_sentinel + 1)); try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Bytes).Struct.fields.len); switch (aggregate.storage) { - .bytes => |bytes| ip.string_bytes.appendSliceAssumeCapacity(bytes[0..@intCast(len)]), + .bytes => |bytes| ip.string_bytes.appendSliceAssumeCapacity(bytes.toSlice(len, ip)), .elems => |elems| for (elems[0..@intCast(len)]) |elem| switch (ip.indexToKey(elem)) { .undef => { ip.string_bytes.shrinkRetainingCapacity(string_bytes_index); @@ -5730,15 +5782,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { else => unreachable, }, } - const has_internal_null = - std.mem.indexOfScalar(u8, ip.string_bytes.items[string_bytes_index..], 0) != null; if (sentinel != .none) ip.string_bytes.appendAssumeCapacity( @intCast(ip.indexToKey(sentinel).int.storage.u64), ); - const string: String = if (has_internal_null) - @enumFromInt(string_bytes_index) - else - (try ip.getOrPutTrailingString(gpa, @intCast(len_including_sentinel))).toString(); + const string = try ip.getOrPutTrailingString( + gpa, + @intCast(len_including_sentinel), + .maybe_embedded_nulls, + ); ip.items.appendAssumeCapacity(.{ .tag = .bytes, .data = ip.addExtraAssumeCapacity(Bytes{ @@ -5780,7 +5831,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { .tag = .memoized_call, .data = ip.addExtraAssumeCapacity(MemoizedCall{ .func = memoized_call.func, - .args_len = @as(u32, @intCast(memoized_call.arg_values.len)), + .args_len = @intCast(memoized_call.arg_values.len), .result = memoized_call.result, }), }); @@ -6753,7 +6804,7 @@ fn finishFuncInstance( const decl = ip.declPtr(decl_index); decl.name = try ip.getOrPutStringFmt(gpa, "{}__anon_{d}", .{ fn_owner_decl.name.fmt(ip), @intFromEnum(decl_index), - }); + }, .no_embedded_nulls); return func_index; } @@ -7216,7 +7267,7 @@ pub fn remove(ip: *InternPool, index: Index) void { } fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void { - const limbs_len = @as(u32, @intCast(limbs.len)); + const limbs_len: u32 = @intCast(limbs.len); try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len); ip.items.appendAssumeCapacity(.{ .tag = tag, @@ -7235,7 +7286,7 @@ fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 } fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { - const result = @as(u32, @intCast(ip.extra.items.len)); + const result: u32 = @intCast(ip.extra.items.len); inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| { ip.extra.appendAssumeCapacity(switch (field.type) { Index, @@ -7286,7 +7337,7 @@ fn addLimbsExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { @sizeOf(u64) => {}, else => @compileError("unsupported host"), } - const result = @as(u32, @intCast(ip.limbs.items.len)); + const result: u32 = @intCast(ip.limbs.items.len); inline for (@typeInfo(@TypeOf(extra)).Struct.fields, 0..) |field, i| { const new: u32 = switch (field.type) { u32 => @field(extra, field.name), @@ -7374,7 +7425,7 @@ fn limbData(ip: *const InternPool, comptime T: type, index: usize) T { @field(result, field.name) = switch (field.type) { u32 => int32, - Index => @as(Index, @enumFromInt(int32)), + Index => @enumFromInt(int32), else => @compileError("bad field type: " ++ @typeName(field.type)), }; } @@ -7410,8 +7461,8 @@ fn limbsSliceToIndex(ip: *const InternPool, limbs: []const Limb) LimbsAsIndexes }; // TODO: https://github.com/ziglang/zig/issues/1738 return .{ - .start = @as(u32, @intCast(@divExact(@intFromPtr(limbs.ptr) - @intFromPtr(host_slice.ptr), @sizeOf(Limb)))), - .len = @as(u32, @intCast(limbs.len)), + .start = @intCast(@divExact(@intFromPtr(limbs.ptr) - @intFromPtr(host_slice.ptr), @sizeOf(Limb))), + .len = @intCast(limbs.len), }; } @@ -7683,7 +7734,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al .val = error_union.val, } }), .aggregate => |aggregate| { - const new_len = @as(usize, @intCast(ip.aggregateTypeLen(new_ty))); + const new_len: usize = @intCast(ip.aggregateTypeLen(new_ty)); direct: { const old_ty_child = switch (ip.indexToKey(old_ty)) { inline .array_type, .vector_type => |seq_type| seq_type.child, @@ -7696,16 +7747,11 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al else => unreachable, }; if (old_ty_child != new_ty_child) break :direct; - // TODO: write something like getCoercedInts to avoid needing to dupe here switch (aggregate.storage) { - .bytes => |bytes| { - const bytes_copy = try gpa.dupe(u8, bytes[0..new_len]); - defer gpa.free(bytes_copy); - return ip.get(gpa, .{ .aggregate = .{ - .ty = new_ty, - .storage = .{ .bytes = bytes_copy }, - } }); - }, + .bytes => |bytes| return ip.get(gpa, .{ .aggregate = .{ + .ty = new_ty, + .storage = .{ .bytes = bytes }, + } }), .elems => |elems| { const elems_copy = try gpa.dupe(Index, elems[0..new_len]); defer gpa.free(elems_copy); @@ -7729,14 +7775,13 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al // lifetime issues, since it'll allow us to avoid referencing `aggregate` after we // begin interning elems. switch (aggregate.storage) { - .bytes => { + .bytes => |bytes| { // We have to intern each value here, so unfortunately we can't easily avoid // the repeated indexToKey calls. - for (agg_elems, 0..) |*elem, i| { - const x = ip.indexToKey(val).aggregate.storage.bytes[i]; + for (agg_elems, 0..) |*elem, index| { elem.* = try ip.get(gpa, .{ .int = .{ .ty = .u8_type, - .storage = .{ .u64 = x }, + .storage = .{ .u64 = bytes.at(index, ip) }, } }); } }, @@ -8169,9 +8214,8 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { .bytes => b: { const info = ip.extraData(Bytes, data); - const len = @as(u32, @intCast(ip.aggregateTypeLenIncludingSentinel(info.ty))); - break :b @sizeOf(Bytes) + len + - @intFromBool(ip.string_bytes.items[@intFromEnum(info.bytes) + len - 1] != 0); + const len: usize = @intCast(ip.aggregateTypeLenIncludingSentinel(info.ty)); + break :b @sizeOf(Bytes) + len + @intFromBool(info.bytes.at(len - 1, ip) != 0); }, .aggregate => b: { const info = ip.extraData(Tag.Aggregate, data); @@ -8434,15 +8478,35 @@ pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: NamespaceIndex) }; } +const EmbeddedNulls = enum { + no_embedded_nulls, + maybe_embedded_nulls, + + fn StringType(comptime embedded_nulls: EmbeddedNulls) type { + return switch (embedded_nulls) { + .no_embedded_nulls => NullTerminatedString, + .maybe_embedded_nulls => String, + }; + } + + fn OptionalStringType(comptime embedded_nulls: EmbeddedNulls) type { + return switch (embedded_nulls) { + .no_embedded_nulls => OptionalNullTerminatedString, + .maybe_embedded_nulls => OptionalString, + }; + } +}; + pub fn getOrPutString( ip: *InternPool, gpa: Allocator, - s: []const u8, -) Allocator.Error!NullTerminatedString { - try ip.string_bytes.ensureUnusedCapacity(gpa, s.len + 1); - ip.string_bytes.appendSliceAssumeCapacity(s); + slice: []const u8, + comptime embedded_nulls: EmbeddedNulls, +) Allocator.Error!embedded_nulls.StringType() { + try ip.string_bytes.ensureUnusedCapacity(gpa, slice.len + 1); + ip.string_bytes.appendSliceAssumeCapacity(slice); ip.string_bytes.appendAssumeCapacity(0); - return ip.getOrPutTrailingString(gpa, s.len + 1); + return ip.getOrPutTrailingString(gpa, slice.len + 1, embedded_nulls); } pub fn getOrPutStringFmt( @@ -8450,23 +8514,24 @@ pub fn getOrPutStringFmt( gpa: Allocator, comptime format: []const u8, args: anytype, -) Allocator.Error!NullTerminatedString { + comptime embedded_nulls: EmbeddedNulls, +) Allocator.Error!embedded_nulls.StringType() { // ensure that references to string_bytes in args do not get invalidated const len: usize = @intCast(std.fmt.count(format, args) + 1); try ip.string_bytes.ensureUnusedCapacity(gpa, len); ip.string_bytes.writer(undefined).print(format, args) catch unreachable; ip.string_bytes.appendAssumeCapacity(0); - return ip.getOrPutTrailingString(gpa, len); + return ip.getOrPutTrailingString(gpa, len, embedded_nulls); } pub fn getOrPutStringOpt( ip: *InternPool, gpa: Allocator, - optional_string: ?[]const u8, -) Allocator.Error!OptionalNullTerminatedString { - const s = optional_string orelse return .none; - const interned = try getOrPutString(ip, gpa, s); - return interned.toOptional(); + slice: ?[]const u8, + comptime embedded_nulls: EmbeddedNulls, +) Allocator.Error!embedded_nulls.OptionalStringType() { + const string = try getOrPutString(ip, gpa, slice orelse return .none, embedded_nulls); + return string.toOptional(); } /// Uses the last len bytes of ip.string_bytes as the key. @@ -8474,7 +8539,8 @@ pub fn getOrPutTrailingString( ip: *InternPool, gpa: Allocator, len: usize, -) Allocator.Error!NullTerminatedString { + comptime embedded_nulls: EmbeddedNulls, +) Allocator.Error!embedded_nulls.StringType() { const string_bytes = &ip.string_bytes; const str_index: u32 = @intCast(string_bytes.items.len - len); if (len > 0 and string_bytes.getLast() == 0) { @@ -8483,6 +8549,14 @@ pub fn getOrPutTrailingString( try string_bytes.ensureUnusedCapacity(gpa, 1); } const key: []const u8 = string_bytes.items[str_index..]; + const has_embedded_null = std.mem.indexOfScalar(u8, key, 0) != null; + switch (embedded_nulls) { + .no_embedded_nulls => assert(!has_embedded_null), + .maybe_embedded_nulls => if (has_embedded_null) { + string_bytes.appendAssumeCapacity(0); + return @enumFromInt(str_index); + }, + } const gop = try ip.string_table.getOrPutContextAdapted(gpa, key, std.hash_map.StringIndexAdapter{ .bytes = string_bytes, }, std.hash_map.StringIndexContext{ @@ -8498,58 +8572,10 @@ pub fn getOrPutTrailingString( } } -/// Uses the last len bytes of ip.string_bytes as the key. -pub fn getTrailingAggregate( - ip: *InternPool, - gpa: Allocator, - ty: Index, - len: usize, -) Allocator.Error!Index { - try ip.items.ensureUnusedCapacity(gpa, 1); - try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Bytes).Struct.fields.len); - - const str: String = @enumFromInt(ip.string_bytes.items.len - len); - const adapter: KeyAdapter = .{ .intern_pool = ip }; - const gop = try ip.map.getOrPutAdapted(gpa, Key{ .aggregate = .{ - .ty = ty, - .storage = .{ .bytes = ip.string_bytes.items[@intFromEnum(str)..] }, - } }, adapter); - if (gop.found_existing) return @enumFromInt(gop.index); - - ip.items.appendAssumeCapacity(.{ - .tag = .bytes, - .data = ip.addExtraAssumeCapacity(Bytes{ - .ty = ty, - .bytes = str, - }), - }); - return @enumFromInt(ip.items.len - 1); -} - pub fn getString(ip: *InternPool, s: []const u8) OptionalNullTerminatedString { - if (ip.string_table.getKeyAdapted(s, std.hash_map.StringIndexAdapter{ + return if (ip.string_table.getKeyAdapted(s, std.hash_map.StringIndexAdapter{ .bytes = &ip.string_bytes, - })) |index| { - return @as(NullTerminatedString, @enumFromInt(index)).toOptional(); - } else { - return .none; - } -} - -pub fn stringToSlice(ip: *const InternPool, s: NullTerminatedString) [:0]const u8 { - const string_bytes = ip.string_bytes.items; - const start = @intFromEnum(s); - var end: usize = start; - while (string_bytes[end] != 0) end += 1; - return string_bytes[start..end :0]; -} - -pub fn stringToSliceUnwrap(ip: *const InternPool, s: OptionalNullTerminatedString) ?[:0]const u8 { - return ip.stringToSlice(s.unwrap() orelse return null); -} - -pub fn stringEqlSlice(ip: *const InternPool, a: NullTerminatedString, b: []const u8) bool { - return std.mem.eql(u8, stringToSlice(ip, a), b); + })) |index| @enumFromInt(index) else .none; } pub fn typeOf(ip: *const InternPool, index: Index) Index { @@ -8767,7 +8793,7 @@ pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 { return switch (ip.indexToKey(ty)) { .struct_type => ip.loadStructType(ty).field_types.len, .anon_struct_type => |anon_struct_type| anon_struct_type.types.len, - .array_type => |array_type| array_type.len + @intFromBool(array_type.sentinel != .none), + .array_type => |array_type| array_type.lenIncludingSentinel(), .vector_type => |vector_type| vector_type.len, else => unreachable, }; diff --git a/src/Module.zig b/src/Module.zig index 0399a2f85b..c4d7f43fe4 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -763,11 +763,11 @@ pub const Namespace = struct { ) !InternPool.NullTerminatedString { const ip = &zcu.intern_pool; const count = count: { - var count: usize = ip.stringToSlice(name).len + 1; + var count: usize = name.length(ip) + 1; var cur_ns = &ns; while (true) { const decl = zcu.declPtr(cur_ns.decl_index); - count += ip.stringToSlice(decl.name).len + 1; + count += decl.name.length(ip) + 1; cur_ns = zcu.namespacePtr(cur_ns.parent.unwrap() orelse { count += ns.file_scope.sub_file_path.len; break :count count; @@ -793,7 +793,7 @@ pub const Namespace = struct { }; } - return ip.getOrPutTrailingString(gpa, ip.string_bytes.items.len - start); + return ip.getOrPutTrailingString(gpa, ip.string_bytes.items.len - start, .no_embedded_nulls); } pub fn getType(ns: Namespace, zcu: *Zcu) Type { @@ -980,17 +980,13 @@ pub const File = struct { const ip = &mod.intern_pool; const start = ip.string_bytes.items.len; try file.renderFullyQualifiedName(ip.string_bytes.writer(mod.gpa)); - return ip.getOrPutTrailingString(mod.gpa, ip.string_bytes.items.len - start); + return ip.getOrPutTrailingString(mod.gpa, ip.string_bytes.items.len - start, .no_embedded_nulls); } pub fn fullPath(file: File, ally: Allocator) ![]u8 { return file.mod.root.joinString(ally, file.sub_file_path); } - pub fn fullPathZ(file: File, ally: Allocator) ![:0]u8 { - return file.mod.root.joinStringZ(ally, file.sub_file_path); - } - pub fn dumpSrc(file: *File, src: LazySrcLoc) void { const loc = std.zig.findLineColumn(file.source.bytes, src); std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 }); @@ -2534,6 +2530,7 @@ fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void { const name_ip = try zcu.intern_pool.getOrPutString( zcu.gpa, old_zir.nullTerminatedString(name_zir), + .no_embedded_nulls, ); try old_names.put(zcu.gpa, name_ip, {}); } @@ -2551,6 +2548,7 @@ fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void { const name_ip = try zcu.intern_pool.getOrPutString( zcu.gpa, old_zir.nullTerminatedString(name_zir), + .no_embedded_nulls, ); if (!old_names.swapRemove(name_ip)) continue; // Name added @@ -3555,37 +3553,46 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { const gpa = mod.gpa; const zir = decl.getFileScope(mod).zir; - const builtin_type_target_index: InternPool.Index = blk: { + const builtin_type_target_index: InternPool.Index = ip_index: { const std_mod = mod.std_mod; - if (decl.getFileScope(mod).mod != std_mod) break :blk .none; + if (decl.getFileScope(mod).mod != std_mod) break :ip_index .none; // We're in the std module. const std_file = (try mod.importPkg(std_mod)).file; const std_decl = mod.declPtr(std_file.root_decl.unwrap().?); const std_namespace = std_decl.getInnerNamespace(mod).?; - const builtin_str = try ip.getOrPutString(gpa, "builtin"); - const builtin_decl = mod.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, DeclAdapter{ .zcu = mod }) orelse break :blk .none); - const builtin_namespace = builtin_decl.getInnerNamespaceIndex(mod).unwrap() orelse break :blk .none; - if (decl.src_namespace != builtin_namespace) break :blk .none; + const builtin_str = try ip.getOrPutString(gpa, "builtin", .no_embedded_nulls); + const builtin_decl = mod.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, DeclAdapter{ .zcu = mod }) orelse break :ip_index .none); + const builtin_namespace = builtin_decl.getInnerNamespaceIndex(mod).unwrap() orelse break :ip_index .none; + if (decl.src_namespace != builtin_namespace) break :ip_index .none; // We're in builtin.zig. This could be a builtin we need to add to a specific InternPool index. - for ([_]struct { []const u8, InternPool.Index }{ - .{ "AtomicOrder", .atomic_order_type }, - .{ "AtomicRmwOp", .atomic_rmw_op_type }, - .{ "CallingConvention", .calling_convention_type }, - .{ "AddressSpace", .address_space_type }, - .{ "FloatMode", .float_mode_type }, - .{ "ReduceOp", .reduce_op_type }, - .{ "CallModifier", .call_modifier_type }, - .{ "PrefetchOptions", .prefetch_options_type }, - .{ "ExportOptions", .export_options_type }, - .{ "ExternOptions", .extern_options_type }, - .{ "Type", .type_info_type }, - }) |pair| { - const decl_name = ip.stringToSlice(decl.name); - if (std.mem.eql(u8, decl_name, pair[0])) { - break :blk pair[1]; - } + for ([_][]const u8{ + "AtomicOrder", + "AtomicRmwOp", + "CallingConvention", + "AddressSpace", + "FloatMode", + "ReduceOp", + "CallModifier", + "PrefetchOptions", + "ExportOptions", + "ExternOptions", + "Type", + }, [_]InternPool.Index{ + .atomic_order_type, + .atomic_rmw_op_type, + .calling_convention_type, + .address_space_type, + .float_mode_type, + .reduce_op_type, + .call_modifier_type, + .prefetch_options_type, + .export_options_type, + .extern_options_type, + .type_info_type, + }) |type_name, type_ip| { + if (decl.name.eqlSlice(type_name, ip)) break :ip_index type_ip; } - break :blk .none; + break :ip_index .none; }; mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.Depender.wrap(.{ .decl = decl_index })); @@ -3725,8 +3732,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { } else if (bytes.len == 0) { return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{}); } - const section = try ip.getOrPutString(gpa, bytes); - break :blk section.toOptional(); + break :blk try ip.getOrPutStringOpt(gpa, bytes, .no_embedded_nulls); }; decl.@"addrspace" = blk: { const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) { @@ -4101,7 +4107,10 @@ fn newEmbedFile( .sentinel = .zero_u8, .child = .u8_type, } }); - const array_val = try ip.getTrailingAggregate(gpa, array_ty, bytes.len); + const array_val = try ip.get(gpa, .{ .aggregate = .{ + .ty = array_ty, + .storage = .{ .bytes = try ip.getOrPutTrailingString(gpa, bytes.len, .maybe_embedded_nulls) }, + } }); const ptr_ty = (try mod.ptrType(.{ .child = array_ty, @@ -4111,7 +4120,6 @@ fn newEmbedFile( .address_space = .generic, }, })).toIntern(); - const ptr_val = try ip.get(gpa, .{ .ptr = .{ .ty = ptr_ty, .addr = .{ .anon_decl = .{ @@ -4122,7 +4130,7 @@ fn newEmbedFile( result.* = new_file; new_file.* = .{ - .sub_file_path = try ip.getOrPutString(gpa, sub_file_path), + .sub_file_path = try ip.getOrPutString(gpa, sub_file_path, .no_embedded_nulls), .owner = pkg, .stat = stat, .val = ptr_val, @@ -4214,11 +4222,11 @@ const ScanDeclIter = struct { const zcu = iter.zcu; const gpa = zcu.gpa; const ip = &zcu.intern_pool; - var name = try ip.getOrPutStringFmt(gpa, fmt, args); + var name = try ip.getOrPutStringFmt(gpa, fmt, args, .no_embedded_nulls); var gop = try iter.seen_decls.getOrPut(gpa, name); var next_suffix: u32 = 0; while (gop.found_existing) { - name = try ip.getOrPutStringFmt(gpa, fmt ++ "_{d}", args ++ .{next_suffix}); + name = try ip.getOrPutStringFmt(gpa, "{}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls); gop = try iter.seen_decls.getOrPut(gpa, name); next_suffix += 1; } @@ -4300,7 +4308,11 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void }; } else info: { if (iter.pass != .named) return; - const name = try ip.getOrPutString(gpa, zir.nullTerminatedString(declaration.name.toString(zir).?)); + const name = try ip.getOrPutString( + gpa, + zir.nullTerminatedString(declaration.name.toString(zir).?), + .no_embedded_nulls, + ); try iter.seen_decls.putNoClobber(gpa, name, {}); break :info .{ name, @@ -4362,9 +4374,10 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void if (!comp.config.is_test) break :a false; if (decl_mod != zcu.main_mod) break :a false; if (is_named_test and comp.test_filters.len > 0) { - const decl_fqn = ip.stringToSlice(try namespace.fullyQualifiedName(zcu, decl_name)); + const decl_fqn = try namespace.fullyQualifiedName(zcu, decl_name); + const decl_fqn_slice = decl_fqn.toSlice(ip); for (comp.test_filters) |test_filter| { - if (mem.indexOf(u8, decl_fqn, test_filter)) |_| break; + if (mem.indexOf(u8, decl_fqn_slice, test_filter)) |_| break; } else break :a false; } zcu.test_functions.putAssumeCapacity(decl_index, {}); // may clobber on incremental update @@ -4377,8 +4390,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void // `is_export` is unchanged. In this case, the incremental update mechanism will handle // re-analysis for us if necessary. if (prev_exported != declaration.flags.is_export or decl.analysis == .unreferenced) { - log.debug("scanDecl queue analyze_decl file='{s}' decl_name='{s}' decl_index={d}", .{ - namespace.file_scope.sub_file_path, ip.stringToSlice(decl_name), decl_index, + log.debug("scanDecl queue analyze_decl file='{s}' decl_name='{}' decl_index={d}", .{ + namespace.file_scope.sub_file_path, decl_name.fmt(ip), decl_index, }); comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = decl_index }); } @@ -5300,7 +5313,7 @@ pub fn populateTestFunctions( const builtin_file = (mod.importPkg(builtin_mod) catch unreachable).file; const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?); const builtin_namespace = mod.namespacePtr(root_decl.src_namespace); - const test_functions_str = try ip.getOrPutString(gpa, "test_functions"); + const test_functions_str = try ip.getOrPutString(gpa, "test_functions", .no_embedded_nulls); const decl_index = builtin_namespace.decls.getKeyAdapted( test_functions_str, DeclAdapter{ .zcu = mod }, @@ -5327,16 +5340,16 @@ pub fn populateTestFunctions( for (test_fn_vals, mod.test_functions.keys()) |*test_fn_val, test_decl_index| { const test_decl = mod.declPtr(test_decl_index); - const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(try test_decl.fullyQualifiedName(mod))); - defer gpa.free(test_decl_name); + const test_decl_name = try test_decl.fullyQualifiedName(mod); + const test_decl_name_len = test_decl_name.length(ip); const test_name_anon_decl: InternPool.Key.Ptr.Addr.AnonDecl = n: { const test_name_ty = try mod.arrayType(.{ - .len = test_decl_name.len, + .len = test_decl_name_len, .child = .u8_type, }); const test_name_val = try mod.intern(.{ .aggregate = .{ .ty = test_name_ty.toIntern(), - .storage = .{ .bytes = test_decl_name }, + .storage = .{ .bytes = test_decl_name.toString() }, } }); break :n .{ .orig_ty = (try mod.singleConstPtrType(test_name_ty)).toIntern(), @@ -5354,7 +5367,7 @@ pub fn populateTestFunctions( } }), .len = try mod.intern(.{ .int = .{ .ty = .usize_type, - .storage = .{ .u64 = test_decl_name.len }, + .storage = .{ .u64 = test_decl_name_len }, } }), } }), // func diff --git a/src/Sema.zig b/src/Sema.zig index d64226fef0..d3989f630c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2059,12 +2059,12 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) const st_ptr = try err_trace_block.addTy(.alloc, try mod.singleMutPtrType(stack_trace_ty)); // st.instruction_addresses = &addrs; - const instruction_addresses_field_name = try ip.getOrPutString(gpa, "instruction_addresses"); + const instruction_addresses_field_name = try ip.getOrPutString(gpa, "instruction_addresses", .no_embedded_nulls); const addr_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, instruction_addresses_field_name, src, true); try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store); // st.index = 0; - const index_field_name = try ip.getOrPutString(gpa, "index"); + const index_field_name = try ip.getOrPutString(gpa, "index", .no_embedded_nulls); const index_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, index_field_name, src, true); try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, .zero_usize, src, .store); @@ -2348,13 +2348,13 @@ fn failWithInvalidFieldAccess( fn typeSupportsFieldAccess(mod: *const Module, ty: Type, field_name: InternPool.NullTerminatedString) bool { const ip = &mod.intern_pool; switch (ty.zigTypeTag(mod)) { - .Array => return ip.stringEqlSlice(field_name, "len"), + .Array => return field_name.eqlSlice("len", ip), .Pointer => { const ptr_info = ty.ptrInfo(mod); if (ptr_info.flags.size == .Slice) { - return ip.stringEqlSlice(field_name, "ptr") or ip.stringEqlSlice(field_name, "len"); + return field_name.eqlSlice("ptr", ip) or field_name.eqlSlice("len", ip); } else if (Type.fromInterned(ptr_info.child).zigTypeTag(mod) == .Array) { - return ip.stringEqlSlice(field_name, "len"); + return field_name.eqlSlice("len", ip); } else return false; }, .Type, .Struct, .Union => return true, @@ -2703,12 +2703,20 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() }; }), .decl_val => |str| capture: { - const decl_name = try ip.getOrPutString(sema.gpa, sema.code.nullTerminatedString(str)); + const decl_name = try ip.getOrPutString( + sema.gpa, + sema.code.nullTerminatedString(str), + .no_embedded_nulls, + ); const decl = try sema.lookupIdentifier(block, .unneeded, decl_name); // TODO: could we need this src loc? break :capture InternPool.CaptureValue.wrap(.{ .decl_val = decl }); }, .decl_ref => |str| capture: { - const decl_name = try ip.getOrPutString(sema.gpa, sema.code.nullTerminatedString(str)); + const decl_name = try ip.getOrPutString( + sema.gpa, + sema.code.nullTerminatedString(str), + .no_embedded_nulls, + ); const decl = try sema.lookupIdentifier(block, .unneeded, decl_name); // TODO: could we need this src loc? break :capture InternPool.CaptureValue.wrap(.{ .decl_ref = decl }); }, @@ -2882,7 +2890,7 @@ fn createAnonymousDeclTypeNamed( const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{ src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index), - }) catch unreachable; + }, .no_embedded_nulls) catch unreachable; try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); return new_decl_index; }, @@ -2923,7 +2931,7 @@ fn createAnonymousDeclTypeNamed( }; try writer.writeByte(')'); - const name = try mod.intern_pool.getOrPutString(gpa, buf.items); + const name = try mod.intern_pool.getOrPutString(gpa, buf.items, .no_embedded_nulls); try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); return new_decl_index; }, @@ -2937,8 +2945,7 @@ fn createAnonymousDeclTypeNamed( const name = try mod.intern_pool.getOrPutStringFmt(gpa, "{}.{s}", .{ src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code), - }); - + }, .no_embedded_nulls); try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); return new_decl_index; }, @@ -3157,7 +3164,7 @@ fn zirEnumDecl( const field_name_zir = sema.code.nullTerminatedString(field_name_index); extra_index += 2; // field name, doc comment - const field_name = try mod.intern_pool.getOrPutString(gpa, field_name_zir); + const field_name = try mod.intern_pool.getOrPutString(gpa, field_name_zir, .no_embedded_nulls); const tag_overflow = if (has_tag_value) overflow: { const tag_val_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); @@ -3462,7 +3469,7 @@ fn zirErrorSetDecl( while (extra_index < extra_index_end) : (extra_index += 2) { // +2 to skip over doc_string const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]); const name = sema.code.nullTerminatedString(name_index); - const name_ip = try mod.intern_pool.getOrPutString(gpa, name); + const name_ip = try mod.intern_pool.getOrPutString(gpa, name, .no_embedded_nulls); _ = try mod.getErrorValue(name_ip); const result = names.getOrPutAssumeCapacity(name_ip); assert(!result.found_existing); // verified in AstGen @@ -3635,7 +3642,7 @@ fn indexablePtrLen( const is_pointer_to = object_ty.isSinglePointer(mod); const indexable_ty = if (is_pointer_to) object_ty.childType(mod) else object_ty; try checkIndexable(sema, block, src, indexable_ty); - const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "len"); + const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "len", .no_embedded_nulls); return sema.fieldVal(block, src, object, field_name, src); } @@ -3649,7 +3656,7 @@ fn indexablePtrLenOrNone( const operand_ty = sema.typeOf(operand); try checkMemOperand(sema, block, src, operand_ty); if (operand_ty.ptrSize(mod) == .Many) return .none; - const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "len"); + const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "len", .no_embedded_nulls); return sema.fieldVal(block, src, operand, field_name, src); } @@ -4363,7 +4370,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. } if (!object_ty.indexableHasLen(mod)) continue; - break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, "len"), arg_src); + break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, "len", .no_embedded_nulls), arg_src); }; const arg_len = try sema.coerce(block, Type.usize, arg_len_uncoerced, arg_src); if (len == .none) { @@ -4747,7 +4754,11 @@ fn validateUnionInit( const field_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(field_ptr)].pl_node; const field_src: LazySrcLoc = .{ .node_offset_initializer = field_ptr_data.src_node }; const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; - const field_name = try mod.intern_pool.getOrPutString(gpa, sema.code.nullTerminatedString(field_ptr_extra.field_name_start)); + const field_name = try mod.intern_pool.getOrPutString( + gpa, + sema.code.nullTerminatedString(field_ptr_extra.field_name_start), + .no_embedded_nulls, + ); const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src); const air_tags = sema.air_instructions.items(.tag); const air_datas = sema.air_instructions.items(.data); @@ -4890,6 +4901,7 @@ fn validateStructInit( const field_name = try ip.getOrPutString( gpa, sema.code.nullTerminatedString(field_ptr_extra.field_name_start), + .no_embedded_nulls, ); field_index.* = if (struct_ty.isTuple(mod)) try sema.tupleFieldIndex(block, struct_ty, field_name, field_src) @@ -5672,25 +5684,26 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v fn zirStr(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const bytes = sema.code.instructions.items(.data)[@intFromEnum(inst)].str.get(sema.code); - return sema.addStrLitNoAlias(bytes); + return sema.addStrLit( + try sema.mod.intern_pool.getOrPutString(sema.gpa, bytes, .maybe_embedded_nulls), + bytes.len, + ); } -fn addStrLit(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref { - const duped_bytes = try sema.arena.dupe(u8, bytes); - return addStrLitNoAlias(sema, duped_bytes); +fn addNullTerminatedStrLit(sema: *Sema, string: InternPool.NullTerminatedString) CompileError!Air.Inst.Ref { + return sema.addStrLit(string.toString(), string.length(&sema.mod.intern_pool)); } -/// Safe to call when `bytes` does not point into `InternPool`. -fn addStrLitNoAlias(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref { +fn addStrLit(sema: *Sema, string: InternPool.String, len: u64) CompileError!Air.Inst.Ref { const mod = sema.mod; const array_ty = try mod.arrayType(.{ - .len = bytes.len, + .len = len, .sentinel = .zero_u8, .child = .u8_type, }); const val = try mod.intern(.{ .aggregate = .{ .ty = array_ty.toIntern(), - .storage = .{ .bytes = bytes }, + .storage = .{ .bytes = string }, } }); return anonDeclRef(sema, val); } @@ -6370,7 +6383,11 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const src = inst_data.src(); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; - const decl_name = try mod.intern_pool.getOrPutString(mod.gpa, sema.code.nullTerminatedString(extra.decl_name)); + const decl_name = try mod.intern_pool.getOrPutString( + mod.gpa, + sema.code.nullTerminatedString(extra.decl_name), + .no_embedded_nulls, + ); const decl_index = if (extra.namespace != .none) index_blk: { const container_ty = try sema.resolveType(block, operand_src, extra.namespace); const container_namespace = container_ty.getNamespaceIndex(mod); @@ -6721,7 +6738,11 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; const src = inst_data.src(); - const decl_name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code)); + const decl_name = try mod.intern_pool.getOrPutString( + sema.gpa, + inst_data.get(sema.code), + .no_embedded_nulls, + ); const decl_index = try sema.lookupIdentifier(block, src, decl_name); try sema.addReferencedBy(block, src, decl_index); return sema.analyzeDeclRef(decl_index); @@ -6731,7 +6752,11 @@ fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; const src = inst_data.src(); - const decl_name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code)); + const decl_name = try mod.intern_pool.getOrPutString( + sema.gpa, + inst_data.get(sema.code), + .no_embedded_nulls, + ); const decl = try sema.lookupIdentifier(block, src, decl_name); return sema.analyzeDeclVal(block, src, decl); } @@ -6883,7 +6908,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, else => |e| return e, }; - const field_name = try mod.intern_pool.getOrPutString(gpa, "index"); + const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls); const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, .unneeded) catch |err| switch (err) { error.AnalysisFail, error.NeededSourceLocation => @panic("std.builtin.StackTrace is corrupt"), error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, @@ -6926,7 +6951,7 @@ fn popErrorReturnTrace( try sema.resolveTypeFields(stack_trace_ty); const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty); const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty); - const field_name = try mod.intern_pool.getOrPutString(gpa, "index"); + const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls); const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty, true); try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store); } else if (is_non_error == null) { @@ -6952,7 +6977,7 @@ fn popErrorReturnTrace( try sema.resolveTypeFields(stack_trace_ty); const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty); const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty); - const field_name = try mod.intern_pool.getOrPutString(gpa, "index"); + const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls); const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty, true); try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store); _ = try then_block.addBr(cond_block_inst, .void_value); @@ -7010,7 +7035,11 @@ fn zirCall( .direct => .{ .direct = try sema.resolveInst(extra.data.callee) }, .field => blk: { const object_ptr = try sema.resolveInst(extra.data.obj_ptr); - const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.data.field_name_start)); + const field_name = try mod.intern_pool.getOrPutString( + sema.gpa, + sema.code.nullTerminatedString(extra.data.field_name_start), + .no_embedded_nulls, + ); const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node }; break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src); }, @@ -7073,7 +7102,7 @@ fn zirCall( if (input_is_error or (pop_error_return_trace and return_ty.isError(mod))) { const stack_trace_ty = try sema.getBuiltinType("StackTrace"); try sema.resolveTypeFields(stack_trace_ty); - const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index"); + const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index", .no_embedded_nulls); const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src); // Insert a save instruction before the arg resolution + call instructions we just generated @@ -8648,7 +8677,11 @@ fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! _ = block; const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; - const name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code)); + const name = try mod.intern_pool.getOrPutString( + sema.gpa, + inst_data.get(sema.code), + .no_embedded_nulls, + ); _ = try mod.getErrorValue(name); // Create an error set type with only this error value, and return the value. const error_set_type = try mod.singleErrorSetType(name); @@ -8804,7 +8837,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; const name = inst_data.get(sema.code); return Air.internedToRef((try mod.intern(.{ - .enum_literal = try mod.intern_pool.getOrPutString(sema.gpa, name), + .enum_literal = try mod.intern_pool.getOrPutString(sema.gpa, name, .no_embedded_nulls), }))); } @@ -9761,7 +9794,7 @@ fn funcCommon( const func_index = try ip.getExternFunc(gpa, .{ .ty = func_ty, .decl = sema.owner_decl_index, - .lib_name = try mod.intern_pool.getOrPutStringOpt(gpa, opt_lib_name), + .lib_name = try mod.intern_pool.getOrPutStringOpt(gpa, opt_lib_name, .no_embedded_nulls), }); return finishFunc( sema, @@ -10225,7 +10258,11 @@ fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const src = inst_data.src(); const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node }; const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; - const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start)); + const field_name = try mod.intern_pool.getOrPutString( + sema.gpa, + sema.code.nullTerminatedString(extra.field_name_start), + .no_embedded_nulls, + ); const object = try sema.resolveInst(extra.lhs); return sema.fieldVal(block, src, object, field_name, field_name_src); } @@ -10239,7 +10276,11 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const src = inst_data.src(); const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node }; const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; - const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start)); + const field_name = try mod.intern_pool.getOrPutString( + sema.gpa, + sema.code.nullTerminatedString(extra.field_name_start), + .no_embedded_nulls, + ); const object_ptr = try sema.resolveInst(extra.lhs); return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false); } @@ -10253,7 +10294,11 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi const src = inst_data.src(); const field_name_src: LazySrcLoc = .{ .node_offset_field_name_init = inst_data.src_node }; const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; - const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start)); + const field_name = try mod.intern_pool.getOrPutString( + sema.gpa, + sema.code.nullTerminatedString(extra.field_name_start), + .no_embedded_nulls, + ); const object_ptr = try sema.resolveInst(extra.lhs); const struct_ty = sema.typeOf(object_ptr).childType(mod); switch (struct_ty.zigTypeTag(mod)) { @@ -13759,8 +13804,8 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai switch (ip.indexToKey(ty.toIntern())) { .ptr_type => |ptr_type| switch (ptr_type.flags.size) { .Slice => { - if (ip.stringEqlSlice(field_name, "ptr")) break :hf true; - if (ip.stringEqlSlice(field_name, "len")) break :hf true; + if (field_name.eqlSlice("ptr", ip)) break :hf true; + if (field_name.eqlSlice("len", ip)) break :hf true; break :hf false; }, else => {}, @@ -13783,7 +13828,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .enum_type => { break :hf ip.loadEnumType(ty.toIntern()).nameIndex(ip, field_name) != null; }, - .array_type => break :hf ip.stringEqlSlice(field_name, "len"), + .array_type => break :hf field_name.eqlSlice("len", ip), else => {}, } return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{ @@ -13885,7 +13930,11 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; - const name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code)); + const name = try mod.intern_pool.getOrPutString( + sema.gpa, + inst_data.get(sema.code), + .no_embedded_nulls, + ); _ = try mod.getErrorValue(name); const error_set_type = try mod.singleErrorSetType(name); return Air.internedToRef((try mod.intern(.{ .err = .{ @@ -17552,11 +17601,9 @@ fn zirBuiltinSrc( const gpa = sema.gpa; const func_name_val = v: { - // This dupe prevents InternPool string pool memory from being reallocated - // while a reference exists. - const bytes = try sema.arena.dupe(u8, ip.stringToSlice(fn_owner_decl.name)); + const func_name_len = fn_owner_decl.name.length(ip); const array_ty = try ip.get(gpa, .{ .array_type = .{ - .len = bytes.len, + .len = func_name_len, .sentinel = .zero_u8, .child = .u8_type, } }); @@ -17568,19 +17615,19 @@ fn zirBuiltinSrc( .orig_ty = .slice_const_u8_sentinel_0_type, .val = try ip.get(gpa, .{ .aggregate = .{ .ty = array_ty, - .storage = .{ .bytes = bytes }, + .storage = .{ .bytes = fn_owner_decl.name.toString() }, } }), } }, } }), - .len = (try mod.intValue(Type.usize, bytes.len)).toIntern(), + .len = (try mod.intValue(Type.usize, func_name_len)).toIntern(), } }); }; const file_name_val = v: { // The compiler must not call realpath anywhere. - const bytes = try fn_owner_decl.getFileScope(mod).fullPathZ(sema.arena); + const file_name = try fn_owner_decl.getFileScope(mod).fullPath(sema.arena); const array_ty = try ip.get(gpa, .{ .array_type = .{ - .len = bytes.len, + .len = file_name.len, .sentinel = .zero_u8, .child = .u8_type, } }); @@ -17592,11 +17639,13 @@ fn zirBuiltinSrc( .orig_ty = .slice_const_u8_sentinel_0_type, .val = try ip.get(gpa, .{ .aggregate = .{ .ty = array_ty, - .storage = .{ .bytes = bytes }, + .storage = .{ + .bytes = try ip.getOrPutString(gpa, file_name, .maybe_embedded_nulls), + }, } }), } }, } }), - .len = (try mod.intValue(Type.usize, bytes.len)).toIntern(), + .len = (try mod.intValue(Type.usize, file_name.len)).toIntern(), } }); }; @@ -17651,7 +17700,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Fn"), + try ip.getOrPutString(gpa, "Fn", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(fn_info_decl_index); const fn_info_decl = mod.declPtr(fn_info_decl_index); @@ -17661,7 +17710,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, fn_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Param"), + try ip.getOrPutString(gpa, "Param", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(param_info_decl_index); const param_info_decl = mod.declPtr(param_info_decl_index); @@ -17762,7 +17811,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Int"), + try ip.getOrPutString(gpa, "Int", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(int_info_decl_index); const int_info_decl = mod.declPtr(int_info_decl_index); @@ -17790,7 +17839,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Float"), + try ip.getOrPutString(gpa, "Float", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(float_info_decl_index); const float_info_decl = mod.declPtr(float_info_decl_index); @@ -17822,7 +17871,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, (try sema.getBuiltinType("Type")).getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Pointer"), + try ip.getOrPutString(gpa, "Pointer", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(decl_index); const decl = mod.declPtr(decl_index); @@ -17833,7 +17882,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, pointer_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Size"), + try ip.getOrPutString(gpa, "Size", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(decl_index); const decl = mod.declPtr(decl_index); @@ -17876,7 +17925,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Array"), + try ip.getOrPutString(gpa, "Array", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(array_field_ty_decl_index); const array_field_ty_decl = mod.declPtr(array_field_ty_decl_index); @@ -17907,7 +17956,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Vector"), + try ip.getOrPutString(gpa, "Vector", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(vector_field_ty_decl_index); const vector_field_ty_decl = mod.declPtr(vector_field_ty_decl_index); @@ -17936,7 +17985,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Optional"), + try ip.getOrPutString(gpa, "Optional", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(optional_field_ty_decl_index); const optional_field_ty_decl = mod.declPtr(optional_field_ty_decl_index); @@ -17963,7 +18012,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Error"), + try ip.getOrPutString(gpa, "Error", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(set_field_ty_decl_index); const set_field_ty_decl = mod.declPtr(set_field_ty_decl_index); @@ -17980,18 +18029,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai else => |err_set_ty_index| blk: { const names = ip.indexToKey(err_set_ty_index).error_set_type.names; const vals = try sema.arena.alloc(InternPool.Index, names.len); - for (vals, 0..) |*field_val, i| { - // TODO: write something like getCoercedInts to avoid needing to dupe - const name = try sema.arena.dupeZ(u8, ip.stringToSlice(names.get(ip)[i])); - const name_val = v: { + for (vals, 0..) |*field_val, error_index| { + const error_name = names.get(ip)[error_index]; + const error_name_len = error_name.length(ip); + const error_name_val = v: { const new_decl_ty = try mod.arrayType(.{ - .len = name.len, + .len = error_name_len, .sentinel = .zero_u8, .child = .u8_type, }); const new_decl_val = try mod.intern(.{ .aggregate = .{ .ty = new_decl_ty.toIntern(), - .storage = .{ .bytes = name }, + .storage = .{ .bytes = error_name.toString() }, } }); break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, @@ -18002,13 +18051,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .orig_ty = .slice_const_u8_sentinel_0_type, } }, } }), - .len = (try mod.intValue(Type.usize, name.len)).toIntern(), + .len = (try mod.intValue(Type.usize, error_name_len)).toIntern(), } }); }; const error_field_fields = .{ // name: [:0]const u8, - name_val, + error_name_val, }; field_val.* = try mod.intern(.{ .aggregate = .{ .ty = error_field_ty.toIntern(), @@ -18069,7 +18118,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "ErrorUnion"), + try ip.getOrPutString(gpa, "ErrorUnion", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(error_union_field_ty_decl_index); const error_union_field_ty_decl = mod.declPtr(error_union_field_ty_decl_index); @@ -18099,7 +18148,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "EnumField"), + try ip.getOrPutString(gpa, "EnumField", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(enum_field_ty_decl_index); const enum_field_ty_decl = mod.declPtr(enum_field_ty_decl_index); @@ -18107,27 +18156,29 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }; const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len); - for (enum_field_vals, 0..) |*field_val, i| { + for (enum_field_vals, 0..) |*field_val, tag_index| { const enum_type = ip.loadEnumType(ty.toIntern()); const value_val = if (enum_type.values.len > 0) try mod.intern_pool.getCoercedInts( mod.gpa, - mod.intern_pool.indexToKey(enum_type.values.get(ip)[i]).int, + mod.intern_pool.indexToKey(enum_type.values.get(ip)[tag_index]).int, .comptime_int_type, ) else - (try mod.intValue(Type.comptime_int, i)).toIntern(); + (try mod.intValue(Type.comptime_int, tag_index)).toIntern(); + // TODO: write something like getCoercedInts to avoid needing to dupe - const name = try sema.arena.dupeZ(u8, ip.stringToSlice(enum_type.names.get(ip)[i])); const name_val = v: { + const tag_name = enum_type.names.get(ip)[tag_index]; + const tag_name_len = tag_name.length(ip); const new_decl_ty = try mod.arrayType(.{ - .len = name.len, + .len = tag_name_len, .sentinel = .zero_u8, .child = .u8_type, }); const new_decl_val = try mod.intern(.{ .aggregate = .{ .ty = new_decl_ty.toIntern(), - .storage = .{ .bytes = name }, + .storage = .{ .bytes = tag_name.toString() }, } }); break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, @@ -18138,7 +18189,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .orig_ty = .slice_const_u8_sentinel_0_type, } }, } }), - .len = (try mod.intValue(Type.usize, name.len)).toIntern(), + .len = (try mod.intValue(Type.usize, tag_name_len)).toIntern(), } }); }; @@ -18191,7 +18242,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Enum"), + try ip.getOrPutString(gpa, "Enum", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(type_enum_ty_decl_index); const type_enum_ty_decl = mod.declPtr(type_enum_ty_decl_index); @@ -18223,7 +18274,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Union"), + try ip.getOrPutString(gpa, "Union", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(type_union_ty_decl_index); const type_union_ty_decl = mod.declPtr(type_union_ty_decl_index); @@ -18235,7 +18286,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "UnionField"), + try ip.getOrPutString(gpa, "UnionField", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(union_field_ty_decl_index); const union_field_ty_decl = mod.declPtr(union_field_ty_decl_index); @@ -18250,18 +18301,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const union_field_vals = try gpa.alloc(InternPool.Index, tag_type.names.len); defer gpa.free(union_field_vals); - for (union_field_vals, 0..) |*field_val, i| { - // TODO: write something like getCoercedInts to avoid needing to dupe - const name = try sema.arena.dupeZ(u8, ip.stringToSlice(tag_type.names.get(ip)[i])); + for (union_field_vals, 0..) |*field_val, field_index| { const name_val = v: { + const field_name = tag_type.names.get(ip)[field_index]; + const field_name_len = field_name.length(ip); const new_decl_ty = try mod.arrayType(.{ - .len = name.len, + .len = field_name_len, .sentinel = .zero_u8, .child = .u8_type, }); const new_decl_val = try mod.intern(.{ .aggregate = .{ .ty = new_decl_ty.toIntern(), - .storage = .{ .bytes = name }, + .storage = .{ .bytes = field_name.toString() }, } }); break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, @@ -18272,16 +18323,16 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .orig_ty = .slice_const_u8_sentinel_0_type, } }, } }), - .len = (try mod.intValue(Type.usize, name.len)).toIntern(), + .len = (try mod.intValue(Type.usize, field_name_len)).toIntern(), } }); }; const alignment = switch (layout) { - .auto, .@"extern" => try sema.unionFieldAlignment(union_obj, @intCast(i)), + .auto, .@"extern" => try sema.unionFieldAlignment(union_obj, @intCast(field_index)), .@"packed" => .none, }; - const field_ty = union_obj.field_types.get(ip)[i]; + const field_ty = union_obj.field_types.get(ip)[field_index]; const union_field_fields = .{ // name: [:0]const u8, name_val, @@ -18338,7 +18389,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, (try sema.getBuiltinType("Type")).getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "ContainerLayout"), + try ip.getOrPutString(gpa, "ContainerLayout", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(decl_index); const decl = mod.declPtr(decl_index); @@ -18371,7 +18422,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Struct"), + try ip.getOrPutString(gpa, "Struct", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(type_struct_ty_decl_index); const type_struct_ty_decl = mod.declPtr(type_struct_ty_decl_index); @@ -18383,7 +18434,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "StructField"), + try ip.getOrPutString(gpa, "StructField", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(struct_field_ty_decl_index); const struct_field_ty_decl = mod.declPtr(struct_field_ty_decl_index); @@ -18396,27 +18447,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai defer gpa.free(struct_field_vals); fv: { const struct_type = switch (ip.indexToKey(ty.toIntern())) { - .anon_struct_type => |tuple| { - struct_field_vals = try gpa.alloc(InternPool.Index, tuple.types.len); - for (struct_field_vals, 0..) |*struct_field_val, i| { - const anon_struct_type = ip.indexToKey(ty.toIntern()).anon_struct_type; - const field_ty = anon_struct_type.types.get(ip)[i]; - const field_val = anon_struct_type.values.get(ip)[i]; + .anon_struct_type => |anon_struct_type| { + struct_field_vals = try gpa.alloc(InternPool.Index, anon_struct_type.types.len); + for (struct_field_vals, 0..) |*struct_field_val, field_index| { + const field_ty = anon_struct_type.types.get(ip)[field_index]; + const field_val = anon_struct_type.values.get(ip)[field_index]; const name_val = v: { - // TODO: write something like getCoercedInts to avoid needing to dupe - const bytes = if (tuple.names.len != 0) - // https://github.com/ziglang/zig/issues/15709 - try sema.arena.dupeZ(u8, ip.stringToSlice(ip.indexToKey(ty.toIntern()).anon_struct_type.names.get(ip)[i])) + const field_name = if (anon_struct_type.names.len != 0) + anon_struct_type.names.get(ip)[field_index] else - try std.fmt.allocPrintZ(sema.arena, "{d}", .{i}); + try ip.getOrPutStringFmt(gpa, "{d}", .{field_index}, .no_embedded_nulls); + const field_name_len = field_name.length(ip); const new_decl_ty = try mod.arrayType(.{ - .len = bytes.len, + .len = field_name_len, .sentinel = .zero_u8, .child = .u8_type, }); const new_decl_val = try mod.intern(.{ .aggregate = .{ .ty = new_decl_ty.toIntern(), - .storage = .{ .bytes = bytes }, + .storage = .{ .bytes = field_name.toString() }, } }); break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, @@ -18427,7 +18476,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .orig_ty = .slice_const_u8_sentinel_0_type, } }, } }), - .len = (try mod.intValue(Type.usize, bytes.len)).toIntern(), + .len = (try mod.intValue(Type.usize, field_name_len)).toIntern(), } }); }; @@ -18462,24 +18511,24 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try sema.resolveStructFieldInits(ty); - for (struct_field_vals, 0..) |*field_val, i| { - // TODO: write something like getCoercedInts to avoid needing to dupe - const name = if (struct_type.fieldName(ip, i).unwrap()) |name_nts| - try sema.arena.dupeZ(u8, ip.stringToSlice(name_nts)) + for (struct_field_vals, 0..) |*field_val, field_index| { + const field_name = if (struct_type.fieldName(ip, field_index).unwrap()) |field_name| + field_name else - try std.fmt.allocPrintZ(sema.arena, "{d}", .{i}); - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); - const field_init = struct_type.fieldInit(ip, i); - const field_is_comptime = struct_type.fieldIsComptime(ip, i); + try ip.getOrPutStringFmt(gpa, "{d}", .{field_index}, .no_embedded_nulls); + const field_name_len = field_name.length(ip); + const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); + const field_init = struct_type.fieldInit(ip, field_index); + const field_is_comptime = struct_type.fieldIsComptime(ip, field_index); const name_val = v: { const new_decl_ty = try mod.arrayType(.{ - .len = name.len, + .len = field_name_len, .sentinel = .zero_u8, .child = .u8_type, }); const new_decl_val = try mod.intern(.{ .aggregate = .{ .ty = new_decl_ty.toIntern(), - .storage = .{ .bytes = name }, + .storage = .{ .bytes = field_name.toString() }, } }); break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, @@ -18490,7 +18539,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .orig_ty = .slice_const_u8_sentinel_0_type, } }, } }), - .len = (try mod.intValue(Type.usize, name.len)).toIntern(), + .len = (try mod.intValue(Type.usize, field_name_len)).toIntern(), } }); }; @@ -18499,7 +18548,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const alignment = switch (struct_type.layout) { .@"packed" => .none, else => try sema.structFieldAlignment( - struct_type.fieldAlign(ip, i), + struct_type.fieldAlign(ip, field_index), field_ty, struct_type.layout, ), @@ -18569,7 +18618,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, (try sema.getBuiltinType("Type")).getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "ContainerLayout"), + try ip.getOrPutString(gpa, "ContainerLayout", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(decl_index); const decl = mod.declPtr(decl_index); @@ -18605,7 +18654,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai block, src, type_info_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, "Opaque"), + try ip.getOrPutString(gpa, "Opaque", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(type_opaque_ty_decl_index); const type_opaque_ty_decl = mod.declPtr(type_opaque_ty_decl_index); @@ -18648,7 +18697,7 @@ fn typeInfoDecls( block, src, type_info_ty.getNamespaceIndex(mod), - try mod.intern_pool.getOrPutString(gpa, "Declaration"), + try mod.intern_pool.getOrPutString(gpa, "Declaration", .no_embedded_nulls), )).?; try sema.ensureDeclAnalyzed(declaration_ty_decl_index); const declaration_ty_decl = mod.declPtr(declaration_ty_decl_index); @@ -18722,16 +18771,15 @@ fn typeInfoNamespaceDecls( } if (decl.kind != .named) continue; const name_val = v: { - // TODO: write something like getCoercedInts to avoid needing to dupe - const name = try sema.arena.dupeZ(u8, ip.stringToSlice(decl.name)); + const decl_name_len = decl.name.length(ip); const new_decl_ty = try mod.arrayType(.{ - .len = name.len, + .len = decl_name_len, .sentinel = .zero_u8, .child = .u8_type, }); const new_decl_val = try mod.intern(.{ .aggregate = .{ .ty = new_decl_ty.toIntern(), - .storage = .{ .bytes = name }, + .storage = .{ .bytes = decl.name.toString() }, } }); break :v try mod.intern(.{ .slice = .{ .ty = .slice_const_u8_sentinel_0_type, @@ -18742,7 +18790,7 @@ fn typeInfoNamespaceDecls( .val = new_decl_val, } }, } }), - .len = (try mod.intValue(Type.usize, name.len)).toIntern(), + .len = (try mod.intValue(Type.usize, decl_name_len)).toIntern(), } }); }; @@ -19385,7 +19433,11 @@ fn zirRetErrValue( ) CompileError!void { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; - const err_name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code)); + const err_name = try mod.intern_pool.getOrPutString( + sema.gpa, + inst_data.get(sema.code), + .no_embedded_nulls, + ); _ = try mod.getErrorValue(err_name); const src = inst_data.src(); // Return the error code from the function. @@ -20072,7 +20124,11 @@ fn zirStructInit( const field_type_data = zir_datas[@intFromEnum(item.data.field_type)].pl_node; const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node }; const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; - const field_name = try ip.getOrPutString(gpa, sema.code.nullTerminatedString(field_type_extra.name_start)); + const field_name = try ip.getOrPutString( + gpa, + sema.code.nullTerminatedString(field_type_extra.name_start), + .no_embedded_nulls, + ); const field_index = if (resolved_ty.isTuple(mod)) try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src) else @@ -20109,7 +20165,11 @@ fn zirStructInit( const field_type_data = zir_datas[@intFromEnum(item.data.field_type)].pl_node; const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node }; const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; - const field_name = try ip.getOrPutString(gpa, sema.code.nullTerminatedString(field_type_extra.name_start)); + const field_name = try ip.getOrPutString( + gpa, + sema.code.nullTerminatedString(field_type_extra.name_start), + .no_embedded_nulls, + ); const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src); const tag_ty = resolved_ty.unionTagTypeHypothetical(mod); const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index); @@ -20417,8 +20477,7 @@ fn structInitAnon( }, }; - const name_ip = try mod.intern_pool.getOrPutString(gpa, name); - field_name.* = name_ip; + field_name.* = try mod.intern_pool.getOrPutString(gpa, name, .no_embedded_nulls); const init = try sema.resolveInst(item.data.init); field_ty.* = sema.typeOf(init).toIntern(); @@ -20809,7 +20868,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp }; const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(mod); const zir_field_name = sema.code.nullTerminatedString(extra.name_start); - const field_name = try ip.getOrPutString(sema.gpa, zir_field_name); + const field_name = try ip.getOrPutString(sema.gpa, zir_field_name, .no_embedded_nulls); return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src); } @@ -20975,7 +21034,7 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| { const err_name = sema.mod.intern_pool.indexToKey(val.toIntern()).err.name; - return sema.addStrLit(sema.mod.intern_pool.stringToSlice(err_name)); + return sema.addNullTerminatedStrLit(err_name); } // Similar to zirTagName, we have special AIR instruction for the error name in case an optimimzation pass @@ -21093,7 +21152,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .EnumLiteral => { const val = try sema.resolveConstDefinedValue(block, .unneeded, operand, undefined); const tag_name = ip.indexToKey(val.toIntern()).enum_literal; - return sema.addStrLit(ip.stringToSlice(tag_name)); + return sema.addNullTerminatedStrLit(tag_name); }, .Enum => operand_ty, .Union => operand_ty.unionTagType(mod) orelse @@ -21127,7 +21186,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air }; // TODO: write something like getCoercedInts to avoid needing to dupe const field_name = enum_ty.enumFieldName(field_index, mod); - return sema.addStrLit(ip.stringToSlice(field_name)); + return sema.addNullTerminatedStrLit(field_name); } try sema.requireRuntimeBlock(block, src, operand_src); if (block.wantSafety() and sema.mod.backendSupportsFeature(.is_named_enum_value)) { @@ -21179,11 +21238,11 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const signedness_val = try Value.fromInterned(union_val.val).fieldValue( mod, - struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "signedness")).?, + struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "signedness", .no_embedded_nulls)).?, ); const bits_val = try Value.fromInterned(union_val.val).fieldValue( mod, - struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "bits")).?, + struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "bits", .no_embedded_nulls)).?, ); const signedness = mod.toEnum(std.builtin.Signedness, signedness_val); @@ -21195,11 +21254,11 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "len"), + try ip.getOrPutString(gpa, "len", .no_embedded_nulls), ).?); const child_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "child"), + try ip.getOrPutString(gpa, "child", .no_embedded_nulls), ).?); const len: u32 = @intCast(try len_val.toUnsignedIntAdvanced(sema)); @@ -21217,7 +21276,7 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const bits_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "bits"), + try ip.getOrPutString(gpa, "bits", .no_embedded_nulls), ).?); const bits: u16 = @intCast(try bits_val.toUnsignedIntAdvanced(sema)); @@ -21235,35 +21294,35 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const size_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "size"), + try ip.getOrPutString(gpa, "size", .no_embedded_nulls), ).?); const is_const_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "is_const"), + try ip.getOrPutString(gpa, "is_const", .no_embedded_nulls), ).?); const is_volatile_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "is_volatile"), + try ip.getOrPutString(gpa, "is_volatile", .no_embedded_nulls), ).?); const alignment_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "alignment"), + try ip.getOrPutString(gpa, "alignment", .no_embedded_nulls), ).?); const address_space_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "address_space"), + try ip.getOrPutString(gpa, "address_space", .no_embedded_nulls), ).?); const child_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "child"), + try ip.getOrPutString(gpa, "child", .no_embedded_nulls), ).?); const is_allowzero_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "is_allowzero"), + try ip.getOrPutString(gpa, "is_allowzero", .no_embedded_nulls), ).?); const sentinel_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "sentinel"), + try ip.getOrPutString(gpa, "sentinel", .no_embedded_nulls), ).?); if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { @@ -21341,15 +21400,15 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const len_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "len"), + try ip.getOrPutString(gpa, "len", .no_embedded_nulls), ).?); const child_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "child"), + try ip.getOrPutString(gpa, "child", .no_embedded_nulls), ).?); const sentinel_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "sentinel"), + try ip.getOrPutString(gpa, "sentinel", .no_embedded_nulls), ).?); const len = try len_val.toUnsignedIntAdvanced(sema); @@ -21370,7 +21429,7 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const child_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "child"), + try ip.getOrPutString(gpa, "child", .no_embedded_nulls), ).?); const child_ty = child_val.toType(); @@ -21382,11 +21441,11 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const error_set_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "error_set"), + try ip.getOrPutString(gpa, "error_set", .no_embedded_nulls), ).?); const payload_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "payload"), + try ip.getOrPutString(gpa, "payload", .no_embedded_nulls), ).?); const error_set_ty = error_set_val.toType(); @@ -21415,7 +21474,7 @@ fn zirReify( const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "name"), + try ip.getOrPutString(gpa, "name", .no_embedded_nulls), ).?); const name = try sema.sliceToIpString(block, src, name_val, .{ @@ -21437,23 +21496,23 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "layout"), + try ip.getOrPutString(gpa, "layout", .no_embedded_nulls), ).?); const backing_integer_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "backing_integer"), + try ip.getOrPutString(gpa, "backing_integer", .no_embedded_nulls), ).?); const fields_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "fields"), + try ip.getOrPutString(gpa, "fields", .no_embedded_nulls), ).?); const decls_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "decls"), + try ip.getOrPutString(gpa, "decls", .no_embedded_nulls), ).?); const is_tuple_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "is_tuple"), + try ip.getOrPutString(gpa, "is_tuple", .no_embedded_nulls), ).?); const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val); @@ -21477,19 +21536,19 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "tag_type"), + try ip.getOrPutString(gpa, "tag_type", .no_embedded_nulls), ).?); const fields_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "fields"), + try ip.getOrPutString(gpa, "fields", .no_embedded_nulls), ).?); const decls_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "decls"), + try ip.getOrPutString(gpa, "decls", .no_embedded_nulls), ).?); const is_exhaustive_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "is_exhaustive"), + try ip.getOrPutString(gpa, "is_exhaustive", .no_embedded_nulls), ).?); if (try decls_val.sliceLen(sema) > 0) { @@ -21506,7 +21565,7 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const decls_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "decls"), + try ip.getOrPutString(gpa, "decls", .no_embedded_nulls), ).?); // Decls @@ -21544,19 +21603,19 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const layout_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "layout"), + try ip.getOrPutString(gpa, "layout", .no_embedded_nulls), ).?); const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "tag_type"), + try ip.getOrPutString(gpa, "tag_type", .no_embedded_nulls), ).?); const fields_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "fields"), + try ip.getOrPutString(gpa, "fields", .no_embedded_nulls), ).?); const decls_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "decls"), + try ip.getOrPutString(gpa, "decls", .no_embedded_nulls), ).?); if (try decls_val.sliceLen(sema) > 0) { @@ -21574,23 +21633,23 @@ fn zirReify( const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); const calling_convention_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "calling_convention"), + try ip.getOrPutString(gpa, "calling_convention", .no_embedded_nulls), ).?); const is_generic_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "is_generic"), + try ip.getOrPutString(gpa, "is_generic", .no_embedded_nulls), ).?); const is_var_args_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "is_var_args"), + try ip.getOrPutString(gpa, "is_var_args", .no_embedded_nulls), ).?); const return_type_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "return_type"), + try ip.getOrPutString(gpa, "return_type", .no_embedded_nulls), ).?); const params_slice_val = try Value.fromInterned(union_val.val).fieldValue(mod, struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "params"), + try ip.getOrPutString(gpa, "params", .no_embedded_nulls), ).?); const is_generic = is_generic_val.toBool(); @@ -21620,15 +21679,15 @@ fn zirReify( const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "is_generic"), + try ip.getOrPutString(gpa, "is_generic", .no_embedded_nulls), ).?); const param_is_noalias_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "is_noalias"), + try ip.getOrPutString(gpa, "is_noalias", .no_embedded_nulls), ).?); const opt_param_type_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( ip, - try ip.getOrPutString(gpa, "type"), + try ip.getOrPutString(gpa, "type", .no_embedded_nulls), ).?); if (param_is_generic_val.toBool()) { @@ -22366,13 +22425,14 @@ fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; + const ip = &mod.intern_pool; + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const ty = try sema.resolveType(block, ty_src, inst_data.operand); - var bytes = std.ArrayList(u8).init(sema.arena); - try ty.print(bytes.writer(), mod); - return addStrLitNoAlias(sema, bytes.items); + const type_name = try ip.getOrPutStringFmt(sema.gpa, "{}", .{ty.fmt(mod)}, .no_embedded_nulls); + return sema.addNullTerminatedStrLit(type_name); } fn zirFrameType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -23507,7 +23567,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 } const field_index = if (ty.isTuple(mod)) blk: { - if (ip.stringEqlSlice(field_name, "len")) { + if (field_name.eqlSlice("len", ip)) { return sema.fail(block, src, "no offset available for 'len' field of tuple", .{}); } break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src); @@ -23977,18 +24037,18 @@ fn resolveExportOptions( const section_src = sema.maybeOptionsSrc(block, src, "section"); const visibility_src = sema.maybeOptionsSrc(block, src, "visibility"); - const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name"), name_src); + const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name", .no_embedded_nulls), name_src); const name = try sema.toConstString(block, name_src, name_operand, .{ .needed_comptime_reason = "name of exported value must be comptime-known", }); - const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage"), linkage_src); + const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage", .no_embedded_nulls), linkage_src); const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_operand, .{ .needed_comptime_reason = "linkage of exported value must be comptime-known", }); const linkage = mod.toEnum(std.builtin.GlobalLinkage, linkage_val); - const section_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "section"), section_src); + const section_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "section", .no_embedded_nulls), section_src); const section_opt_val = try sema.resolveConstDefinedValue(block, section_src, section_operand, .{ .needed_comptime_reason = "linksection of exported value must be comptime-known", }); @@ -23999,7 +24059,7 @@ fn resolveExportOptions( else null; - const visibility_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "visibility"), visibility_src); + const visibility_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "visibility", .no_embedded_nulls), visibility_src); const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_operand, .{ .needed_comptime_reason = "visibility of exported value must be comptime-known", }); @@ -24016,9 +24076,9 @@ fn resolveExportOptions( } return .{ - .name = try ip.getOrPutString(gpa, name), + .name = try ip.getOrPutString(gpa, name, .no_embedded_nulls), .linkage = linkage, - .section = try ip.getOrPutStringOpt(gpa, section), + .section = try ip.getOrPutStringOpt(gpa, section, .no_embedded_nulls), .visibility = visibility, }; } @@ -24896,7 +24956,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins const field_index = switch (parent_ty.zigTypeTag(mod)) { .Struct => blk: { if (parent_ty.isTuple(mod)) { - if (ip.stringEqlSlice(field_name, "len")) { + if (field_name.eqlSlice("len", ip)) { return sema.fail(block, inst_src, "cannot get @fieldParentPtr of 'len' field of tuple", .{}); } break :blk try sema.tupleFieldIndex(block, parent_ty, field_name, field_name_src); @@ -25578,7 +25638,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const runtime_src = rs: { const ptr_val = try sema.resolveDefinedValue(block, dest_src, dest_ptr) orelse break :rs dest_src; - const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, "len"), dest_src); + const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, "len", .no_embedded_nulls), dest_src); const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src; const len_u64 = (try len_val.getUnsignedIntAdvanced(mod, sema)).?; const len = try sema.usizeCast(block, dest_src, len_u64); @@ -25708,7 +25768,7 @@ fn zirVarExtended( .ty = var_ty.toIntern(), .init = init_val, .decl = sema.owner_decl_index, - .lib_name = try mod.intern_pool.getOrPutStringOpt(sema.gpa, lib_name), + .lib_name = try mod.intern_pool.getOrPutStringOpt(sema.gpa, lib_name, .no_embedded_nulls), .is_extern = small.is_extern, .is_const = small.is_const, .is_threadlocal = small.is_threadlocal, @@ -26076,17 +26136,17 @@ fn resolvePrefetchOptions( const locality_src = sema.maybeOptionsSrc(block, src, "locality"); const cache_src = sema.maybeOptionsSrc(block, src, "cache"); - const rw = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "rw"), rw_src); + const rw = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "rw", .no_embedded_nulls), rw_src); const rw_val = try sema.resolveConstDefinedValue(block, rw_src, rw, .{ .needed_comptime_reason = "prefetch read/write must be comptime-known", }); - const locality = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "locality"), locality_src); + const locality = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "locality", .no_embedded_nulls), locality_src); const locality_val = try sema.resolveConstDefinedValue(block, locality_src, locality, .{ .needed_comptime_reason = "prefetch locality must be comptime-known", }); - const cache = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "cache"), cache_src); + const cache = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "cache", .no_embedded_nulls), cache_src); const cache_val = try sema.resolveConstDefinedValue(block, cache_src, cache, .{ .needed_comptime_reason = "prefetch cache must be comptime-known", }); @@ -26155,23 +26215,23 @@ fn resolveExternOptions( const linkage_src = sema.maybeOptionsSrc(block, src, "linkage"); const thread_local_src = sema.maybeOptionsSrc(block, src, "thread_local"); - const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name"), name_src); + const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name", .no_embedded_nulls), name_src); const name = try sema.toConstString(block, name_src, name_ref, .{ .needed_comptime_reason = "name of the extern symbol must be comptime-known", }); - const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "library_name"), library_src); + const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "library_name", .no_embedded_nulls), library_src); const library_name_val = try sema.resolveConstDefinedValue(block, library_src, library_name_inst, .{ .needed_comptime_reason = "library in which extern symbol is must be comptime-known", }); - const linkage_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage"), linkage_src); + const linkage_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage", .no_embedded_nulls), linkage_src); const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_ref, .{ .needed_comptime_reason = "linkage of the extern symbol must be comptime-known", }); const linkage = mod.toEnum(std.builtin.GlobalLinkage, linkage_val); - const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "is_thread_local"), thread_local_src); + const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "is_thread_local", .no_embedded_nulls), thread_local_src); const is_thread_local_val = try sema.resolveConstDefinedValue(block, thread_local_src, is_thread_local, .{ .needed_comptime_reason = "threadlocality of the extern symbol must be comptime-known", }); @@ -26196,8 +26256,8 @@ fn resolveExternOptions( } return .{ - .name = try ip.getOrPutString(gpa, name), - .library_name = try ip.getOrPutStringOpt(gpa, library_name), + .name = try ip.getOrPutString(gpa, name, .no_embedded_nulls), + .library_name = try ip.getOrPutStringOpt(gpa, library_name, .no_embedded_nulls), .linkage = linkage, .is_thread_local = is_thread_local_val.toBool(), }; @@ -26809,7 +26869,7 @@ fn preparePanicId(sema: *Sema, block: *Block, panic_id: Module.PanicId) !InternP block, .unneeded, panic_messages_ty.getNamespaceIndex(mod), - try mod.intern_pool.getOrPutString(gpa, @tagName(panic_id)), + try mod.intern_pool.getOrPutString(gpa, @tagName(panic_id), .no_embedded_nulls), ) catch |err| switch (err) { error.AnalysisFail, error.NeededSourceLocation => @panic("std.builtin.panic_messages is corrupt"), error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable, @@ -27129,9 +27189,9 @@ fn fieldVal( switch (inner_ty.zigTypeTag(mod)) { .Array => { - if (ip.stringEqlSlice(field_name, "len")) { + if (field_name.eqlSlice("len", ip)) { return Air.internedToRef((try mod.intValue(Type.usize, inner_ty.arrayLen(mod))).toIntern()); - } else if (ip.stringEqlSlice(field_name, "ptr") and is_pointer_to) { + } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) { const ptr_info = object_ty.ptrInfo(mod); const result_ty = try sema.ptrType(.{ .child = Type.fromInterned(ptr_info.child).childType(mod).toIntern(), @@ -27160,13 +27220,13 @@ fn fieldVal( .Pointer => { const ptr_info = inner_ty.ptrInfo(mod); if (ptr_info.flags.size == .Slice) { - if (ip.stringEqlSlice(field_name, "ptr")) { + if (field_name.eqlSlice("ptr", ip)) { const slice = if (is_pointer_to) try sema.analyzeLoad(block, src, object, object_src) else object; return sema.analyzeSlicePtr(block, object_src, slice, inner_ty); - } else if (ip.stringEqlSlice(field_name, "len")) { + } else if (field_name.eqlSlice("len", ip)) { const slice = if (is_pointer_to) try sema.analyzeLoad(block, src, object, object_src) else @@ -27319,10 +27379,10 @@ fn fieldPtr( switch (inner_ty.zigTypeTag(mod)) { .Array => { - if (ip.stringEqlSlice(field_name, "len")) { + if (field_name.eqlSlice("len", ip)) { const int_val = try mod.intValue(Type.usize, inner_ty.arrayLen(mod)); return anonDeclRef(sema, int_val.toIntern()); - } else if (ip.stringEqlSlice(field_name, "ptr") and is_pointer_to) { + } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) { const ptr_info = object_ty.ptrInfo(mod); const new_ptr_ty = try sema.ptrType(.{ .child = Type.fromInterned(ptr_info.child).childType(mod).toIntern(), @@ -27370,7 +27430,7 @@ fn fieldPtr( const attr_ptr_ty = if (is_pointer_to) object_ty else object_ptr_ty; - if (ip.stringEqlSlice(field_name, "ptr")) { + if (field_name.eqlSlice("ptr", ip)) { const slice_ptr_ty = inner_ty.slicePtrFieldType(mod); const result_ty = try sema.ptrType(.{ @@ -27396,7 +27456,7 @@ fn fieldPtr( const field_ptr = try block.addTyOp(.ptr_slice_ptr_ptr, result_ty, inner_ptr); try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); return field_ptr; - } else if (ip.stringEqlSlice(field_name, "len")) { + } else if (field_name.eqlSlice("len", ip)) { const result_ty = try sema.ptrType(.{ .child = .usize_type, .flags = .{ @@ -27584,7 +27644,7 @@ fn fieldCallBind( return sema.finishFieldCallBind(block, src, ptr_ty, field_ty, field_index, object_ptr); } else if (concrete_ty.isTuple(mod)) { - if (ip.stringEqlSlice(field_name, "len")) { + if (field_name.eqlSlice("len", ip)) { return .{ .direct = try mod.intRef(Type.usize, concrete_ty.structFieldCount(mod)) }; } if (field_name.toUnsigned(ip)) |field_index| { @@ -27808,7 +27868,7 @@ fn structFieldPtr( try sema.resolveStructLayout(struct_ty); if (struct_ty.isTuple(mod)) { - if (ip.stringEqlSlice(field_name, "len")) { + if (field_name.eqlSlice("len", ip)) { const len_inst = try mod.intRef(Type.usize, struct_ty.structFieldCount(mod)); return sema.analyzeRef(block, src, len_inst); } @@ -28023,7 +28083,7 @@ fn tupleFieldVal( tuple_ty: Type, ) CompileError!Air.Inst.Ref { const mod = sema.mod; - if (mod.intern_pool.stringEqlSlice(field_name, "len")) { + if (field_name.eqlSlice("len", &mod.intern_pool)) { return mod.intRef(Type.usize, tuple_ty.structFieldCount(mod)); } const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src); @@ -28039,16 +28099,17 @@ fn tupleFieldIndex( field_name_src: LazySrcLoc, ) CompileError!u32 { const mod = sema.mod; - assert(!mod.intern_pool.stringEqlSlice(field_name, "len")); - if (field_name.toUnsigned(&mod.intern_pool)) |field_index| { + const ip = &mod.intern_pool; + assert(!field_name.eqlSlice("len", ip)); + if (field_name.toUnsigned(ip)) |field_index| { if (field_index < tuple_ty.structFieldCount(mod)) return field_index; return sema.fail(block, field_name_src, "index '{}' out of bounds of tuple '{}'", .{ - field_name.fmt(&mod.intern_pool), tuple_ty.fmt(mod), + field_name.fmt(ip), tuple_ty.fmt(mod), }); } return sema.fail(block, field_name_src, "no field named '{}' in tuple '{}'", .{ - field_name.fmt(&mod.intern_pool), tuple_ty.fmt(mod), + field_name.fmt(ip), tuple_ty.fmt(mod), }); } @@ -28076,7 +28137,7 @@ fn tupleFieldValByIndex( return switch (mod.intern_pool.indexToKey(tuple_val.toIntern())) { .undef => mod.undefRef(field_ty), .aggregate => |aggregate| Air.internedToRef(switch (aggregate.storage) { - .bytes => |bytes| try mod.intValue(Type.u8, bytes[0]), + .bytes => |bytes| try mod.intValue(Type.u8, bytes.at(field_index, &mod.intern_pool)), .elems => |elems| Value.fromInterned(elems[field_index]), .repeated_elem => |elem| Value.fromInterned(elem), }.toIntern()), @@ -32266,38 +32327,36 @@ fn coerceTupleToStruct( .struct_type => ip.loadStructType(inst_ty.toIntern()).field_types.len, else => unreachable, }; - for (0..field_count) |field_index_usize| { - const field_i: u32 = @intCast(field_index_usize); + for (0..field_count) |tuple_field_index| { const field_src = inst_src; // TODO better source location - // https://github.com/ziglang/zig/issues/15709 const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) { .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0) - anon_struct_type.names.get(ip)[field_i] + anon_struct_type.names.get(ip)[tuple_field_index] else - try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}), - .struct_type => ip.loadStructType(inst_ty.toIntern()).field_names.get(ip)[field_i], + try ip.getOrPutStringFmt(sema.gpa, "{d}", .{tuple_field_index}, .no_embedded_nulls), + .struct_type => ip.loadStructType(inst_ty.toIntern()).field_names.get(ip)[tuple_field_index], else => unreachable, }; - const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src); - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); - const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); - const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); - field_refs[field_index] = coerced; - if (struct_type.fieldIsComptime(ip, field_index)) { + const struct_field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src); + const struct_field_ty = Type.fromInterned(struct_type.field_types.get(ip)[struct_field_index]); + const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, @intCast(tuple_field_index)); + const coerced = try sema.coerce(block, struct_field_ty, elem_ref, field_src); + field_refs[struct_field_index] = coerced; + if (struct_type.fieldIsComptime(ip, struct_field_index)) { const init_val = (try sema.resolveValue(coerced)) orelse { return sema.failWithNeededComptime(block, field_src, .{ .needed_comptime_reason = "value stored in comptime field must be comptime-known", }); }; - const field_init = Value.fromInterned(struct_type.field_inits.get(ip)[field_index]); - if (!init_val.eql(field_init, field_ty, sema.mod)) { - return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i); + const field_init = Value.fromInterned(struct_type.field_inits.get(ip)[struct_field_index]); + if (!init_val.eql(field_init, struct_field_ty, sema.mod)) { + return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, tuple_field_index); } } if (runtime_src == null) { if (try sema.resolveValue(coerced)) |field_val| { - field_vals[field_index] = field_val.toIntern(); + field_vals[struct_field_index] = field_val.toIntern(); } else { runtime_src = field_src; } @@ -32382,24 +32441,23 @@ fn coerceTupleToTuple( for (0..dest_field_count) |field_index_usize| { const field_i: u32 = @intCast(field_index_usize); const field_src = inst_src; // TODO better source location - // https://github.com/ziglang/zig/issues/15709 const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) { .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0) anon_struct_type.names.get(ip)[field_i] else - try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}), + try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}, .no_embedded_nulls), .struct_type => s: { const struct_type = ip.loadStructType(inst_ty.toIntern()); if (struct_type.field_names.len > 0) { break :s struct_type.field_names.get(ip)[field_i]; } else { - break :s try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}); + break :s try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}, .no_embedded_nulls); } }, else => unreachable, }; - if (ip.stringEqlSlice(field_name, "len")) + if (field_name.eqlSlice("len", ip)) return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{}); const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) { @@ -34196,7 +34254,7 @@ const PeerResolveResult = union(enum) { /// There was an error when resolving the type of a struct or tuple field. field_error: struct { /// The name of the field which caused the failure. - field_name: []const u8, + field_name: InternPool.NullTerminatedString, /// The type of this field in each peer. field_types: []Type, /// The error from resolving the field type. Guaranteed not to be `success`. @@ -34237,8 +34295,8 @@ const PeerResolveResult = union(enum) { }; }, .field_error => |field_error| { - const fmt = "struct field '{s}' has conflicting types"; - const args = .{field_error.field_name}; + const fmt = "struct field '{}' has conflicting types"; + const args = .{field_error.field_name.fmt(&mod.intern_pool)}; if (opt_msg) |msg| { try sema.errNote(block, src, msg, fmt, args); } else { @@ -35321,7 +35379,7 @@ fn resolvePeerTypesInner( const sub_peer_tys = try sema.arena.alloc(?Type, peer_tys.len); const sub_peer_vals = try sema.arena.alloc(?Value, peer_vals.len); - for (field_types, field_vals, 0..) |*field_ty, *field_val, field_idx| { + for (field_types, field_vals, 0..) |*field_ty, *field_val, field_index| { // Fill buffers with types and values of the field for (peer_tys, peer_vals, sub_peer_tys, sub_peer_vals) |opt_ty, opt_val, *peer_field_ty, *peer_field_val| { const ty = opt_ty orelse { @@ -35329,8 +35387,8 @@ fn resolvePeerTypesInner( peer_field_val.* = null; continue; }; - peer_field_ty.* = ty.structFieldType(field_idx, mod); - peer_field_val.* = if (opt_val) |val| try val.fieldValue(mod, field_idx) else null; + peer_field_ty.* = ty.structFieldType(field_index, mod); + peer_field_val.* = if (opt_val) |val| try val.fieldValue(mod, field_index) else null; } // Resolve field type recursively @@ -35339,9 +35397,10 @@ fn resolvePeerTypesInner( else => |result| { const result_buf = try sema.arena.create(PeerResolveResult); result_buf.* = result; - const field_name = if (is_tuple) name: { - break :name try std.fmt.allocPrint(sema.arena, "{d}", .{field_idx}); - } else try sema.arena.dupe(u8, ip.stringToSlice(field_names[field_idx])); + const field_name = if (is_tuple) + try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_index}, .no_embedded_nulls) + else + field_names[field_index]; // The error info needs the field types, but we can't reuse sub_peer_tys // since the recursive call may have clobbered it. @@ -35350,7 +35409,7 @@ fn resolvePeerTypesInner( // Already-resolved types won't be referenced by the error so it's fine // to leave them undefined. const ty = opt_ty orelse continue; - peer_field_ty.* = ty.structFieldType(field_idx, mod); + peer_field_ty.* = ty.structFieldType(field_index, mod); } return .{ .field_error = .{ @@ -35369,7 +35428,7 @@ fn resolvePeerTypesInner( const struct_ty = opt_ty orelse continue; try sema.resolveStructFieldInits(struct_ty); - const uncoerced_field_val = try struct_ty.structFieldValueComptime(mod, field_idx) orelse { + const uncoerced_field_val = try struct_ty.structFieldValueComptime(mod, field_index) orelse { comptime_val = null; break; }; @@ -36811,7 +36870,7 @@ fn semaStructFields( // This string needs to outlive the ZIR code. if (opt_field_name_zir) |field_name_zir| { - const field_name = try ip.getOrPutString(gpa, field_name_zir); + const field_name = try ip.getOrPutString(gpa, field_name_zir, .no_embedded_nulls); assert(struct_type.addFieldName(ip, field_name) == null); } @@ -37342,7 +37401,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded } // This string needs to outlive the ZIR code. - const field_name = try ip.getOrPutString(gpa, field_name_zir); + const field_name = try ip.getOrPutString(gpa, field_name_zir, .no_embedded_nulls); if (enum_field_names.len != 0) { enum_field_names[field_i] = field_name; } @@ -37528,7 +37587,12 @@ fn generateUnionTagTypeNumbered( const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node); errdefer mod.destroyDecl(new_decl_index); const fqn = try union_owner_decl.fullyQualifiedName(mod); - const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); + const name = try ip.getOrPutStringFmt( + gpa, + "@typeInfo({}).Union.tag_type.?", + .{fqn.fmt(ip)}, + .no_embedded_nulls, + ); try mod.initNewAnonDecl( new_decl_index, src_decl.src_line, @@ -37574,7 +37638,12 @@ fn generateUnionTagTypeSimple( const src_decl = mod.declPtr(block.src_decl); const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node); errdefer mod.destroyDecl(new_decl_index); - const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); + const name = try ip.getOrPutStringFmt( + gpa, + "@typeInfo({}).Union.tag_type.?", + .{fqn.fmt(ip)}, + .no_embedded_nulls, + ); try mod.initNewAnonDecl( new_decl_index, src_decl.src_line, @@ -37638,7 +37707,7 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int block, src, mod.declPtr(std_file.root_decl.unwrap().?).src_namespace.toOptional(), - try ip.getOrPutString(gpa, "builtin"), + try ip.getOrPutString(gpa, "builtin", .no_embedded_nulls), )) orelse @panic("lib/std.zig is corrupt and missing 'builtin'"); const builtin_inst = try sema.analyzeLoad(block, src, opt_builtin_inst, src); const builtin_ty = sema.analyzeAsType(block, src, builtin_inst) catch |err| switch (err) { @@ -37649,7 +37718,7 @@ fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!Int block, src, builtin_ty.getNamespaceIndex(mod), - try ip.getOrPutString(gpa, name), + try ip.getOrPutString(gpa, name, .no_embedded_nulls), )) orelse std.debug.panic("lib/std/builtin.zig is corrupt and missing '{s}'", .{name}); return decl_index; } @@ -38820,7 +38889,7 @@ fn intFitsInType( .aggregate => |aggregate| { assert(ty.zigTypeTag(mod) == .Vector); return switch (aggregate.storage) { - .bytes => |bytes| for (bytes, 0..) |byte, i| { + .bytes => |bytes| for (bytes.toSlice(ty.vectorLen(mod), &mod.intern_pool), 0..) |byte, i| { if (byte == 0) continue; const actual_needed_bits = std.math.log2(byte) + 1 + @intFromBool(info.signedness == .signed); if (info.bits >= actual_needed_bits) continue; diff --git a/src/Value.zig b/src/Value.zig index 7a9775e198..0f8dc5f7dc 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -52,30 +52,31 @@ pub fn toIpString(val: Value, ty: Type, mod: *Module) !InternPool.NullTerminated assert(ty.zigTypeTag(mod) == .Array); assert(ty.childType(mod).toIntern() == .u8_type); const ip = &mod.intern_pool; - return switch (mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage) { - .bytes => |bytes| try ip.getOrPutString(mod.gpa, bytes), - .elems => try arrayToIpString(val, ty.arrayLen(mod), mod), + switch (mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage) { + .bytes => |bytes| return bytes.toNullTerminatedString(ty.arrayLen(mod), ip), + .elems => return arrayToIpString(val, ty.arrayLen(mod), mod), .repeated_elem => |elem| { - const byte = @as(u8, @intCast(Value.fromInterned(elem).toUnsignedInt(mod))); - const len = @as(usize, @intCast(ty.arrayLen(mod))); + const byte: u8 = @intCast(Value.fromInterned(elem).toUnsignedInt(mod)); + const len: usize = @intCast(ty.arrayLen(mod)); try ip.string_bytes.appendNTimes(mod.gpa, byte, len); - return ip.getOrPutTrailingString(mod.gpa, len); + return ip.getOrPutTrailingString(mod.gpa, len, .no_embedded_nulls); }, - }; + } } /// Asserts that the value is representable as an array of bytes. /// Copies the value into a freshly allocated slice of memory, which is owned by the caller. pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator, mod: *Module) ![]u8 { - return switch (mod.intern_pool.indexToKey(val.toIntern())) { - .enum_literal => |enum_literal| allocator.dupe(u8, mod.intern_pool.stringToSlice(enum_literal)), + const ip = &mod.intern_pool; + return switch (ip.indexToKey(val.toIntern())) { + .enum_literal => |enum_literal| allocator.dupe(u8, enum_literal.toSlice(ip)), .slice => |slice| try arrayToAllocatedBytes(val, Value.fromInterned(slice.len).toUnsignedInt(mod), allocator, mod), .aggregate => |aggregate| switch (aggregate.storage) { - .bytes => |bytes| try allocator.dupe(u8, bytes), + .bytes => |bytes| try allocator.dupe(u8, bytes.toSlice(ty.arrayLenIncludingSentinel(mod), ip)), .elems => try arrayToAllocatedBytes(val, ty.arrayLen(mod), allocator, mod), .repeated_elem => |elem| { - const byte = @as(u8, @intCast(Value.fromInterned(elem).toUnsignedInt(mod))); - const result = try allocator.alloc(u8, @as(usize, @intCast(ty.arrayLen(mod)))); + const byte: u8 = @intCast(Value.fromInterned(elem).toUnsignedInt(mod)); + const result = try allocator.alloc(u8, @intCast(ty.arrayLen(mod))); @memset(result, byte); return result; }, @@ -85,10 +86,10 @@ pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator, mod: *Module } fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator, mod: *Module) ![]u8 { - const result = try allocator.alloc(u8, @as(usize, @intCast(len))); + const result = try allocator.alloc(u8, @intCast(len)); for (result, 0..) |*elem, i| { const elem_val = try val.elemValue(mod, i); - elem.* = @as(u8, @intCast(elem_val.toUnsignedInt(mod))); + elem.* = @intCast(elem_val.toUnsignedInt(mod)); } return result; } @@ -96,7 +97,7 @@ fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator, mod: *Modul fn arrayToIpString(val: Value, len_u64: u64, mod: *Module) !InternPool.NullTerminatedString { const gpa = mod.gpa; const ip = &mod.intern_pool; - const len = @as(usize, @intCast(len_u64)); + const len: usize = @intCast(len_u64); try ip.string_bytes.ensureUnusedCapacity(gpa, len); for (0..len) |i| { // I don't think elemValue has the possibility to affect ip.string_bytes. Let's @@ -104,10 +105,10 @@ fn arrayToIpString(val: Value, len_u64: u64, mod: *Module) !InternPool.NullTermi const prev = ip.string_bytes.items.len; const elem_val = try val.elemValue(mod, i); assert(ip.string_bytes.items.len == prev); - const byte = @as(u8, @intCast(elem_val.toUnsignedInt(mod))); + const byte: u8 = @intCast(elem_val.toUnsignedInt(mod)); ip.string_bytes.appendAssumeCapacity(byte); } - return ip.getOrPutTrailingString(gpa, len); + return ip.getOrPutTrailingString(gpa, len, .no_embedded_nulls); } pub fn fromInterned(i: InternPool.Index) Value { @@ -256,7 +257,7 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 const base_addr = (try Value.fromInterned(field.base).getUnsignedIntAdvanced(mod, opt_sema)) orelse return null; const struct_ty = Value.fromInterned(field.base).typeOf(mod).childType(mod); if (opt_sema) |sema| try sema.resolveTypeLayout(struct_ty); - return base_addr + struct_ty.structFieldOffset(@as(usize, @intCast(field.index)), mod); + return base_addr + struct_ty.structFieldOffset(@intCast(field.index), mod); }, else => null, }, @@ -351,17 +352,17 @@ pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{ bigint.writeTwosComplement(buffer[0..byte_count], endian); }, .Float => switch (ty.floatBits(target)) { - 16 => std.mem.writeInt(u16, buffer[0..2], @as(u16, @bitCast(val.toFloat(f16, mod))), endian), - 32 => std.mem.writeInt(u32, buffer[0..4], @as(u32, @bitCast(val.toFloat(f32, mod))), endian), - 64 => std.mem.writeInt(u64, buffer[0..8], @as(u64, @bitCast(val.toFloat(f64, mod))), endian), - 80 => std.mem.writeInt(u80, buffer[0..10], @as(u80, @bitCast(val.toFloat(f80, mod))), endian), - 128 => std.mem.writeInt(u128, buffer[0..16], @as(u128, @bitCast(val.toFloat(f128, mod))), endian), + 16 => std.mem.writeInt(u16, buffer[0..2], @bitCast(val.toFloat(f16, mod)), endian), + 32 => std.mem.writeInt(u32, buffer[0..4], @bitCast(val.toFloat(f32, mod)), endian), + 64 => std.mem.writeInt(u64, buffer[0..8], @bitCast(val.toFloat(f64, mod)), endian), + 80 => std.mem.writeInt(u80, buffer[0..10], @bitCast(val.toFloat(f80, mod)), endian), + 128 => std.mem.writeInt(u128, buffer[0..16], @bitCast(val.toFloat(f128, mod)), endian), else => unreachable, }, .Array => { const len = ty.arrayLen(mod); const elem_ty = ty.childType(mod); - const elem_size = @as(usize, @intCast(elem_ty.abiSize(mod))); + const elem_size: usize = @intCast(elem_ty.abiSize(mod)); var elem_i: usize = 0; var buf_off: usize = 0; while (elem_i < len) : (elem_i += 1) { @@ -380,17 +381,17 @@ pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{ const struct_type = mod.typeToStruct(ty) orelse return error.IllDefinedMemoryLayout; switch (struct_type.layout) { .auto => return error.IllDefinedMemoryLayout, - .@"extern" => for (0..struct_type.field_types.len) |i| { - const off: usize = @intCast(ty.structFieldOffset(i, mod)); + .@"extern" => for (0..struct_type.field_types.len) |field_index| { + const off: usize = @intCast(ty.structFieldOffset(field_index, mod)); const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) { .bytes => |bytes| { - buffer[off] = bytes[i]; + buffer[off] = bytes.at(field_index, ip); continue; }, - .elems => |elems| elems[i], + .elems => |elems| elems[field_index], .repeated_elem => |elem| elem, }); - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); + const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); try writeToMemory(field_val, field_ty, mod, buffer[off..]); }, .@"packed" => { @@ -423,7 +424,7 @@ pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{ const field_index = mod.unionTagFieldIndex(union_obj, union_tag).?; const field_type = Type.fromInterned(union_obj.field_types.get(&mod.intern_pool)[field_index]); const field_val = try val.fieldValue(mod, field_index); - const byte_count = @as(usize, @intCast(field_type.abiSize(mod))); + const byte_count: usize = @intCast(field_type.abiSize(mod)); return writeToMemory(field_val, field_type, mod, buffer[0..byte_count]); } else { const backing_ty = try ty.unionBackingType(mod); @@ -471,7 +472,7 @@ pub fn writeToPackedMemory( const target = mod.getTarget(); const endian = target.cpu.arch.endian(); if (val.isUndef(mod)) { - const bit_size = @as(usize, @intCast(ty.bitSize(mod))); + const bit_size: usize = @intCast(ty.bitSize(mod)); std.mem.writeVarPackedInt(buffer, bit_offset, bit_size, @as(u1, 0), endian); return; } @@ -507,17 +508,17 @@ pub fn writeToPackedMemory( } }, .Float => switch (ty.floatBits(target)) { - 16 => std.mem.writePackedInt(u16, buffer, bit_offset, @as(u16, @bitCast(val.toFloat(f16, mod))), endian), - 32 => std.mem.writePackedInt(u32, buffer, bit_offset, @as(u32, @bitCast(val.toFloat(f32, mod))), endian), - 64 => std.mem.writePackedInt(u64, buffer, bit_offset, @as(u64, @bitCast(val.toFloat(f64, mod))), endian), - 80 => std.mem.writePackedInt(u80, buffer, bit_offset, @as(u80, @bitCast(val.toFloat(f80, mod))), endian), - 128 => std.mem.writePackedInt(u128, buffer, bit_offset, @as(u128, @bitCast(val.toFloat(f128, mod))), endian), + 16 => std.mem.writePackedInt(u16, buffer, bit_offset, @bitCast(val.toFloat(f16, mod)), endian), + 32 => std.mem.writePackedInt(u32, buffer, bit_offset, @bitCast(val.toFloat(f32, mod)), endian), + 64 => std.mem.writePackedInt(u64, buffer, bit_offset, @bitCast(val.toFloat(f64, mod)), endian), + 80 => std.mem.writePackedInt(u80, buffer, bit_offset, @bitCast(val.toFloat(f80, mod)), endian), + 128 => std.mem.writePackedInt(u128, buffer, bit_offset, @bitCast(val.toFloat(f128, mod)), endian), else => unreachable, }, .Vector => { const elem_ty = ty.childType(mod); - const elem_bit_size = @as(u16, @intCast(elem_ty.bitSize(mod))); - const len = @as(usize, @intCast(ty.arrayLen(mod))); + const elem_bit_size: u16 = @intCast(elem_ty.bitSize(mod)); + const len: usize = @intCast(ty.arrayLen(mod)); var bits: u16 = 0; var elem_i: usize = 0; @@ -644,22 +645,22 @@ pub fn readFromMemory( .Float => return Value.fromInterned((try mod.intern(.{ .float = .{ .ty = ty.toIntern(), .storage = switch (ty.floatBits(target)) { - 16 => .{ .f16 = @as(f16, @bitCast(std.mem.readInt(u16, buffer[0..2], endian))) }, - 32 => .{ .f32 = @as(f32, @bitCast(std.mem.readInt(u32, buffer[0..4], endian))) }, - 64 => .{ .f64 = @as(f64, @bitCast(std.mem.readInt(u64, buffer[0..8], endian))) }, - 80 => .{ .f80 = @as(f80, @bitCast(std.mem.readInt(u80, buffer[0..10], endian))) }, - 128 => .{ .f128 = @as(f128, @bitCast(std.mem.readInt(u128, buffer[0..16], endian))) }, + 16 => .{ .f16 = @bitCast(std.mem.readInt(u16, buffer[0..2], endian)) }, + 32 => .{ .f32 = @bitCast(std.mem.readInt(u32, buffer[0..4], endian)) }, + 64 => .{ .f64 = @bitCast(std.mem.readInt(u64, buffer[0..8], endian)) }, + 80 => .{ .f80 = @bitCast(std.mem.readInt(u80, buffer[0..10], endian)) }, + 128 => .{ .f128 = @bitCast(std.mem.readInt(u128, buffer[0..16], endian)) }, else => unreachable, }, } }))), .Array => { const elem_ty = ty.childType(mod); const elem_size = elem_ty.abiSize(mod); - const elems = try arena.alloc(InternPool.Index, @as(usize, @intCast(ty.arrayLen(mod)))); + const elems = try arena.alloc(InternPool.Index, @intCast(ty.arrayLen(mod))); var offset: usize = 0; for (elems) |*elem| { elem.* = (try readFromMemory(elem_ty, mod, buffer[offset..], arena)).toIntern(); - offset += @as(usize, @intCast(elem_size)); + offset += @intCast(elem_size); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -795,7 +796,7 @@ pub fn readFromPackedMemory( }; // Slow path, we have to construct a big-int - const abi_size = @as(usize, @intCast(ty.abiSize(mod))); + const abi_size: usize = @intCast(ty.abiSize(mod)); const Limb = std.math.big.Limb; const limb_count = (abi_size + @sizeOf(Limb) - 1) / @sizeOf(Limb); const limbs_buffer = try arena.alloc(Limb, limb_count); @@ -812,20 +813,20 @@ pub fn readFromPackedMemory( .Float => return Value.fromInterned((try mod.intern(.{ .float = .{ .ty = ty.toIntern(), .storage = switch (ty.floatBits(target)) { - 16 => .{ .f16 = @as(f16, @bitCast(std.mem.readPackedInt(u16, buffer, bit_offset, endian))) }, - 32 => .{ .f32 = @as(f32, @bitCast(std.mem.readPackedInt(u32, buffer, bit_offset, endian))) }, - 64 => .{ .f64 = @as(f64, @bitCast(std.mem.readPackedInt(u64, buffer, bit_offset, endian))) }, - 80 => .{ .f80 = @as(f80, @bitCast(std.mem.readPackedInt(u80, buffer, bit_offset, endian))) }, - 128 => .{ .f128 = @as(f128, @bitCast(std.mem.readPackedInt(u128, buffer, bit_offset, endian))) }, + 16 => .{ .f16 = @bitCast(std.mem.readPackedInt(u16, buffer, bit_offset, endian)) }, + 32 => .{ .f32 = @bitCast(std.mem.readPackedInt(u32, buffer, bit_offset, endian)) }, + 64 => .{ .f64 = @bitCast(std.mem.readPackedInt(u64, buffer, bit_offset, endian)) }, + 80 => .{ .f80 = @bitCast(std.mem.readPackedInt(u80, buffer, bit_offset, endian)) }, + 128 => .{ .f128 = @bitCast(std.mem.readPackedInt(u128, buffer, bit_offset, endian)) }, else => unreachable, }, } }))), .Vector => { const elem_ty = ty.childType(mod); - const elems = try arena.alloc(InternPool.Index, @as(usize, @intCast(ty.arrayLen(mod)))); + const elems = try arena.alloc(InternPool.Index, @intCast(ty.arrayLen(mod))); var bits: u16 = 0; - const elem_bit_size = @as(u16, @intCast(elem_ty.bitSize(mod))); + const elem_bit_size: u16 = @intCast(elem_ty.bitSize(mod)); for (elems, 0..) |_, i| { // On big-endian systems, LLVM reverses the element order of vectors by default const tgt_elem_i = if (endian == .big) elems.len - i - 1 else i; @@ -909,7 +910,7 @@ fn bigIntToFloat(limbs: []const std.math.big.Limb, positive: bool) f128 { var i: usize = limbs.len; while (i != 0) { i -= 1; - const limb: f128 = @as(f128, @floatFromInt(limbs[i])); + const limb: f128 = @floatFromInt(limbs[i]); result = @mulAdd(f128, base, result, limb); } if (positive) { @@ -934,7 +935,7 @@ pub fn ctz(val: Value, ty: Type, mod: *Module) u64 { pub fn popCount(val: Value, ty: Type, mod: *Module) u64 { var bigint_buf: BigIntSpace = undefined; const bigint = val.toBigInt(&bigint_buf, mod); - return @as(u64, @intCast(bigint.popCount(ty.intInfo(mod).bits))); + return @intCast(bigint.popCount(ty.intInfo(mod).bits)); } pub fn bitReverse(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value { @@ -1191,7 +1192,7 @@ pub fn compareAllWithZeroAdvancedExtra( inline else => |x| if (std.math.isNan(x)) return op == .neq, }, .aggregate => |aggregate| return switch (aggregate.storage) { - .bytes => |bytes| for (bytes) |byte| { + .bytes => |bytes| for (bytes.toSlice(lhs.typeOf(mod).arrayLenIncludingSentinel(mod), &mod.intern_pool)) |byte| { if (!std.math.order(byte, 0).compare(op)) break false; } else true, .elems => |elems| for (elems) |elem| { @@ -1279,7 +1280,7 @@ pub fn elemValue(val: Value, zcu: *Zcu, index: usize) Allocator.Error!Value { if (index < len) return Value.fromInterned(switch (aggregate.storage) { .bytes => |bytes| try zcu.intern(.{ .int = .{ .ty = .u8_type, - .storage = .{ .u64 = bytes[index] }, + .storage = .{ .u64 = bytes.at(index, ip) }, } }), .elems => |elems| elems[index], .repeated_elem => |elem| elem, @@ -1318,28 +1319,37 @@ pub fn sliceArray( start: usize, end: usize, ) error{OutOfMemory}!Value { - // TODO: write something like getCoercedInts to avoid needing to dupe const mod = sema.mod; - const aggregate = mod.intern_pool.indexToKey(val.toIntern()).aggregate; - return Value.fromInterned(try mod.intern(.{ .aggregate = .{ - .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) { - .array_type => |array_type| try mod.arrayType(.{ - .len = @as(u32, @intCast(end - start)), - .child = array_type.child, - .sentinel = if (end == array_type.len) array_type.sentinel else .none, - }), - .vector_type => |vector_type| try mod.vectorType(.{ - .len = @as(u32, @intCast(end - start)), - .child = vector_type.child, - }), - else => unreachable, - }.toIntern(), - .storage = switch (aggregate.storage) { - .bytes => .{ .bytes = try sema.arena.dupe(u8, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.bytes[start..end]) }, - .elems => .{ .elems = try sema.arena.dupe(InternPool.Index, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.elems[start..end]) }, - .repeated_elem => |elem| .{ .repeated_elem = elem }, + const ip = &mod.intern_pool; + return Value.fromInterned(try mod.intern(.{ + .aggregate = .{ + .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) { + .array_type => |array_type| try mod.arrayType(.{ + .len = @intCast(end - start), + .child = array_type.child, + .sentinel = if (end == array_type.len) array_type.sentinel else .none, + }), + .vector_type => |vector_type| try mod.vectorType(.{ + .len = @intCast(end - start), + .child = vector_type.child, + }), + else => unreachable, + }.toIntern(), + .storage = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { + .bytes => |bytes| storage: { + try ip.string_bytes.ensureUnusedCapacity(sema.gpa, end - start + 1); + break :storage .{ .bytes = try ip.getOrPutString( + sema.gpa, + bytes.toSlice(end, ip)[start..], + .maybe_embedded_nulls, + ) }; + }, + // TODO: write something like getCoercedInts to avoid needing to dupe + .elems => |elems| .{ .elems = try sema.arena.dupe(InternPool.Index, elems[start..end]) }, + .repeated_elem => |elem| .{ .repeated_elem = elem }, + }, }, - } })); + })); } pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value { @@ -1350,7 +1360,7 @@ pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value { .aggregate => |aggregate| Value.fromInterned(switch (aggregate.storage) { .bytes => |bytes| try mod.intern(.{ .int = .{ .ty = .u8_type, - .storage = .{ .u64 = bytes[index] }, + .storage = .{ .u64 = bytes.at(index, &mod.intern_pool) }, } }), .elems => |elems| elems[index], .repeated_elem => |elem| elem, @@ -1461,7 +1471,7 @@ pub fn getErrorName(val: Value, mod: *const Module) InternPool.OptionalNullTermi pub fn getErrorInt(val: Value, mod: *const Module) Module.ErrorInt { return if (getErrorName(val, mod).unwrap()) |err_name| - @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(err_name).?)) + @intCast(mod.global_error_set.getIndex(err_name).?) else 0; } @@ -2413,14 +2423,14 @@ pub fn intTruncBitsAsValue( for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); const bits_elem = try bits.elemValue(mod, i); - scalar.* = (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, @as(u16, @intCast(bits_elem.toUnsignedInt(mod))), mod)).toIntern(); + scalar.* = (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, @intCast(bits_elem.toUnsignedInt(mod)), mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), .storage = .{ .elems = result_data }, } }))); } - return intTruncScalar(val, ty, allocator, signedness, @as(u16, @intCast(bits.toUnsignedInt(mod))), mod); + return intTruncScalar(val, ty, allocator, signedness, @intCast(bits.toUnsignedInt(mod)), mod); } pub fn intTruncScalar( @@ -2468,7 +2478,7 @@ pub fn shlScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *M // resorting to BigInt first. var lhs_space: Value.BigIntSpace = undefined; const lhs_bigint = lhs.toBigInt(&lhs_space, mod); - const shift = @as(usize, @intCast(rhs.toUnsignedInt(mod))); + const shift: usize = @intCast(rhs.toUnsignedInt(mod)); const limbs = try allocator.alloc( std.math.big.Limb, lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1, @@ -2530,7 +2540,7 @@ pub fn shlWithOverflowScalar( const info = ty.intInfo(mod); var lhs_space: Value.BigIntSpace = undefined; const lhs_bigint = lhs.toBigInt(&lhs_space, mod); - const shift = @as(usize, @intCast(rhs.toUnsignedInt(mod))); + const shift: usize = @intCast(rhs.toUnsignedInt(mod)); const limbs = try allocator.alloc( std.math.big.Limb, lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1, @@ -2587,7 +2597,7 @@ pub fn shlSatScalar( var lhs_space: Value.BigIntSpace = undefined; const lhs_bigint = lhs.toBigInt(&lhs_space, mod); - const shift = @as(usize, @intCast(rhs.toUnsignedInt(mod))); + const shift: usize = @intCast(rhs.toUnsignedInt(mod)); const limbs = try arena.alloc( std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(info.bits) + 1, @@ -2659,7 +2669,7 @@ pub fn shrScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *M // resorting to BigInt first. var lhs_space: Value.BigIntSpace = undefined; const lhs_bigint = lhs.toBigInt(&lhs_space, mod); - const shift = @as(usize, @intCast(rhs.toUnsignedInt(mod))); + const shift: usize = @intCast(rhs.toUnsignedInt(mod)); const result_limbs = lhs_bigint.limbs.len -| (shift / (@sizeOf(std.math.big.Limb) * 8)); if (result_limbs == 0) { diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index b9f8259c05..ddde72345e 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -4345,8 +4345,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier .data = .{ .reg = .x30 }, }); } else if (func_value.getExternFunc(mod)) |extern_func| { - const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name); - const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name); + const decl_name = mod.declPtr(extern_func.decl).name.toSlice(&mod.intern_pool); + const lib_name = extern_func.lib_name.toSlice(&mod.intern_pool); if (self.bin_file.cast(link.File.MachO)) |macho_file| { _ = macho_file; @panic("TODO airCall"); diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 022f2f9bee..83159ec80e 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -2199,9 +2199,9 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif const atom = func.bin_file.getAtomPtr(atom_index); const type_index = try func.bin_file.storeDeclType(extern_func.decl, func_type); try func.bin_file.addOrUpdateImport( - mod.intern_pool.stringToSlice(ext_decl.name), + ext_decl.name.toSlice(&mod.intern_pool), atom.sym_index, - mod.intern_pool.stringToSliceUnwrap(ext_decl.getOwnedExternFunc(mod).?.lib_name), + ext_decl.getOwnedExternFunc(mod).?.lib_name.toSlice(&mod.intern_pool), type_index, ); break :blk extern_func.decl; @@ -7236,8 +7236,8 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const fqn = ip.stringToSlice(try mod.declPtr(enum_decl_index).fullyQualifiedName(mod)); - const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn}); + const fqn = try mod.declPtr(enum_decl_index).fullyQualifiedName(mod); + const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{}", .{fqn.fmt(ip)}); // check if we already generated code for this. if (func.bin_file.findGlobalSymbol(func_name)) |loc| { @@ -7268,17 +7268,18 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { // generate an if-else chain for each tag value as well as constant. 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_name = tag_names.get(ip)[tag_index]; + const tag_name_len = tag_name.length(ip); // for each tag name, create an unnamed const, // and then get a pointer to its value. const name_ty = try mod.arrayType(.{ - .len = tag_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 = tag_name }, + .storage = .{ .bytes = tag_name.toString() }, } }); const tag_sym_index = try func.bin_file.lowerUnnamedConst( Value.fromInterned(name_val), @@ -7338,7 +7339,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { // store length try writer.writeByte(std.wasm.opcode(.i32_const)); - try leb.writeULEB128(writer, @as(u32, @intCast(tag_name.len))); + try leb.writeULEB128(writer, @as(u32, @intCast(tag_name_len))); try writer.writeByte(std.wasm.opcode(.i32_store)); try leb.writeULEB128(writer, encoded_alignment); try leb.writeULEB128(writer, @as(u32, 4)); @@ -7359,7 +7360,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { // store length try writer.writeByte(std.wasm.opcode(.i64_const)); - try leb.writeULEB128(writer, @as(u64, @intCast(tag_name.len))); + try leb.writeULEB128(writer, @as(u64, @intCast(tag_name_len))); try writer.writeByte(std.wasm.opcode(.i64_store)); try leb.writeULEB128(writer, encoded_alignment); try leb.writeULEB128(writer, @as(u32, 8)); diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 7a90eacf54..c165baf7e8 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -2247,7 +2247,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { var data_off: i32 = 0; 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_name_len = tag_names.get(ip)[tag_index].length(ip); const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index)); const tag_mcv = try self.genTypedValue(tag_val); try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv); @@ -12314,8 +12314,8 @@ fn genCall(self: *Self, info: union(enum) { }, .extern_func => |extern_func| { const owner_decl = mod.declPtr(extern_func.decl); - const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name); - const decl_name = mod.intern_pool.stringToSlice(owner_decl.name); + const lib_name = extern_func.lib_name.toSlice(&mod.intern_pool); + const decl_name = owner_decl.name.toSlice(&mod.intern_pool); try self.genExternSymbolRef(.call, lib_name, decl_name); }, else => return self.fail("TODO implement calling bitcasted functions", .{}), diff --git a/src/codegen.zig b/src/codegen.zig index 76be8be974..b45777564a 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -97,7 +97,7 @@ fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian _ = target; const bits = @typeInfo(F).Float.bits; const Int = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = bits } }); - const int = @as(Int, @bitCast(f)); + const int: Int = @bitCast(f); mem.writeInt(Int, code[0..@divExact(bits, 8)], int, endian); } @@ -136,24 +136,24 @@ pub fn generateLazySymbol( if (lazy_sym.ty.isAnyError(zcu)) { alignment.* = .@"4"; const err_names = zcu.global_error_set.keys(); - mem.writeInt(u32, try code.addManyAsArray(4), @as(u32, @intCast(err_names.len)), endian); + mem.writeInt(u32, try code.addManyAsArray(4), @intCast(err_names.len), endian); var offset = code.items.len; try code.resize((1 + err_names.len + 1) * 4); for (err_names) |err_name_nts| { - const err_name = zcu.intern_pool.stringToSlice(err_name_nts); - mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian); + const err_name = err_name_nts.toSlice(ip); + mem.writeInt(u32, code.items[offset..][0..4], @intCast(code.items.len), endian); offset += 4; try code.ensureUnusedCapacity(err_name.len + 1); code.appendSliceAssumeCapacity(err_name); code.appendAssumeCapacity(0); } - mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian); + mem.writeInt(u32, code.items[offset..][0..4], @intCast(code.items.len), endian); return Result.ok; } else if (lazy_sym.ty.zigTypeTag(zcu) == .Enum) { alignment.* = .@"1"; 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]); + const tag_name = tag_names.get(ip)[tag_index].toSlice(ip); try code.ensureUnusedCapacity(tag_name.len + 1); code.appendSliceAssumeCapacity(tag_name); code.appendAssumeCapacity(0); @@ -241,13 +241,13 @@ pub fn generateSymbol( }, .err => |err| { const int = try mod.getErrorValue(err.name); - try code.writer().writeInt(u16, @as(u16, @intCast(int)), endian); + try code.writer().writeInt(u16, @intCast(int), endian); }, .error_union => |error_union| { const payload_ty = ty.errorUnionPayload(mod); - const err_val = switch (error_union.val) { - .err_name => |err_name| @as(u16, @intCast(try mod.getErrorValue(err_name))), - .payload => @as(u16, 0), + const err_val: u16 = switch (error_union.val) { + .err_name => |err_name| @intCast(try mod.getErrorValue(err_name)), + .payload => 0, }; if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { @@ -357,15 +357,13 @@ pub fn generateSymbol( }, .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) { .array_type => |array_type| switch (aggregate.storage) { - .bytes => |bytes| try code.appendSlice(bytes), + .bytes => |bytes| try code.appendSlice(bytes.toSlice(array_type.lenIncludingSentinel(), ip)), .elems, .repeated_elem => { var index: u64 = 0; - const len_including_sentinel = - array_type.len + @intFromBool(array_type.sentinel != .none); - while (index < len_including_sentinel) : (index += 1) { + while (index < array_type.lenIncludingSentinel()) : (index += 1) { switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (aggregate.storage) { .bytes => unreachable, - .elems => |elems| elems[@as(usize, @intCast(index))], + .elems => |elems| elems[@intCast(index)], .repeated_elem => |elem| if (index < array_type.len) elem else @@ -399,7 +397,7 @@ pub fn generateSymbol( }) { .bool_true => true, .bool_false => false, - else => |elem| switch (mod.intern_pool.indexToKey(elem)) { + else => |elem| switch (ip.indexToKey(elem)) { .undef => continue, .int => |int| switch (int.storage) { .u64 => |x| switch (x) { @@ -420,7 +418,7 @@ pub fn generateSymbol( } } else { switch (aggregate.storage) { - .bytes => |bytes| try code.appendSlice(bytes), + .bytes => |bytes| try code.appendSlice(bytes.toSlice(vector_type.len, ip)), .elems, .repeated_elem => { var index: u64 = 0; while (index < vector_type.len) : (index += 1) { @@ -457,7 +455,7 @@ pub fn generateSymbol( const field_val = switch (aggregate.storage) { .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ .ty = field_ty, - .storage = .{ .u64 = bytes[index] }, + .storage = .{ .u64 = bytes.at(index, ip) }, } }), .elems => |elems| elems[index], .repeated_elem => |elem| elem, @@ -493,7 +491,7 @@ pub fn generateSymbol( const field_val = switch (aggregate.storage) { .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ .ty = field_ty, - .storage = .{ .u64 = bytes[index] }, + .storage = .{ .u64 = bytes.at(index, ip) }, } }), .elems => |elems| elems[index], .repeated_elem => |elem| elem, @@ -513,7 +511,7 @@ pub fn generateSymbol( } else { Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), mod, code.items[current_pos..], bits) catch unreachable; } - bits += @as(u16, @intCast(Type.fromInterned(field_ty).bitSize(mod))); + bits += @intCast(Type.fromInterned(field_ty).bitSize(mod)); } }, .auto, .@"extern" => { @@ -529,7 +527,7 @@ pub fn generateSymbol( const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ .ty = field_ty, - .storage = .{ .u64 = bytes[field_index] }, + .storage = .{ .u64 = bytes.at(field_index, ip) }, } }), .elems => |elems| elems[field_index], .repeated_elem => |elem| elem, @@ -625,7 +623,8 @@ fn lowerParentPtr( reloc_info: RelocInfo, ) CodeGenError!Result { const mod = bin_file.comp.module.?; - const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr; + const ip = &mod.intern_pool; + const ptr = ip.indexToKey(parent_ptr).ptr; return switch (ptr.addr) { .decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info), .anon_decl => |ad| try lowerAnonDeclRef(bin_file, src_loc, ad, code, debug_output, reloc_info), @@ -636,10 +635,10 @@ fn lowerParentPtr( eu_payload, code, debug_output, - reloc_info.offset(@as(u32, @intCast(errUnionPayloadOffset( - Type.fromInterned(mod.intern_pool.typeOf(eu_payload)), + reloc_info.offset(@intCast(errUnionPayloadOffset( + Type.fromInterned(ip.typeOf(eu_payload)), mod, - )))), + ))), ), .opt_payload => |opt_payload| try lowerParentPtr( bin_file, @@ -655,19 +654,19 @@ fn lowerParentPtr( elem.base, code, debug_output, - reloc_info.offset(@as(u32, @intCast(elem.index * - Type.fromInterned(mod.intern_pool.typeOf(elem.base)).elemType2(mod).abiSize(mod)))), + reloc_info.offset(@intCast(elem.index * + Type.fromInterned(ip.typeOf(elem.base)).elemType2(mod).abiSize(mod))), ), .field => |field| { - const base_ptr_ty = mod.intern_pool.typeOf(field.base); - const base_ty = mod.intern_pool.indexToKey(base_ptr_ty).ptr_type.child; + const base_ptr_ty = ip.typeOf(field.base); + const base_ty = ip.indexToKey(base_ptr_ty).ptr_type.child; return lowerParentPtr( bin_file, src_loc, field.base, code, debug_output, - reloc_info.offset(switch (mod.intern_pool.indexToKey(base_ty)) { + reloc_info.offset(switch (ip.indexToKey(base_ty)) { .ptr_type => |ptr_type| switch (ptr_type.flags.size) { .One, .Many, .C => unreachable, .Slice => switch (field.index) { @@ -723,11 +722,12 @@ fn lowerAnonDeclRef( ) CodeGenError!Result { _ = debug_output; const zcu = lf.comp.module.?; + const ip = &zcu.intern_pool; const target = lf.comp.root_mod.resolved_target.result; const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); const decl_val = anon_decl.val; - const decl_ty = Type.fromInterned(zcu.intern_pool.typeOf(decl_val)); + const decl_ty = Type.fromInterned(ip.typeOf(decl_val)); log.debug("lowerAnonDecl: ty = {}", .{decl_ty.fmt(zcu)}); const is_fn_body = decl_ty.zigTypeTag(zcu) == .Fn; if (!is_fn_body and !decl_ty.hasRuntimeBits(zcu)) { @@ -735,7 +735,7 @@ fn lowerAnonDeclRef( return Result.ok; } - const decl_align = zcu.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; + const decl_align = ip.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; const res = try lf.lowerAnonDecl(decl_val, decl_align, src_loc); switch (res) { .ok => {}, @@ -787,8 +787,8 @@ fn lowerDeclRef( }); const endian = target.cpu.arch.endian(); switch (ptr_width) { - 16 => mem.writeInt(u16, try code.addManyAsArray(2), @as(u16, @intCast(vaddr)), endian), - 32 => mem.writeInt(u32, try code.addManyAsArray(4), @as(u32, @intCast(vaddr)), endian), + 16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(vaddr), endian), + 32 => mem.writeInt(u32, try code.addManyAsArray(4), @intCast(vaddr), endian), 64 => mem.writeInt(u64, try code.addManyAsArray(8), vaddr, endian), else => unreachable, } @@ -859,6 +859,7 @@ fn genDeclRef( ptr_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { const zcu = lf.comp.module.?; + const ip = &zcu.intern_pool; const ty = val.typeOf(zcu); log.debug("genDeclRef: val = {}", .{val.fmtValue(zcu)}); @@ -869,7 +870,7 @@ fn genDeclRef( const ptr_bits = target.ptrBitWidth(); const ptr_bytes: u64 = @divExact(ptr_bits, 8); - const decl_index = switch (zcu.intern_pool.indexToKey(ptr_decl.val.toIntern())) { + const decl_index = switch (ip.indexToKey(ptr_decl.val.toIntern())) { .func => |func| func.owner_decl, .extern_func => |extern_func| extern_func.decl, else => ptr_decl_index, @@ -909,12 +910,9 @@ fn genDeclRef( if (lf.cast(link.File.Elf)) |elf_file| { if (is_extern) { - const name = zcu.intern_pool.stringToSlice(decl.name); + const name = decl.name.toSlice(ip); // TODO audit this - const lib_name = if (decl.getOwnedVariable(zcu)) |ov| - zcu.intern_pool.stringToSliceUnwrap(ov.lib_name) - else - null; + const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null; const sym_index = try elf_file.getGlobalSymbol(name, lib_name); elf_file.symbol(elf_file.zigObjectPtr().?.symbol(sym_index)).flags.needs_got = true; return GenResult.mcv(.{ .load_symbol = sym_index }); @@ -927,11 +925,8 @@ fn genDeclRef( return GenResult.mcv(.{ .load_symbol = sym.esym_index }); } else if (lf.cast(link.File.MachO)) |macho_file| { if (is_extern) { - const name = zcu.intern_pool.stringToSlice(decl.name); - const lib_name = if (decl.getOwnedVariable(zcu)) |ov| - zcu.intern_pool.stringToSliceUnwrap(ov.lib_name) - else - null; + const name = decl.name.toSlice(ip); + const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null; const sym_index = try macho_file.getGlobalSymbol(name, lib_name); macho_file.getSymbol(macho_file.getZigObject().?.symbols.items[sym_index]).flags.needs_got = true; return GenResult.mcv(.{ .load_symbol = sym_index }); @@ -944,12 +939,9 @@ fn genDeclRef( return GenResult.mcv(.{ .load_symbol = sym.nlist_idx }); } else if (lf.cast(link.File.Coff)) |coff_file| { if (is_extern) { - const name = zcu.intern_pool.stringToSlice(decl.name); + const name = decl.name.toSlice(ip); // TODO audit this - const lib_name = if (decl.getOwnedVariable(zcu)) |ov| - zcu.intern_pool.stringToSliceUnwrap(ov.lib_name) - else - null; + const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null; const global_index = try coff_file.getGlobalSymbol(name, lib_name); try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT return GenResult.mcv(.{ .load_got = link.File.Coff.global_symbol_bit | global_index }); @@ -1012,6 +1004,7 @@ pub fn genTypedValue( owner_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { const zcu = lf.comp.module.?; + const ip = &zcu.intern_pool; const ty = val.typeOf(zcu); log.debug("genTypedValue: val = {}", .{val.fmtValue(zcu)}); @@ -1024,7 +1017,7 @@ pub fn genTypedValue( const target = namespace.file_scope.mod.resolved_target.result; const ptr_bits = target.ptrBitWidth(); - if (!ty.isSlice(zcu)) switch (zcu.intern_pool.indexToKey(val.toIntern())) { + if (!ty.isSlice(zcu)) switch (ip.indexToKey(val.toIntern())) { .ptr => |ptr| switch (ptr.addr) { .decl => |decl| return genDeclRef(lf, src_loc, val, decl), else => {}, @@ -1041,7 +1034,7 @@ pub fn genTypedValue( return GenResult.mcv(.{ .immediate = 0 }); }, .none => {}, - else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { + else => switch (ip.indexToKey(val.toIntern())) { .int => { return GenResult.mcv(.{ .immediate = val.toUnsignedInt(zcu) }); }, @@ -1052,8 +1045,8 @@ pub fn genTypedValue( .Int => { const info = ty.intInfo(zcu); if (info.bits <= ptr_bits) { - const unsigned = switch (info.signedness) { - .signed => @as(u64, @bitCast(val.toSignedInt(zcu))), + const unsigned: u64 = switch (info.signedness) { + .signed => @bitCast(val.toSignedInt(zcu)), .unsigned => val.toUnsignedInt(zcu), }; return GenResult.mcv(.{ .immediate = unsigned }); @@ -1075,7 +1068,7 @@ pub fn genTypedValue( } }, .Enum => { - const enum_tag = zcu.intern_pool.indexToKey(val.toIntern()).enum_tag; + const enum_tag = ip.indexToKey(val.toIntern()).enum_tag; return genTypedValue( lf, src_loc, @@ -1084,7 +1077,7 @@ pub fn genTypedValue( ); }, .ErrorSet => { - const err_name = zcu.intern_pool.indexToKey(val.toIntern()).err.name; + const err_name = ip.indexToKey(val.toIntern()).err.name; const error_index = zcu.global_error_set.getIndex(err_name).?; return GenResult.mcv(.{ .immediate = error_index }); }, @@ -1094,7 +1087,7 @@ pub fn genTypedValue( if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { // We use the error type directly as the type. const err_int_ty = try zcu.errorIntType(); - switch (zcu.intern_pool.indexToKey(val.toIntern()).error_union.val) { + switch (ip.indexToKey(val.toIntern()).error_union.val) { .err_name => |err_name| return genTypedValue( lf, src_loc, diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 576cc55b63..0b3d2f9836 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -505,7 +505,7 @@ pub const Function = struct { .never_inline, => |owner_decl| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{ @tagName(key), - fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), + fmtIdent(zcu.declPtr(owner_decl).name.toSlice(&zcu.intern_pool)), @intFromEnum(owner_decl), }), }, @@ -898,7 +898,7 @@ pub const DeclGen = struct { }, }, .err => |err| try writer.print("zig_error_{}", .{ - fmtIdent(ip.stringToSlice(err.name)), + fmtIdent(err.name.toSlice(ip)), }), .error_union => |error_union| { const payload_ty = ty.errorUnionPayload(zcu); @@ -1178,7 +1178,7 @@ pub const DeclGen = struct { switch (ip.indexToKey(val.toIntern()).aggregate.storage) { .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ .ty = field_ty.toIntern(), - .storage = .{ .u64 = bytes[field_index] }, + .storage = .{ .u64 = bytes.at(field_index, ip) }, } }), .elems => |elems| elems[field_index], .repeated_elem => |elem| elem, @@ -1212,7 +1212,7 @@ pub const DeclGen = struct { const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ .ty = field_ty.toIntern(), - .storage = .{ .u64 = bytes[field_index] }, + .storage = .{ .u64 = bytes.at(field_index, ip) }, } }), .elems => |elems| elems[field_index], .repeated_elem => |elem| elem, @@ -1258,7 +1258,7 @@ pub const DeclGen = struct { const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ .ty = field_ty.toIntern(), - .storage = .{ .u64 = bytes[field_index] }, + .storage = .{ .u64 = bytes.at(field_index, ip) }, } }), .elems => |elems| elems[field_index], .repeated_elem => |elem| elem, @@ -1299,7 +1299,7 @@ pub const DeclGen = struct { const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ .ty = field_ty.toIntern(), - .storage = .{ .u64 = bytes[field_index] }, + .storage = .{ .u64 = bytes.at(field_index, ip) }, } }), .elems => |elems| elems[field_index], .repeated_elem => |elem| elem, @@ -1392,7 +1392,7 @@ pub const DeclGen = struct { try writer.writeAll(" .payload = {"); } if (field_ty.hasRuntimeBits(zcu)) { - try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))}); + try writer.print(" .{ } = ", .{fmtIdent(field_name.toSlice(ip))}); try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); try writer.writeByte(' '); } else for (0..loaded_union.field_types.len) |this_field_index| { @@ -1741,14 +1741,12 @@ pub const DeclGen = struct { switch (name) { .export_index => |export_index| mangled: { const maybe_exports = zcu.decl_exports.get(fn_decl_index); - const external_name = ip.stringToSlice( - if (maybe_exports) |exports| - exports.items[export_index].opts.name - else if (fn_decl.isExtern(zcu)) - fn_decl.name - else - break :mangled, - ); + const external_name = (if (maybe_exports) |exports| + exports.items[export_index].opts.name + else if (fn_decl.isExtern(zcu)) + fn_decl.name + else + break :mangled).toSlice(ip); const is_mangled = isMangledIdent(external_name, true); const is_export = export_index > 0; if (is_mangled and is_export) { @@ -1756,7 +1754,7 @@ pub const DeclGen = struct { fmtIdent(external_name), fmtStringLiteral(external_name, null), fmtStringLiteral( - ip.stringToSlice(maybe_exports.?.items[0].opts.name), + maybe_exports.?.items[0].opts.name.toSlice(ip), null, ), }); @@ -1767,7 +1765,7 @@ pub const DeclGen = struct { } else if (is_export) { try w.print(" zig_export({s}, {s})", .{ fmtStringLiteral( - ip.stringToSlice(maybe_exports.?.items[0].opts.name), + maybe_exports.?.items[0].opts.name.toSlice(ip), null, ), fmtStringLiteral(external_name, null), @@ -2075,12 +2073,12 @@ pub const DeclGen = struct { .complete, ); mangled: { - const external_name = zcu.intern_pool.stringToSlice(if (maybe_exports) |exports| + const external_name = (if (maybe_exports) |exports| exports.items[0].opts.name else if (variable.is_extern) decl.name else - break :mangled); + break :mangled).toSlice(&zcu.intern_pool); if (isMangledIdent(external_name, true)) { try fwd.print(" zig_mangled_{s}({ }, {s})", .{ @tagName(fwd_kind), @@ -2094,15 +2092,16 @@ pub const DeclGen = struct { fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void { const zcu = dg.zcu; + const ip = &zcu.intern_pool; const decl = zcu.declPtr(decl_index); if (zcu.decl_exports.get(decl_index)) |exports| { try writer.print("{ }", .{ - fmtIdent(zcu.intern_pool.stringToSlice(exports.items[export_index].opts.name)), + fmtIdent(exports.items[export_index].opts.name.toSlice(ip)), }); } else if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| { try writer.print("{ }", .{ - fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(extern_decl_index).name)), + fmtIdent(zcu.declPtr(extern_decl_index).name.toSlice(ip)), }); } else { // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), @@ -2226,7 +2225,7 @@ fn renderFwdDeclTypeName( switch (fwd_decl.name) { .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}), .owner_decl => |owner_decl| try w.print("{}__{d}", .{ - fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), + fmtIdent(zcu.declPtr(owner_decl).name.toSlice(&zcu.intern_pool)), @intFromEnum(owner_decl), }), } @@ -2548,7 +2547,7 @@ pub fn genErrDecls(o: *Object) !void { try writer.writeAll("enum {\n"); o.indent_writer.pushIndent(); for (zcu.global_error_set.keys()[1..], 1..) |name_nts, value| { - const name = ip.stringToSlice(name_nts); + const name = name_nts.toSlice(ip); max_name_len = @max(name.len, max_name_len); const err_val = try zcu.intern(.{ .err = .{ .ty = .anyerror_type, @@ -2566,19 +2565,19 @@ pub fn genErrDecls(o: *Object) !void { defer o.dg.gpa.free(name_buf); @memcpy(name_buf[0..name_prefix.len], name_prefix); - for (zcu.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]; + for (zcu.global_error_set.keys()) |name| { + const name_slice = name.toSlice(ip); + @memcpy(name_buf[name_prefix.len..][0..name_slice.len], name_slice); + const identifier = name_buf[0 .. name_prefix.len + name_slice.len]; const name_ty = try zcu.arrayType(.{ - .len = name.len, + .len = name_slice.len, .child = .u8_type, .sentinel = .zero_u8, }); const name_val = try zcu.intern(.{ .aggregate = .{ .ty = name_ty.toIntern(), - .storage = .{ .bytes = name }, + .storage = .{ .bytes = name.toString() }, } }); try writer.writeAll("static "); @@ -2611,7 +2610,7 @@ pub fn genErrDecls(o: *Object) !void { ); try writer.writeAll(" = {"); for (zcu.global_error_set.keys(), 0..) |name_nts, value| { - const name = ip.stringToSlice(name_nts); + const name = name_nts.toSlice(ip); if (value != 0) try writer.writeByte(','); try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{ fmtIdent(name), @@ -2659,7 +2658,7 @@ fn genExports(o: *Object) !void { for (exports.items[1..]) |@"export"| { try fwd.writeAll("zig_extern "); if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage "); - const export_name = ip.stringToSlice(@"export".opts.name); + const export_name = @"export".opts.name.toSlice(ip); try o.dg.renderTypeAndName( fwd, decl.typeOf(zcu), @@ -2672,11 +2671,11 @@ fn genExports(o: *Object) !void { try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{ fmtIdent(export_name), fmtStringLiteral(export_name, null), - fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null), + fmtStringLiteral(exports.items[0].opts.name.toSlice(ip), null), }); } else { try fwd.print(" zig_export({s}, {s})", .{ - fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null), + fmtStringLiteral(exports.items[0].opts.name.toSlice(ip), null), fmtStringLiteral(export_name, null), }); } @@ -2706,17 +2705,18 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn try w.writeAll(") {\n switch (tag) {\n"); const tag_names = enum_ty.enumFields(zcu); for (0..tag_names.len) |tag_index| { - const tag_name = ip.stringToSlice(tag_names.get(ip)[tag_index]); + const tag_name = tag_names.get(ip)[tag_index]; + const tag_name_len = tag_name.length(ip); const tag_val = try zcu.enumValueFieldIndex(enum_ty, @intCast(tag_index)); const name_ty = try zcu.arrayType(.{ - .len = tag_name.len, + .len = tag_name_len, .child = .u8_type, .sentinel = .zero_u8, }); const name_val = try zcu.intern(.{ .aggregate = .{ .ty = name_ty.toIntern(), - .storage = .{ .bytes = tag_name }, + .storage = .{ .bytes = tag_name.toString() }, } }); try w.print(" case {}: {{\n static ", .{ @@ -2729,7 +2729,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn try o.dg.renderType(w, name_slice_ty); try w.print("){{{}, {}}};\n", .{ fmtIdent("name"), - try o.dg.fmtIntLiteral(try zcu.intValue(Type.usize, tag_name.len), .Other), + try o.dg.fmtIntLiteral(try zcu.intValue(Type.usize, tag_name_len), .Other), }); try w.writeAll(" }\n"); @@ -2797,7 +2797,7 @@ pub fn genFunc(f: *Function) !void { try o.indent_writer.insertNewline(); if (!is_global) try o.writer().writeAll("static "); - if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| + if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s| try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)}); try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 }); try o.writer().writeByte(' '); @@ -2887,7 +2887,7 @@ pub fn genDecl(o: *Object) !void { if (!is_global) try w.writeAll("static "); if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal "); - if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| + if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s| try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); const decl_c_value = .{ .decl = decl_index }; try o.dg.renderTypeAndName(w, decl_ty, decl_c_value, .{}, decl.alignment, .complete); @@ -2920,7 +2920,7 @@ pub fn genDeclValue( switch (o.dg.pass) { .decl => |decl_index| { if (zcu.decl_exports.get(decl_index)) |exports| { - const export_name = zcu.intern_pool.stringToSlice(exports.items[0].opts.name); + const export_name = exports.items[0].opts.name.toSlice(&zcu.intern_pool); if (isMangledIdent(export_name, true)) { try fwd_decl_writer.print(" zig_mangled_final({ }, {s})", .{ fmtIdent(export_name), fmtStringLiteral(export_name, null), @@ -2936,7 +2936,7 @@ pub fn genDeclValue( const w = o.writer(); if (!is_global) try w.writeAll("static "); - if (zcu.intern_pool.stringToSliceUnwrap(@"linksection")) |s| + if (@"linksection".toSlice(&zcu.intern_pool)) |s| try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete); try w.writeAll(" = "); @@ -5454,7 +5454,7 @@ fn fieldLocation( .{ .byte_offset = loaded_struct.offsets.get(ip)[field_index] } else .{ .field = if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| - .{ .identifier = ip.stringToSlice(field_name) } + .{ .identifier = field_name.toSlice(ip) } else .{ .field = field_index } }, .@"packed" => if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0) @@ -5470,7 +5470,7 @@ fn fieldLocation( .{ .byte_offset = container_ty.structFieldOffset(field_index, zcu) } else .{ .field = if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name| - .{ .identifier = ip.stringToSlice(field_name) } + .{ .identifier = field_name.toSlice(ip) } else .{ .field = field_index } }, .union_type => { @@ -5485,9 +5485,9 @@ fn fieldLocation( .begin; const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; return .{ .field = if (loaded_union.hasTag(ip)) - .{ .payload_identifier = ip.stringToSlice(field_name) } + .{ .payload_identifier = field_name.toSlice(ip) } else - .{ .identifier = ip.stringToSlice(field_name) } }; + .{ .identifier = field_name.toSlice(ip) } }; }, .@"packed" => return .begin, } @@ -5643,7 +5643,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { const loaded_struct = ip.loadStructType(struct_ty.toIntern()); switch (loaded_struct.layout) { .auto, .@"extern" => break :field_name if (loaded_struct.fieldName(ip, extra.field_index).unwrap()) |field_name| - .{ .identifier = ip.stringToSlice(field_name) } + .{ .identifier = field_name.toSlice(ip) } else .{ .field = extra.field_index }, .@"packed" => { @@ -5701,7 +5701,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { } }, .anon_struct_type => |anon_struct_info| if (anon_struct_info.fieldName(ip, extra.field_index).unwrap()) |field_name| - .{ .identifier = ip.stringToSlice(field_name) } + .{ .identifier = field_name.toSlice(ip) } else .{ .field = extra.field_index }, .union_type => field_name: { @@ -5710,9 +5710,9 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { .auto, .@"extern" => { const name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index]; break :field_name if (loaded_union.hasTag(ip)) - .{ .payload_identifier = ip.stringToSlice(name) } + .{ .payload_identifier = name.toSlice(ip) } else - .{ .identifier = ip.stringToSlice(name) }; + .{ .identifier = name.toSlice(ip) }; }, .@"packed" => { const operand_lval = if (struct_byval == .constant) blk: { @@ -7062,7 +7062,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { const a = try Assignment.start(f, writer, field_ty); try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| - .{ .identifier = ip.stringToSlice(field_name) } + .{ .identifier = field_name.toSlice(ip) } else .{ .field = field_index }); try a.assign(f, writer); @@ -7142,7 +7142,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { const a = try Assignment.start(f, writer, field_ty); try f.writeCValueMember(writer, local, if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name| - .{ .identifier = ip.stringToSlice(field_name) } + .{ .identifier = field_name.toSlice(ip) } else .{ .field = field_index }); try a.assign(f, writer); @@ -7190,8 +7190,8 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, zcu))}); try a.end(f, writer); } - break :field .{ .payload_identifier = ip.stringToSlice(field_name) }; - } else .{ .identifier = ip.stringToSlice(field_name) }; + break :field .{ .payload_identifier = field_name.toSlice(ip) }; + } else .{ .identifier = field_name.toSlice(ip) }; const a = try Assignment.start(f, writer, payload_ty); try f.writeCValueMember(writer, local, field); diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig index 1c460acc6b..83d28dcb4f 100644 --- a/src/codegen/c/Type.zig +++ b/src/codegen/c/Type.zig @@ -1465,7 +1465,7 @@ pub const Pool = struct { }, }, .array_type => |array_info| { - const len = array_info.len + @intFromBool(array_info.sentinel != .none); + const len = array_info.lenIncludingSentinel(); if (len == 0) return .{ .index = .void }; const elem_type = Type.fromInterned(array_info.child); const elem_ctype = try pool.fromType( @@ -1479,7 +1479,7 @@ pub const Pool = struct { if (elem_ctype.index == .void) return .{ .index = .void }; const array_ctype = try pool.getArray(allocator, .{ .elem_ctype = elem_ctype, - .len = array_info.len + @intFromBool(array_info.sentinel != .none), + .len = len, }); if (!kind.isParameter()) return array_ctype; var fields = [_]Info.Field{ @@ -1625,7 +1625,7 @@ pub const Pool = struct { if (field_ctype.index == .void) continue; const field_name = if (loaded_struct.fieldName(ip, field_index) .unwrap()) |field_name| - try pool.string(allocator, ip.stringToSlice(field_name)) + try pool.string(allocator, field_name.toSlice(ip)) else try pool.fmt(allocator, "f{d}", .{field_index}); const field_alignas = AlignAs.fromAlignment(.{ @@ -1685,7 +1685,7 @@ pub const Pool = struct { if (field_ctype.index == .void) continue; const field_name = if (anon_struct_info.fieldName(ip, @intCast(field_index)) .unwrap()) |field_name| - try pool.string(allocator, ip.stringToSlice(field_name)) + try pool.string(allocator, field_name.toSlice(ip)) else try pool.fmt(allocator, "f{d}", .{field_index}); pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ @@ -1766,7 +1766,7 @@ pub const Pool = struct { if (field_ctype.index == .void) continue; const field_name = try pool.string( allocator, - ip.stringToSlice(loaded_tag.names.get(ip)[field_index]), + loaded_tag.names.get(ip)[field_index].toSlice(ip), ); const field_alignas = AlignAs.fromAlignment(.{ .@"align" = loaded_union.fieldAlign(ip, @intCast(field_index)), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 7419e778a1..db0eaa3ce5 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1011,7 +1011,7 @@ pub const Object = struct { llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty); for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| { - const name_string = try o.builder.stringNull(mod.intern_pool.stringToSlice(name)); + const name_string = try o.builder.stringNull(name.toSlice(&mod.intern_pool)); const name_init = try o.builder.stringConst(name_string); const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); @@ -1086,7 +1086,7 @@ pub const Object = struct { for (object.extern_collisions.keys()) |decl_index| { const global = object.decl_map.get(decl_index) orelse continue; // Same logic as below but for externs instead of exports. - const decl_name = object.builder.strtabStringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue; + const decl_name = object.builder.strtabStringIfExists(mod.declPtr(decl_index).name.toSlice(&mod.intern_pool)) orelse continue; const other_global = object.builder.getGlobal(decl_name) orelse continue; if (other_global.toConst().getBase(&object.builder) == global.toConst().getBase(&object.builder)) continue; @@ -1116,7 +1116,7 @@ pub const Object = struct { for (export_list) |exp| { // Detect if the LLVM global has already been created as an extern. In such // case, we need to replace all uses of it with this exported global. - const exp_name = object.builder.strtabStringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue; + const exp_name = object.builder.strtabStringIfExists(exp.opts.name.toSlice(&mod.intern_pool)) orelse continue; const other_global = object.builder.getGlobal(exp_name) orelse continue; if (other_global.toConst().getBase(&object.builder) == global_base) continue; @@ -1442,7 +1442,7 @@ pub const Object = struct { } }, &o.builder); } - if (ip.stringToSliceUnwrap(decl.@"linksection")) |section| + if (decl.@"linksection".toSlice(ip)) |section| function_index.setSection(try o.builder.string(section), &o.builder); var deinit_wip = true; @@ -1662,7 +1662,7 @@ pub const Object = struct { const subprogram = try o.builder.debugSubprogram( file, - try o.builder.metadataString(ip.stringToSlice(decl.name)), + try o.builder.metadataString(decl.name.toSlice(ip)), try o.builder.metadataStringFromStrtabString(function_index.name(&o.builder)), line_number, line_number + func.lbrace_line, @@ -1752,6 +1752,7 @@ pub const Object = struct { .value => |val| return updateExportedValue(self, mod, val, exports), }; const gpa = mod.gpa; + const ip = &mod.intern_pool; // If the module does not already have the function, we ignore this function call // because we call `updateExports` at the end of `updateFunc` and `updateDecl`. const global_index = self.decl_map.get(decl_index) orelse return; @@ -1759,17 +1760,14 @@ pub const Object = struct { const comp = mod.comp; if (decl.isExtern(mod)) { const decl_name = decl_name: { - const decl_name = mod.intern_pool.stringToSlice(decl.name); - if (mod.getTarget().isWasm() and decl.val.typeOf(mod).zigTypeTag(mod) == .Fn) { - if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { + if (decl.getOwnedExternFunc(mod).?.lib_name.toSlice(ip)) |lib_name| { if (!std.mem.eql(u8, lib_name, "c")) { - break :decl_name try self.builder.strtabStringFmt("{s}|{s}", .{ decl_name, lib_name }); + break :decl_name try self.builder.strtabStringFmt("{}|{s}", .{ decl.name.fmt(ip), lib_name }); } } } - - break :decl_name try self.builder.strtabString(decl_name); + break :decl_name try self.builder.strtabString(decl.name.toSlice(ip)); }; if (self.builder.getGlobal(decl_name)) |other_global| { @@ -1792,9 +1790,7 @@ pub const Object = struct { if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder); } } else if (exports.len != 0) { - const main_exp_name = try self.builder.strtabString( - mod.intern_pool.stringToSlice(exports[0].opts.name), - ); + const main_exp_name = try self.builder.strtabString(exports[0].opts.name.toSlice(ip)); try global_index.rename(main_exp_name, &self.builder); if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal) @@ -1803,9 +1799,7 @@ pub const Object = struct { return updateExportedGlobal(self, mod, global_index, exports); } else { - const fqn = try self.builder.strtabString( - mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)), - ); + const fqn = try self.builder.strtabString((try decl.fullyQualifiedName(mod)).toSlice(ip)); try global_index.rename(fqn, &self.builder); global_index.setLinkage(.internal, &self.builder); if (comp.config.dll_export_fns) @@ -1832,9 +1826,8 @@ pub const Object = struct { exports: []const *Module.Export, ) link.File.UpdateExportsError!void { const gpa = mod.gpa; - const main_exp_name = try o.builder.strtabString( - mod.intern_pool.stringToSlice(exports[0].opts.name), - ); + const ip = &mod.intern_pool; + const main_exp_name = try o.builder.strtabString(exports[0].opts.name.toSlice(ip)); const global_index = i: { const gop = try o.anon_decl_map.getOrPut(gpa, exported_value); if (gop.found_existing) { @@ -1845,7 +1838,7 @@ pub const Object = struct { const llvm_addr_space = toLlvmAddressSpace(.generic, o.target); const variable_index = try o.builder.addVariable( main_exp_name, - try o.lowerType(Type.fromInterned(mod.intern_pool.typeOf(exported_value))), + try o.lowerType(Type.fromInterned(ip.typeOf(exported_value))), llvm_addr_space, ); const global_index = variable_index.ptrConst(&o.builder).global; @@ -1867,8 +1860,9 @@ pub const Object = struct { global_index: Builder.Global.Index, exports: []const *Module.Export, ) link.File.UpdateExportsError!void { - global_index.setUnnamedAddr(.default, &o.builder); const comp = mod.comp; + const ip = &mod.intern_pool; + global_index.setUnnamedAddr(.default, &o.builder); if (comp.config.dll_export_fns) global_index.setDllStorageClass(.dllexport, &o.builder); global_index.setLinkage(switch (exports[0].opts.linkage) { @@ -1882,7 +1876,7 @@ pub const Object = struct { .hidden => .hidden, .protected => .protected, }, &o.builder); - if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section| + if (exports[0].opts.section.toSlice(ip)) |section| switch (global_index.ptrConst(&o.builder).kind) { .variable => |impl_index| impl_index.setSection( try o.builder.string(section), @@ -1900,7 +1894,7 @@ pub const Object = struct { // Until then we iterate over existing aliases and make them point // to the correct decl, or otherwise add a new alias. Old aliases are leaked. for (exports[1..]) |exp| { - const exp_name = try o.builder.strtabString(mod.intern_pool.stringToSlice(exp.opts.name)); + const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip)); if (o.builder.getGlobal(exp_name)) |global| { switch (global.ptrConst(&o.builder).kind) { .alias => |alias| { @@ -2013,7 +2007,7 @@ pub const Object = struct { std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst(); enumerators[i] = try o.builder.debugEnumerator( - try o.builder.metadataString(ip.stringToSlice(field_name_ip)), + try o.builder.metadataString(field_name_ip.toSlice(ip)), int_info.signedness == .unsigned, int_info.bits, bigint, @@ -2473,7 +2467,7 @@ pub const Object = struct { offset = field_offset + field_size; const field_name = if (tuple.names.len != 0) - ip.stringToSlice(tuple.names.get(ip)[i]) + tuple.names.get(ip)[i].toSlice(ip) else try std.fmt.allocPrintZ(gpa, "{d}", .{i}); defer if (tuple.names.len == 0) gpa.free(field_name); @@ -2557,10 +2551,10 @@ pub const Object = struct { const field_offset = ty.structFieldOffset(field_index, mod); const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse - try ip.getOrPutStringFmt(gpa, "{d}", .{field_index}); + try ip.getOrPutStringFmt(gpa, "{d}", .{field_index}, .no_embedded_nulls); fields.appendAssumeCapacity(try o.builder.debugMemberType( - try o.builder.metadataString(ip.stringToSlice(field_name)), + try o.builder.metadataString(field_name.toSlice(ip)), .none, // File debug_fwd_ref, 0, // Line @@ -2655,7 +2649,7 @@ pub const Object = struct { const field_name = tag_type.names.get(ip)[field_index]; fields.appendAssumeCapacity(try o.builder.debugMemberType( - try o.builder.metadataString(ip.stringToSlice(field_name)), + try o.builder.metadataString(field_name.toSlice(ip)), .none, // File debug_union_fwd_ref, 0, // Line @@ -2827,7 +2821,7 @@ pub const Object = struct { const mod = o.module; const decl = mod.declPtr(decl_index); return o.builder.debugStructType( - try o.builder.metadataString(mod.intern_pool.stringToSlice(decl.name)), // TODO use fully qualified name + try o.builder.metadataString(decl.name.toSlice(&mod.intern_pool)), // TODO use fully qualified name try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope), try o.namespaceToDebugScope(decl.src_namespace), decl.src_line + 1, @@ -2844,11 +2838,11 @@ pub const Object = struct { const std_mod = mod.std_mod; const std_file = (mod.importPkg(std_mod) catch unreachable).file; - const builtin_str = try mod.intern_pool.getOrPutString(mod.gpa, "builtin"); + const builtin_str = try mod.intern_pool.getOrPutString(mod.gpa, "builtin", .no_embedded_nulls); const std_namespace = mod.namespacePtr(mod.declPtr(std_file.root_decl.unwrap().?).src_namespace); const builtin_decl = std_namespace.decls.getKeyAdapted(builtin_str, Module.DeclAdapter{ .zcu = mod }).?; - const stack_trace_str = try mod.intern_pool.getOrPutString(mod.gpa, "StackTrace"); + const stack_trace_str = try mod.intern_pool.getOrPutString(mod.gpa, "StackTrace", .no_embedded_nulls); // buffer is only used for int_type, `builtin` is a struct. const builtin_ty = mod.declPtr(builtin_decl).val.toType(); const builtin_namespace = mod.namespacePtrUnwrap(builtin_ty.getNamespaceIndex(mod)).?; @@ -2892,10 +2886,10 @@ pub const Object = struct { const is_extern = decl.isExtern(zcu); const function_index = try o.builder.addFunction( try o.lowerType(zig_fn_type), - try o.builder.strtabString(ip.stringToSlice(if (is_extern) + try o.builder.strtabString((if (is_extern) decl.name else - try decl.fullyQualifiedName(zcu))), + try decl.fullyQualifiedName(zcu)).toSlice(ip)), toLlvmAddressSpace(decl.@"addrspace", target), ); gop.value_ptr.* = function_index.ptrConst(&o.builder).global; @@ -2910,9 +2904,9 @@ pub const Object = struct { if (target.isWasm()) { try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("wasm-import-name"), - .value = try o.builder.string(ip.stringToSlice(decl.name)), + .value = try o.builder.string(decl.name.toSlice(ip)), } }, &o.builder); - if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(zcu).?.lib_name)) |lib_name| { + if (decl.getOwnedExternFunc(zcu).?.lib_name.toSlice(ip)) |lib_name| { if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("wasm-import-module"), .value = try o.builder.string(lib_name), @@ -3108,9 +3102,10 @@ pub const Object = struct { const is_extern = decl.isExtern(mod); const variable_index = try o.builder.addVariable( - try o.builder.strtabString(mod.intern_pool.stringToSlice( - if (is_extern) decl.name else try decl.fullyQualifiedName(mod), - )), + try o.builder.strtabString((if (is_extern) + decl.name + else + try decl.fullyQualifiedName(mod)).toSlice(&mod.intern_pool)), try o.lowerType(decl.typeOf(mod)), toLlvmGlobalAddressSpace(decl.@"addrspace", mod.getTarget()), ); @@ -3258,7 +3253,7 @@ pub const Object = struct { }; }, .array_type => |array_type| o.builder.arrayType( - array_type.len + @intFromBool(array_type.sentinel != .none), + array_type.lenIncludingSentinel(), try o.lowerType(Type.fromInterned(array_type.child)), ), .vector_type => |vector_type| o.builder.vectorType( @@ -3335,9 +3330,7 @@ pub const Object = struct { return int_ty; } - const name = try o.builder.string(ip.stringToSlice( - try mod.declPtr(struct_type.decl.unwrap().?).fullyQualifiedName(mod), - )); + const fqn = try mod.declPtr(struct_type.decl.unwrap().?).fullyQualifiedName(mod); var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){}; defer llvm_field_types.deinit(o.gpa); @@ -3402,7 +3395,7 @@ pub const Object = struct { ); } - const ty = try o.builder.opaqueType(name); + const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip))); try o.type_map.put(o.gpa, t.toIntern(), ty); o.builder.namedTypeSetBody( @@ -3491,9 +3484,7 @@ pub const Object = struct { return enum_tag_ty; } - const name = try o.builder.string(ip.stringToSlice( - try mod.declPtr(union_obj.decl).fullyQualifiedName(mod), - )); + const fqn = try mod.declPtr(union_obj.decl).fullyQualifiedName(mod); const aligned_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[layout.most_aligned_field]); const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty); @@ -3513,7 +3504,7 @@ pub const Object = struct { }; if (layout.tag_size == 0) { - const ty = try o.builder.opaqueType(name); + const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip))); try o.type_map.put(o.gpa, t.toIntern(), ty); o.builder.namedTypeSetBody( @@ -3541,7 +3532,7 @@ pub const Object = struct { llvm_fields_len += 1; } - const ty = try o.builder.opaqueType(name); + const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip))); try o.type_map.put(o.gpa, t.toIntern(), ty); o.builder.namedTypeSetBody( @@ -3554,8 +3545,8 @@ pub const Object = struct { const gop = try o.type_map.getOrPut(o.gpa, t.toIntern()); if (!gop.found_existing) { const decl = mod.declPtr(ip.loadOpaqueType(t.toIntern()).decl); - const name = try o.builder.string(ip.stringToSlice(try decl.fullyQualifiedName(mod))); - gop.value_ptr.* = try o.builder.opaqueType(name); + const fqn = try decl.fullyQualifiedName(mod); + gop.value_ptr.* = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip))); } return gop.value_ptr.*; }, @@ -3859,7 +3850,9 @@ pub const Object = struct { }, .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) { .array_type => |array_type| switch (aggregate.storage) { - .bytes => |bytes| try o.builder.stringConst(try o.builder.string(bytes)), + .bytes => |bytes| try o.builder.stringConst(try o.builder.string( + bytes.toSlice(array_type.lenIncludingSentinel(), ip), + )), .elems => |elems| { const array_ty = try o.lowerType(ty); const elem_ty = array_ty.childType(&o.builder); @@ -3892,8 +3885,7 @@ pub const Object = struct { }, .repeated_elem => |elem| { const len: usize = @intCast(array_type.len); - const len_including_sentinel: usize = - @intCast(len + @intFromBool(array_type.sentinel != .none)); + const len_including_sentinel: usize = @intCast(array_type.lenIncludingSentinel()); const array_ty = try o.lowerType(ty); const elem_ty = array_ty.childType(&o.builder); @@ -3942,7 +3934,7 @@ pub const Object = struct { defer allocator.free(vals); switch (aggregate.storage) { - .bytes => |bytes| for (vals, bytes) |*result_val, byte| { + .bytes => |bytes| for (vals, bytes.toSlice(vector_type.len, ip)) |*result_val, byte| { result_val.* = try o.builder.intConst(.i8, byte); }, .elems => |elems| for (vals, elems) |*result_val, elem| { @@ -4633,7 +4625,7 @@ pub const Object = struct { defer wip_switch.finish(&wip); for (0..enum_type.names.len) |field_index| { - const name = try o.builder.stringNull(ip.stringToSlice(enum_type.names.get(ip)[field_index])); + const name = try o.builder.stringNull(enum_type.names.get(ip)[field_index].toSlice(ip)); const name_init = try o.builder.stringConst(name); const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); @@ -4693,6 +4685,7 @@ pub const DeclGen = struct { fn genDecl(dg: *DeclGen) !void { const o = dg.object; const zcu = o.module; + const ip = &zcu.intern_pool; const decl = dg.decl; const decl_index = dg.decl_index; assert(decl.has_tv); @@ -4705,7 +4698,7 @@ pub const DeclGen = struct { decl.getAlignment(zcu).toLlvm(), &o.builder, ); - if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section| + if (decl.@"linksection".toSlice(ip)) |section| variable_index.setSection(try o.builder.string(section), &o.builder); assert(decl.has_tv); const init_val = if (decl.val.getVariable(zcu)) |decl_var| decl_var.init else init_val: { @@ -4728,7 +4721,7 @@ pub const DeclGen = struct { const debug_file = try o.getDebugFile(namespace.file_scope); const debug_global_var = try o.builder.debugGlobalVar( - try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)), // Name + try o.builder.metadataString(decl.name.toSlice(ip)), // Name try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name debug_file, // File debug_file, // Scope @@ -5156,8 +5149,8 @@ pub const FuncGen = struct { self.scope = try o.builder.debugSubprogram( self.file, - try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)), - try o.builder.metadataString(zcu.intern_pool.stringToSlice(fqn)), + try o.builder.metadataString(decl.name.toSlice(&zcu.intern_pool)), + try o.builder.metadataString(fqn.toSlice(&zcu.intern_pool)), line_number, line_number + func.lbrace_line, try o.lowerDebugType(fn_ty), diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 2570343763..53ec59d531 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1028,39 +1028,30 @@ const DeclGen = struct { inline .array_type, .vector_type => |array_type, tag| { const elem_ty = Type.fromInterned(array_type.child); - const constituents = try self.gpa.alloc(IdRef, @as(u32, @intCast(ty.arrayLenIncludingSentinel(mod)))); + const constituents = try self.gpa.alloc(IdRef, @intCast(ty.arrayLenIncludingSentinel(mod))); defer self.gpa.free(constituents); switch (aggregate.storage) { .bytes => |bytes| { // TODO: This is really space inefficient, perhaps there is a better // way to do it? - for (bytes, 0..) |byte, i| { - constituents[i] = try self.constInt(elem_ty, byte, .indirect); + for (constituents, bytes.toSlice(constituents.len, ip)) |*constituent, byte| { + constituent.* = try self.constInt(elem_ty, byte, .indirect); } }, .elems => |elems| { - for (0..@as(usize, @intCast(array_type.len))) |i| { - constituents[i] = try self.constant(elem_ty, Value.fromInterned(elems[i]), .indirect); + for (constituents, elems) |*constituent, elem| { + constituent.* = try self.constant(elem_ty, Value.fromInterned(elem), .indirect); } }, .repeated_elem => |elem| { - const val_id = try self.constant(elem_ty, Value.fromInterned(elem), .indirect); - for (0..@as(usize, @intCast(array_type.len))) |i| { - constituents[i] = val_id; - } + @memset(constituents, try self.constant(elem_ty, Value.fromInterned(elem), .indirect)); }, } switch (tag) { - inline .array_type => { - if (array_type.sentinel != .none) { - const sentinel = Value.fromInterned(array_type.sentinel); - constituents[constituents.len - 1] = try self.constant(elem_ty, sentinel, .indirect); - } - return self.constructArray(ty, constituents); - }, - inline .vector_type => return self.constructVector(ty, constituents), + .array_type => return self.constructArray(ty, constituents), + .vector_type => return self.constructVector(ty, constituents), else => unreachable, } }, @@ -1683,9 +1674,9 @@ const DeclGen = struct { } const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse - try ip.getOrPutStringFmt(mod.gpa, "{d}", .{field_index}); + try ip.getOrPutStringFmt(mod.gpa, "{d}", .{field_index}, .no_embedded_nulls); try member_types.append(try self.resolveType(field_ty, .indirect)); - try member_names.append(ip.stringToSlice(field_name)); + try member_names.append(field_name.toSlice(ip)); } const result_id = try self.spv.structType(member_types.items, member_names.items); @@ -2123,12 +2114,12 @@ const DeclGen = struct { // Append the actual code into the functions section. try self.spv.addFunction(spv_decl_index, self.func); - const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module)); - try self.spv.debugName(result_id, fqn); + const fqn = try decl.fullyQualifiedName(self.module); + try self.spv.debugName(result_id, fqn.toSlice(ip)); // Temporarily generate a test kernel declaration if this is a test function. if (self.module.test_functions.contains(self.decl_index)) { - try self.generateTestEntryPoint(fqn, spv_decl_index); + try self.generateTestEntryPoint(fqn.toSlice(ip), spv_decl_index); } }, .global => { @@ -2152,8 +2143,8 @@ const DeclGen = struct { .storage_class = final_storage_class, }); - const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module)); - try self.spv.debugName(result_id, fqn); + const fqn = try decl.fullyQualifiedName(self.module); + try self.spv.debugName(result_id, fqn.toSlice(ip)); try self.spv.declareDeclDeps(spv_decl_index, &.{}); }, .invocation_global => { @@ -2197,8 +2188,8 @@ const DeclGen = struct { try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); try self.spv.addFunction(spv_decl_index, self.func); - const fqn = ip.stringToSlice(try decl.fullyQualifiedName(self.module)); - try self.spv.debugNameFmt(initializer_id, "initializer of {s}", .{fqn}); + const fqn = try decl.fullyQualifiedName(self.module); + try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{fqn.fmt(ip)}); try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{ .id_result_type = ptr_ty_id, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index aaf840e02c..413294489a 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1176,9 +1176,9 @@ pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclInd gop.value_ptr.* = .{}; } const unnamed_consts = gop.value_ptr; - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); const index = unnamed_consts.items.len; - const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); + const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index }); defer gpa.free(sym_name); const ty = val.typeOf(mod); const atom_index = switch (try self.lowerConst(sym_name, val, ty.abiAlignment(mod), self.rdata_section_index.?, decl.srcLoc(mod))) { @@ -1257,8 +1257,8 @@ pub fn updateDecl( if (decl.isExtern(mod)) { // TODO make this part of getGlobalSymbol const variable = decl.getOwnedVariable(mod).?; - const name = mod.intern_pool.stringToSlice(decl.name); - const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name); + const name = decl.name.toSlice(&mod.intern_pool); + const lib_name = variable.lib_name.toSlice(&mod.intern_pool); const global_index = try self.getGlobalSymbol(name, lib_name); try self.need_got_table.put(gpa, global_index, {}); return; @@ -1425,9 +1425,9 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); - log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); + log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl }); const required_alignment: u32 = @intCast(decl.getAlignment(mod).toByteUnits() orelse 0); const decl_metadata = self.decls.get(decl_index).?; @@ -1439,7 +1439,7 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com if (atom.size != 0) { const sym = atom.getSymbolPtr(self); - try self.setSymbolName(sym, decl_name); + try self.setSymbolName(sym, decl_name.toSlice(&mod.intern_pool)); sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_index + 1)); sym.type = .{ .complex_type = complex_type, .base_type = .NULL }; @@ -1447,7 +1447,7 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, sym.value, required_alignment); if (need_realloc) { const vaddr = try self.growAtom(atom_index, code_len, required_alignment); - log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, sym.value, vaddr }); + log.debug("growing {} from 0x{x} to 0x{x}", .{ decl_name.fmt(&mod.intern_pool), sym.value, vaddr }); log.debug(" (required alignment 0x{x}", .{required_alignment}); if (vaddr != sym.value) { @@ -1463,13 +1463,13 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com self.getAtomPtr(atom_index).size = code_len; } else { const sym = atom.getSymbolPtr(self); - try self.setSymbolName(sym, decl_name); + try self.setSymbolName(sym, decl_name.toSlice(&mod.intern_pool)); sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_index + 1)); sym.type = .{ .complex_type = complex_type, .base_type = .NULL }; const vaddr = try self.allocateAtom(atom_index, code_len, required_alignment); errdefer self.freeAtom(atom_index); - log.debug("allocated atom for {s} at 0x{x}", .{ decl_name, vaddr }); + log.debug("allocated atom for {} at 0x{x}", .{ decl_name.fmt(&mod.intern_pool), vaddr }); self.getAtomPtr(atom_index).size = code_len; sym.value = vaddr; @@ -1534,20 +1534,18 @@ pub fn updateExports( else => std.builtin.CallingConvention.C, }; const decl_cc = exported_decl.typeOf(mod).fnCallingConvention(mod); - if (decl_cc == .C and ip.stringEqlSlice(exp.opts.name, "main") and - comp.config.link_libc) - { + if (decl_cc == .C and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) { mod.stage1_flags.have_c_main = true; } else if (decl_cc == winapi_cc and target.os.tag == .windows) { - if (ip.stringEqlSlice(exp.opts.name, "WinMain")) { + if (exp.opts.name.eqlSlice("WinMain", ip)) { mod.stage1_flags.have_winmain = true; - } else if (ip.stringEqlSlice(exp.opts.name, "wWinMain")) { + } else if (exp.opts.name.eqlSlice("wWinMain", ip)) { mod.stage1_flags.have_wwinmain = true; - } else if (ip.stringEqlSlice(exp.opts.name, "WinMainCRTStartup")) { + } else if (exp.opts.name.eqlSlice("WinMainCRTStartup", ip)) { mod.stage1_flags.have_winmain_crt_startup = true; - } else if (ip.stringEqlSlice(exp.opts.name, "wWinMainCRTStartup")) { + } else if (exp.opts.name.eqlSlice("wWinMainCRTStartup", ip)) { mod.stage1_flags.have_wwinmain_crt_startup = true; - } else if (ip.stringEqlSlice(exp.opts.name, "DllMainCRTStartup")) { + } else if (exp.opts.name.eqlSlice("DllMainCRTStartup", ip)) { mod.stage1_flags.have_dllmain_crt_startup = true; } } @@ -1585,7 +1583,7 @@ pub fn updateExports( for (exports) |exp| { log.debug("adding new export '{}'", .{exp.opts.name.fmt(&mod.intern_pool)}); - if (mod.intern_pool.stringToSliceUnwrap(exp.opts.section)) |section_name| { + if (exp.opts.section.toSlice(&mod.intern_pool)) |section_name| { if (!mem.eql(u8, section_name, ".text")) { try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( gpa, @@ -1607,7 +1605,7 @@ pub fn updateExports( continue; } - const exp_name = mod.intern_pool.stringToSlice(exp.opts.name); + const exp_name = exp.opts.name.toSlice(&mod.intern_pool); const sym_index = metadata.getExport(self, exp_name) orelse blk: { const sym_index = if (self.getGlobalIndex(exp_name)) |global_index| ind: { const global = self.globals.items[global_index]; @@ -1646,18 +1644,18 @@ pub fn updateExports( pub fn deleteDeclExport( self: *Coff, decl_index: InternPool.DeclIndex, - name_ip: InternPool.NullTerminatedString, + name: InternPool.NullTerminatedString, ) void { if (self.llvm_object) |_| return; const metadata = self.decls.getPtr(decl_index) orelse return; const mod = self.base.comp.module.?; - const name = mod.intern_pool.stringToSlice(name_ip); - const sym_index = metadata.getExportPtr(self, name) orelse return; + const name_slice = name.toSlice(&mod.intern_pool); + const sym_index = metadata.getExportPtr(self, name_slice) orelse return; const gpa = self.base.comp.gpa; const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null }; const sym = self.getSymbolPtr(sym_loc); - log.debug("deleting export '{s}'", .{name}); + log.debug("deleting export '{}'", .{name.fmt(&mod.intern_pool)}); assert(sym.storage_class == .EXTERNAL and sym.section_number != .UNDEFINED); sym.* = .{ .name = [_]u8{0} ** 8, @@ -1669,7 +1667,7 @@ pub fn deleteDeclExport( }; self.locals_free_list.append(gpa, sym_index.*) catch {}; - if (self.resolver.fetchRemove(name)) |entry| { + if (self.resolver.fetchRemove(name_slice)) |entry| { defer gpa.free(entry.key); self.globals_free_list.append(gpa, entry.value) catch {}; self.globals.items[entry.value] = .{ diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 6a41bb3793..5f82c924c7 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -339,15 +339,14 @@ pub const DeclState = struct { struct_type.field_names.get(ip), struct_type.field_types.get(ip), struct_type.offsets.get(ip), - ) |field_name_ip, field_ty, field_off| { + ) |field_name, field_ty, field_off| { if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue; - const field_name = ip.stringToSlice(field_name_ip); + const field_name_slice = field_name.toSlice(ip); // DW.AT.member - try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2); + try dbg_info_buffer.ensureUnusedCapacity(field_name_slice.len + 2); dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.struct_member)); // DW.AT.name, DW.FORM.string - dbg_info_buffer.appendSliceAssumeCapacity(field_name); - dbg_info_buffer.appendAssumeCapacity(0); + dbg_info_buffer.appendSliceAssumeCapacity(field_name_slice[0 .. field_name_slice.len + 1]); // DW.AT.type, DW.FORM.ref4 const index = dbg_info_buffer.items.len; try dbg_info_buffer.appendNTimes(0, 4); @@ -374,14 +373,13 @@ pub const DeclState = struct { try dbg_info_buffer.append(0); const enum_type = ip.loadEnumType(ty.ip_index); - for (enum_type.names.get(ip), 0..) |field_name_index, field_i| { - const field_name = ip.stringToSlice(field_name_index); + for (enum_type.names.get(ip), 0..) |field_name, field_i| { + const field_name_slice = field_name.toSlice(ip); // DW.AT.enumerator - try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64)); + try dbg_info_buffer.ensureUnusedCapacity(field_name_slice.len + 2 + @sizeOf(u64)); dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.enum_variant)); // DW.AT.name, DW.FORM.string - dbg_info_buffer.appendSliceAssumeCapacity(field_name); - dbg_info_buffer.appendAssumeCapacity(0); + dbg_info_buffer.appendSliceAssumeCapacity(field_name_slice[0 .. field_name_slice.len + 1]); // DW.AT.const_value, DW.FORM.data8 const value: u64 = value: { if (enum_type.values.len == 0) break :value field_i; // auto-numbered @@ -443,11 +441,11 @@ pub const DeclState = struct { for (union_obj.field_types.get(ip), union_obj.loadTagType(ip).names.get(ip)) |field_ty, field_name| { if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue; + const field_name_slice = field_name.toSlice(ip); // DW.AT.member try dbg_info_buffer.append(@intFromEnum(AbbrevCode.struct_member)); // DW.AT.name, DW.FORM.string - try dbg_info_buffer.appendSlice(ip.stringToSlice(field_name)); - try dbg_info_buffer.append(0); + try dbg_info_buffer.appendSlice(field_name_slice[0 .. field_name_slice.len + 1]); // DW.AT.type, DW.FORM.ref4 const index = dbg_info_buffer.items.len; try dbg_info_buffer.appendNTimes(0, 4); @@ -1155,8 +1153,8 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde dbg_line_buffer.appendAssumeCapacity(DW.LNS.copy); // .debug_info subprogram - const decl_name_slice = mod.intern_pool.stringToSlice(decl.name); - const decl_linkage_name_slice = mod.intern_pool.stringToSlice(decl_linkage_name); + const decl_name_slice = decl.name.toSlice(&mod.intern_pool); + const decl_linkage_name_slice = decl_linkage_name.toSlice(&mod.intern_pool); try dbg_info_buffer.ensureUnusedCapacity(1 + ptr_width_bytes + 4 + 4 + (decl_name_slice.len + 1) + (decl_linkage_name_slice.len + 1)); @@ -2866,15 +2864,14 @@ fn addDbgInfoErrorSetNames( // DW.AT.const_value, DW.FORM.data8 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian); - for (error_names) |error_name_ip| { - const int = try mod.getErrorValue(error_name_ip); - const error_name = mod.intern_pool.stringToSlice(error_name_ip); + for (error_names) |error_name| { + const int = try mod.getErrorValue(error_name); + const error_name_slice = error_name.toSlice(&mod.intern_pool); // DW.AT.enumerator - try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64)); + try dbg_info_buffer.ensureUnusedCapacity(error_name_slice.len + 2 + @sizeOf(u64)); dbg_info_buffer.appendAssumeCapacity(@intFromEnum(AbbrevCode.enum_variant)); // DW.AT.name, DW.FORM.string - dbg_info_buffer.appendSliceAssumeCapacity(error_name); - dbg_info_buffer.appendAssumeCapacity(0); + dbg_info_buffer.appendSliceAssumeCapacity(error_name_slice[0 .. error_name_slice.len + 1]); // DW.AT.const_value, DW.FORM.data8 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), int, target_endian); } diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 8b8dc9bd81..f65ef43eac 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -902,9 +902,9 @@ fn updateDeclCode( const gpa = elf_file.base.comp.gpa; const mod = elf_file.base.comp.module.?; const decl = mod.declPtr(decl_index); - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); - log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); + log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl }); const required_alignment = decl.getAlignment(mod); @@ -915,7 +915,7 @@ fn updateDeclCode( sym.output_section_index = shdr_index; atom_ptr.output_section_index = shdr_index; - sym.name_offset = try self.strtab.insert(gpa, decl_name); + sym.name_offset = try self.strtab.insert(gpa, decl_name.toSlice(&mod.intern_pool)); atom_ptr.flags.alive = true; atom_ptr.name_offset = sym.name_offset; esym.st_name = sym.name_offset; @@ -932,7 +932,7 @@ fn updateDeclCode( const need_realloc = code.len > capacity or !required_alignment.check(atom_ptr.value); if (need_realloc) { try atom_ptr.grow(elf_file); - log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, old_vaddr, atom_ptr.value }); + log.debug("growing {} from 0x{x} to 0x{x}", .{ decl_name.fmt(&mod.intern_pool), old_vaddr, atom_ptr.value }); if (old_vaddr != atom_ptr.value) { sym.value = 0; esym.st_value = 0; @@ -1000,9 +1000,9 @@ fn updateTlv( const gpa = elf_file.base.comp.gpa; const mod = elf_file.base.comp.module.?; const decl = mod.declPtr(decl_index); - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); - log.debug("updateTlv {s} ({*})", .{ decl_name, decl }); + log.debug("updateTlv {} ({*})", .{ decl_name.fmt(&mod.intern_pool), decl }); const required_alignment = decl.getAlignment(mod); @@ -1014,7 +1014,7 @@ fn updateTlv( sym.output_section_index = shndx; atom_ptr.output_section_index = shndx; - sym.name_offset = try self.strtab.insert(gpa, decl_name); + sym.name_offset = try self.strtab.insert(gpa, decl_name.toSlice(&mod.intern_pool)); atom_ptr.flags.alive = true; atom_ptr.name_offset = sym.name_offset; esym.st_value = 0; @@ -1136,8 +1136,8 @@ pub fn updateDecl( if (decl.isExtern(mod)) { // Extern variable gets a .got entry only. const variable = decl.getOwnedVariable(mod).?; - const name = mod.intern_pool.stringToSlice(decl.name); - const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name); + const name = decl.name.toSlice(&mod.intern_pool); + const lib_name = variable.lib_name.toSlice(&mod.intern_pool); const esym_index = try self.getGlobalSymbol(elf_file, name, lib_name); elf_file.symbol(self.symbol(esym_index)).flags.needs_got = true; return; @@ -1293,9 +1293,9 @@ pub fn lowerUnnamedConst( } const unnamed_consts = gop.value_ptr; const decl = mod.declPtr(decl_index); - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); const index = unnamed_consts.items.len; - const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); + const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index }); defer gpa.free(name); const ty = val.typeOf(mod); const sym_index = switch (try self.lowerConst( @@ -1418,7 +1418,7 @@ pub fn updateExports( for (exports) |exp| { if (exp.opts.section.unwrap()) |section_name| { - if (!mod.intern_pool.stringEqlSlice(section_name, ".text")) { + if (!section_name.eqlSlice(".text", &mod.intern_pool)) { try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); mod.failed_exports.putAssumeCapacityNoClobber(exp, try Module.ErrorMsg.create( gpa, @@ -1445,7 +1445,7 @@ pub fn updateExports( }, }; const stt_bits: u8 = @as(u4, @truncate(esym.st_info)); - const exp_name = mod.intern_pool.stringToSlice(exp.opts.name); + const exp_name = exp.opts.name.toSlice(&mod.intern_pool); const name_off = try self.strtab.insert(gpa, exp_name); const global_esym_index = if (metadata.@"export"(self, exp_name)) |exp_index| exp_index.* @@ -1476,9 +1476,9 @@ pub fn updateDeclLineNumber( defer tracy.end(); const decl = mod.declPtr(decl_index); - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); - log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl }); + log.debug("updateDeclLineNumber {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl }); if (self.dwarf) |*dw| { try dw.updateDeclLineNumber(mod, decl_index); @@ -1493,7 +1493,7 @@ pub fn deleteDeclExport( ) void { const metadata = self.decls.getPtr(decl_index) orelse return; const mod = elf_file.base.comp.module.?; - const exp_name = mod.intern_pool.stringToSlice(name); + const exp_name = name.toSlice(&mod.intern_pool); const esym_index = metadata.@"export"(self, exp_name) orelse return; log.debug("deleting export '{s}'", .{exp_name}); const esym = &self.global_esyms.items(.elf_sym)[esym_index.*]; diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index fb27c96525..bb788fcacc 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -716,8 +716,8 @@ pub fn updateDecl( if (decl.isExtern(mod)) { // Extern variable gets a __got entry only const variable = decl.getOwnedVariable(mod).?; - const name = mod.intern_pool.stringToSlice(decl.name); - const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name); + const name = decl.name.toSlice(&mod.intern_pool); + const lib_name = variable.lib_name.toSlice(&mod.intern_pool); const index = try self.getGlobalSymbol(macho_file, name, lib_name); const actual_index = self.symbols.items[index]; macho_file.getSymbol(actual_index).flags.needs_got = true; @@ -786,9 +786,9 @@ fn updateDeclCode( const gpa = macho_file.base.comp.gpa; const mod = macho_file.base.comp.module.?; const decl = mod.declPtr(decl_index); - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); - log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); + log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl }); const required_alignment = decl.getAlignment(mod); @@ -800,7 +800,7 @@ fn updateDeclCode( sym.out_n_sect = sect_index; atom.out_n_sect = sect_index; - sym.name = try self.strtab.insert(gpa, decl_name); + sym.name = try self.strtab.insert(gpa, decl_name.toSlice(&mod.intern_pool)); atom.flags.alive = true; atom.name = sym.name; nlist.n_strx = sym.name; @@ -819,7 +819,7 @@ fn updateDeclCode( if (need_realloc) { try atom.grow(macho_file); - log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, old_vaddr, atom.value }); + log.debug("growing {} from 0x{x} to 0x{x}", .{ decl_name.fmt(&mod.intern_pool), old_vaddr, atom.value }); if (old_vaddr != atom.value) { sym.value = 0; nlist.n_value = 0; @@ -870,23 +870,24 @@ fn updateTlv( ) !void { const mod = macho_file.base.comp.module.?; const decl = mod.declPtr(decl_index); - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); - log.debug("updateTlv {s} ({*})", .{ decl_name, decl }); + log.debug("updateTlv {} ({*})", .{ decl_name.fmt(&mod.intern_pool), decl }); + const decl_name_slice = decl_name.toSlice(&mod.intern_pool); const required_alignment = decl.getAlignment(mod); // 1. Lower TLV initializer const init_sym_index = try self.createTlvInitializer( macho_file, - decl_name, + decl_name_slice, required_alignment, sect_index, code, ); // 2. Create TLV descriptor - try self.createTlvDescriptor(macho_file, sym_index, init_sym_index, decl_name); + try self.createTlvDescriptor(macho_file, sym_index, init_sym_index, decl_name_slice); } fn createTlvInitializer( @@ -1073,9 +1074,9 @@ pub fn lowerUnnamedConst( } const unnamed_consts = gop.value_ptr; const decl = mod.declPtr(decl_index); - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); const index = unnamed_consts.items.len; - const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); + const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index }); defer gpa.free(name); const sym_index = switch (try self.lowerConst( macho_file, @@ -1199,7 +1200,7 @@ pub fn updateExports( for (exports) |exp| { if (exp.opts.section.unwrap()) |section_name| { - if (!mod.intern_pool.stringEqlSlice(section_name, "__text")) { + if (!section_name.eqlSlice("__text", &mod.intern_pool)) { try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); mod.failed_exports.putAssumeCapacityNoClobber(exp, try Module.ErrorMsg.create( gpa, @@ -1220,7 +1221,7 @@ pub fn updateExports( continue; } - const exp_name = mod.intern_pool.stringToSlice(exp.opts.name); + const exp_name = exp.opts.name.toSlice(&mod.intern_pool); const global_nlist_index = if (metadata.@"export"(self, exp_name)) |exp_index| exp_index.* else blk: { @@ -1349,13 +1350,12 @@ pub fn deleteDeclExport( decl_index: InternPool.DeclIndex, name: InternPool.NullTerminatedString, ) void { - const metadata = self.decls.getPtr(decl_index) orelse return; - const mod = macho_file.base.comp.module.?; - const exp_name = mod.intern_pool.stringToSlice(name); - const nlist_index = metadata.@"export"(self, exp_name) orelse return; - log.debug("deleting export '{s}'", .{exp_name}); + const metadata = self.decls.getPtr(decl_index) orelse return; + const nlist_index = metadata.@"export"(self, name.toSlice(&mod.intern_pool)) orelse return; + + log.debug("deleting export '{}'", .{name.fmt(&mod.intern_pool)}); const nlist = &self.symtab.items(.nlist)[nlist_index.*]; self.symtab.items(.size)[nlist_index.*] = 0; diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index d5900d2b16..323cc8c4a9 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -477,11 +477,11 @@ pub fn lowerUnnamedConst(self: *Plan9, val: Value, decl_index: InternPool.DeclIn } const unnamed_consts = gop.value_ptr; - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); const index = unnamed_consts.items.len; // name is freed when the unnamed const is freed - const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); + const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index }); const sym_index = try self.allocateSymbolIndex(); const new_atom_idx = try self.createAtom(); @@ -529,7 +529,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex) const decl = mod.declPtr(decl_index); if (decl.isExtern(mod)) { - log.debug("found extern decl: {s}", .{mod.intern_pool.stringToSlice(decl.name)}); + log.debug("found extern decl: {}", .{decl.name.fmt(&mod.intern_pool)}); return; } const atom_idx = try self.seeDecl(decl_index); @@ -573,7 +573,7 @@ fn updateFinish(self: *Plan9, decl_index: InternPool.DeclIndex) !void { const sym: aout.Sym = .{ .value = undefined, // the value of stuff gets filled in in flushModule .type = atom.type, - .name = try gpa.dupe(u8, mod.intern_pool.stringToSlice(decl.name)), + .name = try gpa.dupe(u8, decl.name.toSlice(&mod.intern_pool)), }; if (atom.sym_index) |s| { @@ -1013,10 +1013,12 @@ fn addDeclExports( const atom = self.getAtom(metadata.index); for (exports) |exp| { - const exp_name = mod.intern_pool.stringToSlice(exp.opts.name); + const exp_name = exp.opts.name.toSlice(&mod.intern_pool); // plan9 does not support custom sections if (exp.opts.section.unwrap()) |section_name| { - if (!mod.intern_pool.stringEqlSlice(section_name, ".text") and !mod.intern_pool.stringEqlSlice(section_name, ".data")) { + if (!section_name.eqlSlice(".text", &mod.intern_pool) and + !section_name.eqlSlice(".data", &mod.intern_pool)) + { try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create( gpa, mod.declPtr(decl_index).srcLoc(mod), @@ -1129,19 +1131,21 @@ pub fn seeDecl(self: *Plan9, decl_index: InternPool.DeclIndex) !Atom.Index { // handle externs here because they might not get updateDecl called on them const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); - const name = mod.intern_pool.stringToSlice(decl.name); if (decl.isExtern(mod)) { // this is a "phantom atom" - it is never actually written to disk, just convenient for us to store stuff about externs - if (std.mem.eql(u8, name, "etext")) { + if (decl.name.eqlSlice("etext", &mod.intern_pool)) { self.etext_edata_end_atom_indices[0] = atom_idx; - } else if (std.mem.eql(u8, name, "edata")) { + } else if (decl.name.eqlSlice("edata", &mod.intern_pool)) { self.etext_edata_end_atom_indices[1] = atom_idx; - } else if (std.mem.eql(u8, name, "end")) { + } else if (decl.name.eqlSlice("end", &mod.intern_pool)) { self.etext_edata_end_atom_indices[2] = atom_idx; } try self.updateFinish(decl_index); - log.debug("seeDecl(extern) for {s} (got_addr=0x{x})", .{ name, self.getAtom(atom_idx).getOffsetTableAddress(self) }); - } else log.debug("seeDecl for {s}", .{name}); + log.debug("seeDecl(extern) for {} (got_addr=0x{x})", .{ + decl.name.fmt(&mod.intern_pool), + self.getAtom(atom_idx).getOffsetTableAddress(self), + }); + } else log.debug("seeDecl for {}", .{decl.name.fmt(&mod.intern_pool)}); return atom_idx; } @@ -1393,7 +1397,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { const sym = self.syms.items[atom.sym_index.?]; try self.writeSym(writer, sym); if (self.base.comp.module.?.decl_exports.get(decl_index)) |exports| { - for (exports.items) |e| if (decl_metadata.getExport(self, ip.stringToSlice(e.opts.name))) |exp_i| { + for (exports.items) |e| if (decl_metadata.getExport(self, e.opts.name.toSlice(ip))) |exp_i| { try self.writeSym(writer, self.syms.items[exp_i]); }; } @@ -1440,7 +1444,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { const sym = self.syms.items[atom.sym_index.?]; try self.writeSym(writer, sym); if (self.base.comp.module.?.decl_exports.get(decl_index)) |exports| { - for (exports.items) |e| if (decl_metadata.getExport(self, ip.stringToSlice(e.opts.name))) |exp_i| { + for (exports.items) |e| if (decl_metadata.getExport(self, e.opts.name.toSlice(ip))) |exp_i| { const s = self.syms.items[exp_i]; if (mem.eql(u8, s.name, "_start")) self.entry_val = s.value; @@ -1483,25 +1487,25 @@ pub fn getDeclVAddr( reloc_info: link.File.RelocInfo, ) !u64 { const mod = self.base.comp.module.?; + const ip = &mod.intern_pool; const decl = mod.declPtr(decl_index); - log.debug("getDeclVAddr for {s}", .{mod.intern_pool.stringToSlice(decl.name)}); + log.debug("getDeclVAddr for {}", .{decl.name.fmt(ip)}); if (decl.isExtern(mod)) { - const extern_name = mod.intern_pool.stringToSlice(decl.name); - if (std.mem.eql(u8, extern_name, "etext")) { + if (decl.name.eqlSlice("etext", ip)) { try self.addReloc(reloc_info.parent_atom_index, .{ .target = undefined, .offset = reloc_info.offset, .addend = reloc_info.addend, .type = .special_etext, }); - } else if (std.mem.eql(u8, extern_name, "edata")) { + } else if (decl.name.eqlSlice("edata", ip)) { try self.addReloc(reloc_info.parent_atom_index, .{ .target = undefined, .offset = reloc_info.offset, .addend = reloc_info.addend, .type = .special_edata, }); - } else if (std.mem.eql(u8, extern_name, "end")) { + } else if (decl.name.eqlSlice("end", ip)) { try self.addReloc(reloc_info.parent_atom_index, .{ .target = undefined, .offset = reloc_info.offset, diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 950e0375f0..0a90a2fd67 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -130,7 +130,7 @@ pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, a const func = module.funcInfo(func_index); const decl = module.declPtr(func.owner_decl); - log.debug("lowering function {s}", .{module.intern_pool.stringToSlice(decl.name)}); + log.debug("lowering function {}", .{decl.name.fmt(&module.intern_pool)}); try self.object.updateFunc(module, func_index, air, liveness); } @@ -141,7 +141,7 @@ pub fn updateDecl(self: *SpirV, module: *Module, decl_index: InternPool.DeclInde } const decl = module.declPtr(decl_index); - log.debug("lowering declaration {s}", .{module.intern_pool.stringToSlice(decl.name)}); + log.debug("lowering declaration {}", .{decl.name.fmt(&module.intern_pool)}); try self.object.updateDecl(module, decl_index); } @@ -178,7 +178,7 @@ pub fn updateExports( for (exports) |exp| { try self.object.spv.declareEntryPoint( spv_decl_index, - mod.intern_pool.stringToSlice(exp.opts.name), + exp.opts.name.toSlice(&mod.intern_pool), execution_model, ); } @@ -227,14 +227,13 @@ pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node try error_info.appendSlice("zig_errors"); const mod = self.base.comp.module.?; - for (mod.global_error_set.keys()) |name_nts| { - const name = mod.intern_pool.stringToSlice(name_nts); + for (mod.global_error_set.keys()) |name| { // Errors can contain pretty much any character - to encode them in a string we must escape // them somehow. Easiest here is to use some established scheme, one which also preseves the // name if it contains no strange characters is nice for debugging. URI encoding fits the bill. // We're using : as separator, which is a reserved character. - const escaped_name = try std.Uri.escapeString(gpa, name); + const escaped_name = try std.Uri.escapeString(gpa, name.toSlice(&mod.intern_pool)); defer gpa.free(escaped_name); try error_info.writer().print(":{s}", .{escaped_name}); } diff --git a/src/link/Wasm/ZigObject.zig b/src/link/Wasm/ZigObject.zig index 9bf7718d2b..bcd98c3d3c 100644 --- a/src/link/Wasm/ZigObject.zig +++ b/src/link/Wasm/ZigObject.zig @@ -258,8 +258,8 @@ pub fn updateDecl( if (decl.isExtern(mod)) { const variable = decl.getOwnedVariable(mod).?; - const name = mod.intern_pool.stringToSlice(decl.name); - const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name); + const name = decl.name.toSlice(&mod.intern_pool); + const lib_name = variable.lib_name.toSlice(&mod.intern_pool); return zig_object.addOrUpdateImport(wasm_file, name, atom.sym_index, lib_name, null); } const val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; @@ -341,8 +341,8 @@ fn finishUpdateDecl( const atom_index = decl_info.atom; const atom = wasm_file.getAtomPtr(atom_index); const sym = zig_object.symbol(atom.sym_index); - const full_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); - sym.name = try zig_object.string_table.insert(gpa, full_name); + const full_name = try decl.fullyQualifiedName(mod); + sym.name = try zig_object.string_table.insert(gpa, full_name.toSlice(&mod.intern_pool)); try atom.code.appendSlice(gpa, code); atom.size = @intCast(code.len); @@ -382,7 +382,7 @@ fn finishUpdateDecl( // Will be freed upon freeing of decl or after cleanup of Wasm binary. const full_segment_name = try std.mem.concat(gpa, u8, &.{ segment_name, - full_name, + full_name.toSlice(&mod.intern_pool), }); errdefer gpa.free(full_segment_name); sym.tag = .data; @@ -427,9 +427,9 @@ pub fn getOrCreateAtomForDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_ind gop.value_ptr.* = .{ .atom = try wasm_file.createAtom(sym_index, zig_object.index) }; const mod = wasm_file.base.comp.module.?; const decl = mod.declPtr(decl_index); - const full_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const full_name = try decl.fullyQualifiedName(mod); const sym = zig_object.symbol(sym_index); - sym.name = try zig_object.string_table.insert(gpa, full_name); + sym.name = try zig_object.string_table.insert(gpa, full_name.toSlice(&mod.intern_pool)); } return gop.value_ptr.atom; } @@ -478,9 +478,9 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, val: Value, d const parent_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index); const parent_atom = wasm_file.getAtom(parent_atom_index); const local_index = parent_atom.locals.items.len; - const fqn = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); - const name = try std.fmt.allocPrintZ(gpa, "__unnamed_{s}_{d}", .{ - fqn, local_index, + const fqn = try decl.fullyQualifiedName(mod); + const name = try std.fmt.allocPrintZ(gpa, "__unnamed_{}_{d}", .{ + fqn.fmt(&mod.intern_pool), local_index, }); defer gpa.free(name); @@ -623,11 +623,11 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm) !void { // Addend for each relocation to the table var addend: u32 = 0; const mod = wasm_file.base.comp.module.?; - for (mod.global_error_set.keys()) |error_name_nts| { + for (mod.global_error_set.keys()) |error_name| { const atom = wasm_file.getAtomPtr(atom_index); - const error_name = mod.intern_pool.stringToSlice(error_name_nts); - const len: u32 = @intCast(error_name.len + 1); // names are 0-terminated + const error_name_slice = error_name.toSlice(&mod.intern_pool); + const len: u32 = @intCast(error_name_slice.len + 1); // names are 0-terminated const slice_ty = Type.slice_const_u8_sentinel_0; const offset = @as(u32, @intCast(atom.code.items.len)); @@ -646,10 +646,9 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm) !void { // as we updated the error name table, we now store the actual name within the names atom try names_atom.code.ensureUnusedCapacity(gpa, len); - names_atom.code.appendSliceAssumeCapacity(error_name); - names_atom.code.appendAssumeCapacity(0); + names_atom.code.appendSliceAssumeCapacity(error_name_slice[0..len]); - log.debug("Populated error name: '{s}'", .{error_name}); + log.debug("Populated error name: '{}'", .{error_name.fmt(&mod.intern_pool)}); } names_atom.size = addend; zig_object.error_names_atom = names_atom_index; @@ -833,8 +832,7 @@ pub fn deleteDeclExport( ) void { const mod = wasm_file.base.comp.module.?; const decl_info = zig_object.decls_map.getPtr(decl_index) orelse return; - const export_name = mod.intern_pool.stringToSlice(name); - if (decl_info.@"export"(zig_object, export_name)) |sym_index| { + if (decl_info.@"export"(zig_object, name.toSlice(&mod.intern_pool))) |sym_index| { const sym = zig_object.symbol(sym_index); decl_info.deleteExport(sym_index); std.debug.assert(zig_object.global_syms.remove(sym.name)); @@ -864,10 +862,10 @@ pub fn updateExports( const atom = wasm_file.getAtom(atom_index); const atom_sym = atom.symbolLoc().getSymbol(wasm_file).*; const gpa = mod.gpa; - log.debug("Updating exports for decl '{s}'", .{mod.intern_pool.stringToSlice(decl.name)}); + log.debug("Updating exports for decl '{}'", .{decl.name.fmt(&mod.intern_pool)}); for (exports) |exp| { - if (mod.intern_pool.stringToSliceUnwrap(exp.opts.section)) |section| { + if (exp.opts.section.toSlice(&mod.intern_pool)) |section| { try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( gpa, decl.srcLoc(mod), @@ -877,10 +875,8 @@ pub fn updateExports( continue; } - const export_string = mod.intern_pool.stringToSlice(exp.opts.name); - const sym_index = if (decl_info.@"export"(zig_object, export_string)) |idx| - idx - else index: { + const export_string = exp.opts.name.toSlice(&mod.intern_pool); + const sym_index = if (decl_info.@"export"(zig_object, export_string)) |idx| idx else index: { const sym_index = try zig_object.allocateSymbol(gpa); try decl_info.appendExport(gpa, sym_index); break :index sym_index; @@ -1089,9 +1085,9 @@ pub fn createDebugSectionForIndex(zig_object: *ZigObject, wasm_file: *Wasm, inde pub fn updateDeclLineNumber(zig_object: *ZigObject, mod: *Module, decl_index: InternPool.DeclIndex) !void { if (zig_object.dwarf) |*dw| { const decl = mod.declPtr(decl_index); - const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); + const decl_name = try decl.fullyQualifiedName(mod); - log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl }); + log.debug("updateDeclLineNumber {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl }); try dw.updateDeclLineNumber(mod, decl_index); } } diff --git a/src/mutable_value.zig b/src/mutable_value.zig index 327c354108..f16a8fd3f9 100644 --- a/src/mutable_value.zig +++ b/src/mutable_value.zig @@ -73,7 +73,7 @@ pub const MutableValue = union(enum) { } }), .bytes => |b| try ip.get(gpa, .{ .aggregate = .{ .ty = b.ty, - .storage = .{ .bytes = b.data }, + .storage = .{ .bytes = try ip.getOrPutString(gpa, b.data, .maybe_embedded_nulls) }, } }), .aggregate => |a| { const elems = try arena.alloc(InternPool.Index, a.elems.len); @@ -158,18 +158,18 @@ pub const MutableValue = union(enum) { }, .aggregate => |agg| switch (agg.storage) { .bytes => |bytes| { - assert(bytes.len == ip.aggregateTypeLenIncludingSentinel(agg.ty)); + const len: usize = @intCast(ip.aggregateTypeLenIncludingSentinel(agg.ty)); assert(ip.childType(agg.ty) == .u8_type); if (allow_bytes) { - const arena_bytes = try arena.alloc(u8, bytes.len); - @memcpy(arena_bytes, bytes); + const arena_bytes = try arena.alloc(u8, len); + @memcpy(arena_bytes, bytes.toSlice(len, ip)); mv.* = .{ .bytes = .{ .ty = agg.ty, .data = arena_bytes, } }; } else { - const mut_elems = try arena.alloc(MutableValue, bytes.len); - for (bytes, mut_elems) |b, *mut_elem| { + const mut_elems = try arena.alloc(MutableValue, len); + for (bytes.toSlice(len, ip), mut_elems) |b, *mut_elem| { mut_elem.* = .{ .interned = try ip.get(gpa, .{ .int = .{ .ty = .u8_type, .storage = .{ .u64 = b }, diff --git a/src/print_value.zig b/src/print_value.zig index 21a322cd63..c021b011c1 100644 --- a/src/print_value.zig +++ b/src/print_value.zig @@ -204,26 +204,35 @@ fn printAggregate( try writer.writeAll(" }"); return; }, - .Array => if (aggregate.storage == .bytes and aggregate.storage.bytes.len > 0) { - const skip_terminator = aggregate.storage.bytes[aggregate.storage.bytes.len - 1] == 0; - const bytes = if (skip_terminator) b: { - break :b aggregate.storage.bytes[0 .. aggregate.storage.bytes.len - 1]; - } else aggregate.storage.bytes; - try writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)}); - if (!is_ref) try writer.writeAll(".*"); - return; - } else if (ty.arrayLen(zcu) == 0) { - if (is_ref) try writer.writeByte('&'); - return writer.writeAll(".{}"); - } else if (ty.arrayLen(zcu) == 1) one_byte_str: { - // The repr isn't `bytes`, but we might still be able to print this as a string - if (ty.childType(zcu).toIntern() != .u8_type) break :one_byte_str; - const elem_val = Value.fromInterned(aggregate.storage.values()[0]); - if (elem_val.isUndef(zcu)) break :one_byte_str; - const byte = elem_val.toUnsignedInt(zcu); - try writer.print("\"{}\"", .{std.zig.fmtEscapes(&.{@intCast(byte)})}); - if (!is_ref) try writer.writeAll(".*"); - return; + .Array => { + switch (aggregate.storage) { + .bytes => |bytes| string: { + const len = ty.arrayLenIncludingSentinel(zcu); + if (len == 0) break :string; + const slice = bytes.toSlice(if (bytes.at(len - 1, ip) == 0) len - 1 else len, ip); + try writer.print("\"{}\"", .{std.zig.fmtEscapes(slice)}); + if (!is_ref) try writer.writeAll(".*"); + return; + }, + .elems, .repeated_elem => {}, + } + switch (ty.arrayLen(zcu)) { + 0 => { + if (is_ref) try writer.writeByte('&'); + return writer.writeAll(".{}"); + }, + 1 => one_byte_str: { + // The repr isn't `bytes`, but we might still be able to print this as a string + if (ty.childType(zcu).toIntern() != .u8_type) break :one_byte_str; + const elem_val = Value.fromInterned(aggregate.storage.values()[0]); + if (elem_val.isUndef(zcu)) break :one_byte_str; + const byte = elem_val.toUnsignedInt(zcu); + try writer.print("\"{}\"", .{std.zig.fmtEscapes(&.{@intCast(byte)})}); + if (!is_ref) try writer.writeAll(".*"); + return; + }, + else => {}, + } }, .Vector => if (ty.arrayLen(zcu) == 0) { if (is_ref) try writer.writeByte('&'); diff --git a/src/type.zig b/src/type.zig index 8352552463..264125c6d0 100644 --- a/src/type.zig +++ b/src/type.zig @@ -490,18 +490,10 @@ pub const Type = struct { }; }, .anyframe_type => true, - .array_type => |array_type| { - if (array_type.sentinel != .none) { - return Type.fromInterned(array_type.child).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); - } else { - return array_type.len > 0 and - try Type.fromInterned(array_type.child).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); - } - }, - .vector_type => |vector_type| { - return vector_type.len > 0 and - try Type.fromInterned(vector_type.child).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); - }, + .array_type => |array_type| return array_type.lenIncludingSentinel() > 0 and + try Type.fromInterned(array_type.child).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), + .vector_type => |vector_type| return vector_type.len > 0 and + try Type.fromInterned(vector_type.child).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat), .opt_type => |child| { const child_ty = Type.fromInterned(child); if (child_ty.isNoReturn(mod)) { @@ -1240,7 +1232,7 @@ pub const Type = struct { .anyframe_type => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) }, .array_type => |array_type| { - const len = array_type.len + @intFromBool(array_type.sentinel != .none); + const len = array_type.lenIncludingSentinel(); if (len == 0) return .{ .scalar = 0 }; switch (try Type.fromInterned(array_type.child).abiSizeAdvanced(mod, strat)) { .scalar => |elem_size| return .{ .scalar = len * elem_size }, @@ -1577,7 +1569,7 @@ pub const Type = struct { .anyframe_type => return target.ptrBitWidth(), .array_type => |array_type| { - const len = array_type.len + @intFromBool(array_type.sentinel != .none); + const len = array_type.lenIncludingSentinel(); if (len == 0) return 0; const elem_ty = Type.fromInterned(array_type.child); const elem_size = @max( @@ -1731,7 +1723,7 @@ pub const Type = struct { .struct_type => ip.loadStructType(ty.toIntern()).haveLayout(ip), .union_type => ip.loadUnionType(ty.toIntern()).haveLayout(ip), .array_type => |array_type| { - if ((array_type.len + @intFromBool(array_type.sentinel != .none)) == 0) return true; + if (array_type.lenIncludingSentinel() == 0) return true; return Type.fromInterned(array_type.child).layoutIsResolved(mod); }, .opt_type => |child| Type.fromInterned(child).layoutIsResolved(mod),