Commit e23b0a01e6
Changed files (6)
src
src/arch/x86_64/CodeGen.zig
@@ -2026,13 +2026,9 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });
var data_off: i32 = 0;
- for (
- exitlude_jump_relocs,
- enum_ty.enumFields(mod),
- 0..,
- ) |*exitlude_jump_reloc, tag_name_ip, index_usize| {
+ for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, index_usize| {
const index = @intCast(u32, index_usize);
- const tag_name = mod.intern_pool.stringToSlice(tag_name_ip);
+ const tag_name = mod.intern_pool.stringToSlice(enum_ty.enumFields(mod)[index_usize]);
const tag_val = try mod.enumValueFieldIndex(enum_ty, index);
const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });
try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);
src/codegen.zig
@@ -517,7 +517,7 @@ pub fn generateSymbol(
const field_ty = field.ty;
if (!field_ty.hasRuntimeBits(mod)) continue;
- const field_val = switch (aggregate.storage) {
+ const field_val = switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).aggregate.storage) {
.bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
.ty = field_ty.toIntern(),
.storage = .{ .u64 = bytes[index] },
src/Module.zig
@@ -5448,7 +5448,6 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
defer comptime_mutable_decls.deinit();
const fn_ty = decl.ty;
- const fn_ty_info = mod.typeToFunc(fn_ty).?;
var sema: Sema = .{
.mod = mod,
@@ -5459,7 +5458,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
.owner_decl_index = decl_index,
.func = func,
.func_index = func_index.toOptional(),
- .fn_ret_ty = fn_ty_info.return_type.toType(),
+ .fn_ret_ty = mod.typeToFunc(fn_ty).?.return_type.toType(),
.owner_func = func,
.owner_func_index = func_index.toOptional(),
.branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
@@ -5499,7 +5498,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
// This could be a generic function instantiation, however, in which case we need to
// map the comptime parameters to constant values and only emit arg AIR instructions
// for the runtime ones.
- const runtime_params_len = @intCast(u32, fn_ty_info.param_types.len);
+ const runtime_params_len = @intCast(u32, mod.typeToFunc(fn_ty).?.param_types.len);
try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`
try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
@@ -5525,7 +5524,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
total_param_index += 1;
continue;
- } else fn_ty_info.param_types[runtime_param_index].toType();
+ } else mod.typeToFunc(fn_ty).?.param_types[runtime_param_index].toType();
const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
error.NeededSourceLocation => unreachable,
@@ -5623,7 +5622,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
// Crucially, this happens *after* we set the function state to success above,
// so that dependencies on the function body will now be satisfied rather than
// result in circular dependency errors.
- sema.resolveFnTypes(mod.typeToFunc(fn_ty).?) catch |err| switch (err) {
+ sema.resolveFnTypes(fn_ty) catch |err| switch (err) {
error.NeededSourceLocation => unreachable,
error.GenericPoison => unreachable,
error.ComptimeReturn => unreachable,
@@ -6378,9 +6377,9 @@ 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);
- // Protects test_decl_name from being invalidated during call to intern() below.
- try ip.string_bytes.ensureUnusedCapacity(gpa, ip.stringToSlice(test_decl.name).len + 10);
- const test_decl_name = ip.stringToSlice(test_decl.name);
+ // TODO: write something like getCoercedInts to avoid needing to dupe
+ const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(test_decl.name));
+ defer gpa.free(test_decl_name);
const test_name_decl_index = n: {
const test_name_decl_ty = try mod.arrayType(.{
.len = test_decl_name.len,
src/Sema.zig
@@ -5227,6 +5227,8 @@ fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Inst.Ref {
const mod = sema.mod;
const gpa = sema.gpa;
+ // TODO: write something like getCoercedInts to avoid needing to dupe
+ const duped_bytes = try sema.arena.dupe(u8, bytes);
const ty = try mod.arrayType(.{
.len = bytes.len,
.child = .u8_type,
@@ -5234,7 +5236,7 @@ fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Ins
});
const val = try mod.intern(.{ .aggregate = .{
.ty = ty.toIntern(),
- .storage = .{ .bytes = bytes },
+ .storage = .{ .bytes = duped_bytes },
} });
const gop = try mod.memoized_decls.getOrPut(gpa, val);
if (!gop.found_existing) {
@@ -11478,7 +11480,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
operand_ty.fmt(mod),
});
}
- for (operand_ty.errorSetNames(mod)) |error_name_ip| {
+ for (0..operand_ty.errorSetNames(mod).len) |i| {
+ const error_name_ip = operand_ty.errorSetNames(mod)[i];
const error_name = mod.intern_pool.stringToSlice(error_name_ip);
if (seen_errors.contains(error_name)) continue;
cases_len += 1;
@@ -15851,7 +15854,8 @@ fn zirBuiltinSrc(
const func_name_val = blk: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
- const name = mod.intern_pool.stringToSlice(fn_owner_decl.name);
+ // TODO: write something like getCoercedInts to avoid needing to dupe
+ const name = try sema.arena.dupe(u8, mod.intern_pool.stringToSlice(fn_owner_decl.name));
const new_decl_ty = try mod.arrayType(.{
.len = name.len,
.child = .u8_type,
@@ -16287,7 +16291,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const error_field_vals = if (ty.isAnyError(mod)) null else blk: {
const vals = try sema.arena.alloc(InternPool.Index, ty.errorSetNames(mod).len);
for (vals, 0..) |*field_val, i| {
- const name = ip.stringToSlice(ty.errorSetNames(mod)[i]);
+ // TODO: write something like getCoercedInts to avoid needing to dupe
+ const name = try sema.arena.dupe(u8, ip.stringToSlice(ty.errorSetNames(mod)[i]));
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
@@ -16417,8 +16422,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const enum_field_vals = try sema.arena.alloc(InternPool.Index, enum_type.names.len);
for (enum_field_vals, 0..) |*field_val, i| {
- const name_ip = ip.indexToKey(ty.toIntern()).enum_type.names[i];
- const name = ip.stringToSlice(name_ip);
+ // TODO: write something like getCoercedInts to avoid needing to dupe
+ const name = try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(ty.toIntern()).enum_type.names[i]));
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
@@ -16556,7 +16561,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
for (union_field_vals, 0..) |*field_val, i| {
const field = union_fields.values()[i];
- const name = ip.stringToSlice(union_fields.keys()[i]);
+ // TODO: write something like getCoercedInts to avoid needing to dupe
+ const name = try sema.arena.dupe(u8, ip.stringToSlice(union_fields.keys()[i]));
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
@@ -16714,9 +16720,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
+ // TODO: write something like getCoercedInts to avoid needing to dupe
const bytes = if (tuple.names.len != 0)
// https://github.com/ziglang/zig/issues/15709
- @as([]const u8, ip.stringToSlice(tuple.names[i]))
+ try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(struct_ty.toIntern()).anon_struct_type.names[i]))
else
try std.fmt.allocPrint(sema.arena, "{d}", .{i});
const new_decl_ty = try mod.arrayType(.{
@@ -16771,7 +16778,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
struct_obj.fields.keys(),
struct_obj.fields.values(),
) |*field_val, name_nts, field| {
- const name = ip.stringToSlice(name_nts);
+ // TODO: write something like getCoercedInts to avoid needing to dupe
+ const name = try sema.arena.dupe(u8, ip.stringToSlice(name_nts));
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
@@ -17020,9 +17028,8 @@ fn typeInfoNamespaceDecls(
const name_val = v: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
- // Protects the decl name slice from being invalidated at the call to intern().
- try ip.string_bytes.ensureUnusedCapacity(sema.gpa, ip.stringToSlice(decl.name).len + 1);
- const name = ip.stringToSlice(decl.name);
+ // TODO: write something like getCoercedInts to avoid needing to dupe
+ const name = try sema.arena.dupe(u8, ip.stringToSlice(decl.name));
const new_decl_ty = try mod.arrayType(.{
.len = name.len,
.child = .u8_type,
@@ -19060,6 +19067,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
};
return sema.failWithOwnedErrorMsg(msg);
};
+ // TODO: write something like getCoercedInts to avoid needing to dupe
const field_name = enum_ty.enumFieldName(field_index, mod);
return sema.addStrLit(block, ip.stringToSlice(field_name));
}
@@ -19601,7 +19609,6 @@ fn zirReify(
// Tag type
const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
var explicit_tags_seen: []bool = &.{};
- var explicit_enum_info: ?InternPool.Key.EnumType = null;
var enum_field_names: []InternPool.NullTerminatedString = &.{};
if (tag_type_val.optionalValue(mod)) |payload_val| {
union_obj.tag_ty = payload_val.toType();
@@ -19611,7 +19618,6 @@ fn zirReify(
else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),
};
- explicit_enum_info = enum_type;
explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
@memset(explicit_tags_seen, false);
} else {
@@ -19640,7 +19646,8 @@ fn zirReify(
enum_field_names[i] = field_name;
}
- if (explicit_enum_info) |tag_info| {
+ if (explicit_tags_seen.len > 0) {
+ const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
const enum_index = tag_info.nameIndex(ip, field_name) orelse {
const msg = msg: {
const msg = try sema.errMsg(block, src, "no field named '{s}' in enum '{}'", .{ ip.stringToSlice(field_name), union_obj.tag_ty.fmt(mod) });
@@ -19705,7 +19712,8 @@ fn zirReify(
}
}
- if (explicit_enum_info) |tag_info| {
+ if (explicit_tags_seen.len > 0) {
+ const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
if (tag_info.names.len > fields_len) {
const msg = msg: {
const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{});
@@ -31625,17 +31633,17 @@ fn resolvePeerTypes(
return chosen_ty;
}
-pub fn resolveFnTypes(sema: *Sema, fn_info: InternPool.Key.FuncType) CompileError!void {
+pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
const mod = sema.mod;
- try sema.resolveTypeFully(fn_info.return_type.toType());
+ try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.return_type.toType());
- if (mod.comp.bin_file.options.error_return_tracing and fn_info.return_type.toType().isError(mod)) {
+ if (mod.comp.bin_file.options.error_return_tracing and mod.typeToFunc(fn_ty).?.return_type.toType().isError(mod)) {
// Ensure the type exists so that backends can assume that.
_ = try sema.getBuiltinType("StackTrace");
}
- for (fn_info.param_types) |param_ty| {
- try sema.resolveTypeFully(param_ty.toType());
+ for (0..mod.typeToFunc(fn_ty).?.param_types.len) |i| {
+ try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.param_types[i].toType());
}
}
@@ -33077,7 +33085,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
var enum_field_names: []InternPool.NullTerminatedString = &.{};
var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{};
var explicit_tags_seen: []bool = &.{};
- var explicit_enum_info: ?InternPool.Key.EnumType = null;
if (tag_type_ref != .none) {
const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x };
const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);
@@ -33114,7 +33121,6 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
};
// The fields of the union must match the enum exactly.
// A flag per field is used to check for missing and extraneous fields.
- explicit_enum_info = enum_type;
explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
@memset(explicit_tags_seen, false);
}
@@ -33256,7 +33262,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
return sema.failWithOwnedErrorMsg(msg);
}
- if (explicit_enum_info) |tag_info| {
+ if (explicit_tags_seen.len > 0) {
+ const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
const enum_index = tag_info.nameIndex(ip, field_name) orelse {
const msg = msg: {
const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
@@ -33346,7 +33353,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
}
}
- if (explicit_enum_info) |tag_info| {
+ if (explicit_tags_seen.len > 0) {
+ const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
if (tag_info.names.len > fields_len) {
const msg = msg: {
const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{});
@@ -33706,9 +33714,10 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
}
// In this case the struct has all comptime-known fields and
// therefore has one possible value.
+ // TODO: write something like getCoercedInts to avoid needing to dupe
return (try mod.intern(.{ .aggregate = .{
.ty = ty.toIntern(),
- .storage = .{ .elems = tuple.values },
+ .storage = .{ .elems = try sema.arena.dupe(InternPool.Index, tuple.values) },
} })).toValue();
},
src/type.zig
@@ -2576,9 +2576,12 @@ pub const Type = struct {
}
// In this case the struct has all comptime-known fields and
// therefore has one possible value.
+ // TODO: write something like getCoercedInts to avoid needing to dupe
+ const duped_values = try mod.gpa.dupe(InternPool.Index, tuple.values);
+ defer mod.gpa.free(duped_values);
return (try mod.intern(.{ .aggregate = .{
.ty = ty.toIntern(),
- .storage = .{ .elems = tuple.values },
+ .storage = .{ .elems = duped_values },
} })).toValue();
},
src/value.zig
@@ -1904,6 +1904,7 @@ pub const Value = struct {
start: usize,
end: usize,
) error{OutOfMemory}!Value {
+ // TODO: write something like getCoercedInts to avoid needing to dupe
return switch (val.ip_index) {
.none => switch (val.tag()) {
.slice => val.castTag(.slice).?.data.ptr.sliceArray(mod, arena, start, end),
@@ -1937,8 +1938,8 @@ pub const Value = struct {
else => unreachable,
}.toIntern(),
.storage = switch (aggregate.storage) {
- .bytes => |bytes| .{ .bytes = bytes[start..end] },
- .elems => |elems| .{ .elems = elems[start..end] },
+ .bytes => .{ .bytes = try arena.dupe(u8, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.bytes[start..end]) },
+ .elems => .{ .elems = try arena.dupe(InternPool.Index, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.elems[start..end]) },
.repeated_elem => |elem| .{ .repeated_elem = elem },
},
} })).toValue(),