authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-09-07 11:17:12+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-10 10:07:32-04:00
log8fbae77770a77ccd645054e06baab45b03c8befd
tree274683fbf2812e735de6cc7228430f2f50d4ad12
parenta06f84fcc62396dc4216d5c9f8da1f0463d17f50
signaturelock-open Commit is signed but in an unrecognized format.

Force LLVM to generate byte-aligned packed unions

Sometimes the frontend and LLVM would disagree on the ABI alignment of a packed union. Solve the problem by telling LLVM we're gonna manage the struct layout by ourselves. Closes #3184

2 files changed, 17 insertions(+), 3 deletions(-)

src/analyze.cpp+5-3
...@@ -7905,6 +7905,8 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu...@@ -7905,6 +7905,8 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu
7905static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveStatus wanted_resolve_status) {7905static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveStatus wanted_resolve_status) {
7906 if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return;7906 if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return;
79077907
7908 bool packed = (union_type->data.unionation.layout == ContainerLayoutPacked);
7909
7908 TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;7910 TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;
7909 ZigType *tag_type = union_type->data.unionation.tag_type;7911 ZigType *tag_type = union_type->data.unionation.tag_type;
7910 uint32_t gen_field_count = union_type->data.unionation.gen_field_count;7912 uint32_t gen_field_count = union_type->data.unionation.gen_field_count;
...@@ -7971,9 +7973,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -7971,9 +7973,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
7971 most_aligned_union_member->type_entry->llvm_type,7973 most_aligned_union_member->type_entry->llvm_type,
7972 get_llvm_type(g, padding_array),7974 get_llvm_type(g, padding_array),
7973 };7975 };
7974 LLVMStructSetBody(union_type->llvm_type, union_element_types, 2, false);7976 LLVMStructSetBody(union_type->llvm_type, union_element_types, 2, packed);
7975 } else {7977 } else {
7976 LLVMStructSetBody(union_type->llvm_type, &most_aligned_union_member->type_entry->llvm_type, 1, false);7978 LLVMStructSetBody(union_type->llvm_type, &most_aligned_union_member->type_entry->llvm_type, 1, packed);
7977 }7979 }
7978 union_type->data.unionation.union_llvm_type = union_type->llvm_type;7980 union_type->data.unionation.union_llvm_type = union_type->llvm_type;
7979 union_type->data.unionation.gen_tag_index = SIZE_MAX;7981 union_type->data.unionation.gen_tag_index = SIZE_MAX;
...@@ -8012,7 +8014,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -8012,7 +8014,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
8012 LLVMTypeRef root_struct_element_types[2];8014 LLVMTypeRef root_struct_element_types[2];
8013 root_struct_element_types[union_type->data.unionation.gen_tag_index] = get_llvm_type(g, tag_type);8015 root_struct_element_types[union_type->data.unionation.gen_tag_index] = get_llvm_type(g, tag_type);
8014 root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref;8016 root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref;
8015 LLVMStructSetBody(union_type->llvm_type, root_struct_element_types, 2, false);8017 LLVMStructSetBody(union_type->llvm_type, root_struct_element_types, 2, packed);
80168018
8017 // create debug type for union8019 // create debug type for union
8018 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,8020 ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
test/stage1/behavior/union.zig+12
...@@ -482,3 +482,15 @@ test "comparison between union and enum literal" {...@@ -482,3 +482,15 @@ test "comparison between union and enum literal" {
482 testComparison();482 testComparison();
483 comptime testComparison();483 comptime testComparison();
484}484}
485
486test "packed union generates correctly aligned LLVM type" {
487 const U = packed union {
488 f1: fn () void,
489 f2: u32,
490 };
491 var foo = [_]U{
492 U{ .f1 = doTest },
493 U{ .f2 = 0 },
494 };
495 foo[0].f1();
496}