authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-30 15:58:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-30 18:33:02-07:00
logc030ec1884ad7c553d6680944b47a1fc7653586f
tree5e11545a9a732ac2565b403bfd723c5f4f285998
parent67db2b85b771d8b0f9d765922951c31fce9c8cc2

LLVM: use unnamed struct llvm type for unions when necessary

The constant value lowering for unions was missing a check for whether the payload was itself an unnamed struct. Lowerings of other types already handle this case. closes #11971

1 files changed, 8 insertions(+), 6 deletions(-)

src/codegen/llvm.zig+8-6
...@@ -3401,6 +3401,13 @@ pub const DeclGen = struct {...@@ -3401,6 +3401,13 @@ pub const DeclGen = struct {
3401 const union_obj = tv.ty.cast(Type.Payload.Union).?.data;3401 const union_obj = tv.ty.cast(Type.Payload.Union).?.data;
3402 const field_index = union_obj.tag_ty.enumTagFieldIndex(tag_and_val.tag, dg.module).?;3402 const field_index = union_obj.tag_ty.enumTagFieldIndex(tag_and_val.tag, dg.module).?;
3403 assert(union_obj.haveFieldTypes());3403 assert(union_obj.haveFieldTypes());
3404
3405 // Sometimes we must make an unnamed struct because LLVM does
3406 // not support bitcasting our payload struct to the true union payload type.
3407 // Instead we use an unnamed struct and every reference to the global
3408 // must pointer cast to the expected type before accessing the union.
3409 var need_unnamed: bool = layout.most_aligned_field != field_index;
3410
3404 const field_ty = union_obj.fields.values()[field_index].ty;3411 const field_ty = union_obj.fields.values()[field_index].ty;
3405 const payload = p: {3412 const payload = p: {
3406 if (!field_ty.hasRuntimeBitsIgnoreComptime()) {3413 if (!field_ty.hasRuntimeBitsIgnoreComptime()) {
...@@ -3408,6 +3415,7 @@ pub const DeclGen = struct {...@@ -3408,6 +3415,7 @@ pub const DeclGen = struct {
3408 break :p dg.context.intType(8).arrayType(padding_len).getUndef();3415 break :p dg.context.intType(8).arrayType(padding_len).getUndef();
3409 }3416 }
3410 const field = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val });3417 const field = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val });
3418 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field);
3411 const field_size = field_ty.abiSize(target);3419 const field_size = field_ty.abiSize(target);
3412 if (field_size == layout.payload_size) {3420 if (field_size == layout.payload_size) {
3413 break :p field;3421 break :p field;
...@@ -3419,12 +3427,6 @@ pub const DeclGen = struct {...@@ -3419,12 +3427,6 @@ pub const DeclGen = struct {
3419 break :p dg.context.constStruct(&fields, fields.len, .True);3427 break :p dg.context.constStruct(&fields, fields.len, .True);
3420 };3428 };
34213429
3422 // In this case we must make an unnamed struct because LLVM does
3423 // not support bitcasting our payload struct to the true union payload type.
3424 // Instead we use an unnamed struct and every reference to the global
3425 // must pointer cast to the expected type before accessing the union.
3426 const need_unnamed = layout.most_aligned_field != field_index;
3427
3428 if (layout.tag_size == 0) {3430 if (layout.tag_size == 0) {
3429 const fields: [1]*const llvm.Value = .{payload};3431 const fields: [1]*const llvm.Value = .{payload};
3430 if (need_unnamed) {3432 if (need_unnamed) {