| author | |
| committer | |
| log | f880af369d4814df7cd1ec0ef5f85343108bbe81 |
| tree | 61c5348ebf815a1233b5dc0829aa96a00447c2a1 |
| parent | dfc7493dcb049788b92137ca09b8bd47cee23865 |
3 files changed, 43 insertions(+), 0 deletions(-)
src/codegen/llvm.zig+18| ... | ... | @@ -3646,6 +3646,24 @@ pub const DeclGen = struct { |
| 3646 | 3646 | }, |
| 3647 | 3647 | .Struct => { |
| 3648 | 3648 | 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 | } | |
| 3649 | 3667 | bitcast_needed = !field_ty.eql(ptr_child_ty, dg.module); |
| 3650 | 3668 | |
| 3651 | 3669 | var ty_buf: Type.Payload.Pointer = undefined; |
src/codegen/llvm/bindings.zig+3| ... | ... | @@ -169,6 +169,9 @@ pub const Value = opaque { |
| 169 | 169 | pub const constNot = LLVMConstNot; |
| 170 | 170 | extern fn LLVMConstNot(ConstantVal: *const Value) *const Value; |
| 171 | 171 | |
| 172 | pub const constAdd = LLVMConstAdd; | |
| 173 | extern fn LLVMConstAdd(LHSConstant: *const Value, RHSConstant: *const Value) *const Value; | |
| 174 | ||
| 172 | 175 | pub const setWeak = LLVMSetWeak; |
| 173 | 176 | extern fn LLVMSetWeak(CmpXchgInst: *const Value, IsWeak: Bool) void; |
| 174 | 177 |
test/behavior/packed-struct.zig+22| ... | ... | @@ -436,3 +436,25 @@ test "load pointer from packed struct" { |
| 436 | 436 | try expect(i == 123); |
| 437 | 437 | } |
| 438 | 438 | } |
| 439 | ||
| 440 | test "@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 | } |