From 5881a2d63771b070107bdc2325aa1bc455b2d926 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 12 May 2023 00:07:32 -0700 Subject: 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. --- src/codegen.zig | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index 5c022392bf..148a69016a 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -156,7 +156,8 @@ pub fn generateLazySymbol( return Result.ok; } else if (lazy_sym.ty.zigTypeTag(mod) == .Enum) { alignment.* = 1; - for (lazy_sym.ty.enumFields().keys()) |tag_name| { + for (lazy_sym.ty.enumFields(mod)) |tag_name_ip| { + const tag_name = mod.intern_pool.stringToSlice(tag_name_ip); try code.ensureUnusedCapacity(tag_name.len + 1); code.appendSliceAssumeCapacity(tag_name); code.appendAssumeCapacity(0); @@ -1229,26 +1230,15 @@ pub fn genTypedValue( }, .Enum => { if (typed_value.val.castTag(.enum_field_index)) |field_index| { - switch (typed_value.ty.tag()) { - .enum_simple => { - return GenResult.mcv(.{ .immediate = field_index.data }); - }, - .enum_numbered, .enum_full, .enum_nonexhaustive => { - const enum_values = if (typed_value.ty.castTag(.enum_numbered)) |pl| - pl.data.values - else - typed_value.ty.cast(Type.Payload.EnumFull).?.data.values; - if (enum_values.count() != 0) { - const tag_val = enum_values.keys()[field_index.data]; - return genTypedValue(bin_file, src_loc, .{ - .ty = try typed_value.ty.intTagType(mod), - .val = tag_val, - }, owner_decl_index); - } else { - return GenResult.mcv(.{ .immediate = field_index.data }); - } - }, - else => unreachable, + const enum_type = mod.intern_pool.indexToKey(typed_value.ty.ip_index).enum_type; + if (enum_type.values.len != 0) { + const tag_val = enum_type.values[field_index.data]; + return genTypedValue(bin_file, src_loc, .{ + .ty = enum_type.tag_ty.toType(), + .val = tag_val.toValue(), + }, owner_decl_index); + } else { + return GenResult.mcv(.{ .immediate = field_index.data }); } } else { const int_tag_ty = try typed_value.ty.intTagType(mod); -- cgit v1.2.3