authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-25 03:44:02-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-25 16:23:55-04:00
log8f385e77caae676ad675ca13baea51751230f200
tree9f38a6d1a62a72d990021765520f631e85a97a99
parent0cfc0d0d13bd1e9f1a9119324fac624371aecdd3

x86_64: implement struct_field_val for packed containers


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 {
37453745 }
37463746
37473747 const mcv = try self.resolveInst(operand);
3748 const struct_ty = self.air.typeOf(operand);
3749 if (struct_ty.zigTypeTag() == .Struct and struct_ty.containerLayout() == .Packed) {
3750 return self.fail("TODO airStructFieldVal implement packed structs", .{});
3751 }
3752 const struct_field_offset = struct_ty.structFieldOffset(index, self.target.*);
3753 const struct_field_ty = struct_ty.structFieldType(index);
3748 const container_ty = self.air.typeOf(operand);
3749 const field_ty = container_ty.structFieldType(index);
3750 const field_bit_offset = switch (container_ty.containerLayout()) {
3751 .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, self.target.*) * 8),
3752 .Packed => if (container_ty.castTag(.@"struct")) |struct_obj|
3753 struct_obj.data.packedFieldBitOffset(self.target.*, index)
3754 else
3755 0,
3756 };
37543757
37553758 const result: MCValue = result: {
37563759 switch (mcv) {
37573760 .stack_offset => |off| {
3758 const stack_offset = off - @intCast(i32, struct_field_offset);
3759 break :result MCValue{ .stack_offset = stack_offset };
3761 const byte_offset = std.math.divExact(u32, field_bit_offset, 8) catch
3762 return self.fail("TODO implement struct_field_val for a packed struct", .{});
3763 break :result MCValue{ .stack_offset = off - @intCast(i32, byte_offset) };
37603764 },
37613765 .register => |reg| {
37623766 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
......@@ -3779,27 +3783,28 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
37793783 defer if (dst_mcv_lock) |lock| self.register_manager.unlockReg(lock);
37803784
37813785 // Shift by struct_field_offset.
3782 const shift = @intCast(u8, struct_field_offset * 8);
3783 try self.genShiftBinOpMir(.shr, Type.usize, dst_mcv.register, .{ .immediate = shift });
3786 try self.genShiftBinOpMir(
3787 .shr,
3788 Type.usize,
3789 dst_mcv.register,
3790 .{ .immediate = field_bit_offset },
3791 );
37843792
3785 // Mask with reg.bitSize() - struct_field_size
3786 const max_reg_bit_width = Register.rax.bitSize();
3787 const mask_shift = @intCast(u6, (max_reg_bit_width - struct_field_ty.bitSize(self.target.*)));
3788 const mask = (~@as(u64, 0)) >> mask_shift;
3793 // Mask to field_bit_size bits
3794 const field_bit_size = field_ty.bitSize(self.target.*);
3795 const mask = ~@as(u64, 0) >> @intCast(u6, 64 - field_bit_size);
37893796
37903797 const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask });
37913798 try self.genBinOpMir(.@"and", Type.usize, dst_mcv, .{ .register = tmp_reg });
37923799
3793 const signedness: std.builtin.Signedness = blk: {
3794 if (struct_field_ty.zigTypeTag() != .Int) break :blk .unsigned;
3795 break :blk struct_field_ty.intInfo(self.target.*).signedness;
3796 };
3797 const field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*));
3798 if (signedness == .signed and field_size < 8) {
3800 const signedness =
3801 if (field_ty.isAbiInt()) field_ty.intInfo(self.target.*).signedness else .unsigned;
3802 const field_byte_size = @intCast(u32, field_ty.abiSize(self.target.*));
3803 if (signedness == .signed and field_byte_size < 8) {
37993804 try self.asmRegisterRegister(
38003805 .movsx,
38013806 dst_mcv.register,
3802 registerAlias(dst_mcv.register, field_size),
3807 registerAlias(dst_mcv.register, field_byte_size),
38033808 );
38043809 }
38053810
test/behavior/bitcast.zig-2
......@@ -157,7 +157,6 @@ test "bitcast generates a temporary value" {
157157}
158158
159159test "@bitCast packed structs at runtime and comptime" {
160 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
161160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
162161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
163162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -215,7 +214,6 @@ test "@bitCast extern structs at runtime and comptime" {
215214}
216215
217216test "bitcast packed struct to integer and back" {
218 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
219217 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
220218 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
221219 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 {
4444}
4545
4646test {
47 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
4847 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
4948 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5049 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" {
254254}
255255
256256test "byte-aligned field pointer offsets" {
257 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
258257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
259258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
260259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -397,7 +396,6 @@ test "@ptrToInt on a packed struct field" {
397396}
398397
399398test "optional pointer in packed struct" {
400 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
401399 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
402400 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
403401 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -530,7 +528,6 @@ test "nested packed struct field access test" {
530528test "runtime init of unnamed packed struct type" {
531529 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
532530 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
533 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
534531 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
535532
536533 var z: u8 = 123;
......@@ -545,7 +542,6 @@ test "runtime init of unnamed packed struct type" {
545542test "packed struct passed to callconv(.C) function" {
546543 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
547544 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
548 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
549545 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
550546
551547 const S = struct {
test/behavior/struct.zig-3
......@@ -387,7 +387,6 @@ const APackedStruct = packed struct {
387387test "packed struct" {
388388 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
389389 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
390 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
391390 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
392391
393392 var foo = APackedStruct{
......@@ -496,7 +495,6 @@ const Bitfields = packed struct {
496495test "packed struct fields are ordered from LSB to MSB" {
497496 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
498497 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
499 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
500498 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
501499
502500 var all: u64 = 0x7765443322221111;
......@@ -632,7 +630,6 @@ test "default struct initialization fields" {
632630}
633631
634632test "packed array 24bits" {
635 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
636633 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
637634 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
638635 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" {
14081408}
14091409
14101410test "packed union in packed struct" {
1411 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14121411 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14131412 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14141413 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -1494,7 +1493,6 @@ test "union reassignment can use previous value" {
14941493}
14951494
14961495test "packed union with zero-bit field" {
1497 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14981496 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14991497 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15001498 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO