| ... | @@ -3013,6 +3013,13 @@ pub const DeclGen = struct { | ... | @@ -3013,6 +3013,13 @@ pub const DeclGen = struct { |
| 3013 | const layout = t.unionGetLayout(target); | 3013 | const layout = t.unionGetLayout(target); |
| 3014 | const union_obj = t.cast(Type.Payload.Union).?.data; | 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 | if (layout.payload_size == 0) { | 3023 | if (layout.payload_size == 0) { |
| 3017 | const enum_tag_llvm_ty = try dg.lowerType(union_obj.tag_ty); | 3024 | const enum_tag_llvm_ty = try dg.lowerType(union_obj.tag_ty); |
| 3018 | gop.value_ptr.* = enum_tag_llvm_ty; | 3025 | gop.value_ptr.* = enum_tag_llvm_ty; |
| ... | @@ -3762,13 +3769,23 @@ pub const DeclGen = struct { | ... | @@ -3762,13 +3769,23 @@ pub const DeclGen = struct { |
| 3762 | const field_index = tv.ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?; | 3769 | const field_index = tv.ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?; |
| 3763 | assert(union_obj.haveFieldTypes()); | 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 | // Sometimes we must make an unnamed struct because LLVM does | 3784 | // Sometimes we must make an unnamed struct because LLVM does |
| 3766 | // not support bitcasting our payload struct to the true union payload type. | 3785 | // not support bitcasting our payload struct to the true union payload type. |
| 3767 | // Instead we use an unnamed struct and every reference to the global | 3786 | // Instead we use an unnamed struct and every reference to the global |
| 3768 | // must pointer cast to the expected type before accessing the union. | 3787 | // must pointer cast to the expected type before accessing the union. |
| 3769 | var need_unnamed: bool = layout.most_aligned_field != field_index; | 3788 | var need_unnamed: bool = layout.most_aligned_field != field_index; |
| 3770 | | | |
| 3771 | const field_ty = union_obj.fields.values()[field_index].ty; | | |
| 3772 | const payload = p: { | 3789 | const payload = p: { |
| 3773 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) { | 3790 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3774 | const padding_len = @intCast(c_uint, layout.payload_size); | 3791 | const padding_len = @intCast(c_uint, layout.payload_size); |
| ... | @@ -3959,6 +3976,9 @@ pub const DeclGen = struct { | ... | @@ -3959,6 +3976,9 @@ pub const DeclGen = struct { |
| 3959 | switch (parent_ty.zigTypeTag()) { | 3976 | switch (parent_ty.zigTypeTag()) { |
| 3960 | .Union => { | 3977 | .Union => { |
| 3961 | bitcast_needed = true; | 3978 | bitcast_needed = true; |
| | 3979 | if (parent_ty.containerLayout() == .Packed) { |
| | 3980 | break :blk parent_llvm_ptr; |
| | 3981 | } |
| 3962 | | 3982 | |
| 3963 | const layout = parent_ty.unionGetLayout(target); | 3983 | const layout = parent_ty.unionGetLayout(target); |
| 3964 | if (layout.payload_size == 0) { | 3984 | if (layout.payload_size == 0) { |
| ... | @@ -5768,7 +5788,21 @@ pub const FuncGen = struct { | ... | @@ -5768,7 +5788,21 @@ pub const FuncGen = struct { |
| 5768 | }, | 5788 | }, |
| 5769 | }, | 5789 | }, |
| 5770 | .Union => { | 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 | else => unreachable, | 5807 | else => unreachable, |
| 5774 | } | 5808 | } |
| ... | @@ -9510,6 +9544,9 @@ pub const FuncGen = struct { | ... | @@ -9510,6 +9544,9 @@ pub const FuncGen = struct { |
| 9510 | if (layout.payload_size == 0) { | 9544 | if (layout.payload_size == 0) { |
| 9511 | return self.builder.buildBitCast(union_ptr, result_llvm_ty, ""); | 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 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); | 9550 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 9514 | const union_llvm_ty = try self.dg.lowerType(union_ty); | 9551 | const union_llvm_ty = try self.dg.lowerType(union_ty); |
| 9515 | const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, union_ptr, payload_index, ""); | 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,7 +10704,10 @@ fn isByRef(ty: Type) bool { |
| 10667 | } | 10704 | } |
| 10668 | return false; | 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 | .ErrorUnion => { | 10711 | .ErrorUnion => { |
| 10672 | const payload_ty = ty.errorUnionPayload(); | 10712 | const payload_ty = ty.errorUnionPayload(); |
| 10673 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | 10713 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |