authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-24 02:14:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-27 00:14:56-04:00
logf1072d0d9fba397b3920015fd854414868e6ea17
treea13926e0dff5a5e9a69ec90e5d64d4ea60b2a10a
parent66636381957f214f1acc22dcea01cb4cd1032649

use llvm named structs for const values when possible

normally we want to use llvm types for constants. but union constants (which are found inside enums) when they are initialized with the non-most-aligned-member must be unnamed structs. these bubble up to all aggregate types. if a constant of an aggregate type contains, recursively, a union constant with a non-most-aligned-member initialized, the aggregate typed constant must be unnamed too. this fixes some of the asserts that were coming in from llvm master branch.

3 files changed, 75 insertions(+), 20 deletions(-)

src/all_types.hpp+3
...@@ -1008,6 +1008,9 @@ struct TypeTableEntryEnum {...@@ -1008,6 +1008,9 @@ struct TypeTableEntryEnum {
10081008
1009 size_t gen_union_index;1009 size_t gen_union_index;
1010 size_t gen_tag_index;1010 size_t gen_tag_index;
1011
1012 uint32_t union_size_bytes;
1013 TypeTableEntry *most_aligned_union_member;
1011};1014};
10121015
1013struct TypeTableEntryEnumTag {1016struct TypeTableEntryEnumTag {
src/analyze.cpp+3-4
...@@ -1363,6 +1363,8 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {...@@ -1363,6 +1363,8 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1363 // unset temporary flag1363 // unset temporary flag
1364 enum_type->data.enumeration.embedded_in_current = false;1364 enum_type->data.enumeration.embedded_in_current = false;
1365 enum_type->data.enumeration.complete = true;1365 enum_type->data.enumeration.complete = true;
1366 enum_type->data.enumeration.union_size_bytes = biggest_size_in_bits / 8;
1367 enum_type->data.enumeration.most_aligned_union_member = most_aligned_union_member;
13661368
1367 if (!enum_type->data.enumeration.is_invalid) {1369 if (!enum_type->data.enumeration.is_invalid) {
1368 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count);1370 TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count);
...@@ -1384,10 +1386,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {...@@ -1384,10 +1386,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
1384 };1386 };
1385 union_type_ref = LLVMStructType(union_element_types, 2, false);1387 union_type_ref = LLVMStructType(union_element_types, 2, false);
1386 } else {1388 } else {
1387 LLVMTypeRef union_element_types[] = {1389 union_type_ref = most_aligned_union_member->type_ref;
1388 most_aligned_union_member->type_ref,
1389 };
1390 union_type_ref = LLVMStructType(union_element_types, 1, false);
1391 }1390 }
1392 enum_type->data.enumeration.union_type_ref = union_type_ref;1391 enum_type->data.enumeration.union_type_ref = union_type_ref;
13931392
src/codegen.cpp+69-16
...@@ -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}
36673667
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
3670static bool is_llvm_value_unnamed_type(TypeTableEntry *type_entry, LLVMValueRef val) {
3671 return LLVMTypeOf(val) != type_entry->type_ref;
3672}
3673
3668static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {3674static 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 }
37623778
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 }
38093834
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;
38343874
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: