| ... | ... | @@ -3013,6 +3013,13 @@ pub const DeclGen = struct { |
| 3013 | 3013 | const layout = t.unionGetLayout(target); |
| 3014 | 3014 | const union_obj = t.cast(Type.Payload.Union).?.data; |
| 3015 | 3015 | |
| 3016 | if (union_obj.layout == .Packed) { |
| 3017 | const bitsize = @intCast(c_uint, t.bitSize(target)); |
| 3018 | const int_llvm_ty = dg.context.intType(bitsize); |
| 3019 | gop.value_ptr.* = int_llvm_ty; |
| 3020 | return int_llvm_ty; |
| 3021 | } |
| 3022 | |
| 3016 | 3023 | if (layout.payload_size == 0) { |
| 3017 | 3024 | const enum_tag_llvm_ty = try dg.lowerType(union_obj.tag_ty); |
| 3018 | 3025 | gop.value_ptr.* = enum_tag_llvm_ty; |
| ... | ... | @@ -3762,13 +3769,23 @@ pub const DeclGen = struct { |
| 3762 | 3769 | const field_index = tv.ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?; |
| 3763 | 3770 | assert(union_obj.haveFieldTypes()); |
| 3764 | 3771 | |
| 3772 | const field_ty = union_obj.fields.values()[field_index].ty; |
| 3773 | if (union_obj.layout == .Packed) { |
| 3774 | const non_int_val = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val }); |
| 3775 | const ty_bit_size = @intCast(u16, field_ty.bitSize(target)); |
| 3776 | const small_int_ty = dg.context.intType(ty_bit_size); |
| 3777 | const small_int_val = if (field_ty.isPtrAtRuntime()) |
| 3778 | non_int_val.constPtrToInt(small_int_ty) |
| 3779 | else |
| 3780 | non_int_val.constBitCast(small_int_ty); |
| 3781 | return small_int_val.constZExtOrBitCast(llvm_union_ty); |
| 3782 | } |
| 3783 | |
| 3765 | 3784 | // Sometimes we must make an unnamed struct because LLVM does |
| 3766 | 3785 | // not support bitcasting our payload struct to the true union payload type. |
| 3767 | 3786 | // Instead we use an unnamed struct and every reference to the global |
| 3768 | 3787 | // must pointer cast to the expected type before accessing the union. |
| 3769 | 3788 | var need_unnamed: bool = layout.most_aligned_field != field_index; |
| 3770 | | |
| 3771 | | const field_ty = union_obj.fields.values()[field_index].ty; |
| 3772 | 3789 | const payload = p: { |
| 3773 | 3790 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3774 | 3791 | const padding_len = @intCast(c_uint, layout.payload_size); |
| ... | ... | @@ -3959,6 +3976,9 @@ pub const DeclGen = struct { |
| 3959 | 3976 | switch (parent_ty.zigTypeTag()) { |
| 3960 | 3977 | .Union => { |
| 3961 | 3978 | bitcast_needed = true; |
| 3979 | if (parent_ty.containerLayout() == .Packed) { |
| 3980 | break :blk parent_llvm_ptr; |
| 3981 | } |
| 3962 | 3982 | |
| 3963 | 3983 | const layout = parent_ty.unionGetLayout(target); |
| 3964 | 3984 | if (layout.payload_size == 0) { |
| ... | ... | @@ -5768,7 +5788,21 @@ pub const FuncGen = struct { |
| 5768 | 5788 | }, |
| 5769 | 5789 | }, |
| 5770 | 5790 | .Union => { |
| 5771 | | return self.todo("airStructFieldVal byval union", .{}); |
| 5791 | assert(struct_ty.containerLayout() == .Packed); |
| 5792 | const containing_int = struct_llvm_val; |
| 5793 | const elem_llvm_ty = try self.dg.lowerType(field_ty); |
| 5794 | if (field_ty.zigTypeTag() == .Float) { |
| 5795 | const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); |
| 5796 | const same_size_int = self.context.intType(elem_bits); |
| 5797 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); |
| 5798 | return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); |
| 5799 | } else if (field_ty.isPtrAtRuntime()) { |
| 5800 | const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); |
| 5801 | const same_size_int = self.context.intType(elem_bits); |
| 5802 | const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, ""); |
| 5803 | return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); |
| 5804 | } |
| 5805 | return self.builder.buildTrunc(containing_int, elem_llvm_ty, ""); |
| 5772 | 5806 | }, |
| 5773 | 5807 | else => unreachable, |
| 5774 | 5808 | } |
| ... | ... | @@ -9510,6 +9544,9 @@ pub const FuncGen = struct { |
| 9510 | 9544 | if (layout.payload_size == 0) { |
| 9511 | 9545 | return self.builder.buildBitCast(union_ptr, result_llvm_ty, ""); |
| 9512 | 9546 | } |
| 9547 | if (union_ty.containerLayout() == .Packed) { |
| 9548 | return self.builder.buildBitCast(union_ptr, result_llvm_ty, ""); |
| 9549 | } |
| 9513 | 9550 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 9514 | 9551 | const union_llvm_ty = try self.dg.lowerType(union_ty); |
| 9515 | 9552 | const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, union_ptr, payload_index, ""); |
| ... | ... | @@ -10667,7 +10704,10 @@ fn isByRef(ty: Type) bool { |
| 10667 | 10704 | } |
| 10668 | 10705 | return false; |
| 10669 | 10706 | }, |
| 10670 | | .Union => return ty.hasRuntimeBits(), |
| 10707 | .Union => switch (ty.containerLayout()) { |
| 10708 | .Packed => return false, |
| 10709 | else => return ty.hasRuntimeBits(), |
| 10710 | }, |
| 10671 | 10711 | .ErrorUnion => { |
| 10672 | 10712 | const payload_ty = ty.errorUnionPayload(); |
| 10673 | 10713 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |