diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-05-12 00:07:32 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-06-10 20:42:30 -0700 |
| commit | 5881a2d63771b070107bdc2325aa1bc455b2d926 (patch) | |
| tree | 0380faab30356377b721943de57c8b566e9f3744 /src/codegen/c.zig | |
| parent | 404cbc36c52a50975a69e78da716f2258e5b1696 (diff) | |
| download | zig-5881a2d63771b070107bdc2325aa1bc455b2d926.tar.gz zig-5881a2d63771b070107bdc2325aa1bc455b2d926.zip | |
stage2: move enum types into the InternPool
Unlike unions and structs, enums are actually *encoded* into the
InternPool directly, rather than using the SegmentedList trick. This
results in them being quite compact, and greatly improved the ergonomics
of using enum types throughout the compiler.
It did however require introducing a new concept to the InternPool which
is an "incomplete" item - something that is added to gain a permanent
Index, but which is then mutated in place. This was necessary because
enum tag values and tag types may reference the namespaces created by
the enum itself, which required constructing the namespace, decl, and
calling analyzeDecl on the decl, which required the decl value, which
required the enum type, which required an InternPool index to be
assigned and for it to be meaningful.
The API for updating enums in place turned out to be quite slick and
efficient - the methods directly populate pre-allocated arrays and
return the information necessary to output the same compilation errors
as before.
Diffstat (limited to 'src/codegen/c.zig')
| -rw-r--r-- | src/codegen/c.zig | 32 |
1 files changed, 9 insertions, 23 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 872bdb94d3..a67d39471a 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1288,27 +1288,12 @@ pub const DeclGen = struct { switch (val.tag()) { .enum_field_index => { const field_index = val.castTag(.enum_field_index).?.data; - switch (ty.tag()) { - .enum_simple => return writer.print("{d}", .{field_index}), - .enum_full, .enum_nonexhaustive => { - const enum_full = ty.cast(Type.Payload.EnumFull).?.data; - if (enum_full.values.count() != 0) { - const tag_val = enum_full.values.keys()[field_index]; - return dg.renderValue(writer, enum_full.tag_ty, tag_val, location); - } else { - return writer.print("{d}", .{field_index}); - } - }, - .enum_numbered => { - const enum_obj = ty.castTag(.enum_numbered).?.data; - if (enum_obj.values.count() != 0) { - const tag_val = enum_obj.values.keys()[field_index]; - return dg.renderValue(writer, enum_obj.tag_ty, tag_val, location); - } else { - return writer.print("{d}", .{field_index}); - } - }, - else => unreachable, + const enum_type = mod.intern_pool.indexToKey(ty.ip_index).enum_type; + if (enum_type.values.len != 0) { + const tag_val = enum_type.values[field_index]; + return dg.renderValue(writer, enum_type.tag_ty.toType(), tag_val.toValue(), location); + } else { + return writer.print("{d}", .{field_index}); } }, else => { @@ -2539,7 +2524,8 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { try w.writeByte('('); try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, 0, .complete); try w.writeAll(") {\n switch (tag) {\n"); - for (enum_ty.enumFields().keys(), 0..) |name, index| { + for (enum_ty.enumFields(mod), 0..) |name_ip, index| { + const name = mod.intern_pool.stringToSlice(name_ip); var tag_pl: Value.Payload.U32 = .{ .base = .{ .tag = .enum_field_index }, .data = @intCast(u32, index), @@ -6930,7 +6916,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { const field: CValue = if (union_ty.unionTagTypeSafety(mod)) |tag_ty| field: { const layout = union_ty.unionGetLayout(mod); if (layout.tag_size != 0) { - const field_index = tag_ty.enumFieldIndex(field_name).?; + const field_index = tag_ty.enumFieldIndex(field_name, mod).?; var tag_pl: Value.Payload.U32 = .{ .base = .{ .tag = .enum_field_index }, |
