aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2023-06-03 15:46:16 +0100
committerAndrew Kelley <andrew@ziglang.org>2023-06-10 20:51:10 -0700
commit2a6b91874ae970c0fba63f8c1357da5a57feec27 (patch)
treeccc245020664b0908c3e674295d3e1ca6e01bd10 /src
parentab86b2024883f67c0fa06108f66e4e88b98c3163 (diff)
downloadzig-2a6b91874ae970c0fba63f8c1357da5a57feec27.tar.gz
zig-2a6b91874ae970c0fba63f8c1357da5a57feec27.zip
stage2: pass most test cases under InternPool
All but 2 test cases now pass (tested on x86_64 Linux, native only). The remaining two signify an issue requiring a larger refactor, which I will do in a separate commit. Notable changes: * Fix uninitialized memory when allocating objects from free lists * Implement TypedValue printing for pointers * Fix some TypedValue printing logic * Work around non-existence of InternPool.remove implementation
Diffstat (limited to 'src')
-rw-r--r--src/InternPool.zig41
-rw-r--r--src/Module.zig8
-rw-r--r--src/Sema.zig57
-rw-r--r--src/TypedValue.zig143
-rw-r--r--src/type.zig3
5 files changed, 214 insertions, 38 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig
index 0363003b36..a46f765ad5 100644
--- a/src/InternPool.zig
+++ b/src/InternPool.zig
@@ -400,14 +400,21 @@ pub const Key = union(enum) {
/// integer tag type of the enum.
pub fn tagValueIndex(self: EnumType, ip: *const InternPool, tag_val: Index) ?u32 {
assert(tag_val != .none);
+ // TODO: we should probably decide a single interface for this function, but currently
+ // it's being called with both tag values and underlying ints. Fix this!
+ const int_tag_val = switch (ip.indexToKey(tag_val)) {
+ .enum_tag => |enum_tag| enum_tag.int,
+ .int => tag_val,
+ else => unreachable,
+ };
if (self.values_map.unwrap()) |values_map| {
const map = &ip.maps.items[@enumToInt(values_map)];
const adapter: Index.Adapter = .{ .indexes = self.values };
- const field_index = map.getIndexAdapted(tag_val, adapter) orelse return null;
+ const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;
return @intCast(u32, field_index);
}
- // Auto-numbered enum. Convert `tag_val` to field index.
- switch (ip.indexToKey(tag_val).int.storage) {
+ // Auto-numbered enum. Convert `int_tag_val` to field index.
+ switch (ip.indexToKey(int_tag_val).int.storage) {
.u64 => |x| {
if (x >= self.names.len) return null;
return @intCast(u32, x);
@@ -4261,12 +4268,8 @@ fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex {
/// This operation only happens under compile error conditions.
/// Leak the index until the next garbage collection.
-pub fn remove(ip: *InternPool, index: Index) void {
- _ = ip;
- _ = index;
- @setCold(true);
- @panic("TODO this is a bit problematic to implement, could we maybe just never support a remove() operation on InternPool?");
-}
+/// TODO: this is a bit problematic to implement, can we get away without it?
+pub const remove = @compileError("InternPool.remove is not currently a supported operation; put a TODO there instead");
fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void {
const limbs_len = @intCast(u32, limbs.len);
@@ -5161,7 +5164,10 @@ pub fn createStruct(
gpa: Allocator,
initialization: Module.Struct,
) Allocator.Error!Module.Struct.Index {
- if (ip.structs_free_list.popOrNull()) |index| return index;
+ if (ip.structs_free_list.popOrNull()) |index| {
+ ip.allocated_structs.at(@enumToInt(index)).* = initialization;
+ return index;
+ }
const ptr = try ip.allocated_structs.addOne(gpa);
ptr.* = initialization;
return @intToEnum(Module.Struct.Index, ip.allocated_structs.len - 1);
@@ -5180,7 +5186,10 @@ pub fn createUnion(
gpa: Allocator,
initialization: Module.Union,
) Allocator.Error!Module.Union.Index {
- if (ip.unions_free_list.popOrNull()) |index| return index;
+ if (ip.unions_free_list.popOrNull()) |index| {
+ ip.allocated_unions.at(@enumToInt(index)).* = initialization;
+ return index;
+ }
const ptr = try ip.allocated_unions.addOne(gpa);
ptr.* = initialization;
return @intToEnum(Module.Union.Index, ip.allocated_unions.len - 1);
@@ -5199,7 +5208,10 @@ pub fn createFunc(
gpa: Allocator,
initialization: Module.Fn,
) Allocator.Error!Module.Fn.Index {
- if (ip.funcs_free_list.popOrNull()) |index| return index;
+ if (ip.funcs_free_list.popOrNull()) |index| {
+ ip.allocated_funcs.at(@enumToInt(index)).* = initialization;
+ return index;
+ }
const ptr = try ip.allocated_funcs.addOne(gpa);
ptr.* = initialization;
return @intToEnum(Module.Fn.Index, ip.allocated_funcs.len - 1);
@@ -5218,7 +5230,10 @@ pub fn createInferredErrorSet(
gpa: Allocator,
initialization: Module.Fn.InferredErrorSet,
) Allocator.Error!Module.Fn.InferredErrorSet.Index {
- if (ip.inferred_error_sets_free_list.popOrNull()) |index| return index;
+ if (ip.inferred_error_sets_free_list.popOrNull()) |index| {
+ ip.allocated_inferred_error_sets.at(@enumToInt(index)).* = initialization;
+ return index;
+ }
const ptr = try ip.allocated_inferred_error_sets.addOne(gpa);
ptr.* = initialization;
return @intToEnum(Module.Fn.InferredErrorSet.Index, ip.allocated_inferred_error_sets.len - 1);
diff --git a/src/Module.zig b/src/Module.zig
index c1d6b8157a..cb3e8884e3 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -4374,7 +4374,8 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
.index = struct_index.toOptional(),
.namespace = new_namespace_index.toOptional(),
} });
- errdefer mod.intern_pool.remove(struct_ty);
+ // TODO: figure out InternPool removals for incremental compilation
+ //errdefer mod.intern_pool.remove(struct_ty);
new_namespace.ty = struct_ty.toType();
file.root_decl = new_decl_index.toOptional();
@@ -5682,7 +5683,10 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
}
pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index {
- if (mod.namespaces_free_list.popOrNull()) |index| return index;
+ if (mod.namespaces_free_list.popOrNull()) |index| {
+ mod.allocated_namespaces.at(@enumToInt(index)).* = initialization;
+ return index;
+ }
const ptr = try mod.allocated_namespaces.addOne(mod.gpa);
ptr.* = initialization;
return @intToEnum(Namespace.Index, mod.allocated_namespaces.len - 1);
diff --git a/src/Sema.zig b/src/Sema.zig
index be354ff350..715c63c77c 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -2801,7 +2801,8 @@ fn zirStructDecl(
.index = struct_index.toOptional(),
.namespace = new_namespace_index.toOptional(),
} });
- errdefer mod.intern_pool.remove(struct_ty);
+ // TODO: figure out InternPool removals for incremental compilation
+ //errdefer mod.intern_pool.remove(struct_ty);
new_decl.val = struct_ty.toValue();
new_namespace.ty = struct_ty.toType();
@@ -3012,7 +3013,8 @@ fn zirEnumDecl(
else
.explicit,
});
- errdefer if (!done) mod.intern_pool.remove(incomplete_enum.index);
+ // TODO: figure out InternPool removals for incremental compilation
+ //errdefer if (!done) mod.intern_pool.remove(incomplete_enum.index);
new_decl.val = incomplete_enum.index.toValue();
new_namespace.ty = incomplete_enum.index.toType();
@@ -3260,7 +3262,8 @@ fn zirUnionDecl(
.ReleaseFast, .ReleaseSmall => .none,
},
} });
- errdefer mod.intern_pool.remove(union_ty);
+ // TODO: figure out InternPool removals for incremental compilation
+ //errdefer mod.intern_pool.remove(union_ty);
new_decl.val = union_ty.toValue();
new_namespace.ty = union_ty.toType();
@@ -3321,7 +3324,8 @@ fn zirOpaqueDecl(
.decl = new_decl_index,
.namespace = new_namespace_index,
} });
- errdefer mod.intern_pool.remove(opaque_ty);
+ // TODO: figure out InternPool removals for incremental compilation
+ //errdefer mod.intern_pool.remove(opaque_ty);
new_decl.val = opaque_ty.toValue();
new_namespace.ty = opaque_ty.toType();
@@ -19424,7 +19428,10 @@ fn zirReify(
}, name_strategy, "enum", inst);
const new_decl = mod.declPtr(new_decl_index);
new_decl.owns_tv = true;
- errdefer mod.abortAnonDecl(new_decl_index);
+ errdefer {
+ new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
+ mod.abortAnonDecl(new_decl_index);
+ }
// Define our empty enum decl
const fields_len = @intCast(u32, try sema.usizeCast(block, src, fields_val.sliceLen(mod)));
@@ -19439,7 +19446,8 @@ fn zirReify(
.explicit,
.tag_ty = int_tag_ty.toIntern(),
});
- errdefer ip.remove(incomplete_enum.index);
+ // TODO: figure out InternPool removals for incremental compilation
+ //errdefer ip.remove(incomplete_enum.index);
new_decl.val = incomplete_enum.index.toValue();
@@ -19514,7 +19522,10 @@ fn zirReify(
}, name_strategy, "opaque", inst);
const new_decl = mod.declPtr(new_decl_index);
new_decl.owns_tv = true;
- errdefer mod.abortAnonDecl(new_decl_index);
+ errdefer {
+ new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
+ mod.abortAnonDecl(new_decl_index);
+ }
const new_namespace_index = try mod.createNamespace(.{
.parent = block.namespace.toOptional(),
@@ -19528,7 +19539,8 @@ fn zirReify(
.decl = new_decl_index,
.namespace = new_namespace_index,
} });
- errdefer ip.remove(opaque_ty);
+ // TODO: figure out InternPool removals for incremental compilation
+ //errdefer ip.remove(opaque_ty);
new_decl.val = opaque_ty.toValue();
new_namespace.ty = opaque_ty.toType();
@@ -19568,7 +19580,10 @@ fn zirReify(
}, name_strategy, "union", inst);
const new_decl = mod.declPtr(new_decl_index);
new_decl.owns_tv = true;
- errdefer mod.abortAnonDecl(new_decl_index);
+ errdefer {
+ new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
+ mod.abortAnonDecl(new_decl_index);
+ }
const new_namespace_index = try mod.createNamespace(.{
.parent = block.namespace.toOptional(),
@@ -19601,7 +19616,8 @@ fn zirReify(
.ReleaseFast, .ReleaseSmall => .none,
},
} });
- errdefer ip.remove(union_ty);
+ // TODO: figure out InternPool removals for incremental compilation
+ //errdefer ip.remove(union_ty);
new_decl.val = union_ty.toValue();
new_namespace.ty = union_ty.toType();
@@ -19865,7 +19881,10 @@ fn reifyStruct(
}, name_strategy, "struct", inst);
const new_decl = mod.declPtr(new_decl_index);
new_decl.owns_tv = true;
- errdefer mod.abortAnonDecl(new_decl_index);
+ errdefer {
+ new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
+ mod.abortAnonDecl(new_decl_index);
+ }
const new_namespace_index = try mod.createNamespace(.{
.parent = block.namespace.toOptional(),
@@ -19892,7 +19911,8 @@ fn reifyStruct(
.index = struct_index.toOptional(),
.namespace = new_namespace_index.toOptional(),
} });
- errdefer ip.remove(struct_ty);
+ // TODO: figure out InternPool removals for incremental compilation
+ //errdefer ip.remove(struct_ty);
new_decl.val = struct_ty.toValue();
new_namespace.ty = struct_ty.toType();
@@ -27515,8 +27535,8 @@ fn coerceInMemoryAllowedFns(
if (rt != .ok) {
return InMemoryCoercionResult{ .fn_return_type = .{
.child = try rt.dupe(sema.arena),
- .actual = dest_return_type,
- .wanted = src_return_type,
+ .actual = src_return_type,
+ .wanted = dest_return_type,
} };
}
},
@@ -29505,7 +29525,8 @@ fn coerceTupleToStruct(
.ty = struct_ty.toIntern(),
.storage = .{ .elems = field_vals },
} });
- errdefer ip.remove(struct_val);
+ // TODO: figure out InternPool removals for incremental compilation
+ //errdefer ip.remove(struct_val);
return sema.addConstant(struct_ty, struct_val.toValue());
}
@@ -34666,14 +34687,14 @@ fn floatToIntScalar(
var big_int = try float128IntPartToBigInt(sema.arena, float);
defer big_int.deinit();
- const result = try mod.intValue_big(int_ty, big_int.toConst());
+ const cti_result = try mod.intValue_big(Type.comptime_int, big_int.toConst());
- if (!(try sema.intFitsInType(result, int_ty, null))) {
+ if (!(try sema.intFitsInType(cti_result, int_ty, null))) {
return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{
val.fmtValue(float_ty, sema.mod), int_ty.fmt(sema.mod),
});
}
- return result;
+ return mod.getCoerced(cti_result, int_ty);
}
/// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
diff --git a/src/TypedValue.zig b/src/TypedValue.zig
index 0d771aa184..723207eeff 100644
--- a/src/TypedValue.zig
+++ b/src/TypedValue.zig
@@ -203,7 +203,7 @@ pub fn print(
.extern_func => |extern_func| return writer.print("(extern function '{s}')", .{
mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name),
}),
- .func => |func| return writer.print("(function '{d}')", .{
+ .func => |func| return writer.print("(function '{s}')", .{
mod.intern_pool.stringToSlice(mod.declPtr(mod.funcPtr(func.index).owner_decl).name),
}),
.int => |int| switch (int.storage) {
@@ -234,7 +234,12 @@ pub fn print(
if (level == 0) {
return writer.writeAll("(enum)");
}
-
+ const enum_type = mod.intern_pool.indexToKey(ty.toIntern()).enum_type;
+ if (enum_type.tagValueIndex(&mod.intern_pool, val.toIntern())) |tag_index| {
+ const tag_name = mod.intern_pool.stringToSlice(enum_type.names[tag_index]);
+ try writer.print(".{}", .{std.zig.fmtId(tag_name)});
+ return;
+ }
try writer.writeAll("@intToEnum(");
try print(.{
.ty = Type.type,
@@ -250,9 +255,129 @@ pub fn print(
},
.empty_enum_value => return writer.writeAll("(empty enum value)"),
.float => |float| switch (float.storage) {
- inline else => |x| return writer.print("{}", .{x}),
+ inline else => |x| return writer.print("{d}", .{@floatCast(f64, x)}),
+ },
+ .ptr => |ptr| {
+ if (ptr.addr == .int) {
+ const i = mod.intern_pool.indexToKey(ptr.addr.int).int;
+ switch (i.storage) {
+ inline else => |addr| return writer.print("{x:0>8}", .{addr}),
+ }
+ }
+
+ const ptr_ty = mod.intern_pool.indexToKey(ty.toIntern()).ptr_type;
+ if (ptr_ty.flags.size == .Slice) {
+ if (level == 0) {
+ return writer.writeAll(".{ ... }");
+ }
+ const elem_ty = ptr_ty.child.toType();
+ const len = ptr.len.toValue().toUnsignedInt(mod);
+ if (elem_ty.eql(Type.u8, mod)) str: {
+ const max_len = @min(len, max_string_len);
+ var buf: [max_string_len]u8 = undefined;
+ for (buf[0..max_len], 0..) |*c, i| {
+ const elem = try val.elemValue(mod, i);
+ if (elem.isUndef(mod)) break :str;
+ c.* = @intCast(u8, elem.toUnsignedInt(mod));
+ }
+ const truncated = if (len > max_string_len) " (truncated)" else "";
+ return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
+ }
+ try writer.writeAll(".{ ");
+ const max_len = @min(len, max_aggregate_items);
+ for (0..max_len) |i| {
+ if (i != 0) try writer.writeAll(", ");
+ try print(.{
+ .ty = elem_ty,
+ .val = try val.elemValue(mod, i),
+ }, writer, level - 1, mod);
+ }
+ if (len > max_aggregate_items) {
+ try writer.writeAll(", ...");
+ }
+ return writer.writeAll(" }");
+ }
+
+ switch (ptr.addr) {
+ .decl => |decl_index| {
+ const decl = mod.declPtr(decl_index);
+ if (level == 0) return writer.print("(decl '{s}')", .{mod.intern_pool.stringToSlice(decl.name)});
+ return print(.{
+ .ty = decl.ty,
+ .val = decl.val,
+ }, writer, level - 1, mod);
+ },
+ .mut_decl => |mut_decl| {
+ const decl = mod.declPtr(mut_decl.decl);
+ if (level == 0) return writer.print("(mut decl '{s}')", .{mod.intern_pool.stringToSlice(decl.name)});
+ return print(.{
+ .ty = decl.ty,
+ .val = decl.val,
+ }, writer, level - 1, mod);
+ },
+ .comptime_field => |field_val_ip| {
+ return print(.{
+ .ty = mod.intern_pool.typeOf(field_val_ip).toType(),
+ .val = field_val_ip.toValue(),
+ }, writer, level - 1, mod);
+ },
+ .int => unreachable,
+ .eu_payload => |eu_ip| {
+ try writer.writeAll("(payload of ");
+ try print(.{
+ .ty = mod.intern_pool.typeOf(eu_ip).toType(),
+ .val = eu_ip.toValue(),
+ }, writer, level - 1, mod);
+ try writer.writeAll(")");
+ },
+ .opt_payload => |opt_ip| {
+ try print(.{
+ .ty = mod.intern_pool.typeOf(opt_ip).toType(),
+ .val = opt_ip.toValue(),
+ }, writer, level - 1, mod);
+ try writer.writeAll(".?");
+ },
+ .elem => |elem| {
+ try print(.{
+ .ty = mod.intern_pool.typeOf(elem.base).toType(),
+ .val = elem.base.toValue(),
+ }, writer, level - 1, mod);
+ try writer.print("[{}]", .{elem.index});
+ },
+ .field => |field| {
+ const container_ty = mod.intern_pool.typeOf(field.base).toType();
+ try print(.{
+ .ty = container_ty,
+ .val = field.base.toValue(),
+ }, writer, level - 1, mod);
+
+ switch (container_ty.zigTypeTag(mod)) {
+ .Struct => {
+ if (container_ty.isTuple(mod)) {
+ try writer.print("[{d}]", .{field.index});
+ }
+ const field_name_ip = container_ty.structFieldName(field.index, mod);
+ const field_name = mod.intern_pool.stringToSlice(field_name_ip);
+ try writer.print(".{}", .{std.zig.fmtId(field_name)});
+ },
+ .Union => {
+ const field_name_ip = container_ty.unionFields(mod).keys()[field.index];
+ const field_name = mod.intern_pool.stringToSlice(field_name_ip);
+ try writer.print(".{}", .{std.zig.fmtId(field_name)});
+ },
+ .Pointer => {
+ std.debug.assert(container_ty.isSlice(mod));
+ try writer.writeAll(switch (field.index) {
+ Value.slice_ptr_index => ".ptr",
+ Value.slice_len_index => ".len",
+ else => unreachable,
+ });
+ },
+ else => unreachable,
+ }
+ },
+ }
},
- .ptr => return writer.writeAll("(ptr)"),
.opt => |opt| switch (opt.val) {
.none => return writer.writeAll("null"),
else => |payload| {
@@ -261,7 +386,15 @@ pub fn print(
},
},
.aggregate => |aggregate| switch (aggregate.storage) {
- .bytes => |bytes| return writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)}),
+ .bytes => |bytes| {
+ // Strip the 0 sentinel off of strings before printing
+ const zero_sent = blk: {
+ const sent = ty.sentinel(mod) orelse break :blk false;
+ break :blk sent.eql(Value.zero_u8, Type.u8, mod);
+ };
+ const str = if (zero_sent) bytes[0..bytes.len - 1] else bytes;
+ return writer.print("\"{}\"", .{std.zig.fmtEscapes(str)});
+ },
.elems, .repeated_elem => return printAggregate(ty, val, writer, level, mod),
},
.un => |un| {
diff --git a/src/type.zig b/src/type.zig
index d9ae710b2d..a6997bc590 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -345,6 +345,9 @@ pub const Type = struct {
}
},
.anon_struct_type => |anon_struct| {
+ if (anon_struct.types.len == 0) {
+ return writer.writeAll("@TypeOf(.{})");
+ }
try writer.writeAll("struct{");
for (anon_struct.types, anon_struct.values, 0..) |field_ty, val, i| {
if (i != 0) try writer.writeAll(", ");