From d41dd499a9fd42be3a30018dccb6a9a9fbf43f3d Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 20 Jul 2022 16:13:36 +0300 Subject: [PATCH 1/2] stage2 llvm: fix handling of pointer fields in packed structs --- src/codegen/llvm.zig | 10 +++++++++- test/behavior/packed-struct.zig | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 53c97c880f..9dc20755eb 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5149,6 +5149,11 @@ pub const FuncGen = struct { const same_size_int = self.context.intType(elem_bits); const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); return self.builder.buildBitCast(truncated_int, elem_llvm_ty, ""); + } else if (field_ty.zigTypeTag() == .Pointer) { + const elem_bits = @intCast(c_uint, field_ty.bitSize(target)); + const same_size_int = self.context.intType(elem_bits); + const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, ""); + return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, ""); } return self.builder.buildTrunc(shifted_value, elem_llvm_ty, ""); }, @@ -7999,7 +8004,10 @@ pub const FuncGen = struct { const non_int_val = try self.resolveInst(elem); const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); const small_int_ty = self.dg.context.intType(ty_bit_size); - const small_int_val = self.builder.buildBitCast(non_int_val, small_int_ty, ""); + const small_int_val = if (field.ty.zigTypeTag() == .Pointer) + self.builder.buildPtrToInt(non_int_val, small_int_ty, "") + else + self.builder.buildBitCast(non_int_val, small_int_ty, ""); const shift_rhs = int_llvm_ty.constInt(running_bits, .False); // If the field is as large as the entire packed struct, this // zext would go from, e.g. i16 to i16. This is legal with diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index ab5adc554a..628c2c287f 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -413,3 +413,24 @@ test "byte-aligned field pointer offsets" { try S.doTheTest(); comptime try S.doTheTest(); } + +test "load pointer from packed struct" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; + + const Symbol = struct { + index: u16, + }; + const Relocation = packed struct { + symbol: *Symbol, + a: u32, + }; + var a: []Relocation = &.{}; + for (a) |rela| { + var b = rela.symbol.index; + _ = b; + } +} From 379beceffd1b0a0b0d8f3163dc02eba1e53ffa39 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 20 Jul 2022 15:21:24 -0700 Subject: [PATCH 2/2] improve test case from previous commit Now it checks that the code is correctly compiled rather than only checking that it does not crash the compiler. --- test/behavior/packed-struct.zig | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 628c2c287f..245514b87e 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -421,16 +421,17 @@ test "load pointer from packed struct" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - const Symbol = struct { + const A = struct { index: u16, }; - const Relocation = packed struct { - symbol: *Symbol, - a: u32, + const B = packed struct { + x: *A, + y: u32, }; - var a: []Relocation = &.{}; - for (a) |rela| { - var b = rela.symbol.index; - _ = b; + var a: A = .{ .index = 123 }; + var b_list: []B = &.{.{ .x = &a, .y = 99 }}; + for (b_list) |b| { + var i = b.x.index; + try expect(i == 123); } }