From c4735941148eb32eee16307ba13876ae21606fba Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Fri, 19 May 2023 23:16:36 -0400 Subject: [PATCH] Sema: port reify struct access to use InternPool --- src/Sema.zig | 202 +++++++++++++++++++++++++++------------------------ src/type.zig | 9 ++- 2 files changed, 116 insertions(+), 95 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 22ae6fb531..ebef3e929b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -18805,6 +18805,7 @@ fn zirReify( const target = mod.getTarget(); const tag_index = type_info_ty.unionTagFieldIndex(union_val.tag, mod).?; if (try union_val.val.anyUndef(mod)) return sema.failWithUseOfUndef(block, src); + const ip = &mod.intern_pool; switch (@intToEnum(std.builtin.TypeId, tag_index)) { .Type => return Air.Inst.Ref.type_type, .Void => return Air.Inst.Ref.void_type, @@ -18817,10 +18818,12 @@ fn zirReify( .AnyFrame => return sema.failWithUseOfAsync(block, src), .EnumLiteral => return Air.Inst.Ref.enum_literal_type, .Int => { - const struct_val = union_val.val.castTag(.aggregate).?.data; - // TODO use reflection instead of magic numbers here - const signedness_val = struct_val[0]; - const bits_val = struct_val[1]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const signedness_index = fields.getIndex("signedness").?; + const bits_index = fields.getIndex("bits").?; + + const signedness_val = try union_val.val.fieldValue(fields.values()[signedness_index].ty, mod, signedness_index); + const bits_val = try union_val.val.fieldValue(fields.values()[bits_index].ty, mod, bits_index); const signedness = mod.toEnum(std.builtin.Signedness, signedness_val); const bits = @intCast(u16, bits_val.toUnsignedInt(mod)); @@ -18828,10 +18831,12 @@ fn zirReify( return sema.addType(ty); }, .Vector => { - const struct_val = union_val.val.castTag(.aggregate).?.data; - // TODO use reflection instead of magic numbers here - const len_val = struct_val[0]; - const child_val = struct_val[1]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const len_index = fields.getIndex("len").?; + const child_index = fields.getIndex("child").?; + + const len_val = try union_val.val.fieldValue(fields.values()[len_index].ty, mod, len_index); + const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index); const len = @intCast(u32, len_val.toUnsignedInt(mod)); const child_ty = child_val.toType(); @@ -18845,10 +18850,10 @@ fn zirReify( return sema.addType(ty); }, .Float => { - const struct_val = union_val.val.castTag(.aggregate).?.data; - // TODO use reflection instead of magic numbers here - // bits: comptime_int, - const bits_val = struct_val[0]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const bits_index = fields.getIndex("bits").?; + + const bits_val = try union_val.val.fieldValue(fields.values()[bits_index].ty, mod, bits_index); const bits = @intCast(u16, bits_val.toUnsignedInt(mod)); const ty = switch (bits) { @@ -18862,16 +18867,24 @@ fn zirReify( return sema.addType(ty); }, .Pointer => { - const struct_val = union_val.val.castTag(.aggregate).?.data; - // TODO use reflection instead of magic numbers here - const size_val = struct_val[0]; - const is_const_val = struct_val[1]; - const is_volatile_val = struct_val[2]; - const alignment_val = struct_val[3]; - const address_space_val = struct_val[4]; - const child_val = struct_val[5]; - const is_allowzero_val = struct_val[6]; - const sentinel_val = struct_val[7]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const size_index = fields.getIndex("size").?; + const is_const_index = fields.getIndex("is_const").?; + const is_volatile_index = fields.getIndex("is_volatile").?; + const alignment_index = fields.getIndex("alignment").?; + const address_space_index = fields.getIndex("address_space").?; + const child_index = fields.getIndex("child").?; + const is_allowzero_index = fields.getIndex("is_allowzero").?; + const sentinel_index = fields.getIndex("sentinel").?; + + const size_val = try union_val.val.fieldValue(fields.values()[size_index].ty, mod, size_index); + const is_const_val = try union_val.val.fieldValue(fields.values()[is_const_index].ty, mod, is_const_index); + const is_volatile_val = try union_val.val.fieldValue(fields.values()[is_volatile_index].ty, mod, is_volatile_index); + const alignment_val = try union_val.val.fieldValue(fields.values()[alignment_index].ty, mod, alignment_index); + const address_space_val = try union_val.val.fieldValue(fields.values()[address_space_index].ty, mod, address_space_index); + const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index); + const is_allowzero_val = try union_val.val.fieldValue(fields.values()[is_allowzero_index].ty, mod, is_allowzero_index); + const sentinel_val = try union_val.val.fieldValue(fields.values()[sentinel_index].ty, mod, sentinel_index); if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { return sema.fail(block, src, "alignment must fit in 'u32'", .{}); @@ -18954,14 +18967,14 @@ fn zirReify( return sema.addType(ty); }, .Array => { - const struct_val = union_val.val.castTag(.aggregate).?.data; - // TODO use reflection instead of magic numbers here - // len: comptime_int, - const len_val = struct_val[0]; - // child: type, - const child_val = struct_val[1]; - // sentinel: ?*const anyopaque, - const sentinel_val = struct_val[2]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const len_index = fields.getIndex("len").?; + const child_index = fields.getIndex("child").?; + const sentinel_index = fields.getIndex("sentinel").?; + + const len_val = try union_val.val.fieldValue(fields.values()[len_index].ty, mod, len_index); + const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index); + const sentinel_val = try union_val.val.fieldValue(fields.values()[sentinel_index].ty, mod, sentinel_index); const len = len_val.toUnsignedInt(mod); const child_ty = child_val.toType(); @@ -18977,10 +18990,10 @@ fn zirReify( return sema.addType(ty); }, .Optional => { - const struct_val = union_val.val.castTag(.aggregate).?.data; - // TODO use reflection instead of magic numbers here - // child: type, - const child_val = struct_val[0]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const child_index = fields.getIndex("child").?; + + const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index); const child_ty = child_val.toType(); @@ -18988,12 +19001,12 @@ fn zirReify( return sema.addType(ty); }, .ErrorUnion => { - const struct_val = union_val.val.castTag(.aggregate).?.data; - // TODO use reflection instead of magic numbers here - // error_set: type, - const error_set_val = struct_val[0]; - // payload: type, - const payload_val = struct_val[1]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const error_set_index = fields.getIndex("error_set").?; + const payload_index = fields.getIndex("payload").?; + + const error_set_val = try union_val.val.fieldValue(fields.values()[error_set_index].ty, mod, error_set_index); + const payload_val = try union_val.val.fieldValue(fields.values()[payload_index].ty, mod, payload_index); const error_set_ty = error_set_val.toType(); const payload_ty = payload_val.toType(); @@ -19031,19 +19044,18 @@ fn zirReify( return sema.addType(ty); }, .Struct => { - // TODO use reflection instead of magic numbers here - const struct_val = union_val.val.castTag(.aggregate).?.data; - // layout: containerlayout, - const layout_val = struct_val[0]; - // backing_int: ?type, - const backing_int_val = struct_val[1]; - // fields: []const enumfield, - const fields_val = struct_val[2]; - // decls: []const declaration, - const decls_val = struct_val[3]; - // is_tuple: bool, - const is_tuple_val = struct_val[4]; - assert(struct_val.len == 5); + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const layout_index = fields.getIndex("layout").?; + const backing_integer_index = fields.getIndex("backing_integer").?; + const fields_index = fields.getIndex("fields").?; + const decls_index = fields.getIndex("decls").?; + const is_tuple_index = fields.getIndex("is_tuple").?; + + const layout_val = try union_val.val.fieldValue(fields.values()[layout_index].ty, mod, layout_index); + const backing_integer_val = try union_val.val.fieldValue(fields.values()[backing_integer_index].ty, mod, backing_integer_index); + const fields_val = try union_val.val.fieldValue(fields.values()[fields_index].ty, mod, fields_index); + const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index); + const is_tuple_val = try union_val.val.fieldValue(fields.values()[is_tuple_index].ty, mod, is_tuple_index); const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val); @@ -19052,23 +19064,23 @@ fn zirReify( return sema.fail(block, src, "reified structs must have no decls", .{}); } - if (layout != .Packed and !backing_int_val.isNull(mod)) { + if (layout != .Packed and !backing_integer_val.isNull(mod)) { return sema.fail(block, src, "non-packed struct does not support backing integer type", .{}); } - return try sema.reifyStruct(block, inst, src, layout, backing_int_val, fields_val, name_strategy, is_tuple_val.toBool(mod)); + return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_val, name_strategy, is_tuple_val.toBool(mod)); }, .Enum => { - const struct_val: []const Value = union_val.val.castTag(.aggregate).?.data; - // TODO use reflection instead of magic numbers here - // tag_type: type, - const tag_type_val = struct_val[0]; - // fields: []const EnumField, - const fields_val = struct_val[1]; - // decls: []const Declaration, - const decls_val = struct_val[2]; - // is_exhaustive: bool, - const is_exhaustive_val = struct_val[3]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const tag_type_index = fields.getIndex("tag_type").?; + const fields_index = fields.getIndex("fields").?; + const decls_index = fields.getIndex("decls").?; + const is_exhaustive_index = fields.getIndex("is_exhaustive").?; + + const tag_type_val = try union_val.val.fieldValue(fields.values()[tag_type_index].ty, mod, tag_type_index); + const fields_val = try union_val.val.fieldValue(fields.values()[fields_index].ty, mod, fields_index); + const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index); + const is_exhaustive_val = try union_val.val.fieldValue(fields.values()[is_exhaustive_index].ty, mod, is_exhaustive_index); // Decls if (decls_val.sliceLen(mod) > 0) { @@ -19160,9 +19172,10 @@ fn zirReify( return sema.analyzeDeclVal(block, src, new_decl_index); }, .Opaque => { - const struct_val = union_val.val.castTag(.aggregate).?.data; - // decls: []const Declaration, - const decls_val = struct_val[0]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const decls_index = fields.getIndex("decls").?; + + const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index); // Decls if (decls_val.sliceLen(mod) > 0) { @@ -19205,16 +19218,16 @@ fn zirReify( return sema.analyzeDeclVal(block, src, new_decl_index); }, .Union => { - // TODO use reflection instead of magic numbers here - const struct_val = union_val.val.castTag(.aggregate).?.data; - // layout: containerlayout, - const layout_val = struct_val[0]; - // tag_type: ?type, - const tag_type_val = struct_val[1]; - // fields: []const enumfield, - const fields_val = struct_val[2]; - // decls: []const declaration, - const decls_val = struct_val[3]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const layout_index = fields.getIndex("layout").?; + const tag_type_index = fields.getIndex("tag_type").?; + const fields_index = fields.getIndex("fields").?; + const decls_index = fields.getIndex("decls").?; + + const layout_val = try union_val.val.fieldValue(fields.values()[layout_index].ty, mod, layout_index); + const tag_type_val = try union_val.val.fieldValue(fields.values()[tag_type_index].ty, mod, tag_type_index); + const fields_val = try union_val.val.fieldValue(fields.values()[fields_index].ty, mod, fields_index); + const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index); // Decls if (decls_val.sliceLen(mod) > 0) { @@ -19411,25 +19424,28 @@ fn zirReify( return sema.analyzeDeclVal(block, src, new_decl_index); }, .Fn => { - const struct_val: []const Value = union_val.val.castTag(.aggregate).?.data; - // TODO use reflection instead of magic numbers here - // calling_convention: CallingConvention, - const cc = mod.toEnum(std.builtin.CallingConvention, struct_val[0]); - // alignment: comptime_int, - const alignment_val = struct_val[1]; - // is_generic: bool, - const is_generic = struct_val[2].toBool(mod); - // is_var_args: bool, - const is_var_args = struct_val[3].toBool(mod); - // return_type: ?type, - const return_type_val = struct_val[4]; - // args: []const Param, - const args_val = struct_val[5]; + const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod); + const calling_convention_index = fields.getIndex("calling_convention").?; + const alignment_index = fields.getIndex("alignment").?; + const is_generic_index = fields.getIndex("is_generic").?; + const is_var_args_index = fields.getIndex("is_var_args").?; + const return_type_index = fields.getIndex("return_type").?; + const params_index = fields.getIndex("params").?; + const calling_convention_val = try union_val.val.fieldValue(fields.values()[calling_convention_index].ty, mod, calling_convention_index); + const alignment_val = try union_val.val.fieldValue(fields.values()[alignment_index].ty, mod, alignment_index); + const is_generic_val = try union_val.val.fieldValue(fields.values()[is_generic_index].ty, mod, is_generic_index); + const is_var_args_val = try union_val.val.fieldValue(fields.values()[is_var_args_index].ty, mod, is_var_args_index); + const return_type_val = try union_val.val.fieldValue(fields.values()[return_type_index].ty, mod, return_type_index); + const params_val = try union_val.val.fieldValue(fields.values()[params_index].ty, mod, params_index); + + const is_generic = is_generic_val.toBool(mod); if (is_generic) { return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{}); } + const is_var_args = is_var_args_val.toBool(mod); + const cc = mod.toEnum(std.builtin.CallingConvention, calling_convention_val); if (is_var_args and cc != .C) { return sema.fail(block, src, "varargs functions must have C calling convention", .{}); } @@ -19448,7 +19464,7 @@ fn zirReify( const return_type = return_type_val.optionalValue(mod) orelse return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{}); - const args_slice_val = args_val.castTag(.slice).?.data; + const args_slice_val = params_val.castTag(.slice).?.data; const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod)); const param_types = try sema.arena.alloc(InternPool.Index, args_len); diff --git a/src/type.zig b/src/type.zig index 019557c5e0..d0cf054845 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3148,8 +3148,13 @@ pub const Type = struct { pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 { const ip = &mod.intern_pool; const enum_type = ip.indexToKey(ty.ip_index).enum_type; - assert(ip.typeOf(enum_tag.ip_index) == enum_type.tag_ty); - return enum_type.tagValueIndex(ip, enum_tag.ip_index); + const int_tag = switch (ip.indexToKey(enum_tag.ip_index)) { + .int => enum_tag.ip_index, + .enum_tag => |info| info.int, + else => unreachable, + }; + assert(ip.typeOf(int_tag) == enum_type.tag_ty); + return enum_type.tagValueIndex(ip, int_tag); } pub fn structFields(ty: Type, mod: *Module) Module.Struct.Fields {