| ... | @@ -3665,6 +3665,12 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con | ... | @@ -3665,6 +3665,12 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 3665 | zig_unreachable(); | 3665 | zig_unreachable(); |
| 3666 | } | 3666 | } |
| 3667 | | 3667 | |
| | 3668 | // We have this because union constants can't be represented by the official union type, |
| | 3669 | // and this property bubbles up in whatever aggregate type contains a union constant |
| | 3670 | static bool is_llvm_value_unnamed_type(TypeTableEntry *type_entry, LLVMValueRef val) { |
| | 3671 | return LLVMTypeOf(val) != type_entry->type_ref; |
| | 3672 | } |
| | 3673 | |
| 3668 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | 3674 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 3669 | TypeTableEntry *type_entry = const_val->type; | 3675 | TypeTableEntry *type_entry = const_val->type; |
| 3670 | assert(!type_entry->zero_bits); | 3676 | assert(!type_entry->zero_bits); |
| ... | @@ -3726,24 +3732,34 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -3726,24 +3732,34 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 3726 | } else { | 3732 | } else { |
| 3727 | LLVMValueRef child_val; | 3733 | LLVMValueRef child_val; |
| 3728 | LLVMValueRef maybe_val; | 3734 | LLVMValueRef maybe_val; |
| | 3735 | bool make_unnamed_struct; |
| 3729 | if (const_val->data.x_maybe) { | 3736 | if (const_val->data.x_maybe) { |
| 3730 | child_val = gen_const_val(g, const_val->data.x_maybe); | 3737 | child_val = gen_const_val(g, const_val->data.x_maybe); |
| 3731 | maybe_val = LLVMConstAllOnes(LLVMInt1Type()); | 3738 | maybe_val = LLVMConstAllOnes(LLVMInt1Type()); |
| | 3739 | |
| | 3740 | make_unnamed_struct = is_llvm_value_unnamed_type(const_val->type, child_val); |
| 3732 | } else { | 3741 | } else { |
| 3733 | child_val = LLVMConstNull(child_type->type_ref); | 3742 | child_val = LLVMGetUndef(child_type->type_ref); |
| 3734 | maybe_val = LLVMConstNull(LLVMInt1Type()); | 3743 | maybe_val = LLVMConstNull(LLVMInt1Type()); |
| | 3744 | |
| | 3745 | make_unnamed_struct = false; |
| 3735 | } | 3746 | } |
| 3736 | LLVMValueRef fields[] = { | 3747 | LLVMValueRef fields[] = { |
| 3737 | child_val, | 3748 | child_val, |
| 3738 | maybe_val, | 3749 | maybe_val, |
| 3739 | }; | 3750 | }; |
| 3740 | return LLVMConstStruct(fields, 2, false); | 3751 | if (make_unnamed_struct) { |
| | 3752 | return LLVMConstStruct(fields, 2, false); |
| | 3753 | } else { |
| | 3754 | return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); |
| | 3755 | } |
| 3741 | } | 3756 | } |
| 3742 | } | 3757 | } |
| 3743 | case TypeTableEntryIdStruct: | 3758 | case TypeTableEntryIdStruct: |
| 3744 | { | 3759 | { |
| 3745 | LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count); | 3760 | LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count); |
| 3746 | size_t src_field_count = type_entry->data.structure.src_field_count; | 3761 | size_t src_field_count = type_entry->data.structure.src_field_count; |
| | 3762 | bool make_unnamed_struct = false; |
| 3747 | if (type_entry->data.structure.layout == ContainerLayoutPacked) { | 3763 | if (type_entry->data.structure.layout == ContainerLayoutPacked) { |
| 3748 | size_t src_field_index = 0; | 3764 | size_t src_field_index = 0; |
| 3749 | while (src_field_index < src_field_count) { | 3765 | while (src_field_index < src_field_count) { |
| ... | @@ -3761,8 +3777,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -3761,8 +3777,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 3761 | } | 3777 | } |
| 3762 | | 3778 | |
| 3763 | if (src_field_index + 1 == src_field_index_end) { | 3779 | if (src_field_index + 1 == src_field_index_end) { |
| 3764 | fields[type_struct_field->gen_index] = | 3780 | ConstExprValue *field_val = &const_val->data.x_struct.fields[src_field_index]; |
| 3765 | gen_const_val(g, &const_val->data.x_struct.fields[src_field_index]); | 3781 | LLVMValueRef val = gen_const_val(g, field_val); |
| | 3782 | fields[type_struct_field->gen_index] = val; |
| | 3783 | make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val); |
| 3766 | } else { | 3784 | } else { |
| 3767 | LLVMTypeRef big_int_type_ref = LLVMStructGetTypeAtIndex(type_entry->type_ref, | 3785 | LLVMTypeRef big_int_type_ref = LLVMStructGetTypeAtIndex(type_entry->type_ref, |
| 3768 | (unsigned)type_struct_field->gen_index); | 3786 | (unsigned)type_struct_field->gen_index); |
| ... | @@ -3790,11 +3808,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -3790,11 +3808,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 3790 | if (type_struct_field->gen_index == SIZE_MAX) { | 3808 | if (type_struct_field->gen_index == SIZE_MAX) { |
| 3791 | continue; | 3809 | continue; |
| 3792 | } | 3810 | } |
| 3793 | fields[type_struct_field->gen_index] = gen_const_val(g, &const_val->data.x_struct.fields[i]); | 3811 | ConstExprValue *field_val = &const_val->data.x_struct.fields[i]; |
| | 3812 | LLVMValueRef val = gen_const_val(g, field_val); |
| | 3813 | fields[type_struct_field->gen_index] = val; |
| | 3814 | make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val); |
| 3794 | } | 3815 | } |
| 3795 | } | 3816 | } |
| 3796 | return LLVMConstStruct(fields, type_entry->data.structure.gen_field_count, | 3817 | if (make_unnamed_struct) { |
| 3797 | type_entry->data.structure.layout == ContainerLayoutPacked); | 3818 | return LLVMConstStruct(fields, type_entry->data.structure.gen_field_count, |
| | 3819 | type_entry->data.structure.layout == ContainerLayoutPacked); |
| | 3820 | } else { |
| | 3821 | return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count); |
| | 3822 | } |
| 3798 | } | 3823 | } |
| 3799 | case TypeTableEntryIdUnion: | 3824 | case TypeTableEntryIdUnion: |
| 3800 | { | 3825 | { |
| ... | @@ -3808,11 +3833,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -3808,11 +3833,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 3808 | } | 3833 | } |
| 3809 | | 3834 | |
| 3810 | LLVMValueRef *values = allocate<LLVMValueRef>(len); | 3835 | LLVMValueRef *values = allocate<LLVMValueRef>(len); |
| | 3836 | LLVMTypeRef element_type_ref = type_entry->data.array.child_type->type_ref; |
| | 3837 | bool make_unnamed_struct = false; |
| 3811 | for (uint64_t i = 0; i < len; i += 1) { | 3838 | for (uint64_t i = 0; i < len; i += 1) { |
| 3812 | ConstExprValue *elem_value = &const_val->data.x_array.s_none.elements[i]; | 3839 | ConstExprValue *elem_value = &const_val->data.x_array.s_none.elements[i]; |
| 3813 | values[i] = gen_const_val(g, elem_value); | 3840 | LLVMValueRef val = gen_const_val(g, elem_value); |
| | 3841 | values[i] = val; |
| | 3842 | make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(elem_value->type, val); |
| | 3843 | } |
| | 3844 | if (make_unnamed_struct) { |
| | 3845 | return LLVMConstStruct(values, len, true); |
| | 3846 | } else { |
| | 3847 | return LLVMConstArray(element_type_ref, values, (unsigned)len); |
| 3814 | } | 3848 | } |
| 3815 | return LLVMConstArray(LLVMTypeOf(values[0]), values, (unsigned)len); | | |
| 3816 | } | 3849 | } |
| 3817 | case TypeTableEntryIdEnum: | 3850 | case TypeTableEntryIdEnum: |
| 3818 | { | 3851 | { |
| ... | @@ -3825,14 +3858,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -3825,14 +3858,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 3825 | TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag]; | 3858 | TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag]; |
| 3826 | assert(enum_field->value == const_val->data.x_enum.tag); | 3859 | assert(enum_field->value == const_val->data.x_enum.tag); |
| 3827 | LLVMValueRef union_value; | 3860 | LLVMValueRef union_value; |
| | 3861 | |
| | 3862 | bool make_unnamed_struct; |
| | 3863 | |
| 3828 | if (type_has_bits(enum_field->type_entry)) { | 3864 | if (type_has_bits(enum_field->type_entry)) { |
| 3829 | uint64_t union_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, | | |
| 3830 | union_type_ref); | | |
| 3831 | uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, | 3865 | uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, |
| 3832 | enum_field->type_entry->type_ref); | 3866 | enum_field->type_entry->type_ref); |
| 3833 | uint64_t pad_bytes = union_type_bytes - field_type_bytes; | 3867 | uint64_t pad_bytes = type_entry->data.enumeration.union_size_bytes - field_type_bytes; |
| | 3868 | |
| | 3869 | ConstExprValue *payload_value = const_val->data.x_enum.payload; |
| | 3870 | LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value); |
| | 3871 | |
| | 3872 | make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) || |
| | 3873 | payload_value->type != type_entry->data.enumeration.most_aligned_union_member; |
| 3834 | | 3874 | |
| 3835 | LLVMValueRef correctly_typed_value = gen_const_val(g, const_val->data.x_enum.payload); | | |
| 3836 | if (pad_bytes == 0) { | 3875 | if (pad_bytes == 0) { |
| 3837 | union_value = correctly_typed_value; | 3876 | union_value = correctly_typed_value; |
| 3838 | } else { | 3877 | } else { |
| ... | @@ -3843,12 +3882,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -3843,12 +3882,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 3843 | union_value = LLVMConstStruct(fields, 2, false); | 3882 | union_value = LLVMConstStruct(fields, 2, false); |
| 3844 | } | 3883 | } |
| 3845 | } else { | 3884 | } else { |
| | 3885 | make_unnamed_struct = false; |
| 3846 | union_value = LLVMGetUndef(union_type_ref); | 3886 | union_value = LLVMGetUndef(union_type_ref); |
| 3847 | } | 3887 | } |
| 3848 | LLVMValueRef fields[2]; | 3888 | LLVMValueRef fields[2]; |
| 3849 | fields[type_entry->data.enumeration.gen_tag_index] = tag_value; | 3889 | fields[type_entry->data.enumeration.gen_tag_index] = tag_value; |
| 3850 | fields[type_entry->data.enumeration.gen_union_index] = union_value; | 3890 | fields[type_entry->data.enumeration.gen_union_index] = union_value; |
| 3851 | return LLVMConstStruct(fields, 2, false); | 3891 | |
| | 3892 | if (make_unnamed_struct) { |
| | 3893 | return LLVMConstStruct(fields, 2, false); |
| | 3894 | } else { |
| | 3895 | return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); |
| | 3896 | } |
| 3852 | } | 3897 | } |
| 3853 | } | 3898 | } |
| 3854 | case TypeTableEntryIdFn: | 3899 | case TypeTableEntryIdFn: |
| ... | @@ -3932,18 +3977,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -3932,18 +3977,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 3932 | } else { | 3977 | } else { |
| 3933 | LLVMValueRef err_tag_value; | 3978 | LLVMValueRef err_tag_value; |
| 3934 | LLVMValueRef err_payload_value; | 3979 | LLVMValueRef err_payload_value; |
| | 3980 | bool make_unnamed_struct; |
| 3935 | if (const_val->data.x_err_union.err) { | 3981 | if (const_val->data.x_err_union.err) { |
| 3936 | err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false); | 3982 | err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false); |
| 3937 | err_payload_value = LLVMConstNull(child_type->type_ref); | 3983 | err_payload_value = LLVMConstNull(child_type->type_ref); |
| | 3984 | make_unnamed_struct = false; |
| 3938 | } else { | 3985 | } else { |
| 3939 | err_tag_value = LLVMConstNull(g->err_tag_type->type_ref); | 3986 | err_tag_value = LLVMConstNull(g->err_tag_type->type_ref); |
| 3940 | err_payload_value = gen_const_val(g, const_val->data.x_err_union.payload); | 3987 | ConstExprValue *payload_val = const_val->data.x_err_union.payload; |
| | 3988 | err_payload_value = gen_const_val(g, payload_val); |
| | 3989 | make_unnamed_struct = is_llvm_value_unnamed_type(payload_val->type, err_payload_value); |
| 3941 | } | 3990 | } |
| 3942 | LLVMValueRef fields[] = { | 3991 | LLVMValueRef fields[] = { |
| 3943 | err_tag_value, | 3992 | err_tag_value, |
| 3944 | err_payload_value, | 3993 | err_payload_value, |
| 3945 | }; | 3994 | }; |
| 3946 | return LLVMConstStruct(fields, 2, false); | 3995 | if (make_unnamed_struct) { |
| | 3996 | return LLVMConstStruct(fields, 2, false); |
| | 3997 | } else { |
| | 3998 | return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); |
| | 3999 | } |
| 3947 | } | 4000 | } |
| 3948 | } | 4001 | } |
| 3949 | case TypeTableEntryIdVoid: | 4002 | case TypeTableEntryIdVoid: |