authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-27 18:58:28-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-27 18:58:28-05:00
log720a5f87d402740045cc28650726c42adb521166
treee28008bbb3ff86babf48fbe4b80d078e9217c2f3
parent139b731d82d0b851c8fb2e6dbb48b735e63eecd1
parent9d4cfd9048d71d7519d759b9849914ce154d1877
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11006 from topolarity/resolve-union-alignment

stage2: Resolve alignment for union field in `@TypeInfo`

3 files changed, 48 insertions(+), 17 deletions(-)

src/Module.zig+2
......@@ -1125,6 +1125,8 @@ pub const Union = struct {
11251125 abi_align: Value,
11261126
11271127 /// Returns the field alignment, assuming the union is not packed.
1128 /// Keep implementation in sync with `Sema.unionFieldAlignment`.
1129 /// Prefer to call that function instead of this one during Sema.
11281130 pub fn normalAlignment(field: Field, target: Target) u32 {
11291131 if (field.abi_align.tag() == .abi_align_default) {
11301132 return field.ty.abiAlignment(target);
src/Sema.zig+46-11
......@@ -9903,63 +9903,63 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
99039903 type_info_ty,
99049904 try Value.Tag.@"union".create(sema.arena, .{
99059905 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Type)),
9906 .val = Value.initTag(.unreachable_value),
9906 .val = Value.@"void",
99079907 }),
99089908 ),
99099909 .Void => return sema.addConstant(
99109910 type_info_ty,
99119911 try Value.Tag.@"union".create(sema.arena, .{
99129912 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Void)),
9913 .val = Value.initTag(.unreachable_value),
9913 .val = Value.@"void",
99149914 }),
99159915 ),
99169916 .Bool => return sema.addConstant(
99179917 type_info_ty,
99189918 try Value.Tag.@"union".create(sema.arena, .{
99199919 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Bool)),
9920 .val = Value.initTag(.unreachable_value),
9920 .val = Value.@"void",
99219921 }),
99229922 ),
99239923 .NoReturn => return sema.addConstant(
99249924 type_info_ty,
99259925 try Value.Tag.@"union".create(sema.arena, .{
99269926 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.NoReturn)),
9927 .val = Value.initTag(.unreachable_value),
9927 .val = Value.@"void",
99289928 }),
99299929 ),
99309930 .ComptimeFloat => return sema.addConstant(
99319931 type_info_ty,
99329932 try Value.Tag.@"union".create(sema.arena, .{
99339933 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ComptimeFloat)),
9934 .val = Value.initTag(.unreachable_value),
9934 .val = Value.@"void",
99359935 }),
99369936 ),
99379937 .ComptimeInt => return sema.addConstant(
99389938 type_info_ty,
99399939 try Value.Tag.@"union".create(sema.arena, .{
99409940 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ComptimeInt)),
9941 .val = Value.initTag(.unreachable_value),
9941 .val = Value.@"void",
99429942 }),
99439943 ),
99449944 .Undefined => return sema.addConstant(
99459945 type_info_ty,
99469946 try Value.Tag.@"union".create(sema.arena, .{
99479947 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Undefined)),
9948 .val = Value.initTag(.unreachable_value),
9948 .val = Value.@"void",
99499949 }),
99509950 ),
99519951 .Null => return sema.addConstant(
99529952 type_info_ty,
99539953 try Value.Tag.@"union".create(sema.arena, .{
99549954 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Null)),
9955 .val = Value.initTag(.unreachable_value),
9955 .val = Value.@"void",
99569956 }),
99579957 ),
99589958 .EnumLiteral => return sema.addConstant(
99599959 type_info_ty,
99609960 try Value.Tag.@"union".create(sema.arena, .{
99619961 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.EnumLiteral)),
9962 .val = Value.initTag(.unreachable_value),
9962 .val = Value.@"void",
99639963 }),
99649964 ),
99659965 .Fn => {
......@@ -10380,6 +10380,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1038010380 };
1038110381
1038210382 const union_ty = try sema.resolveTypeFields(block, src, ty);
10383 try sema.resolveTypeLayout(block, src, ty); // Getting alignment requires type layout
10384 const layout = union_ty.containerLayout();
10385
1038310386 const union_fields = union_ty.unionFields();
1038410387 const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count());
1038510388
......@@ -10398,13 +10401,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1039810401 };
1039910402
1040010403 const union_field_fields = try fields_anon_decl.arena().create([3]Value);
10404 const alignment = switch (layout) {
10405 .Auto, .Extern => try sema.unionFieldAlignment(block, src, field),
10406 .Packed => 0,
10407 };
10408
1040110409 union_field_fields.* = .{
1040210410 // name: []const u8,
1040310411 name_val,
1040410412 // field_type: type,
1040510413 try Value.Tag.ty.create(fields_anon_decl.arena(), field.ty),
1040610414 // alignment: comptime_int,
10407 try field.abi_align.copy(fields_anon_decl.arena()),
10415 try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment),
1040810416 };
1040910417 field_val.* = try Value.Tag.@"struct".create(fields_anon_decl.arena(), union_field_fields);
1041010418 }
......@@ -10435,7 +10443,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1043510443 // layout: ContainerLayout,
1043610444 try Value.Tag.enum_field_index.create(
1043710445 sema.arena,
10438 @enumToInt(union_ty.containerLayout()),
10446 @enumToInt(layout),
1043910447 ),
1044010448
1044110449 // tag_type: ?type,
......@@ -10473,6 +10481,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1047310481 break :t try struct_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
1047410482 };
1047510483 const struct_ty = try sema.resolveTypeFields(block, src, ty);
10484 try sema.resolveTypeLayout(block, src, ty); // Getting alignment requires type layout
1047610485 const layout = struct_ty.containerLayout();
1047710486
1047810487 const struct_field_vals = fv: {
......@@ -17704,6 +17713,10 @@ fn resolveTypeLayout(
1770417713 .Optional => {
1770517714 var buf: Type.Payload.ElemType = undefined;
1770617715 const payload_ty = ty.optionalChild(&buf);
17716 // In case of querying the ABI alignment of this optional, we will ask
17717 // for hasRuntimeBits() of the payload type, so we need "requires comptime"
17718 // to be known already before this function returns.
17719 _ = try sema.typeRequiresComptime(block, src, payload_ty);
1770717720 return sema.resolveTypeLayout(block, src, payload_ty);
1770817721 },
1770917722 .ErrorUnion => {
......@@ -17735,6 +17748,13 @@ fn resolveStructLayout(
1773517748 try sema.resolveTypeLayout(block, src, field.ty);
1773617749 }
1773717750 struct_obj.status = .have_layout;
17751
17752 // In case of querying the ABI alignment of this struct, we will ask
17753 // for hasRuntimeBits() of each field, so we need "requires comptime"
17754 // to be known already before this function returns.
17755 for (struct_obj.fields.values()) |field| {
17756 _ = try sema.typeRequiresComptime(block, src, field.ty);
17757 }
1773817758 }
1773917759 // otherwise it's a tuple; no need to resolve anything
1774017760}
......@@ -19288,6 +19308,21 @@ fn typeAbiAlignment(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u32
1928819308 return ty.abiAlignment(target);
1928919309}
1929019310
19311/// Not valid to call for packed unions.
19312/// Keep implementation in sync with `Module.Union.Field.normalAlignment`.
19313fn unionFieldAlignment(
19314 sema: *Sema,
19315 block: *Block,
19316 src: LazySrcLoc,
19317 field: Module.Union.Field,
19318) !u32 {
19319 if (field.abi_align.tag() == .abi_align_default) {
19320 return sema.typeAbiAlignment(block, src, field.ty);
19321 } else {
19322 return @intCast(u32, field.abi_align.toUnsignedInt());
19323 }
19324}
19325
1929119326/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
1929219327pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
1929319328 const fn_info = ty.fnInfo();
test/behavior/type_info.zig-6
......@@ -249,8 +249,6 @@ fn testEnum() !void {
249249}
250250
251251test "type info: union info" {
252 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
253
254252 try testUnion();
255253 comptime try testUnion();
256254}
......@@ -436,8 +434,6 @@ fn testAnyFrame() !void {
436434}
437435
438436test "type info: pass to function" {
439 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
440
441437 _ = passTypeInfo(@typeInfo(void));
442438 _ = comptime passTypeInfo(@typeInfo(void));
443439}
......@@ -448,8 +444,6 @@ fn passTypeInfo(comptime info: TypeInfo) type {
448444}
449445
450446test "type info: TypeId -> TypeInfo impl cast" {
451 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
452
453447 _ = passTypeInfo(TypeId.Void);
454448 _ = comptime passTypeInfo(TypeId.Void);
455449}