Skip to content

Commit c1f3aca

Browse files
authored
Merge pull request #12177 from Vexu/packed-ptr
stage2 llvm: fix handling of pointer fields in packed structs
2 parents de62bd0 + 379bece commit c1f3aca

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

src/codegen/llvm.zig

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5149,6 +5149,11 @@ pub const FuncGen = struct {
51495149
const same_size_int = self.context.intType(elem_bits);
51505150
const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
51515151
return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
5152+
} else if (field_ty.zigTypeTag() == .Pointer) {
5153+
const elem_bits = @intCast(c_uint, field_ty.bitSize(target));
5154+
const same_size_int = self.context.intType(elem_bits);
5155+
const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
5156+
return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
51525157
}
51535158
return self.builder.buildTrunc(shifted_value, elem_llvm_ty, "");
51545159
},
@@ -7999,7 +8004,10 @@ pub const FuncGen = struct {
79998004
const non_int_val = try self.resolveInst(elem);
80008005
const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
80018006
const small_int_ty = self.dg.context.intType(ty_bit_size);
8002-
const small_int_val = self.builder.buildBitCast(non_int_val, small_int_ty, "");
8007+
const small_int_val = if (field.ty.zigTypeTag() == .Pointer)
8008+
self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
8009+
else
8010+
self.builder.buildBitCast(non_int_val, small_int_ty, "");
80038011
const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
80048012
// If the field is as large as the entire packed struct, this
80058013
// zext would go from, e.g. i16 to i16. This is legal with

test/behavior/packed-struct.zig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,3 +413,25 @@ test "byte-aligned field pointer offsets" {
413413
try S.doTheTest();
414414
comptime try S.doTheTest();
415415
}
416+
417+
test "load pointer from packed struct" {
418+
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
419+
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
420+
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
421+
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
422+
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
423+
424+
const A = struct {
425+
index: u16,
426+
};
427+
const B = packed struct {
428+
x: *A,
429+
y: u32,
430+
};
431+
var a: A = .{ .index = 123 };
432+
var b_list: []B = &.{.{ .x = &a, .y = 99 }};
433+
for (b_list) |b| {
434+
var i = b.x.index;
435+
try expect(i == 123);
436+
}
437+
}

0 commit comments

Comments
 (0)