authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-24 02:37:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-24 02:37:54-07:00
log6b8e33d14c92229b1632c481906d7d698c584000
tree5d752c74a0c84102a91a67ee799dbdd66b37ad0c
parent5b171f446f46c97de111bce0575452be0334a05e

stage2: LLVM: fix lowering of packed structs

* ensure enough capacity when building the LLVM type and value. * add explicit padding field and populate it to ensure proper alignment.

2 files changed, 47 insertions(+), 1 deletions(-)

src/codegen/llvm.zig+44-1
......@@ -845,9 +845,11 @@ pub const DeclGen = struct {
845845 defer llvm_field_types.deinit(gpa);
846846
847847 if (struct_obj.layout == .Packed) {
848 try llvm_field_types.ensureUnusedCapacity(gpa, struct_obj.fields.count() * 2);
848849 const target = dg.module.getTarget();
849850 comptime assert(Type.packed_struct_layout_version == 1);
850851 var offset: u64 = 0;
852 var big_align: u32 = 0;
851853 var running_bits: u16 = 0;
852854 for (struct_obj.fields.values()) |field| {
853855 if (!field.ty.hasCodeGenBits()) continue;
......@@ -863,6 +865,7 @@ pub const DeclGen = struct {
863865 };
864866 const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };
865867 const int_align = int_ty.abiAlignment(target);
868 big_align = @maximum(big_align, int_align);
866869 const llvm_int_ty = try dg.llvmType(int_ty);
867870 const prev_offset = offset;
868871 offset = std.mem.alignForwardGeneric(u64, offset, int_align);
......@@ -875,6 +878,7 @@ pub const DeclGen = struct {
875878 offset += int_ty.abiSize(target);
876879 running_bits = 0;
877880 }
881 big_align = @maximum(big_align, field_align);
878882 const prev_offset = offset;
879883 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
880884 const padding_bytes = @intCast(c_uint, offset - prev_offset);
......@@ -894,6 +898,7 @@ pub const DeclGen = struct {
894898 };
895899 const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };
896900 const int_align = int_ty.abiAlignment(target);
901 big_align = @maximum(big_align, int_align);
897902 const prev_offset = offset;
898903 offset = std.mem.alignForwardGeneric(u64, offset, int_align);
899904 const padding_bytes = @intCast(c_uint, offset - prev_offset);
......@@ -904,6 +909,14 @@ pub const DeclGen = struct {
904909 const llvm_int_ty = try dg.llvmType(int_ty);
905910 llvm_field_types.appendAssumeCapacity(llvm_int_ty);
906911 }
912
913 const prev_offset = offset;
914 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
915 const padding_bytes = @intCast(c_uint, offset - prev_offset);
916 if (padding_bytes != 0) {
917 const padding = dg.context.intType(8).arrayType(padding_bytes);
918 llvm_field_types.appendAssumeCapacity(padding);
919 }
907920 } else {
908921 for (struct_obj.fields.values()) |field| {
909922 if (!field.ty.hasCodeGenBits()) continue;
......@@ -1319,8 +1332,9 @@ pub const DeclGen = struct {
13191332 const llvm_struct_ty = try dg.llvmType(tv.ty);
13201333 const field_vals = tv.val.castTag(.@"struct").?.data;
13211334 const gpa = dg.gpa;
1335 const llvm_field_count = llvm_struct_ty.countStructElementTypes();
13221336
1323 var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, field_vals.len);
1337 var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, llvm_field_count);
13241338 defer llvm_fields.deinit(gpa);
13251339
13261340 const struct_obj = tv.ty.castTag(.@"struct").?.data;
......@@ -1329,6 +1343,7 @@ pub const DeclGen = struct {
13291343 const fields = struct_obj.fields.values();
13301344 comptime assert(Type.packed_struct_layout_version == 1);
13311345 var offset: u64 = 0;
1346 var big_align: u32 = 0;
13321347 var running_bits: u16 = 0;
13331348 var running_int: *const llvm.Value = llvm_struct_ty.structGetTypeAtIndex(0).constNull();
13341349 for (field_vals) |field_val, i| {
......@@ -1349,6 +1364,7 @@ pub const DeclGen = struct {
13491364 running_int = running_int.constOr(shifted);
13501365 running_bits += ty_bit_size;
13511366 } else {
1367 big_align = @maximum(big_align, field_align);
13521368 if (running_bits != 0) {
13531369 var int_payload: Type.Payload.Bits = .{
13541370 .base = .{ .tag = .int_unsigned },
......@@ -1356,6 +1372,7 @@ pub const DeclGen = struct {
13561372 };
13571373 const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };
13581374 const int_align = int_ty.abiAlignment(target);
1375 big_align = @maximum(big_align, int_align);
13591376 const prev_offset = offset;
13601377 offset = std.mem.alignForwardGeneric(u64, offset, int_align);
13611378 const padding_bytes = @intCast(c_uint, offset - prev_offset);
......@@ -1382,6 +1399,32 @@ pub const DeclGen = struct {
13821399 offset += field.ty.abiSize(target);
13831400 }
13841401 }
1402 if (running_bits != 0) {
1403 var int_payload: Type.Payload.Bits = .{
1404 .base = .{ .tag = .int_unsigned },
1405 .data = running_bits,
1406 };
1407 const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };
1408 const int_align = int_ty.abiAlignment(target);
1409 big_align = @maximum(big_align, int_align);
1410 const prev_offset = offset;
1411 offset = std.mem.alignForwardGeneric(u64, offset, int_align);
1412 const padding_bytes = @intCast(c_uint, offset - prev_offset);
1413 if (padding_bytes != 0) {
1414 const padding = dg.context.intType(8).arrayType(padding_bytes);
1415 llvm_fields.appendAssumeCapacity(padding.getUndef());
1416 }
1417 llvm_fields.appendAssumeCapacity(running_int);
1418 offset += int_ty.abiSize(target);
1419 }
1420
1421 const prev_offset = offset;
1422 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
1423 const padding_bytes = @intCast(c_uint, offset - prev_offset);
1424 if (padding_bytes != 0) {
1425 const padding = dg.context.intType(8).arrayType(padding_bytes);
1426 llvm_fields.appendAssumeCapacity(padding.getUndef());
1427 }
13851428 } else {
13861429 for (field_vals) |field_val, i| {
13871430 const field_ty = tv.ty.structFieldType(i);
src/codegen/llvm/bindings.zig+3
......@@ -257,6 +257,9 @@ pub const Type = opaque {
257257
258258 pub const getElementType = LLVMGetElementType;
259259 extern fn LLVMGetElementType(Ty: *const Type) *const Type;
260
261 pub const countStructElementTypes = LLVMCountStructElementTypes;
262 extern fn LLVMCountStructElementTypes(StructTy: *const Type) c_uint;
260263};
261264
262265pub const Module = opaque {