diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 5b16ae5a1c..a4e51c7a8d 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3745,18 +3745,22 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { } const mcv = try self.resolveInst(operand); - const struct_ty = self.air.typeOf(operand); - if (struct_ty.zigTypeTag() == .Struct and struct_ty.containerLayout() == .Packed) { - return self.fail("TODO airStructFieldVal implement packed structs", .{}); - } - const struct_field_offset = struct_ty.structFieldOffset(index, self.target.*); - const struct_field_ty = struct_ty.structFieldType(index); + const container_ty = self.air.typeOf(operand); + const field_ty = container_ty.structFieldType(index); + const field_bit_offset = switch (container_ty.containerLayout()) { + .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, self.target.*) * 8), + .Packed => if (container_ty.castTag(.@"struct")) |struct_obj| + struct_obj.data.packedFieldBitOffset(self.target.*, index) + else + 0, + }; const result: MCValue = result: { switch (mcv) { .stack_offset => |off| { - const stack_offset = off - @intCast(i32, struct_field_offset); - break :result MCValue{ .stack_offset = stack_offset }; + const byte_offset = std.math.divExact(u32, field_bit_offset, 8) catch + return self.fail("TODO implement struct_field_val for a packed struct", .{}); + break :result MCValue{ .stack_offset = off - @intCast(i32, byte_offset) }; }, .register => |reg| { const reg_lock = self.register_manager.lockRegAssumeUnused(reg); @@ -3779,27 +3783,28 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { defer if (dst_mcv_lock) |lock| self.register_manager.unlockReg(lock); // Shift by struct_field_offset. - const shift = @intCast(u8, struct_field_offset * 8); - try self.genShiftBinOpMir(.shr, Type.usize, dst_mcv.register, .{ .immediate = shift }); + try self.genShiftBinOpMir( + .shr, + Type.usize, + dst_mcv.register, + .{ .immediate = field_bit_offset }, + ); - // Mask with reg.bitSize() - struct_field_size - const max_reg_bit_width = Register.rax.bitSize(); - const mask_shift = @intCast(u6, (max_reg_bit_width - struct_field_ty.bitSize(self.target.*))); - const mask = (~@as(u64, 0)) >> mask_shift; + // Mask to field_bit_size bits + const field_bit_size = field_ty.bitSize(self.target.*); + const mask = ~@as(u64, 0) >> @intCast(u6, 64 - field_bit_size); const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask }); try self.genBinOpMir(.@"and", Type.usize, dst_mcv, .{ .register = tmp_reg }); - const signedness: std.builtin.Signedness = blk: { - if (struct_field_ty.zigTypeTag() != .Int) break :blk .unsigned; - break :blk struct_field_ty.intInfo(self.target.*).signedness; - }; - const field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); - if (signedness == .signed and field_size < 8) { + const signedness = + if (field_ty.isAbiInt()) field_ty.intInfo(self.target.*).signedness else .unsigned; + const field_byte_size = @intCast(u32, field_ty.abiSize(self.target.*)); + if (signedness == .signed and field_byte_size < 8) { try self.asmRegisterRegister( .movsx, dst_mcv.register, - registerAlias(dst_mcv.register, field_size), + registerAlias(dst_mcv.register, field_byte_size), ); } diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index 552080c836..8ac87bb9c0 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -157,7 +157,6 @@ test "bitcast generates a temporary value" { } test "@bitCast packed structs at runtime and comptime" { - 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_sparc64) return error.SkipZigTest; // TODO @@ -215,7 +214,6 @@ test "@bitCast extern structs at runtime and comptime" { } test "bitcast packed struct to integer and back" { - 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_sparc64) return error.SkipZigTest; // TODO diff --git a/test/behavior/bugs/9584.zig b/test/behavior/bugs/9584.zig index f80ff05228..307f1689bf 100644 --- a/test/behavior/bugs/9584.zig +++ b/test/behavior/bugs/9584.zig @@ -44,7 +44,6 @@ pub fn b(x: *X) !void { } test { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 6b0570cb96..6cc021dd1a 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -254,7 +254,6 @@ test "regular in irregular packed struct" { } test "byte-aligned field pointer offsets" { - 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_sparc64) return error.SkipZigTest; // TODO @@ -397,7 +396,6 @@ test "@ptrToInt on a packed struct field" { } test "optional pointer in packed struct" { - 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_sparc64) return error.SkipZigTest; // TODO @@ -530,7 +528,6 @@ test "nested packed struct field access test" { test "runtime init of unnamed packed struct type" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var z: u8 = 123; @@ -545,7 +542,6 @@ test "runtime init of unnamed packed struct type" { test "packed struct passed to callconv(.C) function" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 25dd1c7958..61318ad6d2 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -387,7 +387,6 @@ const APackedStruct = packed struct { test "packed struct" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var foo = APackedStruct{ @@ -496,7 +495,6 @@ const Bitfields = packed struct { test "packed struct fields are ordered from LSB to MSB" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var all: u64 = 0x7765443322221111; @@ -632,7 +630,6 @@ test "default struct initialization fields" { } test "packed array 24bits" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO diff --git a/test/behavior/union.zig b/test/behavior/union.zig index b78bac5c3e..35bdca270e 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1408,7 +1408,6 @@ test "union field ptr - zero sized field" { } test "packed union in packed struct" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO @@ -1494,7 +1493,6 @@ test "union reassignment can use previous value" { } test "packed union with zero-bit field" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO