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 {
33703370 return llvm_int.constIntToPtr(try dg.lowerType(tv.ty));
33713371 },
33723372 .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);
33743374 },
33753375 .null_value, .zero => {
33763376 const llvm_type = try dg.lowerType(tv.ty);
......@@ -3378,7 +3378,7 @@ pub const DeclGen = struct {
33783378 },
33793379 .opt_payload => {
33803380 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);
33823382 },
33833383 else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{
33843384 tv.ty.fmtDebug(), tag,
......@@ -3967,7 +3967,7 @@ pub const DeclGen = struct {
39673967 return try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index);
39683968 }
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 {
39713971 const target = dg.module.getTarget();
39723972 switch (ptr_val.tag()) {
39733973 .decl_ref_mut => {
......@@ -3996,7 +3996,7 @@ pub const DeclGen = struct {
39963996 },
39973997 .field_ptr => {
39983998 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);
40004000 const parent_ty = field_ptr.container_ty;
40014001
40024002 const field_index = @intCast(u32, field_ptr.field_index);
......@@ -4026,6 +4026,7 @@ pub const DeclGen = struct {
40264026 },
40274027 .Struct => {
40284028 if (parent_ty.containerLayout() == .Packed) {
4029 if (!byte_aligned) return parent_llvm_ptr;
40294030 const llvm_usize = dg.context.intType(target.cpu.arch.ptrBitWidth());
40304031 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
40314032 // count bits of fields before this one
......@@ -4072,7 +4073,7 @@ pub const DeclGen = struct {
40724073 },
40734074 .elem_ptr => {
40744075 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
40774078 const llvm_usize = try dg.lowerType(Type.usize);
40784079 const indices: [1]*llvm.Value = .{
......@@ -4083,7 +4084,7 @@ pub const DeclGen = struct {
40834084 },
40844085 .opt_payload_ptr => {
40854086 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);
40874088 var buf: Type.Payload.ElemType = undefined;
40884089
40894090 const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf);
......@@ -4105,7 +4106,7 @@ pub const DeclGen = struct {
41054106 },
41064107 .eu_payload_ptr => {
41074108 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
41104111 const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload();
41114112 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
test/behavior/packed-struct.zig+26
......@@ -599,3 +599,29 @@ test "packed struct initialized in bitcast" {
599599 const t = @bitCast(u8, T{ .val = val });
600600 try expect(t == val);
601601}
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}