authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-27 13:22:33-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-27 16:19:23-07:00
logf880af369d4814df7cd1ec0ef5f85343108bbe81
tree61c5348ebf815a1233b5dc0829aa96a00447c2a1
parentdfc7493dcb049788b92137ca09b8bd47cee23865

LLVM: fix lowering byte-aligned packed struct field pointers


3 files changed, 43 insertions(+), 0 deletions(-)

src/codegen/llvm.zig+18
......@@ -3646,6 +3646,24 @@ pub const DeclGen = struct {
36463646 },
36473647 .Struct => {
36483648 const field_ty = parent_ty.structFieldType(field_index);
3649 if (parent_ty.containerLayout() == .Packed) {
3650 const llvm_usize = dg.context.intType(target.cpu.arch.ptrBitWidth());
3651 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
3652 // count bits of fields before this one
3653 const prev_bits = b: {
3654 var b: usize = 0;
3655 for (parent_ty.structFields().values()[0..field_index]) |field| {
3656 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
3657 b += field.ty.bitSize(target);
3658 }
3659 break :b b;
3660 };
3661 const byte_offset = llvm_usize.constInt((prev_bits + 7) / 8, .False);
3662 const field_addr = base_addr.constAdd(byte_offset);
3663 bitcast_needed = false;
3664 const final_llvm_ty = (try dg.lowerType(ptr_child_ty)).pointerType(0);
3665 break :blk field_addr.constIntToPtr(final_llvm_ty);
3666 }
36493667 bitcast_needed = !field_ty.eql(ptr_child_ty, dg.module);
36503668
36513669 var ty_buf: Type.Payload.Pointer = undefined;
src/codegen/llvm/bindings.zig+3
......@@ -169,6 +169,9 @@ pub const Value = opaque {
169169 pub const constNot = LLVMConstNot;
170170 extern fn LLVMConstNot(ConstantVal: *const Value) *const Value;
171171
172 pub const constAdd = LLVMConstAdd;
173 extern fn LLVMConstAdd(LHSConstant: *const Value, RHSConstant: *const Value) *const Value;
174
172175 pub const setWeak = LLVMSetWeak;
173176 extern fn LLVMSetWeak(CmpXchgInst: *const Value, IsWeak: Bool) void;
174177
test/behavior/packed-struct.zig+22
......@@ -436,3 +436,25 @@ test "load pointer from packed struct" {
436436 try expect(i == 123);
437437 }
438438}
439
440test "@ptrToInt on a packed struct field" {
441 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
442 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
443 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
444 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
445 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
446
447 const S = struct {
448 const P = packed struct {
449 x: u8,
450 y: u8,
451 z: u32,
452 };
453 var p0: P = P{
454 .x = 1,
455 .y = 2,
456 .z = 0,
457 };
458 };
459 try expect(@ptrToInt(&S.p0.z) - @ptrToInt(&S.p0.x) == 2);
460}