authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-13 17:52:54+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-17 20:28:42+02:00
log6e067dc0506c8d5342ddaa0934770f7339619d36
treeea616fd22b7cf34e61c0c11f10433c79426592cb
parent06e9b2c4e360e738c3be3d3e5d5a36006fd5b224

llvm: do not offset packed struct field pointers if they have a host size

Closes #14261

2 files changed, 34 insertions(+), 7 deletions(-)

src/codegen/llvm.zig+8-7
...@@ -3370,7 +3370,7 @@ pub const DeclGen = struct {...@@ -3370,7 +3370,7 @@ pub const DeclGen = struct {
3370 return llvm_int.constIntToPtr(try dg.lowerType(tv.ty));3370 return llvm_int.constIntToPtr(try dg.lowerType(tv.ty));
3371 },3371 },
3372 .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => {3372 .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => {
3373 return dg.lowerParentPtr(tv.val);3373 return dg.lowerParentPtr(tv.val, tv.ty.ptrInfo().data.bit_offset % 8 == 0);
3374 },3374 },
3375 .null_value, .zero => {3375 .null_value, .zero => {
3376 const llvm_type = try dg.lowerType(tv.ty);3376 const llvm_type = try dg.lowerType(tv.ty);
...@@ -3378,7 +3378,7 @@ pub const DeclGen = struct {...@@ -3378,7 +3378,7 @@ pub const DeclGen = struct {
3378 },3378 },
3379 .opt_payload => {3379 .opt_payload => {
3380 const payload = tv.val.castTag(.opt_payload).?.data;3380 const payload = tv.val.castTag(.opt_payload).?.data;
3381 return dg.lowerParentPtr(payload);3381 return dg.lowerParentPtr(payload, tv.ty.ptrInfo().data.bit_offset % 8 == 0);
3382 },3382 },
3383 else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{3383 else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{
3384 tv.ty.fmtDebug(), tag,3384 tv.ty.fmtDebug(), tag,
...@@ -3967,7 +3967,7 @@ pub const DeclGen = struct {...@@ -3967,7 +3967,7 @@ pub const DeclGen = struct {
3967 return try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index);3967 return try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index);
3968 }3968 }
39693969
3970 fn lowerParentPtr(dg: *DeclGen, ptr_val: Value) Error!*llvm.Value {3970 fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value {
3971 const target = dg.module.getTarget();3971 const target = dg.module.getTarget();
3972 switch (ptr_val.tag()) {3972 switch (ptr_val.tag()) {
3973 .decl_ref_mut => {3973 .decl_ref_mut => {
...@@ -3996,7 +3996,7 @@ pub const DeclGen = struct {...@@ -3996,7 +3996,7 @@ pub const DeclGen = struct {
3996 },3996 },
3997 .field_ptr => {3997 .field_ptr => {
3998 const field_ptr = ptr_val.castTag(.field_ptr).?.data;3998 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
3999 const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.container_ptr);3999 const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.container_ptr, byte_aligned);
4000 const parent_ty = field_ptr.container_ty;4000 const parent_ty = field_ptr.container_ty;
40014001
4002 const field_index = @intCast(u32, field_ptr.field_index);4002 const field_index = @intCast(u32, field_ptr.field_index);
...@@ -4026,6 +4026,7 @@ pub const DeclGen = struct {...@@ -4026,6 +4026,7 @@ pub const DeclGen = struct {
4026 },4026 },
4027 .Struct => {4027 .Struct => {
4028 if (parent_ty.containerLayout() == .Packed) {4028 if (parent_ty.containerLayout() == .Packed) {
4029 if (!byte_aligned) return parent_llvm_ptr;
4029 const llvm_usize = dg.context.intType(target.cpu.arch.ptrBitWidth());4030 const llvm_usize = dg.context.intType(target.cpu.arch.ptrBitWidth());
4030 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);4031 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
4031 // count bits of fields before this one4032 // count bits of fields before this one
...@@ -4072,7 +4073,7 @@ pub const DeclGen = struct {...@@ -4072,7 +4073,7 @@ pub const DeclGen = struct {
4072 },4073 },
4073 .elem_ptr => {4074 .elem_ptr => {
4074 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;4075 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
4075 const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr);4076 const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr, true);
40764077
4077 const llvm_usize = try dg.lowerType(Type.usize);4078 const llvm_usize = try dg.lowerType(Type.usize);
4078 const indices: [1]*llvm.Value = .{4079 const indices: [1]*llvm.Value = .{
...@@ -4083,7 +4084,7 @@ pub const DeclGen = struct {...@@ -4083,7 +4084,7 @@ pub const DeclGen = struct {
4083 },4084 },
4084 .opt_payload_ptr => {4085 .opt_payload_ptr => {
4085 const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;4086 const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
4086 const parent_llvm_ptr = try dg.lowerParentPtr(opt_payload_ptr.container_ptr);4087 const parent_llvm_ptr = try dg.lowerParentPtr(opt_payload_ptr.container_ptr, true);
4087 var buf: Type.Payload.ElemType = undefined;4088 var buf: Type.Payload.ElemType = undefined;
40884089
4089 const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf);4090 const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf);
...@@ -4105,7 +4106,7 @@ pub const DeclGen = struct {...@@ -4105,7 +4106,7 @@ pub const DeclGen = struct {
4105 },4106 },
4106 .eu_payload_ptr => {4107 .eu_payload_ptr => {
4107 const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;4108 const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
4108 const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr);4109 const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, true);
41094110
4110 const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload();4111 const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload();
4111 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {4112 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
test/behavior/packed-struct.zig+26
...@@ -599,3 +599,29 @@ test "packed struct initialized in bitcast" {...@@ -599,3 +599,29 @@ test "packed struct initialized in bitcast" {
599 const t = @bitCast(u8, T{ .val = val });599 const t = @bitCast(u8, T{ .val = val });
600 try expect(t == val);600 try expect(t == val);
601}601}
602
603test "pointer to container level packed struct field" {
604 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
605 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
606 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
607 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
608 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
609
610 const S = packed struct(u32) {
611 test_bit: bool,
612 someother_data: u12,
613 other_test_bit: bool,
614 someother_more_different_data: u12,
615 other_bits: packed struct(u6) {
616 enable_1: bool,
617 enable_2: bool,
618 enable_3: bool,
619 enable_4: bool,
620 enable_5: bool,
621 enable_6: bool,
622 },
623 var arr = [_]u32{0} ** 2;
624 };
625 @ptrCast(*S, &S.arr[0]).other_bits.enable_3 = true;
626 try expect(S.arr[0] == 0x10000000);
627}