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 {...@@ -845,9 +845,11 @@ pub const DeclGen = struct {
845 defer llvm_field_types.deinit(gpa);845 defer llvm_field_types.deinit(gpa);
846846
847 if (struct_obj.layout == .Packed) {847 if (struct_obj.layout == .Packed) {
848 try llvm_field_types.ensureUnusedCapacity(gpa, struct_obj.fields.count() * 2);
848 const target = dg.module.getTarget();849 const target = dg.module.getTarget();
849 comptime assert(Type.packed_struct_layout_version == 1);850 comptime assert(Type.packed_struct_layout_version == 1);
850 var offset: u64 = 0;851 var offset: u64 = 0;
852 var big_align: u32 = 0;
851 var running_bits: u16 = 0;853 var running_bits: u16 = 0;
852 for (struct_obj.fields.values()) |field| {854 for (struct_obj.fields.values()) |field| {
853 if (!field.ty.hasCodeGenBits()) continue;855 if (!field.ty.hasCodeGenBits()) continue;
...@@ -863,6 +865,7 @@ pub const DeclGen = struct {...@@ -863,6 +865,7 @@ pub const DeclGen = struct {
863 };865 };
864 const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };866 const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };
865 const int_align = int_ty.abiAlignment(target);867 const int_align = int_ty.abiAlignment(target);
868 big_align = @maximum(big_align, int_align);
866 const llvm_int_ty = try dg.llvmType(int_ty);869 const llvm_int_ty = try dg.llvmType(int_ty);
867 const prev_offset = offset;870 const prev_offset = offset;
868 offset = std.mem.alignForwardGeneric(u64, offset, int_align);871 offset = std.mem.alignForwardGeneric(u64, offset, int_align);
...@@ -875,6 +878,7 @@ pub const DeclGen = struct {...@@ -875,6 +878,7 @@ pub const DeclGen = struct {
875 offset += int_ty.abiSize(target);878 offset += int_ty.abiSize(target);
876 running_bits = 0;879 running_bits = 0;
877 }880 }
881 big_align = @maximum(big_align, field_align);
878 const prev_offset = offset;882 const prev_offset = offset;
879 offset = std.mem.alignForwardGeneric(u64, offset, field_align);883 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
880 const padding_bytes = @intCast(c_uint, offset - prev_offset);884 const padding_bytes = @intCast(c_uint, offset - prev_offset);
...@@ -894,6 +898,7 @@ pub const DeclGen = struct {...@@ -894,6 +898,7 @@ pub const DeclGen = struct {
894 };898 };
895 const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };899 const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };
896 const int_align = int_ty.abiAlignment(target);900 const int_align = int_ty.abiAlignment(target);
901 big_align = @maximum(big_align, int_align);
897 const prev_offset = offset;902 const prev_offset = offset;
898 offset = std.mem.alignForwardGeneric(u64, offset, int_align);903 offset = std.mem.alignForwardGeneric(u64, offset, int_align);
899 const padding_bytes = @intCast(c_uint, offset - prev_offset);904 const padding_bytes = @intCast(c_uint, offset - prev_offset);
...@@ -904,6 +909,14 @@ pub const DeclGen = struct {...@@ -904,6 +909,14 @@ pub const DeclGen = struct {
904 const llvm_int_ty = try dg.llvmType(int_ty);909 const llvm_int_ty = try dg.llvmType(int_ty);
905 llvm_field_types.appendAssumeCapacity(llvm_int_ty);910 llvm_field_types.appendAssumeCapacity(llvm_int_ty);
906 }911 }
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 }
907 } else {920 } else {
908 for (struct_obj.fields.values()) |field| {921 for (struct_obj.fields.values()) |field| {
909 if (!field.ty.hasCodeGenBits()) continue;922 if (!field.ty.hasCodeGenBits()) continue;
...@@ -1319,8 +1332,9 @@ pub const DeclGen = struct {...@@ -1319,8 +1332,9 @@ pub const DeclGen = struct {
1319 const llvm_struct_ty = try dg.llvmType(tv.ty);1332 const llvm_struct_ty = try dg.llvmType(tv.ty);
1320 const field_vals = tv.val.castTag(.@"struct").?.data;1333 const field_vals = tv.val.castTag(.@"struct").?.data;
1321 const gpa = dg.gpa;1334 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);
1324 defer llvm_fields.deinit(gpa);1338 defer llvm_fields.deinit(gpa);
13251339
1326 const struct_obj = tv.ty.castTag(.@"struct").?.data;1340 const struct_obj = tv.ty.castTag(.@"struct").?.data;
...@@ -1329,6 +1343,7 @@ pub const DeclGen = struct {...@@ -1329,6 +1343,7 @@ pub const DeclGen = struct {
1329 const fields = struct_obj.fields.values();1343 const fields = struct_obj.fields.values();
1330 comptime assert(Type.packed_struct_layout_version == 1);1344 comptime assert(Type.packed_struct_layout_version == 1);
1331 var offset: u64 = 0;1345 var offset: u64 = 0;
1346 var big_align: u32 = 0;
1332 var running_bits: u16 = 0;1347 var running_bits: u16 = 0;
1333 var running_int: *const llvm.Value = llvm_struct_ty.structGetTypeAtIndex(0).constNull();1348 var running_int: *const llvm.Value = llvm_struct_ty.structGetTypeAtIndex(0).constNull();
1334 for (field_vals) |field_val, i| {1349 for (field_vals) |field_val, i| {
...@@ -1349,6 +1364,7 @@ pub const DeclGen = struct {...@@ -1349,6 +1364,7 @@ pub const DeclGen = struct {
1349 running_int = running_int.constOr(shifted);1364 running_int = running_int.constOr(shifted);
1350 running_bits += ty_bit_size;1365 running_bits += ty_bit_size;
1351 } else {1366 } else {
1367 big_align = @maximum(big_align, field_align);
1352 if (running_bits != 0) {1368 if (running_bits != 0) {
1353 var int_payload: Type.Payload.Bits = .{1369 var int_payload: Type.Payload.Bits = .{
1354 .base = .{ .tag = .int_unsigned },1370 .base = .{ .tag = .int_unsigned },
...@@ -1356,6 +1372,7 @@ pub const DeclGen = struct {...@@ -1356,6 +1372,7 @@ pub const DeclGen = struct {
1356 };1372 };
1357 const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };1373 const int_ty: Type = .{ .ptr_otherwise = &int_payload.base };
1358 const int_align = int_ty.abiAlignment(target);1374 const int_align = int_ty.abiAlignment(target);
1375 big_align = @maximum(big_align, int_align);
1359 const prev_offset = offset;1376 const prev_offset = offset;
1360 offset = std.mem.alignForwardGeneric(u64, offset, int_align);1377 offset = std.mem.alignForwardGeneric(u64, offset, int_align);
1361 const padding_bytes = @intCast(c_uint, offset - prev_offset);1378 const padding_bytes = @intCast(c_uint, offset - prev_offset);
...@@ -1382,6 +1399,32 @@ pub const DeclGen = struct {...@@ -1382,6 +1399,32 @@ pub const DeclGen = struct {
1382 offset += field.ty.abiSize(target);1399 offset += field.ty.abiSize(target);
1383 }1400 }
1384 }1401 }
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 }
1385 } else {1428 } else {
1386 for (field_vals) |field_val, i| {1429 for (field_vals) |field_val, i| {
1387 const field_ty = tv.ty.structFieldType(i);1430 const field_ty = tv.ty.structFieldType(i);
src/codegen/llvm/bindings.zig+3
...@@ -257,6 +257,9 @@ pub const Type = opaque {...@@ -257,6 +257,9 @@ pub const Type = opaque {
257257
258 pub const getElementType = LLVMGetElementType;258 pub const getElementType = LLVMGetElementType;
259 extern fn LLVMGetElementType(Ty: *const Type) *const Type;259 extern fn LLVMGetElementType(Ty: *const Type) *const Type;
260
261 pub const countStructElementTypes = LLVMCountStructElementTypes;
262 extern fn LLVMCountStructElementTypes(StructTy: *const Type) c_uint;
260};263};
261264
262pub const Module = opaque {265pub const Module = opaque {