diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 0d314aebdf58..c3bb5bf3c925 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4,7 +4,6 @@ const assert = std.debug.assert; const Allocator = std.mem.Allocator; const log = std.log.scoped(.codegen); const math = std.math; -const native_endian = builtin.cpu.arch.endian(); const DW = std.dwarf; const Builder = @import("llvm/Builder.zig"); @@ -10722,7 +10721,21 @@ pub const FuncGen = struct { if (isByRef(elem_ty, mod)) { return self.loadByRef(ptr, elem_ty, ptr_alignment, info.flags.is_volatile); } - return self.wip.load(ptr_kind, try o.lowerType(elem_ty), ptr, ptr_alignment, ""); + const llvm_elem_ty = try o.lowerType(elem_ty); + const llvm_load_ty = if (elem_ty.isAbiInt(mod)) + try o.builder.intType(@intCast(elem_ty.abiSize(mod) * 8)) + else + llvm_elem_ty; + const loaded = try self.wip.load(ptr_kind, llvm_load_ty, ptr, ptr_alignment, ""); + const shifted = if (llvm_elem_ty != llvm_load_ty and o.target.cpu.arch.endian() == .Big) + try self.wip.bin(.lshr, loaded, try o.builder.intValue( + llvm_load_ty, + (elem_ty.abiSize(mod) - (std.math.divCeil(u64, elem_ty.bitSize(mod), 8) catch + unreachable)) * 8, + ), "") + else + loaded; + return self.wip.conv(.unneeded, shifted, llvm_elem_ty, ""); } const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8)); diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index d3d761c3dbc4..465ef4358c99 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -650,3 +650,18 @@ test "bitcast back and forth" { try expect(s.one == s2.one); try expect(s.two == s2.two); } + +test "field access of packed struct smaller than its abi size inside struct initialized with rls" { + const S = struct { + ps: packed struct { x: i2, y: i2 }, + + fn init(cond: bool) @This() { + return .{ .ps = .{ .x = 0, .y = if (cond) 1 else 0 } }; + } + }; + + var s = S.init(true); + // note: this bug is triggered by the == operator, expectEqual will hide it + try expect(@as(i2, 0) == s.ps.x); + try expect(@as(i2, 1) == s.ps.y); +}