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 {
10081008
10091009 size_t gen_union_index;
10101010 size_t gen_tag_index;
1011
1012 uint32_t union_size_bytes;
1013 TypeTableEntry *most_aligned_union_member;
10111014};
10121015
10131016struct TypeTableEntryEnumTag {
src/analyze.cpp+3-4
......@@ -1363,6 +1363,8 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
13631363 // unset temporary flag
13641364 enum_type->data.enumeration.embedded_in_current = false;
13651365 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
13671369 if (!enum_type->data.enumeration.is_invalid) {
13681370 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) {
13841386 };
13851387 union_type_ref = LLVMStructType(union_element_types, 2, false);
13861388 } else {
1387 LLVMTypeRef union_element_types[] = {
1388 most_aligned_union_member->type_ref,
1389 };
1390 union_type_ref = LLVMStructType(union_element_types, 1, false);
1389 union_type_ref = most_aligned_union_member->type_ref;
13911390 }
13921391 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
36653665 zig_unreachable();
36663666}
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
36683674static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
36693675 TypeTableEntry *type_entry = const_val->type;
36703676 assert(!type_entry->zero_bits);
......@@ -3726,24 +3732,34 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
37263732 } else {
37273733 LLVMValueRef child_val;
37283734 LLVMValueRef maybe_val;
3735 bool make_unnamed_struct;
37293736 if (const_val->data.x_maybe) {
37303737 child_val = gen_const_val(g, const_val->data.x_maybe);
37313738 maybe_val = LLVMConstAllOnes(LLVMInt1Type());
3739
3740 make_unnamed_struct = is_llvm_value_unnamed_type(const_val->type, child_val);
37323741 } else {
3733 child_val = LLVMConstNull(child_type->type_ref);
3742 child_val = LLVMGetUndef(child_type->type_ref);
37343743 maybe_val = LLVMConstNull(LLVMInt1Type());
3744
3745 make_unnamed_struct = false;
37353746 }
37363747 LLVMValueRef fields[] = {
37373748 child_val,
37383749 maybe_val,
37393750 };
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 }
37413756 }
37423757 }
37433758 case TypeTableEntryIdStruct:
37443759 {
37453760 LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count);
37463761 size_t src_field_count = type_entry->data.structure.src_field_count;
3762 bool make_unnamed_struct = false;
37473763 if (type_entry->data.structure.layout == ContainerLayoutPacked) {
37483764 size_t src_field_index = 0;
37493765 while (src_field_index < src_field_count) {
......@@ -3761,8 +3777,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
37613777 }
37623778
37633779 if (src_field_index + 1 == src_field_index_end) {
3764 fields[type_struct_field->gen_index] =
3765 gen_const_val(g, &const_val->data.x_struct.fields[src_field_index]);
3780 ConstExprValue *field_val = &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);
37663784 } else {
37673785 LLVMTypeRef big_int_type_ref = LLVMStructGetTypeAtIndex(type_entry->type_ref,
37683786 (unsigned)type_struct_field->gen_index);
......@@ -3790,11 +3808,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
37903808 if (type_struct_field->gen_index == SIZE_MAX) {
37913809 continue;
37923810 }
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);
37943815 }
37953816 }
3796 return LLVMConstStruct(fields, type_entry->data.structure.gen_field_count,
3797 type_entry->data.structure.layout == ContainerLayoutPacked);
3817 if (make_unnamed_struct) {
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 }
37983823 }
37993824 case TypeTableEntryIdUnion:
38003825 {
......@@ -3808,11 +3833,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
38083833 }
38093834
38103835 LLVMValueRef *values = allocate<LLVMValueRef>(len);
3836 LLVMTypeRef element_type_ref = type_entry->data.array.child_type->type_ref;
3837 bool make_unnamed_struct = false;
38113838 for (uint64_t i = 0; i < len; i += 1) {
38123839 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);
38143848 }
3815 return LLVMConstArray(LLVMTypeOf(values[0]), values, (unsigned)len);
38163849 }
38173850 case TypeTableEntryIdEnum:
38183851 {
......@@ -3825,14 +3858,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
38253858 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag];
38263859 assert(enum_field->value == const_val->data.x_enum.tag);
38273860 LLVMValueRef union_value;
3861
3862 bool make_unnamed_struct;
3863
38283864 if (type_has_bits(enum_field->type_entry)) {
3829 uint64_t union_type_bytes = LLVMStoreSizeOfType(g->target_data_ref,
3830 union_type_ref);
38313865 uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref,
38323866 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);
38363875 if (pad_bytes == 0) {
38373876 union_value = correctly_typed_value;
38383877 } else {
......@@ -3843,12 +3882,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
38433882 union_value = LLVMConstStruct(fields, 2, false);
38443883 }
38453884 } else {
3885 make_unnamed_struct = false;
38463886 union_value = LLVMGetUndef(union_type_ref);
38473887 }
38483888 LLVMValueRef fields[2];
38493889 fields[type_entry->data.enumeration.gen_tag_index] = tag_value;
38503890 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 }
38523897 }
38533898 }
38543899 case TypeTableEntryIdFn:
......@@ -3932,18 +3977,26 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
39323977 } else {
39333978 LLVMValueRef err_tag_value;
39343979 LLVMValueRef err_payload_value;
3980 bool make_unnamed_struct;
39353981 if (const_val->data.x_err_union.err) {
39363982 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);
39373983 err_payload_value = LLVMConstNull(child_type->type_ref);
3984 make_unnamed_struct = false;
39383985 } else {
39393986 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);
39413990 }
39423991 LLVMValueRef fields[] = {
39433992 err_tag_value,
39443993 err_payload_value,
39453994 };
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 }
39474000 }
39484001 }
39494002 case TypeTableEntryIdVoid: