authorgravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-07-12 13:06:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-12 21:34:20-04:00
log2eaef84ebe968224b0cf25206abf12ea1c5e0f5a
treee1fe357fb3dac1e21fd90c143d2ecc5396d3c470
parent7090f0471c0169c60a9476b537b09eebe1bdf6af

stage2 llvm: Use unpacked struct for unions and arrays

Our lowerings for various LLVM types assume that we can anticipate the alignment/layout that LLVM will generate. Among other things, this requires that we keep the alignment of our lowered LLVM types synchronized with their expected alignment in Zig. - Arrays were using packed struct types, which is seems to be incorrect since array elements are supposed to be self-aligned. - Unions were using packed struct types for their payload, which causes layout divergence between what stage2 expects and what LLVM generates Consider this lowered union type: ```llvm %Value = type { <{ i64, [8 x i8] }>, i1, [7 x i8] } ; 24 bytes, align(1) %ErrorUnion = type { %Value, i16 } ; 26 bytes, align(2) ``` Zig expects Value to be align(8) and, by extension, for ErrorUnion to be size 32.

1 files changed, 5 insertions(+), 5 deletions(-)

src/codegen/llvm.zig+5-5
...@@ -2689,7 +2689,7 @@ pub const DeclGen = struct {...@@ -2689,7 +2689,7 @@ pub const DeclGen = struct {
2689 llvm_aligned_field_ty,2689 llvm_aligned_field_ty,
2690 dg.context.intType(8).arrayType(padding_len),2690 dg.context.intType(8).arrayType(padding_len),
2691 };2691 };
2692 break :t dg.context.structType(&fields, fields.len, .True);2692 break :t dg.context.structType(&fields, fields.len, .False);
2693 };2693 };
26942694
2695 if (layout.tag_size == 0) {2695 if (layout.tag_size == 0) {
...@@ -3002,7 +3002,7 @@ pub const DeclGen = struct {...@@ -3002,7 +3002,7 @@ pub const DeclGen = struct {
3002 return dg.context.constStruct(3002 return dg.context.constStruct(
3003 llvm_elems.ptr,3003 llvm_elems.ptr,
3004 @intCast(c_uint, llvm_elems.len),3004 @intCast(c_uint, llvm_elems.len),
3005 .True,3005 .False,
3006 );3006 );
3007 } else {3007 } else {
3008 const llvm_elem_ty = try dg.lowerType(elem_ty);3008 const llvm_elem_ty = try dg.lowerType(elem_ty);
...@@ -3039,7 +3039,7 @@ pub const DeclGen = struct {...@@ -3039,7 +3039,7 @@ pub const DeclGen = struct {
3039 return dg.context.constStruct(3039 return dg.context.constStruct(
3040 llvm_elems.ptr,3040 llvm_elems.ptr,
3041 @intCast(c_uint, llvm_elems.len),3041 @intCast(c_uint, llvm_elems.len),
3042 .True,3042 .False,
3043 );3043 );
3044 } else {3044 } else {
3045 const llvm_elem_ty = try dg.lowerType(elem_ty);3045 const llvm_elem_ty = try dg.lowerType(elem_ty);
...@@ -3056,7 +3056,7 @@ pub const DeclGen = struct {...@@ -3056,7 +3056,7 @@ pub const DeclGen = struct {
3056 const llvm_elems: [1]*const llvm.Value = .{sentinel};3056 const llvm_elems: [1]*const llvm.Value = .{sentinel};
3057 const need_unnamed = dg.isUnnamedType(elem_ty, llvm_elems[0]);3057 const need_unnamed = dg.isUnnamedType(elem_ty, llvm_elems[0]);
3058 if (need_unnamed) {3058 if (need_unnamed) {
3059 return dg.context.constStruct(&llvm_elems, llvm_elems.len, .True);3059 return dg.context.constStruct(&llvm_elems, llvm_elems.len, .False);
3060 } else {3060 } else {
3061 const llvm_elem_ty = try dg.lowerType(elem_ty);3061 const llvm_elem_ty = try dg.lowerType(elem_ty);
3062 return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);3062 return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);
...@@ -3343,7 +3343,7 @@ pub const DeclGen = struct {...@@ -3343,7 +3343,7 @@ pub const DeclGen = struct {
3343 const fields: [2]*const llvm.Value = .{3343 const fields: [2]*const llvm.Value = .{
3344 field, dg.context.intType(8).arrayType(padding_len).getUndef(),3344 field, dg.context.intType(8).arrayType(padding_len).getUndef(),
3345 };3345 };
3346 break :p dg.context.constStruct(&fields, fields.len, .True);3346 break :p dg.context.constStruct(&fields, fields.len, .False);
3347 };3347 };
33483348
3349 if (layout.tag_size == 0) {3349 if (layout.tag_size == 0) {