| author | |
| committer | |
| log | 8f385e77caae676ad675ca13baea51751230f200 |
| tree | 9f38a6d1a62a72d990021765520f631e85a97a99 |
| parent | 0cfc0d0d13bd1e9f1a9119324fac624371aecdd3 |
6 files changed, 26 insertions(+), 33 deletions(-)
src/arch/x86_64/CodeGen.zig+26-21| ... | @@ -3745,18 +3745,22 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3745,18 +3745,22 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 3745 | } | 3745 | } |
| 3746 | 3746 | ||
| 3747 | const mcv = try self.resolveInst(operand); | 3747 | const mcv = try self.resolveInst(operand); |
| 3748 | const struct_ty = self.air.typeOf(operand); | 3748 | const container_ty = self.air.typeOf(operand); |
| 3749 | if (struct_ty.zigTypeTag() == .Struct and struct_ty.containerLayout() == .Packed) { | 3749 | const field_ty = container_ty.structFieldType(index); |
| 3750 | return self.fail("TODO airStructFieldVal implement packed structs", .{}); | 3750 | const field_bit_offset = switch (container_ty.containerLayout()) { |
| 3751 | } | 3751 | .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, self.target.*) * 8), |
| 3752 | const struct_field_offset = struct_ty.structFieldOffset(index, self.target.*); | 3752 | .Packed => if (container_ty.castTag(.@"struct")) |struct_obj| |
| 3753 | const struct_field_ty = struct_ty.structFieldType(index); | 3753 | struct_obj.data.packedFieldBitOffset(self.target.*, index) |
| 3754 | else | ||
| 3755 | 0, | ||
| 3756 | }; | ||
| 3754 | 3757 | ||
| 3755 | const result: MCValue = result: { | 3758 | const result: MCValue = result: { |
| 3756 | switch (mcv) { | 3759 | switch (mcv) { |
| 3757 | .stack_offset => |off| { | 3760 | .stack_offset => |off| { |
| 3758 | const stack_offset = off - @intCast(i32, struct_field_offset); | 3761 | const byte_offset = std.math.divExact(u32, field_bit_offset, 8) catch |
| 3759 | break :result MCValue{ .stack_offset = stack_offset }; | 3762 | return self.fail("TODO implement struct_field_val for a packed struct", .{}); |
| 3763 | break :result MCValue{ .stack_offset = off - @intCast(i32, byte_offset) }; | ||
| 3760 | }, | 3764 | }, |
| 3761 | .register => |reg| { | 3765 | .register => |reg| { |
| 3762 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); | 3766 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); |
| ... | @@ -3779,27 +3783,28 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3779,27 +3783,28 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 3779 | defer if (dst_mcv_lock) |lock| self.register_manager.unlockReg(lock); | 3783 | defer if (dst_mcv_lock) |lock| self.register_manager.unlockReg(lock); |
| 3780 | 3784 | ||
| 3781 | // Shift by struct_field_offset. | 3785 | // Shift by struct_field_offset. |
| 3782 | const shift = @intCast(u8, struct_field_offset * 8); | 3786 | try self.genShiftBinOpMir( |
| 3783 | try self.genShiftBinOpMir(.shr, Type.usize, dst_mcv.register, .{ .immediate = shift }); | 3787 | .shr, |
| 3788 | Type.usize, | ||
| 3789 | dst_mcv.register, | ||
| 3790 | .{ .immediate = field_bit_offset }, | ||
| 3791 | ); | ||
| 3784 | 3792 | ||
| 3785 | // Mask with reg.bitSize() - struct_field_size | 3793 | // Mask to field_bit_size bits |
| 3786 | const max_reg_bit_width = Register.rax.bitSize(); | 3794 | const field_bit_size = field_ty.bitSize(self.target.*); |
| 3787 | const mask_shift = @intCast(u6, (max_reg_bit_width - struct_field_ty.bitSize(self.target.*))); | 3795 | const mask = ~@as(u64, 0) >> @intCast(u6, 64 - field_bit_size); |
| 3788 | const mask = (~@as(u64, 0)) >> mask_shift; | ||
| 3789 | 3796 | ||
| 3790 | const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask }); | 3797 | const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask }); |
| 3791 | try self.genBinOpMir(.@"and", Type.usize, dst_mcv, .{ .register = tmp_reg }); | 3798 | try self.genBinOpMir(.@"and", Type.usize, dst_mcv, .{ .register = tmp_reg }); |
| 3792 | 3799 | ||
| 3793 | const signedness: std.builtin.Signedness = blk: { | 3800 | const signedness = |
| 3794 | if (struct_field_ty.zigTypeTag() != .Int) break :blk .unsigned; | 3801 | if (field_ty.isAbiInt()) field_ty.intInfo(self.target.*).signedness else .unsigned; |
| 3795 | break :blk struct_field_ty.intInfo(self.target.*).signedness; | 3802 | const field_byte_size = @intCast(u32, field_ty.abiSize(self.target.*)); |
| 3796 | }; | 3803 | if (signedness == .signed and field_byte_size < 8) { |
| 3797 | const field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); | ||
| 3798 | if (signedness == .signed and field_size < 8) { | ||
| 3799 | try self.asmRegisterRegister( | 3804 | try self.asmRegisterRegister( |
| 3800 | .movsx, | 3805 | .movsx, |
| 3801 | dst_mcv.register, | 3806 | dst_mcv.register, |
| 3802 | registerAlias(dst_mcv.register, field_size), | 3807 | registerAlias(dst_mcv.register, field_byte_size), |
| 3803 | ); | 3808 | ); |
| 3804 | } | 3809 | } |
| 3805 | 3810 |
test/behavior/bitcast.zig-2| ... | @@ -157,7 +157,6 @@ test "bitcast generates a temporary value" { | ... | @@ -157,7 +157,6 @@ test "bitcast generates a temporary value" { |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | test "@bitCast packed structs at runtime and comptime" { | 159 | test "@bitCast packed structs at runtime and comptime" { |
| 160 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 161 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 160 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 162 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 161 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 163 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 162 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | @@ -215,7 +214,6 @@ test "@bitCast extern structs at runtime and comptime" { | ... | @@ -215,7 +214,6 @@ test "@bitCast extern structs at runtime and comptime" { |
| 215 | } | 214 | } |
| 216 | 215 | ||
| 217 | test "bitcast packed struct to integer and back" { | 216 | test "bitcast packed struct to integer and back" { |
| 218 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 219 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 217 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 220 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 218 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 221 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 219 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/bugs/9584.zig-1| ... | @@ -44,7 +44,6 @@ pub fn b(x: *X) !void { | ... | @@ -44,7 +44,6 @@ pub fn b(x: *X) !void { |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | test { | 46 | test { |
| 47 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 48 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 47 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 49 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 48 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 50 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 49 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
test/behavior/packed-struct.zig-4| ... | @@ -254,7 +254,6 @@ test "regular in irregular packed struct" { | ... | @@ -254,7 +254,6 @@ test "regular in irregular packed struct" { |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | test "byte-aligned field pointer offsets" { | 256 | test "byte-aligned field pointer offsets" { |
| 257 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 258 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 257 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 259 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 258 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 260 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 259 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | @@ -397,7 +396,6 @@ test "@ptrToInt on a packed struct field" { | ... | @@ -397,7 +396,6 @@ test "@ptrToInt on a packed struct field" { |
| 397 | } | 396 | } |
| 398 | 397 | ||
| 399 | test "optional pointer in packed struct" { | 398 | test "optional pointer in packed struct" { |
| 400 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 401 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 399 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 402 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 400 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 403 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 401 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | @@ -530,7 +528,6 @@ test "nested packed struct field access test" { | ... | @@ -530,7 +528,6 @@ test "nested packed struct field access test" { |
| 530 | test "runtime init of unnamed packed struct type" { | 528 | test "runtime init of unnamed packed struct type" { |
| 531 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 529 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 532 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 530 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 533 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 534 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 531 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 535 | 532 | ||
| 536 | var z: u8 = 123; | 533 | var z: u8 = 123; |
| ... | @@ -545,7 +542,6 @@ test "runtime init of unnamed packed struct type" { | ... | @@ -545,7 +542,6 @@ test "runtime init of unnamed packed struct type" { |
| 545 | test "packed struct passed to callconv(.C) function" { | 542 | test "packed struct passed to callconv(.C) function" { |
| 546 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 543 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 547 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 544 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 548 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 549 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 545 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 550 | 546 | ||
| 551 | const S = struct { | 547 | const S = struct { |
test/behavior/struct.zig-3| ... | @@ -387,7 +387,6 @@ const APackedStruct = packed struct { | ... | @@ -387,7 +387,6 @@ const APackedStruct = packed struct { |
| 387 | test "packed struct" { | 387 | test "packed struct" { |
| 388 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 388 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 389 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 389 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 390 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 391 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 390 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 392 | 391 | ||
| 393 | var foo = APackedStruct{ | 392 | var foo = APackedStruct{ |
| ... | @@ -496,7 +495,6 @@ const Bitfields = packed struct { | ... | @@ -496,7 +495,6 @@ const Bitfields = packed struct { |
| 496 | test "packed struct fields are ordered from LSB to MSB" { | 495 | test "packed struct fields are ordered from LSB to MSB" { |
| 497 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 496 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 498 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 497 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 499 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 500 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 498 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 501 | 499 | ||
| 502 | var all: u64 = 0x7765443322221111; | 500 | var all: u64 = 0x7765443322221111; |
| ... | @@ -632,7 +630,6 @@ test "default struct initialization fields" { | ... | @@ -632,7 +630,6 @@ test "default struct initialization fields" { |
| 632 | } | 630 | } |
| 633 | 631 | ||
| 634 | test "packed array 24bits" { | 632 | test "packed array 24bits" { |
| 635 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 636 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 633 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 637 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 634 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 638 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 635 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/union.zig-2| ... | @@ -1408,7 +1408,6 @@ test "union field ptr - zero sized field" { | ... | @@ -1408,7 +1408,6 @@ test "union field ptr - zero sized field" { |
| 1408 | } | 1408 | } |
| 1409 | 1409 | ||
| 1410 | test "packed union in packed struct" { | 1410 | test "packed union in packed struct" { |
| 1411 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 1412 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1411 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1413 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1412 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1414 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 1413 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| ... | @@ -1494,7 +1493,6 @@ test "union reassignment can use previous value" { | ... | @@ -1494,7 +1493,6 @@ test "union reassignment can use previous value" { |
| 1494 | } | 1493 | } |
| 1495 | 1494 | ||
| 1496 | test "packed union with zero-bit field" { | 1495 | test "packed union with zero-bit field" { |
| 1497 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 1498 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1496 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1499 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1497 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1500 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 1498 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |